1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crate::{word::Word, Error, Forth};
use core::{fmt::Write, ops::Neg};

impl<T: 'static> Forth<T> {
    pub fn float_div_mod(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        if unsafe { a.float == 0.0 } {
            return Err(Error::DivideByZero);
        }
        let rem = unsafe { Word::float(b.float % a.float) };
        self.data_stack.push(rem)?;
        let val = unsafe { Word::float(b.float / a.float) };
        self.data_stack.push(val)?;
        Ok(())
    }

    pub fn float_div(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        let val = unsafe {
            if a.float == 0.0 {
                return Err(Error::DivideByZero);
            }
            Word::float(b.float / a.float)
        };
        self.data_stack.push(val)?;
        Ok(())
    }

    pub fn float_modu(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        let val = unsafe {
            if a.float == 0.0 {
                return Err(Error::DivideByZero);
            }
            Word::float(b.float % a.float)
        };
        self.data_stack.push(val)?;
        Ok(())
    }

    pub fn float_pop_print(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        write!(&mut self.output, "{} ", unsafe { a.float })?;
        Ok(())
    }

    pub fn float_add(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        self.data_stack
            .push(Word::float(unsafe { a.float + b.float }))?;
        Ok(())
    }

    pub fn float_mul(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        self.data_stack
            .push(Word::float(unsafe { a.float * b.float }))?;
        Ok(())
    }

    #[cfg(feature = "use-std")]
    pub fn float_abs(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        self.data_stack
            .push(Word::float(unsafe { a.float.abs() }))?;
        Ok(())
    }

    #[cfg(not(feature = "use-std"))]
    pub fn float_abs(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        self.data_stack.push(Word::float(unsafe {
            if a.float.is_sign_negative() {
                a.float.neg()
            } else {
                a.float
            }
        }))?;
        Ok(())
    }

    pub fn float_negate(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        self.data_stack
            .push(Word::float(unsafe { a.float.neg() }))?;
        Ok(())
    }

    pub fn float_min(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        self.data_stack
            .push(Word::float(unsafe { a.float.min(b.float) }))?;
        Ok(())
    }

    pub fn float_max(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        self.data_stack
            .push(Word::float(unsafe { a.float.max(b.float) }))?;
        Ok(())
    }

    pub fn float_minus(&mut self) -> Result<(), Error> {
        let a = self.data_stack.try_pop()?;
        let b = self.data_stack.try_pop()?;
        self.data_stack
            .push(Word::float(unsafe { b.float - a.float }))?;
        Ok(())
    }
}