X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/3625ff3a8ea0b61d744da30237e6ffc993a585fb..d5a0b33775da13d1589252f75f2f86b81ffff599:/stdlib/math.pvvs diff --git a/stdlib/math.pvvs b/stdlib/math.pvvs index b1a6c0e..eac0181 100644 --- a/stdlib/math.pvvs +++ b/stdlib/math.pvvs @@ -1,15 +1,111 @@ +@ (c) 2020 Aaron Taylor +@ See LICENSE.txt file for copyright and license details. + #ifndef VVS_STDLIB_MATH #define VVS_STDLIB_MATH @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ random (10000) +@ Description: +@ Returns a pseudo-random number. +@ Before using for the first time, seed heap[0] with a non-zero value. +@ This PRNG was taken from: https://en.wikipedia.org/wiki/Xorshift +@ Call Stack: +@ empty +@ Return Stack: +@ random number <-- TOS +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#include +NSSVTSSSSN | Mark: 10000 (random) + +@ Fetch seed from heap[0]. +SSSSN | PUSH 0 (ptr) +TTT | LOAD + +@ Set TOS ^= TOS << 13 +SNS | DUP +SSSTTSTN | PUSH +13 +NSTTSTTSTN | JSR > 101101 (lshift) +NSTTSTSTTN | JSR > 101011 (xor) + +@ Set TOS ^= TOS >> 7 +SNS | DUP +SSSTTTN | PUSH +7 +NSTTSTTSSN | JSR > 101100 (rshift) +NSTTSTSTTN | JSR > 101011 (xor) + +@ Set TOS ^= TOS << 17 +SNS | DUP +SSSTSSSTN | PUSH +17 +NSTTSTTSTN | JSR > 101101 (lshift) +NSTTSTSTTN | JSR > 101011 (xor) + +@ Store a copy of the new seed at heap[0] and return. +SNS | DUP +SSSSN | PUSH 0 (ptr) +SNT | SWAP +TTS | STORE +NTN | RTS + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ fastrand (10011) @ Description: -@ This function returns the absolute value of its argument +@ Returns a pseudo-random number. +@ Probably not as good as `random`, but much faster since it doesn't use XOR. +@ Based on the POSIX.1-2001 example for random(). +@ Before using for the first time, seed heap[0] with a value. +@ Call Stack: +@ empty +@ Return Stack: +@ random number <-- TOS +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +NSSVTSSTTN | Mark: 10011 (fastrand) + +@ Generate the next seed value +SSSSN | PUSH 0 (ptr) +TTT | LOAD +SSSTSSSSSTTTSSSTTSSTSSTTTSSTTSTTSTN | PUSH 1103515245 +TSSN | MULTIPLY +SSSTTSSSSSSTTTSSTN | PUSH 12345 +TSSS | ADD + +@ Store the next seed value but keep a copy on the stack. +SNS | DUP +SSSSN | PUSH 0 (ptr) +SNT | SWAP +TTS | STORE + +@ Calculate the random number and return. +SSSTSSSSSSSSSSSSSSSSN | PUSH 65536 +TSTS | DIVIDE +SSSTSSSSSSSSSSSSSSSN | PUSH 32768 +TSTT | MODULO +NTN | RTS + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ abs (10001) +@ Description: +@ Returns the absolute value of its argument @ Call Stack: @ signed number <-- TOS @ Return Stack: @ 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 @@ -19,4 +115,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: +@ gcd (10010) +@ Description: +@ Returns greatest common divisor of X and Y. +@ Call Stack: +@ Y +@ X <-- TOS +@ Return Stack: +@ gcd(X,Y) <-- TOS +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#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 + +@ 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