diff options
Diffstat (limited to 'hybrids.c')
-rw-r--r-- | hybrids.c | 69 |
1 files changed, 67 insertions, 2 deletions
@@ -8,9 +8,9 @@ Rune primhybridnames[] = L"/\\⌿⍀"; fndyad hybridfunctiondefs[] = { fnReplicateLast, /* / */ - 0, /* \ */ + fnExpandLast, /* \ */ fnReplicateFirst, /* ⌿ */ - 0, /* ⍀ */ + fnExpandFirst, /* ⍀ */ }; opmonad hybridoperatordefs[] = { @@ -28,6 +28,12 @@ fnReplicateLast(Array *left, Array *right) } Array * +fnExpandLast(Array *left, Array *right) +{ + return rundfn(L"⍉⍺⍀⍉⍵", nil, nil, left, right); +} + +Array * fnReplicateFirst(Array *left, Array *right) { Rune *code = @@ -38,6 +44,65 @@ fnReplicateFirst(Array *left, Array *right) return rundfn(code, nil, nil, left, right); } +Array * +fnExpandFirst(Array *left, Array *right) +{ + if(left->type != AtypeInt) + throwerror(nil, EType); + if(left->rank > 1) + throwerror(nil, ERank); + + right = right->rank == 0 ? fnRavel(right) : fnSame(right); + + int npos = 0; + int nsize = 0; + int i; + for(i = 0; i < left->size; i++){ + if(left->intdata[i] > 0) + npos++; + else if(left->intdata[i] == 0) + left->intdata[i] = -1; + + vlong n = left->intdata[i]; + nsize += n > 0 ? n : -n; + } + + if(right->shape[0] != 1 && right->shape[0] != npos) + throwerror(nil, ELength); + + vlong cellsize = right->shape[0] == 0 ? 1 : right->size / right->shape[0]; + 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; + for(from = 0, to = 0, i = 0; to < nsize; i++, to += npos){ + int neg = left->intdata[i] < 0; + npos = left->intdata[i]; + 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]); + if(right->shape[0] != 1 && !neg) + from++; + } + freearray(fill); + freearray(right); + return result; +} + /* operator definitions */ Array * opReduceLast(Datum *lefto, Array *left, Array *right) |