diff --git a/stix/kernel/Stix.st b/stix/kernel/Stix.st index ecd4b90..74364f5 100644 --- a/stix/kernel/Stix.st +++ b/stix/kernel/Stix.st @@ -59,6 +59,19 @@ self primitiveFailed. } + + #method // aNumber + { + + self primitiveFailed. + } + + #method \\ aNumber + { + + self primitiveFailed. + } + #method = aNumber { diff --git a/stix/kernel/test-005.st b/stix/kernel/test-005.st index 8e87b9c..009d172 100644 --- a/stix/kernel/test-005.st +++ b/stix/kernel/test-005.st @@ -270,8 +270,14 @@ PROCESS TESTING (2r111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 * 128971234897128931) dump. -(-10000 rem: -3) dump. -(-10000 quo: -3) dump. +"(-10000 rem: 3) dump. +(-10000 quo: 3) dump. +(-10000 \\ 3) dump. +(-10000 // 3) dump." +(7 rem: -3) dump. +(7 quo: -3) dump. +(7 \\ -3) dump. +(7 // -3) dump. " FFI isNil dump. diff --git a/stix/lib/bigint.c b/stix/lib/bigint.c index 72f014e..930ead8 100644 --- a/stix/lib/bigint.c +++ b/stix/lib/bigint.c @@ -1034,7 +1034,7 @@ oops_einval: return STIX_NULL; } -stix_oop_t stix_divints (stix_t* stix, stix_oop_t x, stix_oop_t y, stix_oop_t* rem) +stix_oop_t stix_divints (stix_t* stix, stix_oop_t x, stix_oop_t y, int modulo, stix_oop_t* rem) { stix_oop_t t; @@ -1054,9 +1054,50 @@ stix_oop_t stix_divints (stix_t* stix, stix_oop_t x, stix_oop_t y, stix_oop_t* r q = xv / yv; STIX_ASSERT (STIX_IN_SMOOI_RANGE(q)); + r = xv - yv * q; /* xv % yv; */ + if (modulo) + { + /* modulo */ + /* + xv yv q r + ------------------------- + 7 3 2 1 + -7 3 -3 2 + 7 -3 -3 -2 + -7 -3 2 -1 + */ + if (r && ((yv ^ r) < 0)) + { + /* if the divisor has a different sign from r, + * change the sign of r to the divisor's sign */ + r += yv; + --q; + STIX_ASSERT (r && ((yv ^ r) >= 0)); + } + } + else + { + /* remainder */ + /* + xv yv q r + ------------------------- + 7 3 2 1 + -7 3 -2 -1 + 7 -3 -2 1 + -7 -3 2 -1 + */ + if (xv && ((xv ^ r) < 0)) + { + /* if the dividend has a different sign from r, + * change the sign of r to the dividend's sign */ + r -= yv; + ++q; + STIX_ASSERT (xv && ((xv ^ r) >= 0)); + } + } + if (rem) { - r = xv - yv * q; /* r = xv % yv; */ STIX_ASSERT (STIX_IN_SMOOI_RANGE(r)); *rem = STIX_SMOOI_TO_OOP(r); } diff --git a/stix/lib/exec.c b/stix/lib/exec.c index c7cbfeb..895de38 100644 --- a/stix/lib/exec.c +++ b/stix/lib/exec.c @@ -1069,7 +1069,7 @@ static int prim_integer_quo (stix_t* stix, stix_ooi_t nargs) rcv = ACTIVE_STACK_GET(stix, stix->sp - 1); arg = ACTIVE_STACK_GET(stix, stix->sp); - quo = stix_divints (stix, rcv, arg, STIX_NULL); + quo = stix_divints (stix, rcv, arg, 0, STIX_NULL); if (!quo) return (stix->errnum == STIX_EINVAL? 0: -1); /* soft or hard failure */ ACTIVE_STACK_POP (stix); @@ -1086,7 +1086,41 @@ static int prim_integer_rem (stix_t* stix, stix_ooi_t nargs) rcv = ACTIVE_STACK_GET(stix, stix->sp - 1); arg = ACTIVE_STACK_GET(stix, stix->sp); - quo = stix_divints (stix, rcv, arg, &rem); + quo = stix_divints (stix, rcv, arg, 0, &rem); + if (!quo) return (stix->errnum == STIX_EINVAL? 0: -1); /* soft or hard failure */ + + ACTIVE_STACK_POP (stix); + ACTIVE_STACK_SETTOP (stix, rem); + return 1; +} + +static int prim_integer_quo2 (stix_t* stix, stix_ooi_t nargs) +{ + stix_oop_t rcv, arg, quo; + + STIX_ASSERT (nargs == 1); + + rcv = ACTIVE_STACK_GET(stix, stix->sp - 1); + arg = ACTIVE_STACK_GET(stix, stix->sp); + + quo = stix_divints (stix, rcv, arg, 1, STIX_NULL); + if (!quo) return (stix->errnum == STIX_EINVAL? 0: -1); /* soft or hard failure */ + + ACTIVE_STACK_POP (stix); + ACTIVE_STACK_SETTOP (stix, quo); + return 1; +} + +static int prim_integer_rem2 (stix_t* stix, stix_ooi_t nargs) +{ + stix_oop_t rcv, arg, quo, rem; + + STIX_ASSERT (nargs == 1); + + rcv = ACTIVE_STACK_GET(stix, stix->sp - 1); + arg = ACTIVE_STACK_GET(stix, stix->sp); + + quo = stix_divints (stix, rcv, arg, 1, &rem); if (!quo) return (stix->errnum == STIX_EINVAL? 0: -1); /* soft or hard failure */ ACTIVE_STACK_POP (stix); @@ -1601,6 +1635,8 @@ static prim_t primitives[] = { 1, prim_integer_mul, "_integer_mul" }, { 1, prim_integer_quo, "_integer_quo" }, { 1, prim_integer_rem, "_integer_rem" }, + { 1, prim_integer_quo2, "_integer_quo2" }, + { 1, prim_integer_rem2, "_integer_rem2" }, { 1, prim_integer_eq, "_integer_eq" }, { 1, prim_integer_ne, "_integer_ne" }, { 1, prim_integer_lt, "_integer_lt" }, diff --git a/stix/lib/stix-prv.h b/stix/lib/stix-prv.h index d901ad0..5203229 100644 --- a/stix/lib/stix-prv.h +++ b/stix/lib/stix-prv.h @@ -1093,6 +1093,7 @@ stix_oop_t stix_divints ( stix_t* stix, stix_oop_t x, stix_oop_t y, + int modulo, stix_oop_t* rem );