spitewaste 0.1.003 → 0.1.004
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|