From 219e5103271f439ab9ed64ae892e4ab6096bb236 Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Sat, 29 Jan 2022 18:35:50 +0000 Subject: Rewrite replicate in C. The implementation is much like that of expand --- hybrids.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/hybrids.c b/hybrids.c index 601898f..8042e5d 100644 --- a/hybrids.c +++ b/hybrids.c @@ -36,12 +36,71 @@ fnExpandLast(Array *left, Array *right) Array * fnReplicateFirst(Array *left, Array *right) { - Rune *code = - L"(0=≢⍴⍵)∧⍺∧.=0: 0⍴⍵ ⋄" - L"⍺∧.=0: (((1,¯1+≢⍴⍵)⌿¯1 1)⌿⍴⍵)⍴⍵ ⋄" - L"1=×⌿⍴,⍵: ↑⍪⌿(+⌿⍺)⍴⊂⍵ ⋄" - L"↑↑⍪⌿⍺ (⍵{e←⊂⍵⌷⍶ ⋄ ⍺>0: ⍺⍴e ⋄ (|⍺)⍴⎕PROTO e})¨⍳≢⍵"; - return rundfn(code, nil, nil, left, right); + if(left->type != AtypeInt) + throwerror(nil, EType); + if(left->rank > 1) + throwerror(nil, ERank); + + /* Reshape right if scalar */ + if(right->size == 1){ + Array *shape = right->rank == 0 ? mkscalarint(1) : fnShape(right); + shape->intdata[0] = left->size; + right = fnReshape(shape, right); + freearray(shape); + }else + right = fnSame(right); + + int nsize = right->shape[0]; + int cellsize = nsize == 0 ? 1 : right->size / nsize; + int i; + if(left->size == 1){ + Array *shape = mkscalarint(nsize); + left = fnReshape(shape, left); + }else + left = fnSame(left); + + if(left->size != nsize){ + freearray(left); + freearray(right); + throwerror(nil, ELength); + } + + nsize = 0; + for(i = 0; i < left->size; i++){ + vlong n = left->intdata[i]; + nsize += n > 0 ? n : -n; + } + + Array *result = allocarray(right->type, right->rank, nsize * cellsize); + result->shape[0] = nsize; + for(i = 1; i < result->rank; i++) + result->shape[i] = right->shape[i]; + + Array *fill = fillelement(right); + int from, to; + int npos; + for(from = 0, to = 0; to < nsize; from++, to += npos){ + int neg = left->intdata[from] < 0; + npos = left->intdata[from]; + if(neg){ + npos = -npos; + for(int j = 0; j < npos*cellsize; j++) + memcpy(result->rawdata + (to*cellsize+j)*datasizes[result->type], + fill->rawdata, datasizes[result->type]); + }else{ + for(int j = 0; j < npos; j++) + memcpy(result->rawdata + (to+j)*cellsize*datasizes[result->type], + right->rawdata + from*cellsize*datasizes[result->type], + cellsize*datasizes[result->type]); + } + if(result->type == AtypeArray) + for(int j = 0; j < npos*cellsize; j++) + incref(result->arraydata[to*cellsize+j]); + } + freearray(fill); + freearray(left); + freearray(right); + return result; } Array * -- cgit v1.2.3