swapforth
1( Floating-Point JCB 22:38 03/22/15)
2
3\ The following words are already defined:
4\
5\ fdup
6\ fdrop
7\ fswap
8\ f0<
9\ fabs
10\ f<
11\ fliteral
12\ f+
13\ f-
14\ f*
15\ f/
16\ f> move from float-stack to the data-stack
17\ >f move from data-stack to the float-stack
18
19: fconstant : postpone fliteral postpone ; ;
20
21: fover f> f> tuck >f >f >f ;
22: f0= f> 0= ;
23: f= f- f0= ;
24: f! f> swap ! ;
25: f@ @ >f ;
26: frot f> f> f> -rot >f >f >f ;
27: falign align ;
28: faligned aligned ;
29: float+ cell+ ;
30: floats cells ;
31: fvariable variable ;
32: fmax fover fover f< if fswap then fdrop ;
33: fmin fover fover f< invert if fswap then fdrop ;
34
35: f>s
36f>d d>s
37;
38
39: d>f
40dup 0< if
41dnegate recurse fnegate
42else
43us>f [ 65536 s>f fdup f* ] fliteral f*
44us>f f+
45then
46;
47
48marker testing-float1
49$feed55000000. 2constant big1
50
51T{ 79218. d>f f>d -> 79218. }T
52T{ 0 79218 d>f f>d -> 0 79218 }T
53T{ -1. d>f f>d -> -1. }T
54T{ big1 d>f f>d -> big1 }T
55
56testing-float1
57
58LOCALWORDS \ {
59
601 s>f fconstant FLT_1
610 s>f fconstant FLT_0
6210 s>f fconstant FLT_10
63FLT_1 FLT_10 f/ fconstant FLT_.1
64
65: exponent
6623 rshift $ff and
67;
68
69: isat ( caddr u c -- caddr u 0 | caddr' u' 1 )
70over 0= if
71drop dup ( caddr 0 0 )
72else
73>r
74over c@ r> = negate
75dup >r
76/string
77r>
78then
79;
80
81: >+-number ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) \ signed version of >number
82[char] - isat if
83>number
842swap dnegate 2swap
85else
86[char] + isat drop
87>number
88then
89;
90
91: tuck0. ( caddr u - 0. caddr u ) \ tuck0. 0. under the string, prepare for >number
920. 2swap
93;
94
95: pow10 ( n -- 10**n)
96dup 0< if
97FLT_1
98negate recurse
99f/
100else
101FLT_1
1020 ?do
103FLT_10 f*
104loop
105then
106;
107
108: isdigit
109[char] 0 [char] 9 1+ within
110;
111
112\ consume the decimal digits, accumulating a floating fraction
113: >frac ( c-addr u -- c-addr' u' ) ( F: 0 -- r )
114FLT_.1 fswap
115begin
116over c@ isdigit
117over 0<> and
118while
119over c@ [char] 0 -
120fover s>f f* f+
121fswap FLT_.1 f* fswap
1221 /string
123repeat
124fswap fdrop
125;
126
127: notafloat
128fdrop 2drop 2drop 2drop false
129;
130
131: finput ( c-addr u -- true | false ) ( F: -- r | )
132[char] - isat >r
133[char] + isat drop
134
135tuck0.
136>number ( int. caddr u )
137
138FLT_0
139[char] . isat if
140>frac
141then ( int. caddr u ) ( F: frac )
142
143tuck0. ( int. exp. caddr u ) ( F: frac )
144[char] e isat >r
145[char] E isat r> or if
146>+-number
1470= if
148drop
149d>s >r \ save exponent
150d>f f+ \ sum int. and fraction
151r> pow10 f* \ exponentiate
152r@ if \ apply sign
153fnegate
154then
155true
156else
157notafloat
158then
159else
160notafloat
161then
162r> drop \ sign
163;
164
165:noname
166>inwas @ >in !
167parse-name
168finput if
169['] fliteral
170else
171-13 throw
172then
173; is hook-number
174
175PUBLICWORDS \ }{
176
177: floor
178f>
179$007fffff over exponent \ 127=no shift, 128==shift 1, etc
180127 - dup 0< if
181drop 2drop 0
182else
18323 min
184rshift invert and
185then
186>f
187;
188
189\ This is rubbish. Should use:
190\ "How to Print Floating-Point Numbers Accurately" Steele & White
191\ https://lists.nongnu.org/archive/html/gcl-devel/2012-10/pdfkieTlklRzN.pdf
192\ http://hub.darcs.net/pointfree/cranberry-net/browse/code/wetland-mcu-nodes/blocks/float.frt
193
194: f.
195fdup f0< if
196fnegate [char] - emit
197then
198fdup f>d 0 d.r
199[char] . emit
200fdup floor f- 10000000e0 f* f>d
201<# # # # # # # # #> type
202space
203;
204
205: .f
206fdepth >r
207[char] < emit
208r@ 0 .r
209[char] > emit
210space
211r@ 0 ?do
212f>
213loop
214r> 0 ?do
215>f fdup f.
216loop
217;
218
219: frac ( F: r0 -- r1 )
220fdup floor f-
221;
222
223: fmod ( F: r0 r1 -- r2 )
224fswap fover ( r1 r0 r1 )
225f/ frac f*
226;
227
228: fround
229fdup f0< if
230fnegate recurse fnegate
231else
232fdup floor fswap frac ( F: integer-part fraction-part )
233fdup 0.5e f= if
234fdrop \ round to nearest even
2350.5e f* 0.5e f+ floor 2.0e f*
236else
2370.5e f< invert if
238FLT_1 f+
239then
240then
241then
242;
243
244DONEWORDS \ }
245
246marker testing-float1
247
248T{ 0.0e fround f0= -> true }T
249T{ 0.0E fround f0= -> true }T
250T{ 7.499e fround 7.0e f= -> true }T
251T{ 7.501e fround 8.0e f= -> true }T
252T{ 0.500e fround 0.0e f= -> true }T
253T{ 1.500e fround 2.0e f= -> true }T
254T{ 2.500e fround 2.0e f= -> true }T
255T{ 3.500e fround 4.0e f= -> true }T
256
257T{ 0e f>d -> 0. }T
258T{ 79218e f>d -> 79218. }T
259T{ -79218e f>d -> -79218. }T
260
261testing-float1
262