X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/e0d5136cb09e6ac4680796af169a611ff6c97996..37372ed0cccf20298fdefc4c3d1153eb58407e45:/stdlib/math.pvvs diff --git a/stdlib/math.pvvs b/stdlib/math.pvvs index 7bd73e5..742522e 100644 --- a/stdlib/math.pvvs +++ b/stdlib/math.pvvs @@ -46,6 +46,17 @@ NTN | RTS @ abs(signed number) <-- TOS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ NSSVTSSSTN | Mark: 10001 (absolute value) + +@ Catch -(2^63) as a special case since its absolute value will overflow +@ a twos-complement 64-bit word. Return zero as though the absolute value +@ overflowed to the bottom of the non-negative integers rather than +@ overflowing back to the most negative integer. +SNS | DUP +SSTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSN | -(2^63) +TSST | SUBTRACT +NTSSSSTSSSTSSSSSSTSN | BRZ > 00010001 00000010 + +@ Handle all the other numbers. SNS | DUP NTTSSSTSSSTSSSSSSSSN | BMI > 00010001 00000000 NSNSSSTSSSTSSSSSSSTN | JMP > 00010001 00000001 @@ -55,22 +66,70 @@ TSSN | MULTIPLY NSSVSSSTSSSTSSSSSSSTN | Mark: 00010001 00000001 NTN | RTS +@ Special case: Push 0 and return. +NSSVSSSTSSSTSSSSSSTSN | Mark: 00010001 00000010 +SNN | DROP +SSSSN | PUSH 0 +NTN | RTS + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: -@ isnegative (1000001) +@ gcd (10010) @ Description: -@ Returns 1 if 'number' is negative, 0 if positive. +@ Returns greatest common divisor of X and Y. @ Call Stack: -@ number <-- TOS +@ Y +@ X <-- TOS @ Return Stack: -@ 1 or 0 <-- TOS +@ gcd(X,Y) <-- TOS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -NSSVTSSSSSTN | Mark: 1000001 (isnegative) -NTTSTSSSSSTSSSSSSSSN | BMI > 01000001 00000000 -SSSSN | PUSH 0 +#include +NSSVTSSTSN | Mark: 10010 (gcd) + +@ Since 1 > -1, transform problem into gcd(abs(X),abs(Y)). +SNT | SWAP +NSTTSSSTN | JSR > 10001 (abs) +SNT | SWAP +NSTTSSSTN | JSR > 10001 (abs) + +@ Verify neither operand is zero. +SNT | SWAP +SNS | DUP +NTSSSSTSSTSSSSSSSSSN | BRZ > 00010010 00000000 (gcd:zero input) +SNT | SWAP +SNS | DUP +NTSSSSTSSTSSSSSSSSSN | BRZ > 00010010 00000000 (gcd:zero input) + +@ Verify X != Y and sort X,Y so the smaller is TOS. +SNS | DUP +SSSTTN | PUSH 3 +NSTTTSSN | JSR > 1100 (deepdup) +SNT | SWAP +TSST | SUBTRACT +@ TOS> Y-X, X, Y +NTTSSSTSSTSSSSSSSSTN | BMI > 00010010 00000001 (gcd:swap inputs) +NSNSSSTSSTSSSSSSSTSN | JMP > 00010010 00000010 (gcd:main loop) +NSSVSSSTSSTSSSSSSSSTN | MARK: 00010010 00000001 (gcd:swap inputs) +SNT | SWAP + +@ Main gcd loop. +@ Euclidean algorithm. +NSSVSSSTSSTSSSSSSSTSN | MARK: 00010010 00000010 (gcd:main loop) +SNS | DUP +SSSTTN | PUSH 3 +NSTTSTSN | JSR > 1010 (stackrotate) +TSTT | MODULO +SNS | DUP +NTSSSSTSSTSSSSSSSTTN | BRZ > 00010010 00000011 (gcd:loop termination) +NSNSSSTSSTSSSSSSSTSN | JMP > 00010010 00000010 (gcd:main loop) +NSSVSSSTSSTSSSSSSSTTN | MARK: 00010010 00000011 (gcd:loop termination) +SNN | DROP NTN | RTS -NSSVSTSSSSSTSSSSSSSSN | Mark: 01000001 00000000 -SSSTN | PUSH 1 + +@ At least one operand was zero. +@ Since we define gcd(a,0) = a, return the other operand. +NSSVSSSTSSTSSSSSSSSSN | MARK: 00010010 00000000 (gcd:zero input) +SNN | DROP NTN | RTS #endif