Added `gcd` function to stdlib.
[vvhitespace] / stdlib / math.pvvs
CommitLineData
3625ff3a
AT
1#ifndef VVS_STDLIB_MATH
2#define VVS_STDLIB_MATH
3
2612f47f 4@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bb21580a
AT
5@ Name:
6@ random (10000)
2612f47f 7@ Description:
b15f1da5
AT
8@ Returns a kinda-random number.
9@ Before using for the first time, seed heap[0] with a value.
2612f47f
AT
10@ Call Stack:
11@ empty
12@ Return Stack:
13@ random number <-- TOS
14@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
15NSSVTSSSSN | Mark: 10000 (random)
b15f1da5
AT
16
17@ Generate the next seed value
18SSSSN | PUSH 0 (ptr)
19TTT | LOAD
20SSSTSSSSSTTTSSSTTSSTSSTTTSSTTSTTSTN | PUSH 1103515245
21TSSN | MULTIPLY
22SSSTTSSSSSSTTTSSTN | PUSH 12345
23TSSS | ADD
24
25@ Store the next seed value but keep a copy on the stack.
26SNS | DUP
27SSSSN | PUSH 0 (ptr)
28SNT | SWAP
29TTS | STORE
30
31@ Calculate the random number and return.
32SSSTSSSSSSSSSSSSSSSSN | PUSH 65536
33TSTS | DIVIDE
34SSSTSSSSSSSSSSSSSSSN | PUSH 32768
35TSTT | MODULO
2612f47f
AT
36NTN | RTS
37
3625ff3a 38@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bb21580a
AT
39@ Name:
40@ abs (10001)
3625ff3a 41@ Description:
bb21580a 42@ Returns the absolute value of its argument
3625ff3a
AT
43@ Call Stack:
44@ signed number <-- TOS
45@ Return Stack:
46@ abs(signed number) <-- TOS
47@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
48NSSVTSSSTN | Mark: 10001 (absolute value)
7359501c
AT
49
50@ Catch -(2^63) as a special case since its absolute value will overflow
51@ a twos-complement 64-bit word. Return zero as though the absolute value
52@ overflowed to the bottom of the non-negative integers rather than
53@ overflowing back to the most negative integer.
54SNS | DUP
55SSTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSN | -(2^63)
56TSST | SUBTRACT
57NTSSSSTSSSTSSSSSSTSN | BRZ > 00010001 00000010
58
59@ Handle all the other numbers.
3625ff3a
AT
60SNS | DUP
61NTTSSSTSSSTSSSSSSSSN | BMI > 00010001 00000000
62NSNSSSTSSSTSSSSSSSTN | JMP > 00010001 00000001
63NSSVSSSTSSSTSSSSSSSSN | Mark: 00010001 00000000
64SSTTN | PUSH -1
65TSSN | MULTIPLY
66NSSVSSSTSSSTSSSSSSSTN | Mark: 00010001 00000001
67NTN | RTS
68
7359501c
AT
69@ Special case: Push 0 and return.
70NSSVSSSTSSSTSSSSSSTSN | Mark: 00010001 00000010
71SNN | DROP
72SSSSN | PUSH 0
73NTN | RTS
74
37372ed0
AT
75@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
76@ Name:
77@ gcd (10010)
78@ Description:
79@ Returns greatest common divisor of X and Y.
80@ Call Stack:
81@ Y
82@ X <-- TOS
83@ Return Stack:
84@ gcd(X,Y) <-- TOS
85@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
86#include <stack.pvvs>
87NSSVTSSTSN | Mark: 10010 (gcd)
88
89@ Since 1 > -1, transform problem into gcd(abs(X),abs(Y)).
90SNT | SWAP
91NSTTSSSTN | JSR > 10001 (abs)
92SNT | SWAP
93NSTTSSSTN | JSR > 10001 (abs)
94
95@ Verify neither operand is zero.
96SNT | SWAP
97SNS | DUP
98NTSSSSTSSTSSSSSSSSSN | BRZ > 00010010 00000000 (gcd:zero input)
99SNT | SWAP
100SNS | DUP
101NTSSSSTSSTSSSSSSSSSN | BRZ > 00010010 00000000 (gcd:zero input)
102
103@ Verify X != Y and sort X,Y so the smaller is TOS.
104SNS | DUP
105SSSTTN | PUSH 3
106NSTTTSSN | JSR > 1100 (deepdup)
107SNT | SWAP
108TSST | SUBTRACT
109@ TOS> Y-X, X, Y
110NTTSSSTSSTSSSSSSSSTN | BMI > 00010010 00000001 (gcd:swap inputs)
111NSNSSSTSSTSSSSSSSTSN | JMP > 00010010 00000010 (gcd:main loop)
112NSSVSSSTSSTSSSSSSSSTN | MARK: 00010010 00000001 (gcd:swap inputs)
113SNT | SWAP
114
115@ Main gcd loop.
116@ Euclidean algorithm.
117NSSVSSSTSSTSSSSSSSTSN | MARK: 00010010 00000010 (gcd:main loop)
118SNS | DUP
119SSSTTN | PUSH 3
120NSTTSTSN | JSR > 1010 (stackrotate)
121TSTT | MODULO
122SNS | DUP
123NTSSSSTSSTSSSSSSSTTN | BRZ > 00010010 00000011 (gcd:loop termination)
124NSNSSSTSSTSSSSSSSTSN | JMP > 00010010 00000010 (gcd:main loop)
125NSSVSSSTSSTSSSSSSSTTN | MARK: 00010010 00000011 (gcd:loop termination)
126SNN | DROP
127NTN | RTS
128
129@ At least one operand was zero.
130@ Since we define gcd(a,0) = a, return the other operand.
131NSSVSSSTSSTSSSSSSSSSN | MARK: 00010010 00000000 (gcd:zero input)
132SNN | DROP
133NTN | RTS
134
3625ff3a 135#endif