summaryrefslogtreecommitdiff
path: root/hybrids.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <petermikkelsen10@gmail.com>2022-01-29 17:23:44 +0000
committerPeter Mikkelsen <petermikkelsen10@gmail.com>2022-01-29 17:23:44 +0000
commit1ea2f6f8af7ef012005d46fd13acd082628f7295 (patch)
treeecd458e81035f6a1f2193d0efe4daf66fe6cfe55 /hybrids.c
parenta9cb9bb4ccc58a24ce2ab31193f179901f56cf5a (diff)
Implement expand last (\) and expand first (⍀)
Diffstat (limited to 'hybrids.c')
-rw-r--r--hybrids.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/hybrids.c b/hybrids.c
index da42e62..601898f 100644
--- a/hybrids.c
+++ b/hybrids.c
@@ -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)