1use crate::executor::expression::ExpressionError;
4use linkrs_core::value::NullType;
5use linkrs_core::Value;
6
7define_function_enum! {
8 pub enum MathFunction {
10 Abs => {
11 name: "abs",
12 arity: 1,
13 variadic: false,
14 description: "Calculating Absolute Values",
15 handler: execute_abs
16 },
17 Sqrt => {
18 name: "sqrt",
19 arity: 1,
20 variadic: false,
21 description: "square root calculation",
22 handler: execute_sqrt
23 },
24 Pow => {
25 name: "pow",
26 arity: 2,
27 variadic: false,
28 description: "exponentiate (math.)",
29 handler: execute_pow
30 },
31 Log => {
32 name: "log",
33 arity: 2,
34 variadic: false,
35 description: "logarithmic",
36 handler: execute_log
37 },
38 Log10 => {
39 name: "log10",
40 arity: 1,
41 variadic: false,
42 description: "Calculating logarithms with base 10",
43 handler: execute_log10
44 },
45 Sin => {
46 name: "sin",
47 arity: 1,
48 variadic: false,
49 description: "calculate the sine",
50 handler: execute_sin
51 },
52 Cos => {
53 name: "cos",
54 arity: 1,
55 variadic: false,
56 description: "calculate the cosine",
57 handler: execute_cos
58 },
59 Tan => {
60 name: "tan",
61 arity: 1,
62 variadic: false,
63 description: "arithmetic tangent (math.)",
64 handler: execute_tan
65 },
66 Round => {
67 name: "round",
68 arity: 1,
69 variadic: false,
70 description: "discard four, but treat five as whole (of decimal points)",
71 handler: execute_round
72 },
73 Ceil => {
74 name: "ceil",
75 arity: 1,
76 variadic: false,
77 description: "Round up",
78 handler: execute_ceil
79 },
80 Floor => {
81 name: "floor",
82 arity: 1,
83 variadic: false,
84 description: "round down",
85 handler: execute_floor
86 },
87 Asin => {
88 name: "asin",
89 arity: 1,
90 variadic: false,
91 description: "calculate the arcsine",
92 handler: execute_asin
93 },
94 Acos => {
95 name: "acos",
96 arity: 1,
97 variadic: false,
98 description: "Calculate the inverse cosine",
99 handler: execute_acos
100 },
101 Atan => {
102 name: "atan",
103 arity: 1,
104 variadic: false,
105 description: "Compute the arctangent",
106 handler: execute_atan
107 },
108 Cbrt => {
109 name: "cbrt",
110 arity: 1,
111 variadic: false,
112 description: "calculate the cube root",
113 handler: execute_cbrt
114 },
115 Hypot => {
116 name: "hypot",
117 arity: 2,
118 variadic: false,
119 description: "Compute the hypotenuse of a right triangle",
120 handler: execute_hypot
121 },
122 Sign => {
123 name: "sign",
124 arity: 1,
125 variadic: false,
126 description: "Return Value Symbol",
127 handler: execute_sign
128 },
129 Rand => {
130 name: "rand",
131 arity: 0,
132 variadic: false,
133 description: "Generate random floating point numbers",
134 handler: execute_rand
135 },
136 Rand32 => {
137 name: "rand32",
138 arity: 0,
139 variadic: true,
140 description: "Generate 32-bit random integers",
141 handler: execute_rand32
142 },
143 Rand64 => {
144 name: "rand64",
145 arity: 0,
146 variadic: false,
147 description: "Generate 64-bit random integers",
148 handler: execute_rand64
149 },
150 E => {
151 name: "e",
152 arity: 0,
153 variadic: false,
154 description: "Returns the natural constant e",
155 handler: execute_e
156 },
157 Pi => {
158 name: "pi",
159 arity: 0,
160 variadic: false,
161 description: "Return to pi",
162 handler: execute_pi
163 },
164 Exp2 => {
165 name: "exp2",
166 arity: 1,
167 variadic: false,
168 description: "Calculating powers of 2",
169 handler: execute_exp2
170 },
171 Log2 => {
172 name: "log2",
173 arity: 1,
174 variadic: false,
175 description: "Calculating logarithms with a base of 2",
176 handler: execute_log2
177 },
178 Radians => {
179 name: "radians",
180 arity: 1,
181 variadic: false,
182 description: "Angle to radian",
183 handler: execute_radians
184 },
185 BitAnd => {
186 name: "bit_and",
187 arity: 2,
188 variadic: false,
189 description: "compatibility with",
190 handler: execute_bit_and
191 },
192 BitOr => {
193 name: "bit_or",
194 arity: 2,
195 variadic: false,
196 description: "push-button or",
197 handler: execute_bit_or
198 },
199 BitXor => {
200 name: "bit_xor",
201 arity: 2,
202 variadic: false,
203 description: "palindromic or binomial (math.)",
204 handler: execute_bit_xor
205 },
206 Atan2 => {
207 name: "atan2",
208 arity: 2,
209 variadic: false,
210 description: "Compute the arctangent of y/x",
211 handler: execute_atan2
212 },
213 Sinh => {
214 name: "sinh",
215 arity: 1,
216 variadic: false,
217 description: "Calculate the hyperbolic sine",
218 handler: execute_sinh
219 },
220 Cosh => {
221 name: "cosh",
222 arity: 1,
223 variadic: false,
224 description: "Calculate the hyperbolic cosine",
225 handler: execute_cosh
226 },
227 Tanh => {
228 name: "tanh",
229 arity: 1,
230 variadic: false,
231 description: "Calculate the hyperbolic tangent",
232 handler: execute_tanh
233 },
234 Degrees => {
235 name: "degrees",
236 arity: 1,
237 variadic: false,
238 description: "Convert radians to degrees",
239 handler: execute_degrees
240 },
241 Gcd => {
242 name: "gcd",
243 arity: 2,
244 variadic: false,
245 description: "Greatest common divisor",
246 handler: execute_gcd
247 },
248 Lcm => {
249 name: "lcm",
250 arity: 2,
251 variadic: false,
252 description: "Least common multiple",
253 handler: execute_lcm
254 },
255 Factorial => {
256 name: "factorial",
257 arity: 1,
258 variadic: false,
259 description: "Calculate factorial of a number",
260 handler: execute_factorial
261 },
262 Gamma => {
263 name: "gamma",
264 arity: 1,
265 variadic: false,
266 description: "Calculate gamma function",
267 handler: execute_gamma
268 },
269 Lgamma => {
270 name: "lgamma",
271 arity: 1,
272 variadic: false,
273 description: "Calculate natural logarithm of absolute value of gamma function",
274 handler: execute_lgamma
275 },
276 Negate => {
277 name: "negate",
278 arity: 1,
279 variadic: false,
280 description: "Negate a number",
281 handler: execute_negate
282 },
283 Even => {
284 name: "even",
285 arity: 1,
286 variadic: false,
287 description: "Round up to nearest even integer",
288 handler: execute_even
289 },
290 SetSeed => {
291 name: "set_seed",
292 arity: 1,
293 variadic: false,
294 description: "Set random seed",
295 handler: execute_set_seed
296 },
297 BitShiftLeft => {
298 name: "bit_shift_left",
299 arity: 2,
300 variadic: false,
301 description: "Bitwise left shift",
302 handler: execute_bit_shift_left
303 },
304 BitShiftRight => {
305 name: "bit_shift_right",
306 arity: 2,
307 variadic: false,
308 description: "Bitwise right shift",
309 handler: execute_bit_shift_right
310 },
311 }
312}
313
314define_unary_numeric_fn!(
315 execute_abs,
316 int: |i: i32| Ok(Value::Int(i.abs())),
317 float: |f: f32| Ok(Value::Float(f.abs())),
318 "abs"
319);
320
321define_unary_float_fn!(execute_sqrt, |v: f32| v.sqrt(), "sqrt");
322define_unary_float_fn!(execute_sin, |v: f32| v.sin(), "sin");
323define_unary_float_fn!(execute_cos, |v: f32| v.cos(), "cos");
324define_unary_float_fn!(execute_tan, |v: f32| v.tan(), "tan");
325define_unary_float_fn!(execute_log10, |v: f32| v.log10(), "log10");
326
327define_unary_numeric_fn!(
328 execute_round,
329 int: |i: i32| Ok(Value::Int(i)),
330 float: |f: f32| Ok(Value::Float(f.round())),
331 "round"
332);
333
334define_unary_numeric_fn!(
335 execute_ceil,
336 int: |i: i32| Ok(Value::Float(i as f32)),
337 float: |f: f32| Ok(Value::Float(f.ceil())),
338 "ceil"
339);
340
341define_unary_numeric_fn!(
342 execute_floor,
343 int: |i: i32| Ok(Value::Float(i as f32)),
344 float: |f: f32| Ok(Value::Float(f.floor())),
345 "floor"
346);
347
348define_binary_numeric_fn!(
349 execute_pow,
350 |a: f32, b: f32| Ok(Value::Float(a.powf(b))),
351 "pow"
352);
353
354define_binary_numeric_fn!(
355 execute_log,
356 |base: f32, val: f32| Ok(Value::Float(val.log(base))),
357 "log"
358);
359
360define_unary_float_fn!(execute_asin, |v: f32| v.asin(), "asin");
362define_unary_float_fn!(execute_acos, |v: f32| v.acos(), "acos");
363define_unary_float_fn!(execute_atan, |v: f32| v.atan(), "atan");
364define_unary_float_fn!(execute_cbrt, |v: f32| v.cbrt(), "cbrt");
365define_unary_float_fn!(execute_exp2, |v: f32| v.exp2(), "exp2");
366define_unary_float_fn!(execute_log2, |v: f32| v.log2(), "log2");
367define_unary_float_fn!(execute_radians, |v: f32| v.to_radians(), "radians");
368
369define_binary_numeric_fn!(
370 execute_hypot,
371 |a: f32, b: f32| Ok(Value::Float(a.hypot(b))),
372 "hypot"
373);
374
375fn execute_sign(args: &[Value]) -> Result<Value, ExpressionError> {
376 match &args[0] {
377 Value::SmallInt(i) => Ok(Value::SmallInt(i.signum())),
378 Value::Int(i) => Ok(Value::Int(i.signum())),
379 Value::BigInt(i) => Ok(Value::BigInt(i.signum())),
380 Value::Float(f) => Ok(Value::Int(f.signum() as i32)),
381 Value::Double(f) => Ok(Value::BigInt(f.signum() as i64)),
382 Value::Null(_) => Ok(Value::Null(NullType::Null)),
383 _ => Err(ExpressionError::type_error(
384 "The sign function requires a numeric type",
385 )),
386 }
387}
388
389fn execute_rand(_args: &[Value]) -> Result<Value, ExpressionError> {
390 use rand::Rng;
391 let mut rng = rand::thread_rng();
392 Ok(Value::Float(rng.gen::<f32>()))
393}
394
395fn execute_rand32(args: &[Value]) -> Result<Value, ExpressionError> {
396 use rand::Rng;
397 let mut rng = rand::thread_rng();
398 let result = match args.len() {
399 0 => rng.gen::<i32>(),
400 1 => match &args[0] {
401 Value::Int(max) => rng.gen_range(0..*max),
402 Value::Null(_) => return Ok(Value::Null(NullType::Null)),
403 _ => {
404 return Err(ExpressionError::type_error(
405 "The rand32 function takes integer arguments",
406 ))
407 }
408 },
409 2 => match (&args[0], &args[1]) {
410 (Value::Int(min), Value::Int(max)) => rng.gen_range(*min..*max),
411 (Value::Null(_), _) | (_, Value::Null(_)) => return Ok(Value::Null(NullType::Null)),
412 _ => {
413 return Err(ExpressionError::type_error(
414 "The rand32 function takes integer arguments",
415 ))
416 }
417 },
418 _ => {
419 return Err(ExpressionError::type_error(
420 "The rand32 function takes 0-2 arguments",
421 ))
422 }
423 };
424 Ok(Value::Int(result))
425}
426
427fn execute_rand64(_args: &[Value]) -> Result<Value, ExpressionError> {
428 use rand::Rng;
429 let mut rng = rand::thread_rng();
430 Ok(Value::BigInt(rng.gen::<i64>()))
431}
432
433fn execute_e(_args: &[Value]) -> Result<Value, ExpressionError> {
434 Ok(Value::Float(std::f32::consts::E))
435}
436
437fn execute_pi(_args: &[Value]) -> Result<Value, ExpressionError> {
438 Ok(Value::Float(std::f32::consts::PI))
439}
440
441fn execute_bit_and(args: &[Value]) -> Result<Value, ExpressionError> {
442 match (&args[0], &args[1]) {
443 (Value::SmallInt(a), Value::SmallInt(b)) => Ok(Value::SmallInt(a & b)),
444 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a & b)),
445 (Value::BigInt(a), Value::BigInt(b)) => Ok(Value::BigInt(a & b)),
446 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
447 _ => Err(ExpressionError::type_error(
448 "The bit_and function takes integer arguments",
449 )),
450 }
451}
452
453fn execute_bit_or(args: &[Value]) -> Result<Value, ExpressionError> {
454 match (&args[0], &args[1]) {
455 (Value::SmallInt(a), Value::SmallInt(b)) => Ok(Value::SmallInt(a | b)),
456 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a | b)),
457 (Value::BigInt(a), Value::BigInt(b)) => Ok(Value::BigInt(a | b)),
458 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
459 _ => Err(ExpressionError::type_error(
460 "The bit_or function takes integer arguments",
461 )),
462 }
463}
464
465define_binary_numeric_fn!(
466 execute_atan2,
467 |y: f32, x: f32| Ok(Value::Float(y.atan2(x))),
468 "atan2"
469);
470
471define_unary_float_fn!(execute_sinh, |v: f32| v.sinh(), "sinh");
472define_unary_float_fn!(execute_cosh, |v: f32| v.cosh(), "cosh");
473define_unary_float_fn!(execute_tanh, |v: f32| v.tanh(), "tanh");
474define_unary_float_fn!(execute_degrees, |v: f32| v.to_degrees(), "degrees");
475
476fn execute_bit_xor(args: &[Value]) -> Result<Value, ExpressionError> {
477 match (&args[0], &args[1]) {
478 (Value::SmallInt(a), Value::SmallInt(b)) => Ok(Value::SmallInt(a ^ b)),
479 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a ^ b)),
480 (Value::BigInt(a), Value::BigInt(b)) => Ok(Value::BigInt(a ^ b)),
481 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
482 _ => Err(ExpressionError::type_error(
483 "The bit_xor function takes integer arguments",
484 )),
485 }
486}
487
488fn execute_gcd(args: &[Value]) -> Result<Value, ExpressionError> {
489 match (&args[0], &args[1]) {
490 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(gcd(*a, *b))),
491 (Value::BigInt(a), Value::BigInt(b)) => Ok(Value::BigInt(gcd(*a, *b))),
492 (Value::Int(a), Value::BigInt(b)) => Ok(Value::BigInt(gcd(*a as i64, *b))),
493 (Value::BigInt(a), Value::Int(b)) => Ok(Value::BigInt(gcd(*a, *b as i64))),
494 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
495 _ => Err(ExpressionError::type_error(
496 "The gcd function requires integer arguments",
497 )),
498 }
499}
500
501fn execute_lcm(args: &[Value]) -> Result<Value, ExpressionError> {
502 match (&args[0], &args[1]) {
503 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(lcm(*a, *b))),
504 (Value::BigInt(a), Value::BigInt(b)) => Ok(Value::BigInt(lcm(*a, *b))),
505 (Value::Int(a), Value::BigInt(b)) => Ok(Value::BigInt(lcm(*a as i64, *b))),
506 (Value::BigInt(a), Value::Int(b)) => Ok(Value::BigInt(lcm(*a, *b as i64))),
507 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
508 _ => Err(ExpressionError::type_error(
509 "The lcm function requires integer arguments",
510 )),
511 }
512}
513
514fn gcd<
515 T: Copy
516 + std::ops::Rem<Output = T>
517 + PartialEq
518 + From<i8>
519 + std::ops::Neg<Output = T>
520 + PartialOrd,
521>(
522 mut a: T,
523 mut b: T,
524) -> T {
525 let zero: T = T::from(0);
526 if a == zero {
527 return b;
528 }
529 if b == zero {
530 return a;
531 }
532 while b != zero {
533 let temp = b;
534 b = a % b;
535 a = temp;
536 }
537 if a < zero {
538 -a
539 } else {
540 a
541 }
542}
543
544fn lcm<
545 T: Copy
546 + std::ops::Rem<Output = T>
547 + PartialEq
548 + From<i8>
549 + std::ops::Neg<Output = T>
550 + PartialOrd
551 + std::ops::Div<Output = T>
552 + std::ops::Mul<Output = T>,
553>(
554 a: T,
555 b: T,
556) -> T {
557 let zero: T = T::from(0);
558 if a == zero || b == zero {
559 return zero;
560 }
561 let g = gcd(a, b);
562 let abs_a = if a < zero { -a } else { a };
563 let abs_b = if b < zero { -b } else { b };
564 (abs_a / g) * abs_b
565}
566
567fn execute_factorial(args: &[Value]) -> Result<Value, ExpressionError> {
568 match &args[0] {
569 Value::SmallInt(i) => {
570 if *i < 0 {
571 return Err(ExpressionError::type_error(
572 "factorial requires a non-negative integer",
573 ));
574 }
575 let mut result: i64 = 1;
576 for j in 2..=*i as i64 {
577 result *= j;
578 }
579 Ok(Value::BigInt(result))
580 }
581 Value::Int(i) => {
582 if *i < 0 {
583 return Err(ExpressionError::type_error(
584 "factorial requires a non-negative integer",
585 ));
586 }
587 let mut result: i64 = 1;
588 for j in 2..=*i as i64 {
589 result *= j;
590 }
591 Ok(Value::BigInt(result))
592 }
593 Value::BigInt(i) => {
594 if *i < 0 {
595 return Err(ExpressionError::type_error(
596 "factorial requires a non-negative integer",
597 ));
598 }
599 let mut result: i64 = 1;
600 for j in 2..=*i {
601 result *= j;
602 }
603 Ok(Value::BigInt(result))
604 }
605 Value::Float(f) => {
606 if *f < 0.0 {
607 return Err(ExpressionError::type_error(
608 "factorial requires a non-negative integer",
609 ));
610 }
611 Ok(Value::Float(gamma(*f + 1.0)))
612 }
613 Value::Double(f) => {
614 if *f < 0.0 {
615 return Err(ExpressionError::type_error(
616 "factorial requires a non-negative integer",
617 ));
618 }
619 Ok(Value::Float(gamma(*f as f32 + 1.0)))
620 }
621 Value::Null(_) => Ok(Value::Null(NullType::Null)),
622 _ => Err(ExpressionError::type_error(
623 "factorial requires a numeric type",
624 )),
625 }
626}
627
628fn gamma(mut x: f32) -> f32 {
629 if x < 0.5 {
630 std::f32::consts::PI / ((std::f32::consts::PI * x).sin() * gamma(1.0 - x))
631 } else {
632 x -= 1.0;
633 let g: usize = 7;
634 let c = [
635 0.999_999_9,
636 676.520_3,
637 -1_259.139_2,
638 771.323_4,
639 -176.615_04,
640 12.507_343,
641 -0.138_571_1,
642 9.984_369e-6,
643 1.505_632_7e-7,
644 ];
645 let mut t = c[0];
646 for (i, val) in c.iter().enumerate().take(g + 2).skip(1) {
647 t += val / (x + i as f32);
648 }
649 let x = x + g as f32 + 0.5;
650 (2.0 * std::f32::consts::PI).sqrt() * x.powf(x - 0.5) * (-x).exp() * t
651 }
652}
653
654fn execute_gamma(args: &[Value]) -> Result<Value, ExpressionError> {
655 match &args[0] {
656 Value::SmallInt(i) => Ok(Value::Float(gamma(*i as f32))),
657 Value::Int(i) => Ok(Value::Float(gamma(*i as f32))),
658 Value::BigInt(i) => Ok(Value::Float(gamma(*i as f32))),
659 Value::Float(f) => Ok(Value::Float(gamma(*f))),
660 Value::Double(f) => Ok(Value::Float(gamma(*f as f32))),
661 Value::Null(_) => Ok(Value::Null(NullType::Null)),
662 _ => Err(ExpressionError::type_error("gamma requires a numeric type")),
663 }
664}
665
666fn execute_lgamma(args: &[Value]) -> Result<Value, ExpressionError> {
667 match &args[0] {
668 Value::SmallInt(i) => Ok(Value::Float(gamma(*i as f32).abs().ln())),
669 Value::Int(i) => Ok(Value::Float(gamma(*i as f32).abs().ln())),
670 Value::BigInt(i) => Ok(Value::Float(gamma(*i as f32).abs().ln())),
671 Value::Float(f) => Ok(Value::Float(gamma(*f).abs().ln())),
672 Value::Double(f) => Ok(Value::Float(gamma(*f as f32).abs().ln())),
673 Value::Null(_) => Ok(Value::Null(NullType::Null)),
674 _ => Err(ExpressionError::type_error(
675 "lgamma requires a numeric type",
676 )),
677 }
678}
679
680fn execute_negate(args: &[Value]) -> Result<Value, ExpressionError> {
681 match &args[0] {
682 Value::SmallInt(i) => Ok(Value::SmallInt(-i)),
683 Value::Int(i) => Ok(Value::Int(-i)),
684 Value::BigInt(i) => Ok(Value::BigInt(-i)),
685 Value::Float(f) => Ok(Value::Float(-f)),
686 Value::Double(f) => Ok(Value::Double(-f)),
687 Value::Null(_) => Ok(Value::Null(NullType::Null)),
688 _ => Err(ExpressionError::type_error(
689 "negate requires a numeric type",
690 )),
691 }
692}
693
694fn execute_even(args: &[Value]) -> Result<Value, ExpressionError> {
695 match &args[0] {
696 Value::SmallInt(i) => Ok(Value::SmallInt(if *i % 2 == 0 { *i } else { *i + 1 })),
697 Value::Int(i) => Ok(Value::Int(if *i % 2 == 0 { *i } else { *i + 1 })),
698 Value::BigInt(i) => Ok(Value::BigInt(if *i % 2 == 0 { *i } else { *i + 1 })),
699 Value::Float(f) => {
700 let rounded = f.round();
701 if rounded % 2.0 == 0.0 {
702 Ok(Value::Float(rounded))
703 } else {
704 Ok(Value::Float(rounded + 1.0))
705 }
706 }
707 Value::Double(f) => {
708 let rounded = f.round();
709 if rounded % 2.0 == 0.0 {
710 Ok(Value::Double(rounded))
711 } else {
712 Ok(Value::Double(rounded + 1.0))
713 }
714 }
715 Value::Null(_) => Ok(Value::Null(NullType::Null)),
716 _ => Err(ExpressionError::type_error("even requires a numeric type")),
717 }
718}
719
720fn execute_set_seed(args: &[Value]) -> Result<Value, ExpressionError> {
721 match &args[0] {
722 Value::SmallInt(_) => Ok(Value::Null(NullType::Null)),
723 Value::Int(_) => Ok(Value::Null(NullType::Null)),
724 Value::BigInt(_) => Ok(Value::Null(NullType::Null)),
725 Value::Float(_) => Ok(Value::Null(NullType::Null)),
726 Value::Double(_) => Ok(Value::Null(NullType::Null)),
727 Value::Null(_) => Ok(Value::Null(NullType::Null)),
728 _ => Err(ExpressionError::type_error(
729 "set_seed requires a numeric type",
730 )),
731 }
732}
733
734fn execute_bit_shift_left(args: &[Value]) -> Result<Value, ExpressionError> {
735 match (&args[0], &args[1]) {
736 (Value::SmallInt(a), Value::SmallInt(b)) => Ok(Value::SmallInt(a << *b)),
737 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a << *b)),
738 (Value::BigInt(a), Value::BigInt(b)) => Ok(Value::BigInt(a << *b)),
739 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
740 _ => Err(ExpressionError::type_error(
741 "bit_shift_left requires integer arguments",
742 )),
743 }
744}
745
746fn execute_bit_shift_right(args: &[Value]) -> Result<Value, ExpressionError> {
747 match (&args[0], &args[1]) {
748 (Value::SmallInt(a), Value::SmallInt(b)) => Ok(Value::SmallInt(a >> *b)),
749 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a >> *b)),
750 (Value::BigInt(a), Value::BigInt(b)) => Ok(Value::BigInt(a >> *b)),
751 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
752 _ => Err(ExpressionError::type_error(
753 "bit_shift_right requires integer arguments",
754 )),
755 }
756}
757
758#[cfg(test)]
759mod tests;