gluesql_core/data/value/binary_op/
f32.rs

1use {
2    super::TryBinaryOperator,
3    crate::{
4        data::{NumericBinaryOperator, ValueError},
5        prelude::Value,
6        result::Result,
7    },
8    Value::*,
9    rust_decimal::prelude::Decimal,
10    std::cmp::Ordering,
11};
12
13impl PartialEq<Value> for f32 {
14    fn eq(&self, other: &Value) -> bool {
15        let lhs = *self;
16
17        match *other {
18            I8(rhs) => (lhs - f32::from(rhs)).abs() < f32::EPSILON,
19            I16(rhs) => (lhs - f32::from(rhs)).abs() < f32::EPSILON,
20            I32(rhs) => (lhs - (rhs as f32)).abs() < f32::EPSILON,
21            I64(rhs) => (lhs - (rhs as f32)).abs() < f32::EPSILON,
22            I128(rhs) => (lhs - (rhs as f32)).abs() < f32::EPSILON,
23            U8(rhs) => (lhs - f32::from(rhs)).abs() < f32::EPSILON,
24            U16(rhs) => (lhs - f32::from(rhs)).abs() < f32::EPSILON,
25            U32(rhs) => (lhs - (rhs as f32)).abs() < f32::EPSILON,
26            U64(rhs) => (lhs - (rhs as f32)).abs() < f32::EPSILON,
27            U128(rhs) => (lhs - (rhs as f32)).abs() < f32::EPSILON,
28            F32(rhs) => (lhs - rhs).abs() < f32::EPSILON,
29            F64(rhs) => (lhs - rhs as f32).abs() < f32::EPSILON,
30            Decimal(rhs) => Decimal::from_f32_retain(lhs).is_some_and(|x| rhs == x),
31            _ => false,
32        }
33    }
34}
35
36impl PartialOrd<Value> for f32 {
37    fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
38        match *other {
39            I8(rhs) => self.partial_cmp(&f32::from(rhs)),
40            I16(rhs) => self.partial_cmp(&f32::from(rhs)),
41            I32(rhs) => self.partial_cmp(&(rhs as f32)),
42            I64(rhs) => self.partial_cmp(&(rhs as f32)),
43            I128(rhs) => self.partial_cmp(&(rhs as f32)),
44            U8(rhs) => self.partial_cmp(&f32::from(rhs)),
45            U16(rhs) => self.partial_cmp(&f32::from(rhs)),
46            U32(rhs) => self.partial_cmp(&(rhs as f32)),
47            U64(rhs) => self.partial_cmp(&(rhs as f32)),
48            U128(rhs) => self.partial_cmp(&(rhs as f32)),
49            F64(rhs) => self.partial_cmp(&(rhs as f32)),
50            F32(rhs) => self.partial_cmp(&rhs),
51            Decimal(rhs) => Decimal::from_f32_retain(*self).and_then(|x| x.partial_cmp(&rhs)),
52            _ => None,
53        }
54    }
55}
56
57impl TryBinaryOperator for f32 {
58    type Rhs = Value;
59
60    fn try_add(&self, rhs: &Self::Rhs) -> Result<Value> {
61        let lhs = *self;
62
63        match *rhs {
64            I8(rhs) => Ok(F32(lhs + f32::from(rhs))),
65            I16(rhs) => Ok(F32(lhs + f32::from(rhs))),
66            I32(rhs) => Ok(F32(lhs + rhs as f32)),
67            I64(rhs) => Ok(F32(lhs + rhs as f32)),
68            I128(rhs) => Ok(F32(lhs + rhs as f32)),
69            U8(rhs) => Ok(F32(lhs + f32::from(rhs))),
70            U16(rhs) => Ok(F32(lhs + f32::from(rhs))),
71            U32(rhs) => Ok(F32(lhs + rhs as f32)),
72            U64(rhs) => Ok(F32(lhs + rhs as f32)),
73            U128(rhs) => Ok(F32(lhs + rhs as f32)),
74            F64(rhs) => Ok(F32(lhs + rhs as f32)),
75            F32(rhs) => Ok(F32(lhs + rhs)),
76            Decimal(rhs) => Decimal::from_f32_retain(lhs).map_or_else(
77                || Err(ValueError::FloatToDecimalConversionFailure(lhs.into()).into()),
78                |x| Ok(Decimal(x + rhs)),
79            ),
80            Null => Ok(Null),
81            _ => Err(ValueError::NonNumericMathOperation {
82                lhs: F32(lhs),
83                operator: NumericBinaryOperator::Add,
84                rhs: rhs.clone(),
85            }
86            .into()),
87        }
88    }
89
90    fn try_subtract(&self, rhs: &Self::Rhs) -> Result<Value> {
91        let lhs = *self;
92
93        match *rhs {
94            I8(rhs) => Ok(F32(lhs - f32::from(rhs))),
95            I16(rhs) => Ok(F32(lhs - f32::from(rhs))),
96            I32(rhs) => Ok(F32(lhs - rhs as f32)),
97            I64(rhs) => Ok(F32(lhs - rhs as f32)),
98            I128(rhs) => Ok(F32(lhs - rhs as f32)),
99            U8(rhs) => Ok(F32(lhs - f32::from(rhs))),
100            U16(rhs) => Ok(F32(lhs - f32::from(rhs))),
101            U32(rhs) => Ok(F32(lhs - rhs as f32)),
102            U64(rhs) => Ok(F32(lhs - rhs as f32)),
103            U128(rhs) => Ok(F32(lhs - rhs as f32)),
104            F64(rhs) => Ok(F32(lhs - rhs as f32)),
105            F32(rhs) => Ok(F32(lhs - rhs)),
106            Decimal(rhs) => Decimal::from_f32_retain(lhs).map_or_else(
107                || Err(ValueError::FloatToDecimalConversionFailure(lhs.into()).into()),
108                |x| Ok(Decimal(x - rhs)),
109            ),
110            Null => Ok(Null),
111            _ => Err(ValueError::NonNumericMathOperation {
112                lhs: F32(lhs),
113                operator: NumericBinaryOperator::Subtract,
114                rhs: rhs.clone(),
115            }
116            .into()),
117        }
118    }
119
120    fn try_multiply(&self, rhs: &Self::Rhs) -> Result<Value> {
121        let lhs = *self;
122
123        match *rhs {
124            I8(rhs) => Ok(F32(lhs * f32::from(rhs))),
125            I16(rhs) => Ok(F32(lhs * f32::from(rhs))),
126            I32(rhs) => Ok(F32(lhs * rhs as f32)),
127            I64(rhs) => Ok(F32(lhs * rhs as f32)),
128            I128(rhs) => Ok(F32(lhs * rhs as f32)),
129            U8(rhs) => Ok(F32(lhs * f32::from(rhs))),
130            U16(rhs) => Ok(F32(lhs * f32::from(rhs))),
131            U32(rhs) => Ok(F32(lhs * rhs as f32)),
132            U64(rhs) => Ok(F32(lhs * rhs as f32)),
133            U128(rhs) => Ok(F32(lhs * rhs as f32)),
134            F64(rhs) => Ok(F32(lhs * rhs as f32)),
135            F32(rhs) => Ok(F32(lhs * rhs)),
136            Interval(rhs) => Ok(Interval(lhs * rhs)),
137            Decimal(rhs) => Decimal::from_f32_retain(lhs).map_or_else(
138                || Err(ValueError::FloatToDecimalConversionFailure(lhs.into()).into()),
139                |x| Ok(Decimal(x * rhs)),
140            ),
141            Null => Ok(Null),
142            _ => Err(ValueError::NonNumericMathOperation {
143                lhs: F32(lhs),
144                operator: NumericBinaryOperator::Multiply,
145                rhs: rhs.clone(),
146            }
147            .into()),
148        }
149    }
150
151    fn try_divide(&self, rhs: &Self::Rhs) -> Result<Value> {
152        let lhs = *self;
153
154        match *rhs {
155            I8(rhs) => Ok(F32(lhs / f32::from(rhs))),
156            I16(rhs) => Ok(F32(lhs / f32::from(rhs))),
157            I32(rhs) => Ok(F32(lhs / rhs as f32)),
158            I64(rhs) => Ok(F32(lhs / rhs as f32)),
159            I128(rhs) => Ok(F32(lhs / rhs as f32)),
160            U8(rhs) => Ok(F32(lhs / f32::from(rhs))),
161            U16(rhs) => Ok(F32(lhs / f32::from(rhs))),
162            U32(rhs) => Ok(F32(lhs / rhs as f32)),
163            U64(rhs) => Ok(F32(lhs / rhs as f32)),
164            U128(rhs) => Ok(F32(lhs / rhs as f32)),
165            F64(rhs) => Ok(F32(lhs / rhs as f32)),
166            F32(rhs) => Ok(F32(lhs / rhs)),
167            Decimal(rhs) => Decimal::from_f32_retain(lhs).map_or_else(
168                || Err(ValueError::FloatToDecimalConversionFailure(lhs.into()).into()),
169                |x| Ok(Decimal(x / rhs)),
170            ),
171            Null => Ok(Null),
172            _ => Err(ValueError::NonNumericMathOperation {
173                lhs: F32(lhs),
174                operator: NumericBinaryOperator::Divide,
175                rhs: rhs.clone(),
176            }
177            .into()),
178        }
179    }
180
181    fn try_modulo(&self, rhs: &Self::Rhs) -> Result<Value> {
182        let lhs = *self;
183
184        match *rhs {
185            I8(rhs) => Ok(F32(lhs % f32::from(rhs))),
186            I16(rhs) => Ok(F32(lhs % f32::from(rhs))),
187            I32(rhs) => Ok(F32(lhs % rhs as f32)),
188            I64(rhs) => Ok(F32(lhs % rhs as f32)),
189            I128(rhs) => Ok(F32(lhs % rhs as f32)),
190            U8(rhs) => Ok(F32(lhs % f32::from(rhs))),
191            U16(rhs) => Ok(F32(lhs % f32::from(rhs))),
192            U32(rhs) => Ok(F32(lhs % rhs as f32)),
193            U64(rhs) => Ok(F32(lhs % rhs as f32)),
194            U128(rhs) => Ok(F32(lhs % rhs as f32)),
195            F64(rhs) => Ok(F32(lhs % rhs as f32)),
196            F32(rhs) => Ok(F32(lhs % rhs)),
197            Decimal(rhs) => match Decimal::from_f32_retain(lhs) {
198                Some(x) => x.checked_rem(rhs).map_or_else(
199                    || {
200                        Err(ValueError::BinaryOperationOverflow {
201                            lhs: F32(lhs),
202                            operator: NumericBinaryOperator::Modulo,
203                            rhs: Decimal(rhs),
204                        }
205                        .into())
206                    },
207                    |y| Ok(Decimal(y)),
208                ),
209                _ => Err(ValueError::FloatToDecimalConversionFailure(lhs.into()).into()),
210            },
211            Null => Ok(Null),
212            _ => Err(ValueError::NonNumericMathOperation {
213                lhs: F32(lhs),
214                operator: NumericBinaryOperator::Modulo,
215                rhs: rhs.clone(),
216            }
217            .into()),
218        }
219    }
220}
221
222#[cfg(test)]
223mod tests {
224    use {
225        super::{TryBinaryOperator, Value::*},
226        crate::data::{NumericBinaryOperator, ValueError},
227        rust_decimal::prelude::Decimal,
228        std::cmp::Ordering,
229    };
230
231    #[test]
232    fn eq() {
233        let base = 1.0_f32;
234
235        assert_eq!(base, I8(1));
236        assert_eq!(base, I16(1));
237        assert_eq!(base, I32(1));
238        assert_eq!(base, I64(1));
239        assert_eq!(base, I128(1));
240        assert_eq!(base, U8(1));
241        assert_eq!(base, U16(1));
242        assert_eq!(base, U32(1));
243        assert_eq!(base, U64(1));
244        assert_eq!(base, U128(1));
245        assert_eq!(base, F64(1.0));
246        assert_eq!(base, F32(1.0_f32));
247        assert_eq!(base, Decimal(Decimal::from(1)));
248
249        assert_ne!(base, Bool(true));
250    }
251
252    #[test]
253    fn partial_cmp() {
254        let base = 1.0_f32;
255
256        assert_eq!(base.partial_cmp(&I8(1)), Some(Ordering::Equal));
257        assert_eq!(base.partial_cmp(&I16(1)), Some(Ordering::Equal));
258        assert_eq!(base.partial_cmp(&I32(1)), Some(Ordering::Equal));
259        assert_eq!(base.partial_cmp(&I64(1)), Some(Ordering::Equal));
260        assert_eq!(base.partial_cmp(&I128(1)), Some(Ordering::Equal));
261        assert_eq!(base.partial_cmp(&U8(1)), Some(Ordering::Equal));
262        assert_eq!(base.partial_cmp(&U16(1)), Some(Ordering::Equal));
263        assert_eq!(base.partial_cmp(&U32(1)), Some(Ordering::Equal));
264        assert_eq!(base.partial_cmp(&U64(1)), Some(Ordering::Equal));
265        assert_eq!(base.partial_cmp(&U128(1)), Some(Ordering::Equal));
266        assert_eq!(base.partial_cmp(&F64(1.0)), Some(Ordering::Equal));
267        assert_eq!(base.partial_cmp(&F32(1.0_f32)), Some(Ordering::Equal));
268        assert_eq!(
269            base.partial_cmp(&Decimal(Decimal::ONE)),
270            Some(Ordering::Equal)
271        );
272
273        assert_eq!(base.partial_cmp(&Bool(true)), None);
274    }
275
276    #[test]
277    fn try_add() {
278        let base = 1.0_f32;
279
280        assert!(matches!(base.try_add(&I8(1)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
281        assert!(matches!(base.try_add(&I16(1)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
282        assert!(matches!(base.try_add(&I32(1)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
283        assert!(matches!(base.try_add(&I64(1)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
284        assert!(matches!(base.try_add(&I128(1)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
285        assert!(matches!(base.try_add(&U8(1)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
286        assert!(matches!(base.try_add(&U16(1)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
287        assert!(matches!(base.try_add(&U32(1)),Ok(F32(x)) if (x-2.0).abs() < f32::EPSILON));
288        assert!(matches!(base.try_add(&U64(1)),Ok(F32(x)) if (x-2.0).abs() < f32::EPSILON));
289        assert!(matches!(base.try_add(&U128(1)),Ok(F32(x)) if (x-2.0).abs()<f32::EPSILON));
290        assert!(matches!(base.try_add(&F64(1.0)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON ));
291        assert!(
292            matches!(base.try_add(&F32(1.0_f32)), Ok(F32(x)) if (x - 2.0).abs() < f32::EPSILON )
293        );
294        assert!(
295            matches!(base.try_add(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::TWO)
296        );
297        assert_eq!(
298            f32::MAX.try_add(&Decimal(Decimal::ONE)),
299            Err(ValueError::FloatToDecimalConversionFailure(f32::MAX.into()).into())
300        );
301
302        assert_eq!(
303            base.try_add(&Bool(true)),
304            Err(ValueError::NonNumericMathOperation {
305                lhs: F32(1.0_f32),
306                operator: NumericBinaryOperator::Add,
307                rhs: Bool(true)
308            }
309            .into())
310        );
311    }
312
313    #[test]
314    fn try_subtract() {
315        let base = 1.0_f32;
316
317        assert!(matches!(base.try_subtract(&I8(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
318        assert!(
319            matches!(base.try_subtract(&I16(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
320        );
321        assert!(
322            matches!(base.try_subtract(&I32(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
323        );
324        assert!(
325            matches!(base.try_subtract(&I64(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
326        );
327        assert!(
328            matches!(base.try_subtract(&I128(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
329        );
330        assert!(matches!(base.try_subtract(&U8(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
331        assert!(
332            matches!(base.try_subtract(&U16(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
333        );
334        assert!(
335            matches!(base.try_subtract(&U32(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
336        );
337
338        assert!(
339            matches!(base.try_subtract(&U64(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
340        );
341        assert!(
342            matches!(base.try_subtract(&U128(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
343        );
344
345        assert!(
346            matches!(base.try_subtract(&F64(1.0)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
347        );
348        assert!(
349            matches!(base.try_subtract(&F32(1.0_f32)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
350        );
351        assert!(
352            matches!(base.try_subtract(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::ZERO)
353        );
354        assert_eq!(
355            f32::MIN.try_subtract(&Decimal(Decimal::ONE)),
356            Err(ValueError::FloatToDecimalConversionFailure(f32::MIN.into()).into())
357        );
358
359        assert_eq!(
360            base.try_subtract(&Bool(true)),
361            Err(ValueError::NonNumericMathOperation {
362                lhs: F32(1.0_f32),
363                operator: NumericBinaryOperator::Subtract,
364                rhs: Bool(true)
365            }
366            .into())
367        );
368    }
369
370    #[test]
371    fn try_multiply() {
372        let base = 1.0_f32;
373
374        assert!(matches!(base.try_multiply(&I8(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
375        assert!(
376            matches!(base.try_multiply(&I16(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
377        );
378        assert!(
379            matches!(base.try_multiply(&I32(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
380        );
381        assert!(
382            matches!(base.try_multiply(&I64(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
383        );
384        assert!(
385            matches!(base.try_multiply(&I128(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
386        );
387        assert!(matches!(base.try_multiply(&U8(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
388        assert!(
389            matches!(base.try_multiply(&U16(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
390        );
391        assert!(
392            matches!(base.try_multiply(&U32(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
393        );
394        assert!(
395            matches!(base.try_multiply(&U64(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
396        );
397        assert!(
398            matches!(base.try_multiply(&U128(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
399        );
400        assert!(
401            matches!(base.try_multiply(&F64(1.0)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
402        );
403        assert!(
404            matches!(base.try_multiply(&F32(1.0_f32)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
405        );
406        assert!(
407            matches!(base.try_multiply(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::ONE)
408        );
409        assert_eq!(
410            f32::MAX.try_multiply(&Decimal(Decimal::TWO)),
411            Err(ValueError::FloatToDecimalConversionFailure(f32::MAX.into()).into())
412        );
413
414        assert_eq!(
415            base.try_multiply(&Bool(true)),
416            Err(ValueError::NonNumericMathOperation {
417                lhs: F32(1.0_f32),
418                operator: NumericBinaryOperator::Multiply,
419                rhs: Bool(true)
420            }
421            .into())
422        );
423    }
424
425    #[test]
426    fn try_divide() {
427        let base = 1.0_f32;
428
429        assert!(matches!(base.try_divide(&I8(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
430        assert!(matches!(base.try_divide(&I16(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
431        assert!(matches!(base.try_divide(&I32(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
432        assert!(matches!(base.try_divide(&I64(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
433        assert!(matches!(base.try_divide(&I128(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
434        assert!(matches!(base.try_divide(&U8(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
435        assert!(matches!(base.try_divide(&U16(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
436        assert!(matches!(base.try_divide(&U32(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
437        assert!(matches!(base.try_divide(&U64(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
438        assert!(matches!(base.try_divide(&U128(1)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON ));
439
440        assert!(
441            matches!(base.try_divide(&F64(1.0)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
442        );
443        assert!(
444            matches!(base.try_divide(&F32(1.0_f32)), Ok(F32(x)) if (x - 1.0).abs() < f32::EPSILON )
445        );
446        assert!(
447            matches!(2.0_f32.try_divide(&Decimal(Decimal::TWO)), Ok(Decimal(x)) if x == Decimal::ONE)
448        );
449        assert_eq!(
450            f32::MIN.try_divide(&Decimal(Decimal::TWO)),
451            Err(ValueError::FloatToDecimalConversionFailure(f32::MIN.into()).into())
452        );
453
454        assert_eq!(
455            base.try_divide(&Bool(true)),
456            Err(ValueError::NonNumericMathOperation {
457                lhs: F32(1.0_f32),
458                operator: NumericBinaryOperator::Divide,
459                rhs: Bool(true)
460            }
461            .into())
462        );
463    }
464
465    #[test]
466    fn try_modulo() {
467        let base = 1.0_f32;
468
469        assert!(matches!(base.try_modulo(&I8(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
470        assert!(matches!(base.try_modulo(&I16(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
471        assert!(matches!(base.try_modulo(&I32(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
472        assert!(matches!(base.try_modulo(&I64(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
473        assert!(matches!(base.try_modulo(&I128(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
474        assert!(matches!(base.try_modulo(&U8(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
475        assert!(matches!(base.try_modulo(&U16(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
476        assert!(matches!(base.try_modulo(&U32(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
477        assert!(matches!(base.try_modulo(&U64(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
478        assert!(matches!(base.try_modulo(&U128(1)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON ));
479
480        assert!(
481            matches!(base.try_modulo(&F64(1.0)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
482        );
483        assert!(
484            matches!(base.try_modulo(&F32(1.0_f32)), Ok(F32(x)) if (x - 0.0).abs() < f32::EPSILON )
485        );
486        assert!(
487            matches!(base.try_modulo(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::ZERO)
488        );
489        assert_eq!(
490            f32::MAX.try_modulo(&Decimal(Decimal::TWO)),
491            Err(ValueError::FloatToDecimalConversionFailure(f32::MAX.into()).into())
492        );
493        assert_eq!(
494            base.try_modulo(&Decimal(Decimal::ZERO)),
495            Err(ValueError::BinaryOperationOverflow {
496                lhs: F32(base),
497                rhs: Decimal(Decimal::ZERO),
498                operator: NumericBinaryOperator::Modulo,
499            }
500            .into())
501        );
502
503        assert_eq!(
504            base.try_modulo(&Bool(true)),
505            Err(ValueError::NonNumericMathOperation {
506                lhs: F32(1.0_f32),
507                operator: NumericBinaryOperator::Modulo,
508                rhs: Bool(true)
509            }
510            .into())
511        );
512    }
513}