summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apl9.h2
-rw-r--r--functions.c69
2 files changed, 69 insertions, 2 deletions
diff --git a/apl9.h b/apl9.h
index a8d234f..00075fd 100644
--- a/apl9.h
+++ b/apl9.h
@@ -290,6 +290,7 @@ Array *fnRecip(Array *);
Array *fnExponent(Array *);
Array *fnNaturalLog(Array *);
Array *fnPiTimes(Array *);
+Array *fnRoll(Array *);
Array *fnMagnitude(Array *);
Array *fnCeiling(Array *);
Array *fnFloor(Array *);
@@ -325,6 +326,7 @@ Array *fnTimes(Array *, Array *);
Array *fnDivide(Array *, Array *);
Array *fnPower(Array *, Array *);
Array *fnLogarithm(Array *, Array *);
+Array *fnDeal(Array *, Array *);
Array *fnResidue(Array *, Array *);
Array *fnMaximum(Array *, Array *);
Array *fnMinimum(Array *, Array *);
diff --git a/functions.c b/functions.c
index 2425798..b72c2bd 100644
--- a/functions.c
+++ b/functions.c
@@ -16,7 +16,7 @@ fnmonad monadfunctiondefs[] = {
0, /* ⌹ */
fnPiTimes, /* ○ */
0, /* ! */
- 0, /* ? */
+ fnRoll, /* ? */
fnMagnitude, /* | */
fnCeiling, /* ⌈ */
fnFloor, /* ⌊ */
@@ -72,7 +72,7 @@ fndyad dyadfunctiondefs[] = {
0, /* ⌹ */
0, /* ○ */
0, /* ! */
- 0, /* ? */
+ fnDeal, /* ? */
fnResidue, /* | */
fnMaximum, /* ⌈ */
fnMinimum, /* ⌊ */
@@ -324,6 +324,45 @@ fnPiTimes(Array *right)
}
Array *
+fnRoll(Array *right)
+{
+ Array *result = nil;
+ if(right->type == AtypeArray){
+ result = duparrayshape(right, AtypeArray);
+ for(int i = 0; i < right->size; i++)
+ result->arraydata[i] = fnRoll(right->arraydata[i]);
+ }else if(right->type == AtypeInt){
+ if(right->size == 0)
+ return duparrayshape(right, AtypeInt);
+ int io = globalIO();
+ vlong lowest = right->intdata[0];
+ for(int i = 1; i < right->size; i++)
+ if(right->intdata[i] < lowest)
+ lowest = right->intdata[i];
+ if(lowest < 0)
+ throwerror(nil, EDomain);
+ else if(lowest == 0){
+ result = duparrayshape(right, AtypeFloat);
+ for(int i = 0; i < right->size; i++){
+ vlong max = right->intdata[i];
+ if(max == 0)
+ do{
+ result->floatdata[i] = frand();
+ }while(result->floatdata[i] == 0);
+ else
+ result->floatdata[i] = io + lrand() % max;
+ }
+ }else{
+ result = duparrayshape(right, AtypeInt);
+ for(int i = 0; i < right->size; i++)
+ result->intdata[i] = io + lrand() % right->intdata[i];
+ }
+ }else
+ throwerror(nil, EType);
+ return result;
+}
+
+Array *
fnMagnitude(Array *right)
{
return rundfn(L"⍵××⍵", nil, nil, nil, right);
@@ -867,6 +906,32 @@ SCALAR_FUNCTION_2(fnLogarithm, 1, left->type,
break;
)
+Array *
+fnDeal(Array *left, Array *right)
+{
+ if(left->type != AtypeInt || right->type != AtypeInt)
+ throwerror(nil, EType);
+ if(left->size != 1 || right->size != 1)
+ throwerror(nil, EShape);
+ vlong x = left->intdata[0];
+ vlong y = right->intdata[0];
+ if(x < 0 || y < 0 || x > y)
+ throwerror(nil, EDomain);
+
+ Array *result = allocarray(AtypeInt, 1, x);
+ result->shape[0] = x;
+ int io = globalIO();
+ for(int i = 0; i < x; i++){
+ result->intdata[i] = io + lrand() % y;
+ for(int j = 0; j < i; j++)
+ if(result->intdata[j] == result->intdata[i]){
+ i--;
+ break;
+ }
+ }
+ return result;
+}
+
SCALAR_FUNCTION_2(fnResidue, 1, left->type,
case AtypeFloat:
if(res->floatdata[i] == 0)