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 f64 {
14 fn eq(&self, other: &Value) -> bool {
15 let lhs = *self;
16
17 match *other {
18 I8(rhs) => (lhs - f64::from(rhs)).abs() < f64::EPSILON,
19 I16(rhs) => (lhs - f64::from(rhs)).abs() < f64::EPSILON,
20 I32(rhs) => (lhs - f64::from(rhs)).abs() < f64::EPSILON,
21 I64(rhs) => (lhs - (rhs as f64)).abs() < f64::EPSILON,
22 I128(rhs) => (lhs - (rhs as f64)).abs() < f64::EPSILON,
23 U8(rhs) => (lhs - f64::from(rhs)).abs() < f64::EPSILON,
24 U16(rhs) => (lhs - f64::from(rhs)).abs() < f64::EPSILON,
25 U32(rhs) => (lhs - f64::from(rhs)).abs() < f64::EPSILON,
26 U64(rhs) => (lhs - (rhs as f64)).abs() < f64::EPSILON,
27 U128(rhs) => (lhs - (rhs as f64)).abs() < f64::EPSILON,
28 F32(rhs) => (lhs - f64::from(rhs)).abs() < f64::EPSILON,
29 F64(rhs) => (lhs - rhs).abs() < f64::EPSILON,
30 Decimal(rhs) => Decimal::from_f64_retain(lhs).is_some_and(|x| rhs == x),
31 _ => false,
32 }
33 }
34}
35
36impl PartialOrd<Value> for f64 {
37 fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
38 match *other {
39 I8(rhs) => self.partial_cmp(&f64::from(rhs)),
40 I16(rhs) => self.partial_cmp(&f64::from(rhs)),
41 I32(rhs) => self.partial_cmp(&f64::from(rhs)),
42 I64(rhs) => self.partial_cmp(&(rhs as f64)),
43 I128(rhs) => self.partial_cmp(&(rhs as f64)),
44 U8(rhs) => self.partial_cmp(&f64::from(rhs)),
45 U16(rhs) => self.partial_cmp(&f64::from(rhs)),
46 U32(rhs) => self.partial_cmp(&f64::from(rhs)),
47 U64(rhs) => self.partial_cmp(&(rhs as f64)),
48 U128(rhs) => self.partial_cmp(&(rhs as f64)),
49 F32(rhs) => self.partial_cmp(&f64::from(rhs)),
50 F64(rhs) => self.partial_cmp(&rhs),
51 Decimal(rhs) => Decimal::from_f64_retain(*self).and_then(|x| x.partial_cmp(&rhs)),
52 _ => None,
53 }
54 }
55}
56
57impl TryBinaryOperator for f64 {
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(F64(lhs + f64::from(rhs))),
65 I16(rhs) => Ok(F64(lhs + f64::from(rhs))),
66 I32(rhs) => Ok(F64(lhs + f64::from(rhs))),
67 I64(rhs) => Ok(F64(lhs + rhs as f64)),
68 I128(rhs) => Ok(F64(lhs + rhs as f64)),
69 U8(rhs) => Ok(F64(lhs + f64::from(rhs))),
70 U16(rhs) => Ok(F64(lhs + f64::from(rhs))),
71 U32(rhs) => Ok(F64(lhs + f64::from(rhs))),
72 U64(rhs) => Ok(F64(lhs + rhs as f64)),
73 U128(rhs) => Ok(F64(lhs + rhs as f64)),
74 F32(rhs) => Ok(F64(lhs + f64::from(rhs))),
75 F64(rhs) => Ok(F64(lhs + rhs)),
76 Decimal(rhs) => Decimal::from_f64_retain(lhs).map_or_else(
77 || Err(ValueError::FloatToDecimalConversionFailure(lhs).into()),
78 |x| Ok(Decimal(x + rhs)),
79 ),
80 Null => Ok(Null),
81 _ => Err(ValueError::NonNumericMathOperation {
82 lhs: F64(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(F64(lhs - f64::from(rhs))),
95 I16(rhs) => Ok(F64(lhs - f64::from(rhs))),
96 I32(rhs) => Ok(F64(lhs - f64::from(rhs))),
97 I64(rhs) => Ok(F64(lhs - rhs as f64)),
98 I128(rhs) => Ok(F64(lhs - rhs as f64)),
99 U8(rhs) => Ok(F64(lhs - f64::from(rhs))),
100 U16(rhs) => Ok(F64(lhs - f64::from(rhs))),
101 U32(rhs) => Ok(F64(lhs - f64::from(rhs))),
102 U64(rhs) => Ok(F64(lhs - rhs as f64)),
103 U128(rhs) => Ok(F64(lhs - rhs as f64)),
104 F32(rhs) => Ok(F64(lhs - f64::from(rhs))),
105 F64(rhs) => Ok(F64(lhs - rhs)),
106 Decimal(rhs) => Decimal::from_f64_retain(lhs).map_or_else(
107 || Err(ValueError::FloatToDecimalConversionFailure(lhs).into()),
108 |x| Ok(Decimal(x - rhs)),
109 ),
110 Null => Ok(Null),
111 _ => Err(ValueError::NonNumericMathOperation {
112 lhs: F64(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(F64(lhs * f64::from(rhs))),
125 I16(rhs) => Ok(F64(lhs * f64::from(rhs))),
126 I32(rhs) => Ok(F64(lhs * f64::from(rhs))),
127 I64(rhs) => Ok(F64(lhs * rhs as f64)),
128 I128(rhs) => Ok(F64(lhs * rhs as f64)),
129 U8(rhs) => Ok(F64(lhs * f64::from(rhs))),
130 U16(rhs) => Ok(F64(lhs * f64::from(rhs))),
131 U32(rhs) => Ok(F64(lhs * f64::from(rhs))),
132 U64(rhs) => Ok(F64(lhs * rhs as f64)),
133 U128(rhs) => Ok(F64(lhs * rhs as f64)),
134 F32(rhs) => Ok(F64(lhs * f64::from(rhs))),
135 F64(rhs) => Ok(F64(lhs * rhs)),
136 Interval(rhs) => Ok(Interval(lhs * rhs)),
137 Decimal(rhs) => Decimal::from_f64_retain(lhs).map_or_else(
138 || Err(ValueError::FloatToDecimalConversionFailure(lhs).into()),
139 |x| Ok(Decimal(x * rhs)),
140 ),
141 Null => Ok(Null),
142 _ => Err(ValueError::NonNumericMathOperation {
143 lhs: F64(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(F64(lhs / f64::from(rhs))),
156 I16(rhs) => Ok(F64(lhs / f64::from(rhs))),
157 I32(rhs) => Ok(F64(lhs / f64::from(rhs))),
158 I64(rhs) => Ok(F64(lhs / rhs as f64)),
159 I128(rhs) => Ok(F64(lhs / rhs as f64)),
160 U8(rhs) => Ok(F64(lhs / f64::from(rhs))),
161 U16(rhs) => Ok(F64(lhs / f64::from(rhs))),
162 U32(rhs) => Ok(F64(lhs / f64::from(rhs))),
163 U64(rhs) => Ok(F64(lhs / rhs as f64)),
164 U128(rhs) => Ok(F64(lhs / rhs as f64)),
165 F32(rhs) => Ok(F64(lhs / f64::from(rhs))),
166 F64(rhs) => Ok(F64(lhs / rhs)),
167 Decimal(rhs) => Decimal::from_f64_retain(lhs).map_or_else(
168 || Err(ValueError::FloatToDecimalConversionFailure(lhs).into()),
169 |x| Ok(Decimal(x / rhs)),
170 ),
171 Null => Ok(Null),
172 _ => Err(ValueError::NonNumericMathOperation {
173 lhs: F64(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(F64(lhs % f64::from(rhs))),
186 I16(rhs) => Ok(F64(lhs % f64::from(rhs))),
187 I32(rhs) => Ok(F64(lhs % f64::from(rhs))),
188 I64(rhs) => Ok(F64(lhs % rhs as f64)),
189 I128(rhs) => Ok(F64(lhs % rhs as f64)),
190 U8(rhs) => Ok(F64(lhs % f64::from(rhs))),
191 U16(rhs) => Ok(F64(lhs % f64::from(rhs))),
192 U32(rhs) => Ok(F64(lhs % f64::from(rhs))),
193 U64(rhs) => Ok(F64(lhs % rhs as f64)),
194 U128(rhs) => Ok(F64(lhs % rhs as f64)),
195 F32(rhs) => Ok(F64(lhs % f64::from(rhs))),
196 F64(rhs) => Ok(F64(lhs % rhs)),
197 Decimal(rhs) => match Decimal::from_f64_retain(lhs) {
198 Some(x) => x.checked_rem(rhs).map_or_else(
199 || {
200 Err(ValueError::BinaryOperationOverflow {
201 lhs: F64(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()),
210 },
211 Null => Ok(Null),
212 _ => Err(ValueError::NonNumericMathOperation {
213 lhs: F64(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_f64;
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, F32(1.0_f32));
246 assert_eq!(base, F64(1.0));
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_f64;
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(&F32(1.0_f32)), Some(Ordering::Equal));
267 assert_eq!(base.partial_cmp(&F64(1.0)), 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_f64;
279
280 assert!(matches!(base.try_add(&I8(1)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
281 assert!(matches!(base.try_add(&I16(1)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
282 assert!(matches!(base.try_add(&I32(1)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
283 assert!(matches!(base.try_add(&I64(1)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
284 assert!(matches!(base.try_add(&I128(1)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
285 assert!(matches!(base.try_add(&U8(1)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
286 assert!(matches!(base.try_add(&U16(1)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
287 assert!(matches!(base.try_add(&U32(1)),Ok(F64(x)) if (x-2.0).abs() < f64::EPSILON));
288 assert!(matches!(base.try_add(&U64(1)),Ok(F64(x)) if (x-2.0).abs() < f64::EPSILON));
289 assert!(matches!(base.try_add(&U128(1)),Ok(F64(x)) if (x-2.0).abs()<f64::EPSILON));
290 assert!(
291 matches!(base.try_add(&F32(1.0_f32)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON )
292 );
293 assert!(matches!(base.try_add(&F64(1.0)), Ok(F64(x)) if (x - 2.0).abs() < f64::EPSILON ));
294 assert!(
295 matches!(base.try_add(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::TWO)
296 );
297
298 assert_eq!(
299 base.try_add(&Bool(true)),
300 Err(ValueError::NonNumericMathOperation {
301 lhs: F64(1.0),
302 operator: NumericBinaryOperator::Add,
303 rhs: Bool(true)
304 }
305 .into())
306 );
307 }
308
309 #[test]
310 fn try_subtract() {
311 let base = 1.0_f64;
312
313 assert!(matches!(base.try_subtract(&I8(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
314 assert!(
315 matches!(base.try_subtract(&I16(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
316 );
317 assert!(
318 matches!(base.try_subtract(&I32(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
319 );
320 assert!(
321 matches!(base.try_subtract(&I64(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
322 );
323 assert!(
324 matches!(base.try_subtract(&I128(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
325 );
326 assert!(matches!(base.try_subtract(&U8(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
327 assert!(
328 matches!(base.try_subtract(&U16(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
329 );
330 assert!(
331 matches!(base.try_subtract(&U32(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
332 );
333
334 assert!(
335 matches!(base.try_subtract(&U64(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
336 );
337 assert!(
338 matches!(base.try_subtract(&U128(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
339 );
340
341 assert!(
342 matches!(base.try_subtract(&F32(1.0_f32)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
343 );
344 assert!(
345 matches!(base.try_subtract(&F64(1.0)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
346 );
347 assert!(
348 matches!(base.try_subtract(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::ZERO)
349 );
350
351 assert_eq!(
352 base.try_subtract(&Bool(true)),
353 Err(ValueError::NonNumericMathOperation {
354 lhs: F64(1.0),
355 operator: NumericBinaryOperator::Subtract,
356 rhs: Bool(true)
357 }
358 .into())
359 );
360 }
361
362 #[test]
363 fn try_multiply() {
364 let base = 1.0_f64;
365
366 assert!(matches!(base.try_multiply(&I8(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
367 assert!(
368 matches!(base.try_multiply(&I16(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
369 );
370 assert!(
371 matches!(base.try_multiply(&I32(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
372 );
373 assert!(
374 matches!(base.try_multiply(&I64(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
375 );
376 assert!(
377 matches!(base.try_multiply(&I128(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
378 );
379 assert!(matches!(base.try_multiply(&U8(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
380 assert!(
381 matches!(base.try_multiply(&U16(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
382 );
383 assert!(
384 matches!(base.try_multiply(&U32(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
385 );
386 assert!(
387 matches!(base.try_multiply(&U64(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
388 );
389 assert!(
390 matches!(base.try_multiply(&U128(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
391 );
392 assert!(
393 matches!(base.try_multiply(&F32(1.0_f32)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
394 );
395 assert!(
396 matches!(base.try_multiply(&F64(1.0)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
397 );
398 assert!(
399 matches!(base.try_multiply(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::ONE)
400 );
401
402 assert_eq!(
403 base.try_multiply(&Bool(true)),
404 Err(ValueError::NonNumericMathOperation {
405 lhs: F64(1.0),
406 operator: NumericBinaryOperator::Multiply,
407 rhs: Bool(true)
408 }
409 .into())
410 );
411 }
412
413 #[test]
414 fn try_divide() {
415 let base = 1.0_f64;
416
417 assert!(matches!(base.try_divide(&I8(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
418 assert!(matches!(base.try_divide(&I16(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
419 assert!(matches!(base.try_divide(&I32(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
420 assert!(matches!(base.try_divide(&I64(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
421 assert!(matches!(base.try_divide(&I128(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
422 assert!(matches!(base.try_divide(&U8(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
423 assert!(matches!(base.try_divide(&U16(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
424 assert!(matches!(base.try_divide(&U32(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
425 assert!(matches!(base.try_divide(&U64(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
426 assert!(matches!(base.try_divide(&U128(1)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON ));
427
428 assert!(
429 matches!(base.try_divide(&F32(1.0_f32)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
430 );
431 assert!(
432 matches!(base.try_divide(&F64(1.0)), Ok(F64(x)) if (x - 1.0).abs() < f64::EPSILON )
433 );
434 assert!(
435 matches!(2.0_f64.try_divide(&Decimal(Decimal::TWO)), Ok(Decimal(x)) if x == Decimal::ONE)
436 );
437
438 assert_eq!(
439 base.try_divide(&Bool(true)),
440 Err(ValueError::NonNumericMathOperation {
441 lhs: F64(1.0),
442 operator: NumericBinaryOperator::Divide,
443 rhs: Bool(true)
444 }
445 .into())
446 );
447 }
448
449 #[test]
450 fn try_modulo() {
451 let base = 1.0_f64;
452
453 assert!(matches!(base.try_modulo(&I8(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
454 assert!(matches!(base.try_modulo(&I16(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
455 assert!(matches!(base.try_modulo(&I32(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
456 assert!(matches!(base.try_modulo(&I64(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
457 assert!(matches!(base.try_modulo(&I128(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
458 assert!(matches!(base.try_modulo(&U8(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
459 assert!(matches!(base.try_modulo(&U16(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
460 assert!(matches!(base.try_modulo(&U32(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
461 assert!(matches!(base.try_modulo(&U64(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
462 assert!(matches!(base.try_modulo(&U128(1)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON ));
463
464 assert!(
465 matches!(base.try_modulo(&F32(1.0_f32)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
466 );
467 assert!(
468 matches!(base.try_modulo(&F64(1.0)), Ok(F64(x)) if (x - 0.0).abs() < f64::EPSILON )
469 );
470 assert!(
471 matches!(base.try_modulo(&Decimal(Decimal::ONE)), Ok(Decimal(x)) if x == Decimal::ZERO)
472 );
473 assert_eq!(
474 f64::MAX.try_modulo(&Decimal(Decimal::TWO)),
475 Err(ValueError::FloatToDecimalConversionFailure(f64::MAX).into())
476 );
477 assert_eq!(
478 base.try_modulo(&Decimal(Decimal::ZERO)),
479 Err(ValueError::BinaryOperationOverflow {
480 lhs: F64(base),
481 rhs: Decimal(Decimal::ZERO),
482 operator: NumericBinaryOperator::Modulo,
483 }
484 .into())
485 );
486
487 assert_eq!(
488 base.try_modulo(&Bool(true)),
489 Err(ValueError::NonNumericMathOperation {
490 lhs: F64(1.0),
491 operator: NumericBinaryOperator::Modulo,
492 rhs: Bool(true)
493 }
494 .into())
495 );
496 }
497}