1use crate::def_package;
2use crate::plugin::*;
3#[cfg(feature = "no_std")]
4use std::prelude::v1::*;
5
6#[cfg(any(
7 not(feature = "no_float"),
8 all(not(feature = "only_i32"), not(feature = "only_i64"))
9))]
10macro_rules! gen_cmp_functions {
11 ($mod_name:ident => $($arg_type:ident),+) => {
12 $({
13 #[export_module]
14 #[allow(clippy::missing_const_for_fn)]
15 pub mod cmp_functions {
16 #[rhai_fn(name = "<")] pub fn lt(x: $arg_type, y: $arg_type) -> bool { x < y }
17 #[rhai_fn(name = "<=")] pub fn lte(x: $arg_type, y: $arg_type) -> bool { x <= y }
18 #[rhai_fn(name = ">")] pub fn gt(x: $arg_type, y: $arg_type) -> bool { x > y }
19 #[rhai_fn(name = ">=")] pub fn gte(x: $arg_type, y: $arg_type) -> bool { x >= y }
20 #[rhai_fn(name = "==")] pub fn eq(x: $arg_type, y: $arg_type) -> bool { x == y }
21 #[rhai_fn(name = "!=")] pub fn ne(x: $arg_type, y: $arg_type) -> bool { x != y }
22 pub fn max(x: $arg_type, y: $arg_type) -> $arg_type { if x >= y { x } else { y } }
23 pub fn min(x: $arg_type, y: $arg_type) -> $arg_type { if x <= y { x } else { y } }
24 }
25
26 combine_with_exported_module!($mod_name, concat!("logic_", stringify($arg_type)), cmp_functions);
27 })*
28 };
29}
30
31def_package! {
32 pub LogicPackage(lib) {
34 lib.set_standard_lib(true);
35
36 #[cfg(not(feature = "only_i32"))]
37 #[cfg(not(feature = "only_i64"))]
38 {
39 gen_cmp_functions!(lib => i8, u8, i16, u16, i32, u32, u64);
40
41 #[cfg(not(target_family = "wasm"))]
42 gen_cmp_functions!(lib => i128, u128);
43 }
44
45 #[cfg(not(feature = "no_float"))]
46 {
47 combine_with_exported_module!(lib, "float", float_functions);
48
49 #[cfg(not(feature = "f32_float"))]
50 {
51 gen_cmp_functions!(lib => f32);
52 combine_with_exported_module!(lib, "f32", f32_functions);
53 }
54 #[cfg(feature = "f32_float")]
55 {
56 gen_cmp_functions!(lib => f64);
57 combine_with_exported_module!(lib, "f64", f64_functions);
58 }
59 }
60
61 #[cfg(feature = "decimal")]
62 combine_with_exported_module!(lib, "decimal", decimal_functions);
63
64 combine_with_exported_module!(lib, "logic", logic_functions);
65
66 combine_with_exported_module!(lib, "min_max", min_max_functions);
67 }
68}
69
70#[export_module]
71mod logic_functions {
72 #[rhai_fn(name = "!")]
73 pub const fn not(x: bool) -> bool {
74 !x
75 }
76}
77
78#[export_module]
79mod min_max_functions {
80 use crate::INT;
81
82 pub const fn max(x: INT, y: INT) -> INT {
90 if x >= y {
91 x
92 } else {
93 y
94 }
95 }
96 pub const fn min(x: INT, y: INT) -> INT {
104 if x <= y {
105 x
106 } else {
107 y
108 }
109 }
110}
111
112#[cfg(not(feature = "no_float"))]
113#[allow(clippy::cast_precision_loss)]
114#[export_module]
115mod float_functions {
116 use crate::INT;
117
118 #[rhai_fn(name = "max")]
119 pub fn max_ff_32(x: f32, y: f32) -> f32 {
120 if x >= y {
121 x
122 } else {
123 y
124 }
125 }
126 #[rhai_fn(name = "max")]
127 pub fn max_if_32(x: INT, y: f32) -> f32 {
128 let (x, y) = (x as f32, y);
129 if x >= y {
130 x
131 } else {
132 y
133 }
134 }
135 #[rhai_fn(name = "max")]
136 pub fn max_fi_32(x: f32, y: INT) -> f32 {
137 let (x, y) = (x, y as f32);
138 if x >= y {
139 x
140 } else {
141 y
142 }
143 }
144 #[rhai_fn(name = "min")]
145 pub fn min_ff_32(x: f32, y: f32) -> f32 {
146 if x <= y {
147 x
148 } else {
149 y
150 }
151 }
152 #[rhai_fn(name = "min")]
153 pub fn min_if_32(x: INT, y: f32) -> f32 {
154 let (x, y) = (x as f32, y);
155 if x <= y {
156 x
157 } else {
158 y
159 }
160 }
161 #[rhai_fn(name = "min")]
162 pub fn min_fi_32(x: f32, y: INT) -> f32 {
163 let (x, y) = (x, y as f32);
164 if x <= y {
165 x
166 } else {
167 y
168 }
169 }
170 #[rhai_fn(name = "max")]
171 pub fn max_ff_64(x: f64, y: f64) -> f64 {
172 if x >= y {
173 x
174 } else {
175 y
176 }
177 }
178 #[rhai_fn(name = "max")]
179 pub fn max_if_64(x: INT, y: f64) -> f64 {
180 let (x, y) = (x as f64, y);
181 if x >= y {
182 x
183 } else {
184 y
185 }
186 }
187 #[rhai_fn(name = "max")]
188 pub fn max_fi_64(x: f64, y: INT) -> f64 {
189 let (x, y) = (x, y as f64);
190 if x >= y {
191 x
192 } else {
193 y
194 }
195 }
196 #[rhai_fn(name = "min")]
197 pub fn min_ff_64(x: f64, y: f64) -> f64 {
198 if x <= y {
199 x
200 } else {
201 y
202 }
203 }
204 #[rhai_fn(name = "min")]
205 pub fn min_if_64(x: INT, y: f64) -> f64 {
206 let (x, y) = (x as f64, y);
207 if x <= y {
208 x
209 } else {
210 y
211 }
212 }
213 #[rhai_fn(name = "min")]
214 pub fn min_fi_64(x: f64, y: INT) -> f64 {
215 let (x, y) = (x, y as f64);
216 if x <= y {
217 x
218 } else {
219 y
220 }
221 }
222}
223
224#[cfg(not(feature = "no_float"))]
225#[cfg(not(feature = "f32_float"))]
226#[allow(clippy::cast_precision_loss)]
227#[export_module]
228mod f32_functions {
229 use crate::{FLOAT, INT};
230 #[cfg(feature = "no_std")]
231 use num_traits::Float;
232
233 #[rhai_fn(name = "==")]
234 pub fn eq_if(x: INT, y: f32) -> bool {
235 #[cfg(feature = "unchecked")]
236 return (x as f32) == y;
237
238 #[cfg(not(feature = "unchecked"))]
239 {
240 let x = x as f32;
241 let max = if x * y == 0.0 {
242 1.0
243 } else {
244 x.abs().max(y.abs())
245 };
246 if max == 0.0 {
247 return true;
248 }
249 (x - y).abs() / max <= f32::EPSILON
250 }
251 }
252 #[rhai_fn(name = "==")]
253 pub fn eq_fi(x: f32, y: INT) -> bool {
254 #[cfg(feature = "unchecked")]
255 return x == (y as f32);
256
257 #[cfg(not(feature = "unchecked"))]
258 {
259 let y = y as f32;
260 let max = if x * y == 0.0 {
261 1.0
262 } else {
263 x.abs().max(y.abs())
264 };
265 if max == 0.0 {
266 return true;
267 }
268 (x - y).abs() / max <= f32::EPSILON
269 }
270 }
271 #[rhai_fn(name = "!=")]
272 pub fn neq_if(x: INT, y: f32) -> bool {
273 #[cfg(feature = "unchecked")]
274 return (x as f32) != y;
275
276 #[cfg(not(feature = "unchecked"))]
277 {
278 let x = x as f32;
279 let max = if x * y == 0.0 {
280 1.0
281 } else {
282 x.abs().max(y.abs())
283 };
284 if max == 0.0 {
285 return false;
286 }
287 (x - y).abs() / max > f32::EPSILON
288 }
289 }
290 #[rhai_fn(name = "!=")]
291 pub fn neq_fi(x: f32, y: INT) -> bool {
292 #[cfg(feature = "unchecked")]
293 return x != (y as f32);
294
295 #[cfg(not(feature = "unchecked"))]
296 {
297 let y = y as f32;
298 let max = if x * y == 0.0 {
299 1.0
300 } else {
301 x.abs().max(y.abs())
302 };
303 if max == 0.0 {
304 return false;
305 }
306 (x - y).abs() / max > f32::EPSILON
307 }
308 }
309 #[rhai_fn(name = ">")]
310 pub fn gt_if(x: INT, y: f32) -> bool {
311 #[cfg(feature = "unchecked")]
312 return (x as f32) > y;
313
314 #[cfg(not(feature = "unchecked"))]
315 {
316 let x = x as f32;
317 let max = if x * y == 0.0 {
318 1.0
319 } else {
320 x.abs().max(y.abs())
321 };
322 if max == 0.0 {
323 return false;
324 }
325 (x - y) / max > f32::EPSILON
326 }
327 }
328 #[rhai_fn(name = ">")]
329 pub fn gt_fi(x: f32, y: INT) -> bool {
330 #[cfg(feature = "unchecked")]
331 return x > (y as f32);
332
333 #[cfg(not(feature = "unchecked"))]
334 {
335 let y = y as f32;
336 let max = if x * y == 0.0 {
337 1.0
338 } else {
339 x.abs().max(y.abs())
340 };
341 if max == 0.0 {
342 return false;
343 }
344 (x - y) / max > f32::EPSILON
345 }
346 }
347 #[rhai_fn(name = ">=")]
348 pub fn gte_if(x: INT, y: f32) -> bool {
349 #[cfg(feature = "unchecked")]
350 return (x as f32) >= y;
351
352 #[cfg(not(feature = "unchecked"))]
353 {
354 let x = x as f32;
355 let max = if x * y == 0.0 {
356 1.0
357 } else {
358 x.abs().max(y.abs())
359 };
360 if max == 0.0 {
361 return true;
362 }
363 (x - y) / max > -f32::EPSILON
364 }
365 }
366 #[rhai_fn(name = ">=")]
367 pub fn gte_fi(x: f32, y: INT) -> bool {
368 #[cfg(feature = "unchecked")]
369 return x >= (y as f32);
370
371 #[cfg(not(feature = "unchecked"))]
372 {
373 let y = y as f32;
374 let max = if x * y == 0.0 {
375 1.0
376 } else {
377 x.abs().max(y.abs())
378 };
379 if max == 0.0 {
380 return true;
381 }
382 (x - y) / max > -f32::EPSILON
383 }
384 }
385 #[rhai_fn(name = "<")]
386 pub fn lt_if(x: INT, y: f32) -> bool {
387 #[cfg(feature = "unchecked")]
388 return (x as f32) < y;
389
390 #[cfg(not(feature = "unchecked"))]
391 {
392 let x = x as f32;
393 let max = if x * y == 0.0 {
394 1.0
395 } else {
396 x.abs().max(y.abs())
397 };
398 if max == 0.0 {
399 return false;
400 }
401 (y - x) / max > f32::EPSILON
402 }
403 }
404 #[rhai_fn(name = "<")]
405 pub fn lt_fi(x: f32, y: INT) -> bool {
406 #[cfg(feature = "unchecked")]
407 return x < (y as f32);
408
409 #[cfg(not(feature = "unchecked"))]
410 {
411 let y = y as f32;
412 let max = if x * y == 0.0 {
413 1.0
414 } else {
415 x.abs().max(y.abs())
416 };
417 if max == 0.0 {
418 return false;
419 }
420 (y - x) / max > f32::EPSILON
421 }
422 }
423 #[rhai_fn(name = "<=")]
424 pub fn lte_if(x: INT, y: f32) -> bool {
425 #[cfg(feature = "unchecked")]
426 return (x as f32) <= y;
427
428 #[cfg(not(feature = "unchecked"))]
429 {
430 let x = x as f32;
431 let max = if x * y == 0.0 {
432 1.0
433 } else {
434 x.abs().max(y.abs())
435 };
436 if max == 0.0 {
437 return true;
438 }
439 (y - x) / max > -f32::EPSILON
440 }
441 }
442 #[rhai_fn(name = "<=")]
443 pub fn lte_fi(x: f32, y: INT) -> bool {
444 #[cfg(feature = "unchecked")]
445 return x <= (y as f32);
446
447 #[cfg(not(feature = "unchecked"))]
448 {
449 let y = y as f32;
450 let max = if x * y == 0.0 {
451 1.0
452 } else {
453 x.abs().max(y.abs())
454 };
455 if max == 0.0 {
456 return true;
457 }
458 (y - x) / max > -f32::EPSILON
459 }
460 }
461
462 #[rhai_fn(name = "max")]
463 pub fn max_64_32(x: FLOAT, y: f32) -> FLOAT {
464 let (x, y) = (x, y as FLOAT);
465 if x >= y {
466 x
467 } else {
468 y
469 }
470 }
471 #[rhai_fn(name = "max")]
472 pub fn max_32_64(x: f32, y: FLOAT) -> FLOAT {
473 let (x, y) = (x as FLOAT, y);
474 if x >= y {
475 x
476 } else {
477 y
478 }
479 }
480 #[rhai_fn(name = "min")]
481 pub fn min_64_32(x: FLOAT, y: f32) -> FLOAT {
482 let (x, y) = (x, y as FLOAT);
483 if x <= y {
484 x
485 } else {
486 y
487 }
488 }
489 #[rhai_fn(name = "min")]
490 pub fn min_32_64(x: f32, y: FLOAT) -> FLOAT {
491 let (x, y) = (x as FLOAT, y);
492 if x <= y {
493 x
494 } else {
495 y
496 }
497 }
498}
499
500#[cfg(not(feature = "no_float"))]
501#[cfg(feature = "f32_float")]
502#[allow(clippy::cast_precision_loss)]
503#[export_module]
504mod f64_functions {
505 use crate::{FLOAT, INT};
506 #[cfg(feature = "no_std")]
507 use num_traits::Float;
508
509 #[rhai_fn(name = "==")]
510 pub fn eq_if(x: INT, y: f64) -> bool {
511 #[cfg(feature = "unchecked")]
512 return (x as f64) == y;
513
514 #[cfg(not(feature = "unchecked"))]
515 {
516 let x = x as f64;
517 let max = if x * y == 0.0 {
518 1.0
519 } else {
520 x.abs().max(y.abs())
521 };
522 if max == 0.0 {
523 return true;
524 }
525 return (x - y).abs() / max <= f64::EPSILON;
526 }
527 }
528 #[rhai_fn(name = "==")]
529 pub fn eq_fi(x: f64, y: INT) -> bool {
530 #[cfg(feature = "unchecked")]
531 return x == (y as f64);
532
533 #[cfg(not(feature = "unchecked"))]
534 {
535 let y = y as f64;
536 let max = if x * y == 0.0 {
537 1.0
538 } else {
539 x.abs().max(y.abs())
540 };
541 if max == 0.0 {
542 return true;
543 }
544 return (x - y).abs() / max <= f64::EPSILON;
545 }
546 }
547 #[rhai_fn(name = "!=")]
548 pub fn neq_if(x: INT, y: f64) -> bool {
549 #[cfg(feature = "unchecked")]
550 return (x as f64) != y;
551
552 #[cfg(not(feature = "unchecked"))]
553 {
554 let x = x as f64;
555 let max = if x * y == 0.0 {
556 1.0
557 } else {
558 x.abs().max(y.abs())
559 };
560 if max == 0.0 {
561 return false;
562 }
563 return (x - y).abs() / max > f64::EPSILON;
564 }
565 }
566 #[rhai_fn(name = "!=")]
567 pub fn neq_fi(x: f64, y: INT) -> bool {
568 #[cfg(feature = "unchecked")]
569 return x != (y as f64);
570
571 #[cfg(not(feature = "unchecked"))]
572 {
573 let y = y as f64;
574 let max = if x * y == 0.0 {
575 1.0
576 } else {
577 x.abs().max(y.abs())
578 };
579 if max == 0.0 {
580 return false;
581 }
582 return (x - y).abs() / max > f64::EPSILON;
583 }
584 }
585 #[rhai_fn(name = ">")]
586 pub fn gt_if(x: INT, y: f64) -> bool {
587 #[cfg(feature = "unchecked")]
588 return (x as f64) > y;
589
590 #[cfg(not(feature = "unchecked"))]
591 {
592 let x = x as f64;
593 let max = if x * y == 0.0 {
594 1.0
595 } else {
596 x.abs().max(y.abs())
597 };
598 if max == 0.0 {
599 return false;
600 }
601 return (x - y) / max > f64::EPSILON;
602 }
603 }
604 #[rhai_fn(name = ">")]
605 pub fn gt_fi(x: f64, y: INT) -> bool {
606 #[cfg(feature = "unchecked")]
607 return x > (y as f64);
608
609 #[cfg(not(feature = "unchecked"))]
610 {
611 let y = y as f64;
612 let max = if x * y == 0.0 {
613 1.0
614 } else {
615 x.abs().max(y.abs())
616 };
617 if max == 0.0 {
618 return false;
619 }
620 return (x - y) / max > f64::EPSILON;
621 }
622 }
623 #[rhai_fn(name = ">=")]
624 pub fn gte_if(x: INT, y: f64) -> bool {
625 #[cfg(feature = "unchecked")]
626 return (x as f64) >= y;
627
628 #[cfg(not(feature = "unchecked"))]
629 {
630 let x = x as f64;
631 let max = if x * y == 0.0 {
632 1.0
633 } else {
634 x.abs().max(y.abs())
635 };
636 if max == 0.0 {
637 return true;
638 }
639 return (x - y) / max > -f64::EPSILON;
640 }
641 }
642 #[rhai_fn(name = ">=")]
643 pub fn gte_fi(x: f64, y: INT) -> bool {
644 #[cfg(feature = "unchecked")]
645 return x >= (y as f64);
646
647 #[cfg(not(feature = "unchecked"))]
648 {
649 let y = y as f64;
650 let max = if x * y == 0.0 {
651 1.0
652 } else {
653 x.abs().max(y.abs())
654 };
655 if max == 0.0 {
656 return true;
657 }
658 return (x - y) / max > -f64::EPSILON;
659 }
660 }
661 #[rhai_fn(name = "<")]
662 pub fn lt_if(x: INT, y: f64) -> bool {
663 #[cfg(feature = "unchecked")]
664 return (x as f64) < y;
665
666 #[cfg(not(feature = "unchecked"))]
667 {
668 let x = x as f64;
669 let max = if x * y == 0.0 {
670 1.0
671 } else {
672 x.abs().max(y.abs())
673 };
674 if max == 0.0 {
675 return false;
676 }
677 return (y - x) / max > f64::EPSILON;
678 }
679 }
680 #[rhai_fn(name = "<")]
681 pub fn lt_fi(x: f64, y: INT) -> bool {
682 #[cfg(feature = "unchecked")]
683 return x < (y as f64);
684
685 #[cfg(not(feature = "unchecked"))]
686 {
687 let y = y as f64;
688 let max = if x * y == 0.0 {
689 1.0
690 } else {
691 x.abs().max(y.abs())
692 };
693 if max == 0.0 {
694 return false;
695 }
696 return (y - x) / max > f64::EPSILON;
697 }
698 }
699 #[rhai_fn(name = "<=")]
700 pub fn lte_if(x: INT, y: f64) -> bool {
701 #[cfg(feature = "unchecked")]
702 return (x as f64) <= y;
703
704 #[cfg(not(feature = "unchecked"))]
705 {
706 let x = x as f64;
707 let max = if x * y == 0.0 {
708 1.0
709 } else {
710 x.abs().max(y.abs())
711 };
712 if max == 0.0 {
713 return true;
714 }
715 return (y - x) / max > -f64::EPSILON;
716 }
717 }
718 #[rhai_fn(name = "<=")]
719 pub fn lte_fi(x: f64, y: INT) -> bool {
720 #[cfg(feature = "unchecked")]
721 return x <= (y as f64);
722
723 #[cfg(not(feature = "unchecked"))]
724 {
725 let y = y as f64;
726 let max = if x * y == 0.0 {
727 1.0
728 } else {
729 x.abs().max(y.abs())
730 };
731 if max == 0.0 {
732 return true;
733 }
734 return (y - x) / max > -f64::EPSILON;
735 }
736 }
737
738 #[rhai_fn(name = "max")]
739 pub fn max_32_64(x: FLOAT, y: f64) -> FLOAT {
740 let (x, y) = (x, y as FLOAT);
741 if x >= y {
742 x
743 } else {
744 y
745 }
746 }
747 #[rhai_fn(name = "max")]
748 pub fn max_64_32(x: f64, y: FLOAT) -> FLOAT {
749 let (x, y) = (x as FLOAT, y);
750 if x >= y {
751 x
752 } else {
753 y
754 }
755 }
756 #[rhai_fn(name = "min")]
757 pub fn min_32_64(x: FLOAT, y: f64) -> FLOAT {
758 let (x, y) = (x, y as FLOAT);
759 if x <= y {
760 x
761 } else {
762 y
763 }
764 }
765 #[rhai_fn(name = "min")]
766 pub fn min_64_32(x: f64, y: FLOAT) -> FLOAT {
767 let (x, y) = (x as FLOAT, y);
768 if x <= y {
769 x
770 } else {
771 y
772 }
773 }
774}
775
776#[cfg(feature = "decimal")]
777#[export_module]
778mod decimal_functions {
779 use crate::INT;
780 use rust_decimal::Decimal;
781
782 #[rhai_fn(name = "max")]
783 pub fn max_dd(x: Decimal, y: Decimal) -> Decimal {
784 if x >= y {
785 x
786 } else {
787 y
788 }
789 }
790 #[rhai_fn(name = "max")]
791 pub fn max_id(x: INT, y: Decimal) -> Decimal {
792 let x = x.into();
793 if x >= y {
794 x
795 } else {
796 y
797 }
798 }
799 #[rhai_fn(name = "max")]
800 pub fn max_di(x: Decimal, y: INT) -> Decimal {
801 let y = y.into();
802 if x >= y {
803 x
804 } else {
805 y
806 }
807 }
808 #[rhai_fn(name = "min")]
809 pub fn min_dd(x: Decimal, y: Decimal) -> Decimal {
810 if x <= y {
811 x
812 } else {
813 y
814 }
815 }
816 #[rhai_fn(name = "min")]
817 pub fn min_id(x: INT, y: Decimal) -> Decimal {
818 let x = x.into();
819 if x <= y {
820 x
821 } else {
822 y
823 }
824 }
825 #[rhai_fn(name = "min")]
826 pub fn min_di(x: Decimal, y: INT) -> Decimal {
827 let y = y.into();
828 if x <= y {
829 x
830 } else {
831 y
832 }
833 }
834}