diff options
-rw-r--r-- | apl9.h | 4 | ||||
-rw-r--r-- | functions.c | 78 |
2 files changed, 78 insertions, 4 deletions
@@ -268,6 +268,10 @@ Array *fnLess(Array *, Array *); Array *fnGreater(Array *, Array *); Array *fnGreaterEqual(Array *, Array *); Array *fnMatch(Array *, Array *); +Array *fnOr(Array *, Array *); +Array *fnAnd(Array *, Array *); +Array *fnNand(Array *, Array *); +Array *fnNor(Array *, Array *); Array *fnTake(Array *, Array *); Array *fnIndex(Array *, Array *); Array *fnCatenateFirst(Array *, Array *); diff --git a/functions.c b/functions.c index 9f23a43..d9b2eb4 100644 --- a/functions.c +++ b/functions.c @@ -87,10 +87,10 @@ fndyad dyadfunctiondefs[] = { fnGreaterEqual, /* ≥ */ fnMatch, /* ≡ */ 0, /* ≢ */ - 0, /* ∨ */ - 0, /* ∧ */ - 0, /* ⍲ */ - 0, /* ⍱ */ + fnOr, /* ∨ */ + fnAnd, /* ∧ */ + fnNand, /* ⍲ */ + fnNor, /* ⍱ */ fnTake, /* ↑ */ 0, /* ↓ */ 0, /* ⊂ */ @@ -116,6 +116,9 @@ fndyad dyadfunctiondefs[] = { 0, /* ⍕ */ }; +vlong gcd_int(vlong, vlong); +double gcd_float(double, double); + /* Runner function */ Array * runfunc(Function f, Array *left, Array *right) @@ -705,6 +708,54 @@ fnMatch(Array *left, Array *right) return mkscalarint(cmp == 0); } +SCALAR_FUNCTION_2(fnOr, 0, left->type, + case AtypeInt: + if((left->intdata[i] == 0 || left->intdata[i] == 1) && (right->intdata[i] == 0 || right->intdata[i] == 1)) + res->intdata[i] = left->intdata[i] || right->intdata[i]; + else + res->intdata[i] = gcd_int(left->intdata[i], right->intdata[i]); + break; + case AtypeFloat: + res->floatdata[i] = gcd_float(left->floatdata[i], right->floatdata[i]); + break; +) + +SCALAR_FUNCTION_2(fnAnd, 0, left->type, + case AtypeInt: + if((left->intdata[i] == 0 || left->intdata[i] == 1) && (right->intdata[i] == 0 || right->intdata[i] == 1)) + res->intdata[i] = left->intdata[i] && right->intdata[i]; + else{ + vlong p = left->intdata[i] * right->intdata[i]; + if(p < 0) + p = -p; + res->intdata[i] = p / gcd_int(left->intdata[i], right->intdata[i]); + } + break; + case AtypeFloat: + res->floatdata[i] = fabs(left->floatdata[i] * right->floatdata[i]) / gcd_float(left->floatdata[i], right->floatdata[i]); + break; +) + +SCALAR_FUNCTION_2(fnNand, 0, AtypeInt, + case AtypeInt: + if(left->intdata[i] != 0 && left->intdata[i] != 1) + throwerror(nil, EType); + if(right->intdata[i] != 0 && right->intdata[i] != 1) + throwerror(nil, EType); + res->intdata[i] = !(left->intdata[i] && right->intdata[i]); + break; +) + +SCALAR_FUNCTION_2(fnNor, 0, AtypeInt, + case AtypeInt: + if(left->intdata[i] != 0 && left->intdata[i] != 1) + throwerror(nil, EType); + if(right->intdata[i] != 0 && right->intdata[i] != 1) + throwerror(nil, EType); + res->intdata[i] = !(left->intdata[i] || right->intdata[i]); + break; +) + Array * fnTake(Array *left, Array *right) { @@ -989,4 +1040,23 @@ fnReshape(Array *left, Array *right) for(i = 0; i < res->size; i++) incref(res->arraydata[i]); return res; +} + +/* helper functions */ +vlong +gcd_int(vlong a, vlong b) +{ + if(b == 0) + return a; + else + return gcd_int(b, a % b); +} + +double +gcd_float(double a, double b) +{ + if(b < 0.0000000001 && b > -0.0000000001) /* Some error tolerance */ + return a; + else + return gcd_float(b, fmod(a,b)); }
\ No newline at end of file |