spitewaste 0.1.003 → 0.1.004
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +27 -10
- data/lib/spitewaste.rb +1 -1
- data/lib/spitewaste/cli/exec.rb +10 -13
- data/lib/spitewaste/libspw/array.spw +5 -1
- data/lib/spitewaste/libspw/bits.spw +4 -2
- data/lib/spitewaste/libspw/case.spw +3 -1
- data/lib/spitewaste/libspw/fun.spw +5 -1
- data/lib/spitewaste/libspw/io.spw +2 -0
- data/lib/spitewaste/libspw/math.spw +83 -45
- data/lib/spitewaste/libspw/prime.spw +3 -2
- data/lib/spitewaste/libspw/random.spw +2 -0
- data/lib/spitewaste/libspw/rational.spw +153 -0
- data/lib/spitewaste/libspw/stack.spw +54 -30
- data/lib/spitewaste/libspw/string.spw +228 -92
- data/lib/spitewaste/libspw/test.spw +3 -0
- data/lib/spitewaste/libspw/util.spw +92 -39
- data/lib/spitewaste/parsers/spitewaste.rb +7 -15
- data/lib/spitewaste/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e6953a0755edbb33708f3cdc1ebeb33cdb6a47c1f3d6335716d25f693dec56c
|
4
|
+
data.tar.gz: 130d57daadcee3de1a465e4be9b28bba16d70c4dafa87c59195696be06e49a7c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1f2075fb27a9ecf5599365cf029bfeebacfda5208a5df357ea94de00465111f61d42cc58a5220e16de710dfe4c778acf911e65ab3d86459c7039cee37f011a6
|
7
|
+
data.tar.gz: ea2003b53fe38c7fa092b2c43c383706980009fd1efa54f5733e40937b180fd76ea08e973dd5e16835fab1854f075add855af1957357aeab391df0dab6945e92
|
data/Rakefile
CHANGED
@@ -7,15 +7,20 @@ Rake::TestTask.new(:test) do |t|
|
|
7
7
|
t.test_files = FileList['test/*_test.rb']
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
task test: :docs
|
11
|
+
|
12
|
+
desc 'Generate standard library documentation.'
|
11
13
|
task :docs do |t|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
docs = {}
|
15
|
+
|
16
|
+
Dir.chdir('lib/spitewaste/libspw') do |d|
|
17
|
+
%w[rational.spw array.spw stack.spw util.spw string.spw math.spw].each do |path|
|
18
|
+
lib = File.basename path, '.spw'
|
19
|
+
docs[lib] = extract_docs path
|
20
|
+
end
|
17
21
|
|
18
|
-
|
22
|
+
File.open('docs.json', ?w) { |f| JSON.dump docs, f }
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
26
|
def extract_docs path
|
@@ -41,12 +46,24 @@ def strpack s
|
|
41
46
|
end
|
42
47
|
|
43
48
|
def parse_stack s
|
44
|
-
s.
|
49
|
+
s.scan(/"[^"]*"|\S+/).map { |v|
|
50
|
+
begin
|
51
|
+
Integer v
|
52
|
+
rescue
|
53
|
+
if v[/R\((-?\d+),(-?\d+)\)/]
|
54
|
+
n, d = $1.to_i, $2.to_i
|
55
|
+
s = (n<=>0) * (d<=>0)
|
56
|
+
(n.abs * 2**31 + d.abs) * 2 + (s == -1 ? 0 : 1)
|
57
|
+
else
|
58
|
+
strpack v.delete %('")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
}
|
45
62
|
end
|
46
63
|
|
47
|
-
|
48
|
-
StackRx = /(?<=\[)[^\]]+(?=\])/ # match [.+], but don't capture the brackets
|
64
|
+
StackRx = /(?<=\[)[^\]]*(?=\])/ # match [.*], but don't capture the brackets
|
49
65
|
|
66
|
+
def parse_doc doc
|
50
67
|
# strip comment character and any implementation details
|
51
68
|
doc.gsub!(/; */, '').gsub!(/^!.+\n/, '')
|
52
69
|
|
data/lib/spitewaste.rb
CHANGED
data/lib/spitewaste/cli/exec.rb
CHANGED
@@ -16,28 +16,25 @@ class SpitewasteCLI
|
|
16
16
|
- use % to write to $HOME/.cache/spitewaste directory, where Spiceweight knows to look',
|
17
17
|
aliases: '-s'
|
18
18
|
|
19
|
-
def exec
|
19
|
+
def exec input = '/dev/stdin'
|
20
20
|
fmt = SpitewasteCLI.validate_format options
|
21
21
|
|
22
|
-
raise LoadError, "No such file '#{
|
22
|
+
raise LoadError, "No such file '#{input}'", [] unless File.exists? input
|
23
23
|
|
24
24
|
opts = options.dup # options is frozen
|
25
25
|
if opts[:symbol_file] == '%'
|
26
|
-
opts[:symbol_file] = SpitewasteCLI.make_cache_path
|
26
|
+
opts[:symbol_file] = SpitewasteCLI.make_cache_path input
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
else
|
36
|
-
file
|
37
|
-
end
|
29
|
+
if File.extname(input) != '.ws'
|
30
|
+
io = Tempfile.new
|
31
|
+
as = Spitewaste::Assembler.new File.read(input), format: fmt, **opts
|
32
|
+
as.assemble! format: :whitespace, io: io
|
33
|
+
input = io.tap(&:close).path
|
34
|
+
end
|
38
35
|
|
39
36
|
cmd = options[:interpreter].split
|
40
|
-
cmd.map! { |c| c == '%' ?
|
37
|
+
cmd.map! { |c| c == '%' ? input : c }
|
41
38
|
Kernel.exec *cmd
|
42
39
|
end
|
43
40
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
import math ; divmod, max, min, pos?
|
2
|
+
import stack ; bury, dig, ncopy, nslide, roll
|
3
|
+
import util ; dec, die!, eq
|
4
|
+
|
1
5
|
$amax = 1000
|
2
6
|
|
3
7
|
arysum: reduce (add) ret
|
@@ -48,7 +52,7 @@ aryat: ; [a i]
|
|
48
52
|
|
49
53
|
_aryat_neg: copy 1 add dup jn _aryat_oob jump aryat
|
50
54
|
|
51
|
-
_aryat_oob: push "(aryat) index out of bounds!" :die
|
55
|
+
_aryat_oob: push "(aryat) index out of bounds!" :die!
|
52
56
|
|
53
57
|
minmax:
|
54
58
|
:arydup reduce (:max)
|
@@ -1,6 +1,8 @@
|
|
1
|
-
import math
|
1
|
+
import math ; ilog, pow
|
2
|
+
import string ; strcat, strlen, strrev
|
3
|
+
import util ; bin, digits, itos
|
2
4
|
|
3
|
-
; TODO: don't use strings for bitwise operations
|
5
|
+
; TODO: don't use strings for bitwise operations!
|
4
6
|
|
5
7
|
; bitwise bitwise_and
|
6
8
|
; ! clobbers heap address -1
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import
|
1
|
+
import array ; arycat, arydup
|
2
|
+
import util ; eq, inc, range
|
2
3
|
|
3
4
|
; returns B raised to the power E
|
4
5
|
; [B E] => [B**E]
|
@@ -41,79 +42,116 @@ _isqrt_update: slide 1 jump _isqrt_loop
|
|
41
42
|
; ! clobbers heap address -1 TODO: maybe unnecessarily?
|
42
43
|
; [N B] => [logB(N)]
|
43
44
|
;
|
44
|
-
; [15
|
45
|
+
; [15 4] => [1]
|
46
|
+
; [16 4] => [2]
|
45
47
|
; [100 10] => [2]
|
46
|
-
; [42
|
48
|
+
; [42 2] => [5]
|
47
49
|
ilog: push -1,0 store ; accumulator at -1
|
48
|
-
_ilog_loop:
|
49
|
-
swap dup jz _ilog_done
|
50
|
-
push -1 :inc
|
51
|
-
copy 1 div swap jump _ilog_loop
|
50
|
+
_ilog_loop: ; [n b]
|
51
|
+
swap copy 1 div dup jz _ilog_done
|
52
|
+
push -1 :inc swap jump _ilog_loop
|
52
53
|
_ilog_done: push -1 load slide 2 ret
|
53
54
|
|
54
|
-
; greatest common divisor
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
; returns the greatest common divisor of A and B
|
56
|
+
; [A B] => [gcd(A, B)]
|
57
|
+
;
|
58
|
+
; [6 9] => [3]
|
59
|
+
; [13 17] => [1]
|
60
|
+
; [24 36] => [12]
|
61
|
+
gcd: dup jz _gcd_done swap copy 1 mod jump gcd
|
60
62
|
_gcd_done: pop ret
|
61
63
|
|
62
|
-
; least common multiple
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
; returns the least common multiple of A and B
|
65
|
+
; [A B] => [lcm(A, B)]
|
66
|
+
;
|
67
|
+
; [6 9] => [18]
|
68
|
+
; [13 17] => [221]
|
69
|
+
; [24 36] => [72]
|
70
|
+
lcm: copy 1 mul swap dup copy 2 swap div :gcd div ret
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
+
; keeps the minimum of the top two stack values
|
73
|
+
; [A B] => [A < B ? A : B]
|
74
|
+
;
|
75
|
+
; [3 1] => [1]
|
76
|
+
; [2 4] => [2]
|
77
|
+
min: copy 1 copy 1 sub jn _min_done swap
|
72
78
|
_min_done: pop ret
|
73
79
|
|
74
|
-
|
75
|
-
|
80
|
+
; keeps the maximum of the top two stack values
|
81
|
+
; [A B] => [A > B ? A : B]
|
82
|
+
;
|
83
|
+
; [3 1] => [3]
|
84
|
+
; [2 4] => [4]
|
85
|
+
max: copy 1 copy 1 sub jn _max_done swap
|
76
86
|
_max_done: slide 1 ret
|
77
87
|
|
78
|
-
|
79
|
-
|
80
|
-
;
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
88
|
+
; returns -1, 0, or 1 to indicate the sign of N
|
89
|
+
; [N] => [-1 | 0 | 1]
|
90
|
+
;
|
91
|
+
; [17] => [1]
|
92
|
+
; [-25] => [-1]
|
93
|
+
; [0] => [0]
|
94
|
+
sign: dup jz _sign_zero jn _sign_neg push 1 ret
|
85
95
|
_sign_zero: ret
|
86
96
|
_sign_neg: push -1 ret
|
87
97
|
|
88
|
-
; absolute value
|
98
|
+
; returns the absolute value of N
|
99
|
+
; [N] => [N < 0 ? -N : N]
|
100
|
+
;
|
101
|
+
; [-5] => [5]
|
102
|
+
; [10] => [10]
|
103
|
+
; [0] => [0]
|
89
104
|
abs: dup :sign mul ret
|
90
105
|
|
91
|
-
|
92
|
-
|
106
|
+
; pops A and B and pushes both their quotient and modulus
|
107
|
+
; [A B] => [A/B A%B]
|
108
|
+
;
|
109
|
+
; [17 5] => [3 2]
|
110
|
+
; [42 6] => [7 0]
|
111
|
+
; [ 1 5] => [0 1]
|
112
|
+
; ! [9 0] => [!!] TODO: find a way to expect exceptions
|
93
113
|
divmod:
|
94
114
|
push -1 swap store
|
95
115
|
dup push -1 load div
|
96
116
|
swap push -1 load mod ret
|
97
117
|
|
98
|
-
|
99
|
-
|
118
|
+
; returns whether N is greater than 0
|
119
|
+
; [N] => [N > 0]
|
120
|
+
;
|
121
|
+
; [5] => [1] [-3] => [0] [0] => [0]
|
100
122
|
pos?: :sign push 1 :eq ret
|
101
|
-
neg?: :sign push -1 :eq ret
|
102
123
|
|
103
|
-
|
124
|
+
; returns whether N is less than 0
|
125
|
+
; [N] => [N < 0]
|
126
|
+
;
|
127
|
+
; [5] => [0] [-3] => [1] [0] => [0]
|
128
|
+
neg?: :sign push -1 :eq ret
|
104
129
|
|
130
|
+
; returns a pseudo-array of the positive divisors of N; as an optimization,
|
131
|
+
; they're not returned in ascending order, but rather in two "halves".
|
132
|
+
; The alternative is unnecessarily invoking to_a and clobbering heap.
|
133
|
+
; [N]
|
134
|
+
;
|
135
|
+
; [10] => [1 2 10 5 4]
|
136
|
+
; [12] => [1 2 3 12 6 4 6]
|
137
|
+
; [25] => [1 5 25 3] ; no duplicate for perfect squares
|
138
|
+
; [60] => [1 2 3 4 5 6 60 30 20 15 12 10 12]
|
105
139
|
divisors: ; [n]
|
106
|
-
dup push -1 swap store ; preserve
|
107
|
-
:isqrt push 1 swap :range dup ; 1..
|
140
|
+
dup push -1 swap store ; preserve N because array operations
|
141
|
+
:isqrt push 1 swap :range dup ; 1..isqrt(N)
|
108
142
|
reject (push -1 load swap mod) :arydup ; get first half of divisors
|
109
143
|
map (push -1 load swap div) :arycat ; map first half to second half
|
110
|
-
push -1 load copy 2 dup mul sub jz _divisors_square
|
111
|
-
ret
|
112
|
-
|
144
|
+
push -1 load copy 2 dup mul sub jz _divisors_square ret
|
113
145
|
_divisors_square: slide 1 $-- ret ; de-duplicate when N is a perfect square
|
114
146
|
|
115
|
-
|
116
|
-
|
147
|
+
; returns the number of ways to choose K elements from a set of N
|
148
|
+
; [N K]
|
149
|
+
;
|
150
|
+
; [ 4 5] => [0]
|
151
|
+
; [ 7 7] => [1]
|
152
|
+
; [13 3] => [286]
|
153
|
+
; [16 4] => [1820]
|
154
|
+
; [50 3] => [19600]
|
117
155
|
nCk:
|
118
156
|
copy 1 copy 1 sub :factorial
|
119
157
|
swap :factorial mul
|
@@ -1,3 +1,6 @@
|
|
1
|
+
import math ; divmod
|
2
|
+
import util ; inc
|
3
|
+
|
1
4
|
; [n] => [0|1]
|
2
5
|
prime?: ; [n]
|
3
6
|
dup push 3 sub jn _prime_special ; special-case < 3
|
@@ -40,7 +43,5 @@ _factor_loop: ; [d n]
|
|
40
43
|
_divisor_loop:
|
41
44
|
dup copy 2 :divmod jz _divisor_keep
|
42
45
|
pop swap :next_prime swap jump _factor_loop
|
43
|
-
|
44
46
|
_divisor_keep: push -2 :inc slide 1 copy 1 swap jump _factor_loop
|
45
|
-
|
46
47
|
_factor_done: slide 1 push 3 sub load ret
|
@@ -0,0 +1,153 @@
|
|
1
|
+
;;; Rational numbers
|
2
|
+
|
3
|
+
import math ; abs, divmod, gcd, pow, sign
|
4
|
+
import util ; die!, neq
|
5
|
+
|
6
|
+
; maximum value of either component of a rational number before behavior is
|
7
|
+
; undefined; 2^31 by default to give interpreters without bignums a chance,
|
8
|
+
; but customizable from userland.
|
9
|
+
$RAT = push 2,31 :pow
|
10
|
+
|
11
|
+
; encodes a numerator N and a denominator D as a rational number R with the
|
12
|
+
; following structure: ((N × $RAT + D) << 1) + sign (0 for negative, else 1).
|
13
|
+
; This representation is nice because, with care, it makes it so that we never
|
14
|
+
; have to involve the heap (besides divmod) just to do fairly basic arithmetic.
|
15
|
+
; [N D] => [R]
|
16
|
+
;
|
17
|
+
; [22 7] => [R(22,7)]
|
18
|
+
; [4 8] => [R(4,8)] ; no implicit simplification TODO: make it configurable?
|
19
|
+
; [5 1] => [R(5,1)] ; no conversion to integer (duh)
|
20
|
+
; [-3 4] => [R(-3,4)]
|
21
|
+
; [3 -4] => [R(-3,4)] ; sign always held in the numerator
|
22
|
+
; [-1 -3] => [R(1,3)]
|
23
|
+
to_r: dup jz _to_r_dbz
|
24
|
+
dup :sign copy 2 :sign mul push -1 :neq
|
25
|
+
copy 2 :abs copy 2 :abs
|
26
|
+
$RAT copy 2 mul add push 2 mul
|
27
|
+
copy 2 add slide 4 ret
|
28
|
+
_to_r_dbz: push "0 in denominator!" :die!
|
29
|
+
|
30
|
+
; returns the numerator N of the rational number R, which may be negative
|
31
|
+
; [R] => [N]
|
32
|
+
;
|
33
|
+
; [R(22,7)] => [22]
|
34
|
+
; [R(-3,4)] => [-3]
|
35
|
+
; [R(3,-4)] => [-3]
|
36
|
+
ratnum: push 2 :divmod push 2 mul push 1 sub swap $RAT div mul ret
|
37
|
+
|
38
|
+
; returns the denominator D of the rational number R; always positive
|
39
|
+
; [R] => [D]
|
40
|
+
;
|
41
|
+
; [R(22,7)] => [7]
|
42
|
+
; [R(-3,4)] => [4]
|
43
|
+
; [R(3,-4)] => [4]
|
44
|
+
ratden: push 2 div $RAT mod ret
|
45
|
+
|
46
|
+
; decomposes the rational number R into its numerator N and denominator D
|
47
|
+
; [R] => [N D]
|
48
|
+
;
|
49
|
+
; [R(22,7)] => [22 7]
|
50
|
+
; [R(-3,4)] => [-3 4]
|
51
|
+
; [R(3,-4)] => [-3 4]
|
52
|
+
; [R(4,8)] => [4 8] ; no implicit simplification
|
53
|
+
from_r: dup :ratnum swap :ratden ret
|
54
|
+
|
55
|
+
; fully simplifies the rational number R by dividing both of its components
|
56
|
+
; by their greatest common divisor
|
57
|
+
; [R] => [R, simplified]
|
58
|
+
;
|
59
|
+
; [R(4,8)] => [R(1,2)]
|
60
|
+
; [R(-3,12)] => [R(-1,4)]
|
61
|
+
; [R(17,-51)] => [R(-1,3)]
|
62
|
+
ratsimp:
|
63
|
+
push 2 :divmod swap $RAT :divmod dup copy 2 :gcd
|
64
|
+
swap copy 1 div copy 2 copy 2 div swap :to_r
|
65
|
+
slide 2 push 2 div push 2 mul add ret
|
66
|
+
|
67
|
+
; helper prologue shared by all but ratmul
|
68
|
+
_rathead:
|
69
|
+
copy 1 :ratnum copy 1 :ratden mul
|
70
|
+
copy 2 :ratden copy 2 :ratnum mul ret
|
71
|
+
|
72
|
+
; helper epilogue shared by all but ratdiv
|
73
|
+
_rattail:
|
74
|
+
copy 2 :ratden copy 2 :ratden mul
|
75
|
+
:to_r :ratsimp slide 2 ret
|
76
|
+
|
77
|
+
; returns the simplified sum of the rational numbers Ra and Rb
|
78
|
+
; [Ra Rb] => [Ra + Rb]
|
79
|
+
;
|
80
|
+
; [R(-9,-14) R(-3,19)] => [R(129,266)]
|
81
|
+
; [R(17,30) R(18,10)] => [R(71,30)]
|
82
|
+
; [R(-27,14) R(15,-23)] => [R(-831,322)]
|
83
|
+
; [R(3,-9) R(8,3)] => [R(7,3)]
|
84
|
+
; [R(-5,27) R(-2,-27)] => [R(-1,9)]
|
85
|
+
; [R(-27,-8) R(-15,22)] => [R(237,88)]
|
86
|
+
; [R(-9,-29) R(-27,3)] => [R(-252,29)]
|
87
|
+
; [R(2,-21) R(4,6)] => [R(4,7)]
|
88
|
+
ratadd: :_rathead add :_rattail ret
|
89
|
+
|
90
|
+
; returns the simplified difference of the rational numbers Ra and Rb
|
91
|
+
; [Ra Rb] => [Ra - Rb]
|
92
|
+
;
|
93
|
+
; [R(21,25) R(-28,27)] => [R(1267,675)]
|
94
|
+
; [R(14,7) R(13,6)] => [R(-1,6)]
|
95
|
+
; [R(-24,-9) R(-5,-21)] => [R(17,7)]
|
96
|
+
; [R(-27,-2) R(-2,26)] => [R(353,26)]
|
97
|
+
; [R(-27,3) R(2,-22)] => [R(-98,11)]
|
98
|
+
; [R(-4,23) R(-9,13)] => [R(155,299)]
|
99
|
+
; [R(-14,19) R(-18,-11)] => [R(-496,209)]
|
100
|
+
; [R(-29,21) R(-15,-16)] => [R(-779,336)]
|
101
|
+
ratsub: :_rathead sub :_rattail ret
|
102
|
+
|
103
|
+
; returns the simplified product of the rational numbers Ra and Rb
|
104
|
+
; [Ra Rb] => [Ra × Rb]
|
105
|
+
;
|
106
|
+
; [R(-24,26) R(-1,-30)] => [R(-2,65)]
|
107
|
+
; [R(19,4) R(27,2)] => [R(513,8)]
|
108
|
+
; [R(25,27) R(4,-11)] => [R(-100,297)]
|
109
|
+
; [R(1,18) R(4,8)] => [R(1,36)]
|
110
|
+
; [R(1,27) R(-8,29)] => [R(-8,783)]
|
111
|
+
; [R(25,-13) R(-6,24)] => [R(25,52)]
|
112
|
+
; [R(6,-13) R(9,23)] => [R(-54,299)]
|
113
|
+
; [R(11,8) R(-19,-19)] => [R(11,8)]
|
114
|
+
ratmul: copy 1 :ratnum copy 1 :ratnum mul :_rattail ret
|
115
|
+
|
116
|
+
; returns the simplified quotient of the rational numbers Ra and Rb
|
117
|
+
; [Ra Rb] => [Ra / Rb]
|
118
|
+
;
|
119
|
+
; [R(-30,-22) R(15,12)] => [R(12,11)]
|
120
|
+
; [R(13,28) R(-15,29)] => [R(-377,420)]
|
121
|
+
; [R(7,-30) R(-22,-12)] => [R(-7,55)]
|
122
|
+
; [R(15,4) R(8,-8)] => [R(-15,4)]
|
123
|
+
; [R(-23,28) R(-16,-15)] => [R(-345,448)]
|
124
|
+
; [R(-18,12) R(6,18)] => [R(-9,2)]
|
125
|
+
; [R(29,-2) R(11,-21)] => [R(609,22)]
|
126
|
+
; [R(-23,25) R(25,-3)] => [R(69,625)]
|
127
|
+
ratdiv: :_rathead :to_r :ratsimp slide 2 ret
|
128
|
+
|
129
|
+
; returns the simplified modulus of the rational numbers Ra and Rb
|
130
|
+
; [Ra Rb] => [Ra % Rb]
|
131
|
+
;
|
132
|
+
; [R(-15,-3) R(-16,-10)] => [R(1,5)]
|
133
|
+
; [R(4,2) R(21,21)] => [R(0,1)]
|
134
|
+
; [R(24,10) R(-18,-3)] => [R(12,5)]
|
135
|
+
; [R(3,-7) R(-2,16)] => [R(-3,56)]
|
136
|
+
; [R(4,28) R(-29,7)] => [R(-4,1)]
|
137
|
+
; [R(7,-27) R(10,23)] => [R(109,621)]
|
138
|
+
; [R(28,-3) R(30,-12)] => [R(-11,6)]
|
139
|
+
; [R(-29,21) R(19,-23)] => [R(-268,483)]
|
140
|
+
ratmod: :_rathead mod :_rattail ret
|
141
|
+
|
142
|
+
; returns the sign of the rational number R
|
143
|
+
; [R] => [-1 | 0 | 1]
|
144
|
+
;
|
145
|
+
; [R(4,3)] => [1]
|
146
|
+
; [R(4,-3)] => [-1]
|
147
|
+
; [R(0,10)] => [0]
|
148
|
+
; [R(-3,4)] => [-1]
|
149
|
+
; [R(-3,-4)] => [1]
|
150
|
+
ratsign:
|
151
|
+
dup $RAT push 2 mul push 2 add sub jn _ratsign_zero
|
152
|
+
push 2 mod push 2 mul push 1 sub ret
|
153
|
+
_ratsign_zero: pop push 0 ret
|