rtforth/
float.rs

1//! Floating-point word set
2
3use core::Core;
4use exception::INVALID_MEMORY_ADDRESS;
5use memory::{DataSpace, Memory};
6use std::f64::consts::PI;
7use std::mem;
8use {FALSE, TRUE};
9
10pub trait Float: Core {
11    fn add_float(&mut self) {
12        self.add_primitive("fconstant", Float::fconstant);
13        self.add_primitive("float+", Float::float_plus);
14        self.add_primitive("floats", Float::floats);
15        self.add_primitive("faligned", Float::faligned);
16        self.add_primitive("falign", Float::falign);
17        self.add_primitive("pi", Float::pi);
18        self.add_primitive("f!", Float::fstore);
19        self.add_primitive("f@", Float::ffetch);
20        self.add_primitive("fabs", Float::fabs);
21        self.add_primitive("fsin", Float::fsin);
22        self.add_primitive("fcos", Float::fcos);
23        self.add_primitive("ftan", Float::ftan);
24        self.add_primitive("fsincos", Float::fsincos);
25        self.add_primitive("fasin", Float::fasin);
26        self.add_primitive("facos", Float::facos);
27        self.add_primitive("fatan", Float::fatan);
28        self.add_primitive("fatan2", Float::fatan2);
29        self.add_primitive("fsqrt", Float::fsqrt);
30        self.add_primitive("fdrop", Float::fdrop);
31        self.add_primitive("fdup", Float::fdup);
32        self.add_primitive("fswap", Float::fswap);
33        self.add_primitive("fnip", Float::fnip);
34        self.add_primitive("fover", Float::fover);
35        self.add_primitive("frot", Float::frot);
36        self.add_primitive("fpick", Float::fpick);
37        self.add_primitive("s>f", Float::s_to_f);
38        self.add_primitive("f>s", Float::f_to_s);
39        self.add_primitive("f+", Float::fplus);
40        self.add_primitive("f-", Float::fminus);
41        self.add_primitive("f*", Float::fstar);
42        self.add_primitive("f/", Float::fslash);
43        self.add_primitive("f**", Float::fpowf);
44        self.add_primitive("f~", Float::fproximate);
45        self.add_primitive("f0<", Float::f_zero_less_than);
46        self.add_primitive("f0=", Float::f_zero_equals);
47        self.add_primitive("f<", Float::f_less_than);
48        self.add_primitive("fmin", Float::fmin);
49        self.add_primitive("fmax", Float::fmax);
50        self.add_primitive("floor", Float::floor);
51        self.add_primitive("fround", Float::fround);
52        self.add_primitive("fceil", Float::fceil);
53        self.add_primitive("fnegate", Float::fnegate);
54    }
55
56    // Defining words
57
58    fn p_fconst(&mut self) {
59        let wp = self.state().word_pointer();
60        let pos = DataSpace::aligned_f64(self.wordlist()[wp].dfa());
61        let v = unsafe { self.data_space().get_f64(pos) };
62        self.f_stack().push(v);
63    }
64
65    fn fconstant(&mut self) {
66        let v = self.f_stack().pop();
67        self.define(Float::p_fconst, Core::compile_fconst);
68        self.data_space().align_f64();
69        self.data_space().compile_f64(v);
70    }
71
72    /// Run-time: ( a-addr1 -- a-addr2 )
73    ///
74    /// Add the size in address units of a float to `a-addr1`, giving `a-addr2`.
75    fn float_plus(&mut self) {
76        let v = self.s_stack().pop();
77        self.s_stack().push(v + mem::size_of::<f64>() as isize);
78    }
79
80    /// Run-time: ( n1 -- n2 )
81    ///
82    /// `n2` is the size in address units of `n1` floats.
83    fn floats(&mut self) {
84        let v = self.s_stack().pop();
85        self.s_stack().push(v * mem::size_of::<f64>() as isize);
86    }
87
88    /// Run-time: ( addr -- a-addr )
89    ///
90    /// Return `a-addr`, the first float-aligned address greater than or equal to `addr`.
91    fn faligned(&mut self) {
92        let pos = self.s_stack().pop();
93        let pos = DataSpace::aligned_f64(pos as usize);
94        self.s_stack().push(pos as isize);
95    }
96
97    /// Run-time: ( -- )
98    ///
99    /// If the data-space pointer is not float-aligned, reserve enough space to align it.
100    fn falign(&mut self) {
101        self.data_space().align_f64();
102    }
103
104    fn pi(&mut self) {
105        self.f_stack().push(PI);
106    }
107
108    // Floating point primitives
109
110    fn ffetch(&mut self) {
111        let t = DataSpace::aligned_f64(self.s_stack().pop() as usize);
112        // Because t is aligned to f64 boundary, and memory is 4K-page aligned,
113        // checking start() <= t < limit() is enough.
114        if self.data_space().start() <= t && t < self.data_space().limit() {
115            let value = unsafe { self.data_space().get_f64(t) };
116            self.f_stack().push(value);
117        } else {
118            self.abort_with(INVALID_MEMORY_ADDRESS);
119        }
120    }
121
122    fn fstore(&mut self) {
123        let t = DataSpace::aligned_f64(self.s_stack().pop() as usize);
124        let n = self.f_stack().pop();
125        // Because t is aligned to f64 boundary, and memory is 4K-page aligned,
126        // checking start() <= t < limit() is enough.
127        if self.data_space().start() <= t && t < self.data_space().limit() {
128            unsafe { self.data_space().put_f64(n, t) };
129        } else {
130            self.abort_with(INVALID_MEMORY_ADDRESS);
131        }
132    }
133
134    fn fabs(&mut self) {
135        let t = self.f_stack().pop();
136        self.f_stack().push(t.abs());
137    }
138
139    fn fsin(&mut self) {
140        let t = self.f_stack().pop();
141        self.f_stack().push(t.sin());
142    }
143
144    fn fcos(&mut self) {
145        let t = self.f_stack().pop();
146        self.f_stack().push(t.cos());
147    }
148
149    fn ftan(&mut self) {
150        let t = self.f_stack().pop();
151        self.f_stack().push(t.tan());
152    }
153
154    fn fsincos(&mut self) {
155        let t = self.f_stack().pop();
156        let (s, c) = t.sin_cos();
157        self.f_stack().push2(s, c);
158    }
159
160    fn fasin(&mut self) {
161        let t = self.f_stack().pop();
162        self.f_stack().push(t.asin());
163    }
164
165    fn facos(&mut self) {
166        let t = self.f_stack().pop();
167        self.f_stack().push(t.acos());
168    }
169
170    fn fatan(&mut self) {
171        let t = self.f_stack().pop();
172        self.f_stack().push(t.atan());
173    }
174
175    fn fatan2(&mut self) {
176        let t = self.f_stack().pop();
177        let n = self.f_stack().pop();
178        self.f_stack().push(n.atan2(t));
179    }
180
181    fn fsqrt(&mut self) {
182        let t = self.f_stack().pop();
183        self.f_stack().push(t.sqrt());
184    }
185
186    fn fswap(&mut self) {
187        let t = self.f_stack().pop();
188        let n = self.f_stack().pop();
189        self.f_stack().push2(t, n);
190    }
191
192    fn fnip(&mut self) {
193        let t = self.f_stack().pop();
194        let _ = self.f_stack().pop();
195        self.f_stack().push(t);
196    }
197
198    fn fdup(&mut self) {
199        let t = self.f_stack().pop();
200        self.f_stack().push2(t, t);
201    }
202
203    fn fdrop(&mut self) {
204        let _ = self.f_stack().pop();
205    }
206
207    fn frot(&mut self) {
208        let x3 = self.f_stack().pop();
209        let x2 = self.f_stack().pop();
210        let x1 = self.f_stack().pop();
211        self.f_stack().push3(x2, x3, x1);
212    }
213
214    fn fover(&mut self) {
215        let t = self.f_stack().pop();
216        let n = self.f_stack().pop();
217        self.f_stack().push3(n, t, n);
218    }
219
220    /// Place a copy of the nth floating point stack entry on top of the floating point stack. `fpick ( n -- ) ( F: ... -- x )`
221    ///
222    /// `0 fpick` is equivalent to `fdup`.
223    fn fpick(&mut self) {
224        let t = self.s_stack().pop() as u8;
225        let len = self.f_stack().len;
226        let x = self.f_stack()[len.wrapping_sub(t.wrapping_add(1))];
227        self.f_stack().push(x);
228    }
229
230    fn s_to_f(&mut self) {
231        let t = self.s_stack().pop();
232        self.f_stack().push(t as f64);
233    }
234
235    fn f_to_s(&mut self) {
236        let t = self.f_stack().pop();
237        self.s_stack().push(t as isize);
238    }
239
240    fn fplus(&mut self) {
241        let t = self.f_stack().pop();
242        let n = self.f_stack().pop();
243        self.f_stack().push(n + t);
244    }
245
246    fn fminus(&mut self) {
247        let t = self.f_stack().pop();
248        let n = self.f_stack().pop();
249        self.f_stack().push(n - t);
250    }
251
252    fn fstar(&mut self) {
253        let t = self.f_stack().pop();
254        let n = self.f_stack().pop();
255        self.f_stack().push(n * t);
256    }
257
258    fn fslash(&mut self) {
259        let t = self.f_stack().pop();
260        let n = self.f_stack().pop();
261        self.f_stack().push(n / t);
262    }
263
264    fn fpowf(&mut self) {
265        let t = self.f_stack().pop();
266        let n = self.f_stack().pop();
267        self.f_stack().push(n.powf(t));
268    }
269
270    fn fproximate(&mut self) {
271        let (x1, x2, x3) = self.f_stack().pop3();
272        if x3 > 0.0 {
273            self.s_stack()
274                .push(if (x1 - x2).abs() < x3 { TRUE } else { FALSE });
275        } else if x3 == 0.0 {
276            self.s_stack().push(if x1 == x2 { TRUE } else { FALSE });
277        } else {
278            self.s_stack()
279                .push(if (x1 - x2).abs() < (x3.abs() * (x1.abs() + x2.abs())) {
280                    TRUE
281                } else {
282                    FALSE
283                });
284        }
285    }
286
287    fn f_zero_less_than(&mut self) {
288        let t = self.f_stack().pop();
289        self.s_stack().push(if t < 0.0 { TRUE } else { FALSE });
290    }
291
292    fn f_zero_equals(&mut self) {
293        let t = self.f_stack().pop();
294        self.s_stack().push(if t == 0.0 { TRUE } else { FALSE });
295    }
296
297    fn f_less_than(&mut self) {
298        let t = self.f_stack().pop();
299        let n = self.f_stack().pop();
300        self.s_stack().push(if n < t { TRUE } else { FALSE });
301    }
302
303    fn fmin(&mut self) {
304        let (n, t) = self.f_stack().pop2();
305        self.f_stack().push(t.min(n));
306    }
307
308    fn fmax(&mut self) {
309        let (n, t) = self.f_stack().pop2();
310        self.f_stack().push(t.max(n));
311    }
312
313    fn fround(&mut self) {
314        let t = self.f_stack().pop();
315        self.f_stack().push(t.round());
316    }
317
318    fn floor(&mut self) {
319        let t = self.f_stack().pop();
320        self.f_stack().push(t.floor());
321    }
322
323    fn fceil(&mut self) {
324        let t = self.f_stack().pop();
325        self.f_stack().push(t.ceil());
326    }
327
328    fn fnegate(&mut self) {
329        let t = self.f_stack().pop();
330        self.f_stack().push(-t);
331    }
332}
333
334#[cfg(test)]
335mod tests {
336    use super::Float;
337    use core::Core;
338    use exception::Exception::UndefinedWord;
339    use mock_vm::VM;
340
341    #[test]
342    fn test_ans_forth_float() {
343        let vm = &mut VM::new();
344        vm.set_source("1E");
345        vm.evaluate_input();
346        assert_eq!(vm.f_stack().len(), 1);
347        assert_ulps_eq!(vm.f_stack().pop(), 1.0);
348        vm.set_source("1.E");
349        vm.evaluate_input();
350        assert_eq!(vm.f_stack().len(), 1);
351        assert_ulps_eq!(vm.f_stack().pop(), 1.0);
352        vm.set_source("1.E+");
353        vm.evaluate_input();
354        assert_eq!(vm.f_stack().len(), 1);
355        assert_ulps_eq!(vm.f_stack().pop(), 1.0);
356        vm.set_source("1.E-");
357        vm.evaluate_input();
358        assert_eq!(vm.f_stack().len(), 1);
359        assert_ulps_eq!(vm.f_stack().pop(), 1.0);
360        vm.set_source("1.E2");
361        vm.evaluate_input();
362        assert_eq!(vm.f_stack().len(), 1);
363        assert_ulps_eq!(vm.f_stack().pop(), 100.0);
364        vm.set_source("1.0E");
365        vm.evaluate_input();
366        assert_eq!(vm.f_stack().len(), 1);
367        assert_ulps_eq!(vm.f_stack().pop(), 1.0);
368        vm.set_source("-1E");
369        vm.evaluate_input();
370        assert_eq!(vm.f_stack().len(), 1);
371        assert_ulps_eq!(vm.f_stack().pop(), -1.0);
372        vm.set_source("1.23E");
373        vm.evaluate_input();
374        assert_eq!(vm.f_stack().len(), 1);
375        assert_ulps_eq!(vm.f_stack().pop(), 1.23);
376        vm.set_source("12.3E-2");
377        vm.evaluate_input();
378        assert_eq!(vm.f_stack().len(), 1);
379        assert_ulps_eq!(vm.f_stack().pop(), 0.123);
380        vm.set_source("-12.3E+2");
381        vm.evaluate_input();
382        assert_eq!(vm.f_stack().len(), 1);
383        assert_ulps_eq!(vm.f_stack().pop(), -1230.0);
384        vm.set_source(".3E");
385        vm.evaluate_input();
386        assert_eq!(vm.last_error(), Some(UndefinedWord));
387        assert_eq!(vm.f_stack().len(), 0);
388    }
389
390    #[test]
391    fn test_evaluate_f64() {
392        let vm = &mut VM::new();
393        vm.set_source("1.0E 2.5E");
394        vm.evaluate_input();
395        assert_eq!(vm.last_error(), None);
396        assert_eq!(vm.f_stack().len(), 2);
397        assert!(0.99999 < vm.f_stack().as_slice()[0]);
398        assert!(vm.f_stack().as_slice()[0] < 1.00001);
399        assert!(2.49999 < vm.f_stack().as_slice()[1]);
400        assert!(vm.f_stack().as_slice()[1] < 2.50001);
401    }
402
403    #[test]
404    fn test_fconstant() {
405        let vm = &mut VM::new();
406        vm.set_source("1.1E fconstant x x x");
407        vm.evaluate_input();
408        assert_eq!(vm.last_error(), None);
409        assert_eq!(vm.f_stack().as_slice(), [1.1, 1.1]);
410    }
411
412    #[test]
413    fn test_fstore_ffetch() {
414        let vm = &mut VM::new();
415        vm.set_source("3.3e here f!  0.0e  here f@");
416        vm.evaluate_input();
417        assert_eq!(vm.last_error(), None);
418        assert_eq!(vm.f_stack().as_slice(), [0.0, 3.3]);
419    }
420
421    #[test]
422    fn test_fabs() {
423        let vm = &mut VM::new();
424        vm.set_source("-3.14E fabs");
425        vm.evaluate_input();
426        assert_eq!(vm.last_error(), None);
427        assert_eq!(vm.f_stack().len(), 1);
428        assert!(match vm.f_stack().pop() {
429            t => t > 3.13999 && t < 3.14001,
430        });
431    }
432
433    #[test]
434    fn test_fsin() {
435        let vm = &mut VM::new();
436        vm.set_source("3.14E fsin");
437        vm.evaluate_input();
438        assert_eq!(vm.last_error(), None);
439        assert_eq!(vm.f_stack().len(), 1);
440        assert!(match vm.f_stack().pop() {
441            t => t > 0.0015925 && t < 0.0015927,
442        });
443    }
444
445    #[test]
446    fn test_fcos() {
447        let vm = &mut VM::new();
448        vm.set_source("3.0E fcos");
449        vm.evaluate_input();
450        assert_eq!(vm.last_error(), None);
451        assert_eq!(vm.f_stack().len(), 1);
452        assert!(match vm.f_stack().pop() {
453            t => t > -0.989993 && t < -0.989991,
454        });
455    }
456
457    #[test]
458    fn test_ftan() {
459        let vm = &mut VM::new();
460        vm.set_source("3.0E ftan");
461        vm.evaluate_input();
462        assert_eq!(vm.last_error(), None);
463        assert_eq!(vm.f_stack().len(), 1);
464        assert!(match vm.f_stack().pop() {
465            t => t > -0.142547 && t < -0.142545,
466        });
467    }
468
469    #[test]
470    fn test_fasin() {
471        let vm = &mut VM::new();
472        vm.set_source("0.3E fasin");
473        vm.evaluate_input();
474        assert_eq!(vm.last_error(), None);
475        assert_eq!(vm.f_stack().len(), 1);
476        assert!(match vm.f_stack().pop() {
477            t => t > 0.304691 && t < 0.304693,
478        });
479    }
480
481    #[test]
482    fn test_facos() {
483        let vm = &mut VM::new();
484        vm.set_source("0.3E facos");
485        vm.evaluate_input();
486        assert_eq!(vm.last_error(), None);
487        assert_eq!(vm.f_stack().len(), 1);
488        assert!(match vm.f_stack().pop() {
489            t => t > 1.266102 && t < 1.266104,
490        });
491    }
492
493    #[test]
494    fn test_fatan() {
495        let vm = &mut VM::new();
496        vm.set_source("0.3E fatan");
497        vm.evaluate_input();
498        assert_eq!(vm.last_error(), None);
499        assert_eq!(vm.f_stack().len(), 1);
500        assert!(match vm.f_stack().pop() {
501            t => t > 0.291455 && t < 0.291457,
502        });
503    }
504
505    #[test]
506    fn test_fatan2() {
507        let vm = &mut VM::new();
508        vm.set_source("3.0E 4.0E fatan2");
509        vm.evaluate_input();
510        assert_eq!(vm.last_error(), None);
511        assert_eq!(vm.f_stack().len(), 1);
512        assert!(match vm.f_stack().pop() {
513            t => t > 0.643500 && t < 0.643502,
514        });
515    }
516
517    #[test]
518    fn test_fsqrt() {
519        let vm = &mut VM::new();
520        vm.set_source("0.3E fsqrt");
521        vm.evaluate_input();
522        assert_eq!(vm.last_error(), None);
523        assert_eq!(vm.f_stack().len(), 1);
524        assert!(match vm.f_stack().pop() {
525            t => t > 0.547721 && t < 0.547723,
526        });
527    }
528
529    #[test]
530    fn test_fdrop() {
531        let vm = &mut VM::new();
532        vm.f_stack().push(1.0);
533        vm.fdrop();
534        assert_eq!(vm.last_error(), None);
535        assert_eq!(vm.f_stack().as_slice(), []);
536    }
537
538    #[test]
539    fn test_fnip() {
540        let vm = &mut VM::new();
541        vm.f_stack().push2(1.0, 2.0);
542        vm.check_stacks();
543        match vm.last_error() {
544            Some(_) => assert!(true, "Floating point stack overflow"),
545            None => {}
546        };
547        vm.fnip();
548        assert_eq!(vm.last_error(), None);
549        assert_eq!(vm.f_stack().as_slice(), [2.0]);
550    }
551
552    #[test]
553    fn test_fswap() {
554        let vm = &mut VM::new();
555        vm.f_stack().push2(1.0, 2.0);
556        vm.check_stacks();
557        match vm.last_error() {
558            Some(_) => assert!(true, "Floating point stack overflow"),
559            None => {}
560        };
561        vm.fswap();
562        assert_eq!(vm.last_error(), None);
563        assert_eq!(vm.f_stack().as_slice(), [2.0, 1.0]);
564    }
565
566    #[test]
567    fn test_fdup() {
568        let vm = &mut VM::new();
569        vm.f_stack().push(1.0);
570        vm.fdup();
571        vm.check_stacks();
572        assert_eq!(vm.last_error(), None);
573        assert_eq!(vm.f_stack().as_slice(), [1.0, 1.0]);
574    }
575
576    #[test]
577    fn test_fover() {
578        let vm = &mut VM::new();
579        vm.f_stack().push2(1.0, 2.0);
580        vm.fover();
581        vm.check_stacks();
582        assert_eq!(vm.last_error(), None);
583        assert_eq!(vm.f_stack().as_slice(), [1.0, 2.0, 1.0]);
584    }
585
586    #[test]
587    fn test_frot() {
588        let vm = &mut VM::new();
589        vm.f_stack().push3(1.0, 2.0, 3.0);
590        vm.frot();
591        vm.check_stacks();
592        assert_eq!(vm.last_error(), None);
593        assert_eq!(vm.f_stack().as_slice(), [2.0, 3.0, 1.0]);
594    }
595
596    #[test]
597    fn test_fpick() {
598        let vm = &mut VM::new();
599        vm.f_stack().push(1.0);
600        vm.s_stack().push(0);
601        vm.fpick();
602        vm.check_stacks();
603        assert_eq!(vm.last_error(), None);
604        assert_eq!(vm.s_stack().as_slice(), []);
605        assert_eq!(vm.f_stack().as_slice(), [1.0, 1.0]);
606
607        let vm = &mut VM::new();
608        vm.f_stack().push(1.0);
609        vm.f_stack().push(0.0);
610        vm.s_stack().push(1);
611        vm.fpick();
612        vm.check_stacks();
613        assert_eq!(vm.last_error(), None);
614        assert_eq!(vm.s_stack().as_slice(), []);
615        assert_eq!(vm.f_stack().as_slice(), [1.0, 0.0, 1.0]);
616    }
617
618    #[test]
619    fn test_fplus_fminus_fstar_fslash() {
620        let vm = &mut VM::new();
621        vm.set_source("9.0e 10.0e f+ 11.0e f- 12.0e f* 13.0e f/");
622        vm.evaluate_input();
623        assert_eq!(vm.last_error(), None);
624        assert_eq!(vm.f_stack().len(), 1);
625        assert!(match vm.f_stack().pop() {
626            t => t > 7.384614 && t < 7.384616,
627        });
628        vm.check_stacks();
629        assert_eq!(vm.last_error(), None);
630    }
631
632    #[test]
633    fn test_f_zero_less_than() {
634        let vm = &mut VM::new();
635        vm.set_source("0.0e f0<   0.1e f0<   -0.1e f0<");
636        vm.evaluate_input();
637        assert_eq!(vm.last_error(), None);
638        assert_eq!(vm.s_stack().len(), 3);
639        assert_eq!(vm.s_stack().pop(), -1);
640        assert_eq!(vm.s_stack().pop(), 0);
641        assert_eq!(vm.s_stack().pop(), 0);
642        assert_eq!(vm.f_stack().as_slice(), []);
643        vm.check_stacks();
644        assert_eq!(vm.last_error(), None);
645    }
646
647    #[test]
648    fn test_f_zero_equals() {
649        let vm = &mut VM::new();
650        vm.set_source("0.0e f0=   0.1e f0=   -0.1e f0=");
651        vm.evaluate_input();
652        assert_eq!(vm.last_error(), None);
653        assert_eq!(vm.s_stack().len(), 3);
654        assert_eq!(vm.s_stack().pop(), 0);
655        assert_eq!(vm.s_stack().pop(), 0);
656        assert_eq!(vm.s_stack().pop(), -1);
657        assert_eq!(vm.f_stack().as_slice(), []);
658        vm.check_stacks();
659        assert_eq!(vm.last_error(), None);
660    }
661
662    #[test]
663    fn test_f_less_than() {
664        let vm = &mut VM::new();
665        vm.set_source("0.0e 0.0e f<   0.1e 0.0e f<   -0.1e 0.0e f<");
666        vm.evaluate_input();
667        assert_eq!(vm.last_error(), None);
668        assert_eq!(vm.s_stack().len(), 3);
669        assert_eq!(vm.s_stack().pop(), -1);
670        assert_eq!(vm.s_stack().pop(), 0);
671        assert_eq!(vm.s_stack().pop(), 0);
672        assert_eq!(vm.f_stack().as_slice(), []);
673        vm.check_stacks();
674        assert_eq!(vm.last_error(), None);
675    }
676
677    #[test]
678    fn test_fproximate() {
679        let vm = &mut VM::new();
680        vm.set_source("0.1e 0.1e 0.0e f~   0.1e 0.1000000001e 0.0e f~");
681        vm.evaluate_input();
682        assert_eq!(vm.last_error(), None);
683        assert_eq!(vm.s_stack().len(), 2);
684        assert_eq!(vm.s_stack().pop(), 0);
685        assert_eq!(vm.s_stack().pop(), -1);
686        assert_eq!(vm.f_stack().as_slice(), []);
687        vm.check_stacks();
688        assert_eq!(vm.last_error(), None);
689        vm.s_stack().reset();
690        vm.set_source("0.1e 0.1e 0.001e f~   0.1e 0.109e 0.01e f~   0.1e 0.111e  0.01e f~");
691        vm.evaluate_input();
692        assert_eq!(vm.last_error(), None);
693        assert_eq!(vm.s_stack().len(), 3);
694        assert_eq!(vm.s_stack().pop(), 0);
695        assert_eq!(vm.s_stack().pop(), -1);
696        assert_eq!(vm.s_stack().pop(), -1);
697        assert_eq!(vm.f_stack().as_slice(), []);
698        vm.check_stacks();
699        assert_eq!(vm.last_error(), None);
700        vm.s_stack().reset();
701        vm.set_source("0.1e 0.1e -0.001e f~   0.1e 0.109e -0.1e f~   0.1e 0.109e  -0.01e f~");
702        vm.evaluate_input();
703        assert_eq!(vm.last_error(), None);
704        assert_eq!(vm.s_stack().len(), 3);
705        assert_eq!(vm.s_stack().pop(), 0);
706        assert_eq!(vm.s_stack().pop(), -1);
707        assert_eq!(vm.s_stack().pop(), -1);
708        assert_eq!(vm.f_stack().as_slice(), []);
709        vm.check_stacks();
710        assert_eq!(vm.last_error(), None);
711        vm.s_stack().reset();
712    }
713
714    #[test]
715    #[cfg(not(target_arch = "x86_64"))]
716    fn test_very_long_float() {
717        let vm = &mut VM::new();
718        vm.set_source("0.10000000000000001e");
719        vm.evaluate_input();
720        assert_eq!(vm.last_error(), Some(UndefinedWord));
721    }
722
723    #[test]
724    #[cfg(target_arch = "x86_64")]
725    fn test_very_long_float() {
726        let vm = &mut VM::new();
727        vm.set_source("0.10000000000000001e");
728        vm.evaluate_input();
729        assert_eq!(vm.last_error(), None);
730    }
731
732    #[test]
733    fn test_n_to_f() {
734        let vm = &mut VM::new();
735        vm.set_source("0 s>f -1 s>f 1 s>f");
736        vm.evaluate_input();
737        assert_eq!(vm.last_error(), None);
738        assert_eq!(vm.f_stack().as_slice(), [0.0, -1.0, 1.0]);
739    }
740
741    #[test]
742    fn test_f_to_n() {
743        let vm = &mut VM::new();
744        vm.set_source("0.0e f>s -1.0e f>s 1.0e f>s");
745        vm.evaluate_input();
746        assert_eq!(vm.last_error(), None);
747        assert_eq!(vm.s_stack().as_slice(), [0, -1, 1]);
748    }
749
750    #[test]
751    fn test_flit_and_compile_float() {
752        let vm = &mut VM::new();
753        vm.set_source(": test 1.0e 2.0e ; test");
754        vm.evaluate_input();
755        assert_eq!(vm.last_error(), None);
756        assert_eq!(vm.f_stack().as_slice(), [1.0, 2.0]);
757    }
758}