1use radiate_error::radiate_bail;
2
3use crate::AnyValue;
4use std::ops::{Add, Div, Mul, Rem, Sub};
5use std::ops::{BitAnd, BitOr, Not};
6
7macro_rules! bin_numeric_op {
10 ($lhs:expr, $rhs:expr, $op:tt) => {{
11 use AnyValue::*;
12 match ($lhs, $rhs) {
13 (Int8(a), Int8(b)) => Int8(a $op b),
14 (Int8(a), Int16(b)) => Int16(i16::from(a) $op b),
15 (Int8(a), Int32(b)) => Int32(i32::from(a) $op b),
16 (Int8(a), Int64(b)) => Int64(i64::from(a) $op b),
17 (Int8(a), Int128(b)) => Int128(i128::from(a) $op b),
18
19 (Int16(a), Int8(b)) => Int16(i16::from(a) $op i16::from(b)),
20 (Int16(a), Int16(b)) => Int16(a $op b),
21 (Int16(a), Int32(b)) => Int32(i32::from(a) $op b),
22 (Int16(a), Int64(b)) => Int64(i64::from(a) $op b),
23 (Int16(a), Int128(b)) => Int128(i128::from(a) $op b),
24
25 (Int32(a), Int8(b)) => Int32(a $op i32::from(b)),
26 (Int32(a), Int16(b)) => Int32(a $op i32::from(b)),
27 (Int32(a), Int32(b)) => Int32(a $op b),
28 (Int32(a), Int64(b)) => Int64(i64::from(a) $op b),
29 (Int32(a), Int128(b)) => Int128(i128::from(a) $op b),
30
31 (Int64(a), Int8(b)) => Int64(a $op i64::from(b)),
32 (Int64(a), Int16(b)) => Int64(a $op i64::from(b)),
33 (Int64(a), Int32(b)) => Int64(a $op i64::from(b)),
34 (Int64(a), Int64(b)) => Int64(a $op b),
35 (Int64(a), Int128(b)) => Int128(i128::from(a) $op b),
36
37 (Int128(a), Int8(b)) => Int128(a $op i128::from(b)),
38 (Int128(a), Int16(b)) => Int128(a $op i128::from(b)),
39 (Int128(a), Int32(b)) => Int128(a $op i128::from(b)),
40 (Int128(a), Int64(b)) => Int128(a $op i128::from(b)),
41 (Int128(a), Int128(b)) => Int128(a $op b),
42
43 (UInt8(a), UInt8(b)) => UInt8(a $op b),
44 (UInt8(a), UInt16(b)) => UInt16(u16::from(a) $op b),
45 (UInt8(a), UInt32(b)) => UInt32(u32::from(a) $op b),
46 (UInt8(a), UInt64(b)) => UInt64(u64::from(a) $op b),
47 (UInt8(a), UInt128(b)) => UInt128(u128::from(a) $op b),
48
49 (UInt16(a), UInt8(b)) => UInt16(a $op u16::from(b)),
50 (UInt16(a), UInt16(b)) => UInt16(a $op b),
51 (UInt16(a), UInt32(b)) => UInt32(u32::from(a) $op b),
52 (UInt16(a), UInt64(b)) => UInt64(u64::from(a) $op b),
53 (UInt16(a), UInt128(b)) => UInt128(u128::from(a) $op b),
54
55 (UInt32(a), UInt8(b)) => UInt32(a $op u32::from(b)),
56 (UInt32(a), UInt16(b)) => UInt32(a $op u32::from(b)),
57 (UInt32(a), UInt32(b)) => UInt32(a $op b),
58 (UInt32(a), UInt64(b)) => UInt64(u64::from(a) $op b),
59 (UInt32(a), UInt128(b)) => UInt128(u128::from(a) $op b),
60
61 (UInt64(a), UInt8(b)) => UInt64(a $op u64::from(b)),
62 (UInt64(a), UInt16(b)) => UInt64(a $op u64::from(b)),
63 (UInt64(a), UInt32(b)) => UInt64(a $op u64::from(b)),
64 (UInt64(a), UInt64(b)) => UInt64(a $op b),
65 (UInt64(a), UInt128(b)) => UInt128(u128::from(a) $op b),
66
67 (Float32(a), Float32(b)) => Float32(a $op b),
68 (Float64(a), Float32(b)) => Float64(a $op b as f64),
69
70 (Float64(a), Float64(b)) => Float64(a $op b),
71 (Float32(a), Float64(b)) => Float64(a as f64 $op b),
72 _ => Null,
73 }
74 }};
75}
76
77macro_rules! bin_numeric_div {
78 ($lhs:expr, $rhs:expr) => {{
79 use AnyValue::*;
80 match ($lhs, $rhs) {
81 (Int8(a), Int8(b)) => Int8(if b == 0 { a } else { a / b }),
82 (Int16(a), Int8(b)) => Int16(if b == 0 { a } else { a / i16::from(b) }),
83 (Int32(a), Int8(b)) => Int32(if b == 0 { a } else { a / i32::from(b) }),
84 (Int64(a), Int8(b)) => Int64(if b == 0 { a } else { a / i64::from(b) }),
85 (Int128(a), Int8(b)) => Int128(if b == 0 { a } else { a / i128::from(b) }),
86
87 (Int16(a), Int16(b)) => Int16(if b == 0 { a } else { a / b }),
88 (Int32(a), Int16(b)) => Int32(if b == 0 { a } else { a / i32::from(b) }),
89 (Int64(a), Int16(b)) => Int64(if b == 0 { a } else { a / i64::from(b) }),
90 (Int128(a), Int16(b)) => Int128(if b == 0 { a } else { a / i128::from(b) }),
91
92 (Int32(a), Int32(b)) => Int32(if b == 0 { a } else { a / b }),
93 (Int64(a), Int32(b)) => Int64(if b == 0 { a } else { a / i64::from(b) }),
94 (Int128(a), Int32(b)) => Int128(if b == 0 { a } else { a / i128::from(b) }),
95
96 (Int64(a), Int64(b)) => Int64(if b == 0 { a } else { a / b }),
97 (Int128(a), Int64(b)) => Int128(if b == 0 { a } else { a / i128::from(b) }),
98
99 (Int128(a), Int128(b)) => Int128(if b == 0 { a } else { a / b }),
100
101 (UInt8(a), UInt8(b)) => UInt8(if b == 0 { a } else { a / b }),
102 (UInt8(a), UInt16(b)) => UInt16(if b == 0 { a as u16 } else { (a as u16) / b }),
103 (UInt8(a), UInt32(b)) => UInt32(if b == 0 { a as u32 } else { (a as u32) / b }),
104 (UInt8(a), UInt64(b)) => UInt64(if b == 0 { a as u64 } else { (a as u64) / b }),
105 (UInt8(a), UInt128(b)) => UInt128(if b == 0 { a as u128 } else { (a as u128) / b }),
106
107 (UInt16(a), UInt16(b)) => UInt16(if b == 0 { a } else { a / b }),
108 (UInt16(a), UInt32(b)) => UInt32(if b == 0 { a as u32 } else { (a as u32) / b }),
109 (UInt16(a), UInt64(b)) => UInt64(if b == 0 { a as u64 } else { (a as u64) / b }),
110 (UInt16(a), UInt128(b)) => UInt128(if b == 0 { a as u128 } else { (a as u128) / b }),
111
112 (UInt32(a), UInt32(b)) => UInt32(if b == 0 { a } else { a / b }),
113 (UInt32(a), UInt64(b)) => UInt64(if b == 0 { a as u64 } else { (a as u64) / b }),
114 (UInt32(a), UInt128(b)) => UInt128(if b == 0 { a as u128 } else { (a as u128) / b }),
115
116 (UInt64(a), UInt64(b)) => UInt64(if b == 0 { a } else { a / b }),
117 (UInt64(a), UInt128(b)) => UInt128(if b == 0 { a as u128 } else { (a as u128) / b }),
118
119 (Float32(a), Float32(b)) => {
120 if b == 0.0 {
121 Null
122 } else {
123 Float32(a / b)
124 }
125 }
126 (Float64(a), Float64(b)) => {
127 if b == 0.0 {
128 Null
129 } else {
130 Float64(a / b)
131 }
132 }
133 (Float32(a), Float64(b)) => {
134 if b == 0.0 {
135 Null
136 } else {
137 Float64((a as f64) / b)
138 }
139 }
140 (Float64(a), Float32(b)) => {
141 if b == 0.0 {
142 Null
143 } else {
144 Float64(a / (b as f64))
145 }
146 }
147 _ => panic!("Division is only supported for numeric types"),
148 }
149 }};
150}
151
152impl Add for AnyValue<'_> {
153 type Output = Self;
154
155 #[inline(always)]
156 fn add(self, other: Self) -> Self {
157 use AnyValue::*;
158 let is_numeric = self.dtype().is_numeric() && other.dtype().is_numeric();
159 let is_nested = self.is_nested() && other.is_nested();
160
161 if !is_numeric && !is_nested {
162 return self;
163 }
164
165 match (self, other) {
166 (Bool(a), Bool(b)) => Bool(a || b),
167 (Vector(a), Vector(b)) => Vector(
168 a.into_iter()
169 .zip(b.into_iter())
170 .map(|(x, y)| x + y)
171 .collect(),
172 ),
173 (Struct(a), Struct(b)) => {
174 if a.len() != b.len() {
175 return Null;
176 }
177
178 Struct(
179 a.into_iter()
180 .zip(b.into_iter())
181 .map(|(one, two)| {
182 if one.0.name() != two.0.name() {
183 return (one.0, Null);
184 }
185
186 (one.0, one.1 + two.1)
187 })
188 .collect(),
189 )
190 }
191 (lhs, rhs) => bin_numeric_op!(lhs, rhs, +),
192 }
193 }
194}
195
196impl Sub for AnyValue<'_> {
197 type Output = Self;
198
199 #[inline(always)]
200 fn sub(self, other: Self) -> Self {
201 use AnyValue::*;
202
203 let is_numeric = self.dtype().is_numeric() && other.dtype().is_numeric();
204 let is_nested = self.is_nested() && other.is_nested();
205
206 if !is_numeric && !is_nested {
207 return self;
208 }
209
210 match (self, other) {
211 (Bool(a), Bool(b)) => Bool(a ^ b),
212 (Vector(a), Vector(b)) => Vector(
213 a.into_iter()
214 .zip(b.into_iter())
215 .map(|(x, y)| x - y)
216 .collect(),
217 ),
218 (Struct(a), Struct(b)) => {
219 if a.len() != b.len() {
220 return Null;
221 }
222
223 Struct(
224 a.into_iter()
225 .zip(b.into_iter())
226 .map(|(one, two)| {
227 if one.0.name() != two.0.name() {
228 return (one.0, Null);
229 }
230
231 (one.0, one.1 - two.1)
232 })
233 .collect(),
234 )
235 }
236 (lhs, rhs) => bin_numeric_op!(lhs, rhs, -),
237 }
238 }
239}
240
241impl Mul for AnyValue<'_> {
242 type Output = Self;
243
244 #[inline(always)]
245 fn mul(self, other: Self) -> Self {
246 use AnyValue::*;
247
248 let is_numeric = self.dtype().is_numeric() && other.dtype().is_numeric();
249 let is_nested = self.is_nested() && other.is_nested();
250
251 if !is_numeric && !is_nested {
252 return self;
253 }
254
255 match (self, other) {
256 (Bool(a), Bool(b)) => Bool(a && b),
257 (Vector(a), Vector(b)) => Vector(
258 a.into_iter()
259 .zip(b.into_iter())
260 .map(|(x, y)| x * y)
261 .collect(),
262 ),
263 (Struct(a), Struct(b)) => {
264 if a.len() != b.len() {
265 return Null;
266 }
267
268 Struct(
269 a.into_iter()
270 .zip(b.into_iter())
271 .map(|(one, two)| {
272 if one.0.name() != two.0.name() {
273 return (one.0, Null);
274 }
275
276 (one.0, one.1 * two.1)
277 })
278 .collect(),
279 )
280 }
281 (lhs, rhs) => bin_numeric_op!(lhs, rhs, *),
282 }
283 }
284}
285
286impl Div for AnyValue<'_> {
287 type Output = Self;
288
289 #[inline(always)]
290 fn div(self, other: Self) -> Self {
291 use AnyValue::*;
292
293 let is_numeric = self.dtype().is_numeric() && other.dtype().is_numeric();
294 let is_nested = self.is_nested() && other.is_nested();
295
296 if !is_numeric && !is_nested {
297 return self;
298 }
299
300 match (self, other) {
301 (Vector(a), Vector(b)) => Vector(
302 a.into_iter()
303 .zip(b.into_iter())
304 .map(|(x, y)| x / y)
305 .collect(),
306 ),
307 (Struct(a), Struct(b)) => {
308 if a.len() != b.len() {
309 return Null;
310 }
311
312 Struct(
313 a.into_iter()
314 .zip(b.into_iter())
315 .map(|(one, two)| {
316 if one.0.name() != two.0.name() {
317 return (one.0, Null);
318 }
319
320 (one.0, one.1 / two.1)
321 })
322 .collect(),
323 )
324 }
325 (lhs, rhs) => bin_numeric_div!(lhs, rhs),
326 }
327 }
328}
329
330impl Rem for AnyValue<'_> {
331 type Output = Self;
332
333 #[inline(always)]
334 fn rem(self, other: Self) -> Self {
335 use AnyValue::*;
336
337 let is_numeric = self.dtype().is_numeric() && other.dtype().is_numeric();
338
339 if !is_numeric {
340 return self;
341 }
342
343 match (self, other) {
344 (Vector(a), Vector(b)) => Vector(
345 a.into_iter()
346 .zip(b.into_iter())
347 .map(|(x, y)| x % y)
348 .collect(),
349 ),
350 (Struct(a), Struct(b)) => {
351 if a.len() != b.len() {
352 return Null;
353 }
354
355 Struct(
356 a.into_iter()
357 .zip(b.into_iter())
358 .map(|(one, two)| {
359 if one.0.name() != two.0.name() {
360 return (one.0, Null);
361 }
362
363 (one.0, one.1 % two.1)
364 })
365 .collect(),
366 )
367 }
368 (lhs, rhs) => bin_numeric_op!(lhs, rhs, %),
369 }
370 }
371}
372
373impl<'a> BitAnd for AnyValue<'a> {
374 type Output = AnyValue<'static>;
375
376 fn bitand(self, rhs: Self) -> Self::Output {
377 match (self, rhs) {
378 (AnyValue::Bool(a), AnyValue::Bool(b)) => AnyValue::Bool(a & b),
379 _ => AnyValue::Null,
380 }
381 }
382}
383
384impl<'a> BitOr for AnyValue<'a> {
385 type Output = AnyValue<'static>;
386
387 fn bitor(self, rhs: Self) -> Self::Output {
388 match (self, rhs) {
389 (AnyValue::Bool(a), AnyValue::Bool(b)) => AnyValue::Bool(a | b),
390 _ => AnyValue::Null,
391 }
392 }
393}
394
395impl<'a> Not for AnyValue<'a> {
396 type Output = AnyValue<'static>;
397
398 fn not(self) -> Self::Output {
399 match self {
400 AnyValue::Bool(v) => AnyValue::Bool(!v),
401 _ => AnyValue::Null,
402 }
403 }
404}
405
406#[inline]
407pub(crate) fn pow_anyvalue(
408 base: &AnyValue<'_>,
409 exp: &AnyValue<'_>,
410) -> Result<AnyValue<'static>, radiate_error::RadiateError> {
411 use AnyValue::*;
412 match (base, exp) {
413 (Int8(a), Int8(b)) => Ok(Int8(a.pow(*b as u32))),
414 (Int16(a), Int8(b)) => Ok(Int16(a.pow(*b as u32))),
415 (Int32(a), Int8(b)) => Ok(Int32(a.pow(*b as u32))),
416 (Int64(a), Int8(b)) => Ok(Int64(a.pow(*b as u32))),
417 (Int128(a), Int8(b)) => Ok(Int128(a.pow(*b as u32))),
418
419 (Int16(a), Int16(b)) => Ok(Int16(a.pow(*b as u32))),
420 (Int32(a), Int16(b)) => Ok(Int32(a.pow(*b as u32))),
421 (Int64(a), Int16(b)) => Ok(Int64(a.pow(*b as u32))),
422 (Int128(a), Int16(b)) => Ok(Int128(a.pow(*b as u32))),
423
424 (Int32(a), Int32(b)) => Ok(Int32(a.pow(*b as u32))),
425 (Int64(a), Int32(b)) => Ok(Int64(a.pow(*b as u32))),
426 (Int128(a), Int32(b)) => Ok(Int128(a.pow(*b as u32))),
427
428 (Int64(a), Int64(b)) => Ok(Int64(a.pow(*b as u32))),
429 (Int128(a), Int64(b)) => Ok(Int128(a.pow(*b as u32))),
430
431 (Int128(a), Int128(b)) => Ok(Int128(a.pow(*b as u32))),
432
433 (UInt8(a), UInt8(b)) => Ok(UInt8(a.pow(*b as u32))),
434 (UInt8(a), UInt16(b)) => Ok(UInt16((u16::from(*a)).pow(u32::from(*b)))),
435 (UInt8(a), UInt32(b)) => Ok(UInt32((u32::from(*a)).pow(u32::from(*b)))),
436
437 (UInt16(a), UInt16(b)) => Ok(UInt16(a.pow(*b as u32))),
438 (UInt16(a), UInt32(b)) => Ok(UInt32((u32::from(*a)).pow(u32::from(*b)))),
439
440 (UInt32(a), UInt32(b)) => Ok(UInt32(a.pow(*b as u32))),
441
442 (UInt64(a), UInt64(b)) => Ok(UInt64(a.pow(*b as u32))),
443
444 (UInt128(a), UInt128(b)) => Ok(UInt128(a.pow(*b as u32))),
445
446 (Float32(a), Float32(b)) => Ok(Float32(a.powf(*b))),
447 (Float32(a), Float64(b)) => Ok(Float64((*a as f64).powf(*b))),
448
449 (Float64(a), Float32(b)) => Ok(Float64(a.powf(*b as f64))),
450 (Float64(a), Float64(b)) => Ok(Float64(a.powf(*b))),
451 _ => {
452 radiate_bail!(Expr: "Exponentiation is only supported for numeric types, got base {:?} and exponent {:?}", base, exp)
453 }
454 }
455}
456
457#[inline]
458#[allow(dead_code)]
459fn mean_anyvalue(one: &AnyValue<'_>, two: &AnyValue<'_>) -> Option<AnyValue<'static>> {
460 use AnyValue::*;
461 if let Some(v) = mean_numeric(one, two) {
462 return Some(v);
463 }
464
465 match (one, two) {
466 (Bool(x), Bool(y)) => Some(Bool(*x && *y)),
467
468 (Vector(xs), Vector(ys)) => super::value::apply_zipped_slice(xs, ys, mean_anyvalue),
469 (Struct(xs), Struct(ys)) => super::value::apply_zipped_struct_slice(xs, ys, mean_anyvalue),
470 _ => None,
471 }
472}
473
474#[inline]
475#[allow(dead_code)]
476fn mean_numeric(a: &AnyValue<'_>, b: &AnyValue<'_>) -> Option<AnyValue<'static>> {
477 use AnyValue::*;
478 let out = match (a, b) {
479 (UInt8(x), UInt8(y)) => UInt8(((u16::from(*x) + u16::from(*y)) / 2) as u8),
480 (UInt16(x), UInt16(y)) => UInt16(((u32::from(*x) + u32::from(*y)) / 2) as u16),
481 (UInt32(x), UInt32(y)) => UInt32(((u64::from(*x) + u64::from(*y)) / 2) as u32),
482 (UInt64(x), UInt64(y)) => UInt64(((u128::from(*x) + u128::from(*y)) / 2) as u64),
483
484 (Int8(x), Int8(y)) => Int8(*x + ((*y as i16 - *x as i16) / 2) as i8),
485 (Int16(x), Int16(y)) => Int16(*x + ((*y as i32 - *x as i32) / 2) as i16),
486 (Int32(x), Int32(y)) => Int32(*x + ((*y as i64 - *x as i64) / 2) as i32),
487 (Int64(x), Int64(y)) => {
488 let dx = (*y as i128) - (*x as i128);
489 Int64(*x + (dx / 2) as i64)
490 }
491 (Int128(x), Int128(y)) => Int128(*x + ((*y - *x) / 2)),
492
493 (Float32(x), Float32(y)) => Float32((*x + *y) / 2.0),
494 (Float64(x), Float64(y)) => Float64((*x + *y) / 2.0),
495
496 _ => return None,
497 };
498
499 Some(out)
500}
501
502#[cfg(test)]
503mod tests {
504 use crate::Field;
505
506 use super::*;
507 use AnyValue::*;
508
509 fn make_vec(xs: Vec<AnyValue<'static>>) -> AnyValue<'static> {
510 AnyValue::Vector(xs)
511 }
512
513 fn make_struct(pairs: Vec<(&'static str, AnyValue<'static>)>) -> AnyValue<'static> {
514 let fields = pairs
515 .into_iter()
516 .map(|(name, val)| (Field::new(name.into(), val.dtype()), val))
517 .collect();
518 AnyValue::Struct(fields)
519 }
520
521 #[test]
523 fn numeric_add_same_type() {
524 assert_eq!(Bool(true) + Bool(false), Bool(true));
525
526 assert_eq!(UInt8(10) + UInt8(5), UInt8(15));
527 assert_eq!(UInt16(10) + UInt16(5), UInt16(15));
528 assert_eq!(UInt32(10) + UInt32(5), UInt32(15));
529 assert_eq!(UInt64(10) + UInt64(5), UInt64(15));
530
531 assert_eq!(Int8(10) + Int8(5), Int8(15));
532 assert_eq!(Int16(10) + Int16(5), Int16(15));
533 assert_eq!(Int32(10) + Int32(5), Int32(15));
534 assert_eq!(Int64(10) + Int64(5), Int64(15));
535 assert_eq!(Int128(10) + Int128(5), Int128(15));
536
537 assert_eq!(Float32(1.5) + Float32(2.0), Float32(3.5));
538 assert_eq!(Float64(1.5) + Float64(2.0), Float64(3.5));
539 }
540
541 #[test]
542 fn numeric_sub_same_type() {
543 assert_eq!(Bool(true) - Bool(false), Bool(true));
544
545 assert_eq!(UInt8(10) - UInt8(3), UInt8(7));
546 assert_eq!(UInt16(10) - UInt16(3), UInt16(7));
547 assert_eq!(UInt32(10) - UInt32(3), UInt32(7));
548 assert_eq!(UInt64(10) - UInt64(3), UInt64(7));
549
550 assert_eq!(Int8(10) - Int8(4), Int8(6));
551 assert_eq!(Int16(10) - Int16(4), Int16(6));
552 assert_eq!(Int32(10) - Int32(4), Int32(6));
553 assert_eq!(Int64(10) - Int64(4), Int64(6));
554 assert_eq!(Int128(10) - Int128(4), Int128(6));
555
556 assert_eq!(Float32(5.0) - Float32(2.5), Float32(2.5));
557 assert_eq!(Float64(5.0) - Float64(2.5), Float64(2.5));
558 }
559
560 #[test]
561 fn numeric_mul_same_type() {
562 assert_eq!(Bool(true) * Bool(false), Bool(true));
563
564 assert_eq!(UInt8(7) * UInt8(6), UInt8(42));
565 assert_eq!(UInt16(7) * UInt16(6), UInt16(42));
566 assert_eq!(UInt32(7) * UInt32(6), UInt32(42));
567 assert_eq!(UInt64(7) * UInt64(6), UInt64(42));
568
569 assert_eq!(Int8(7) * Int8(6), Int8(42));
570 assert_eq!(Int16(7) * Int16(6), Int16(42));
571 assert_eq!(Int32(7) * Int32(6), Int32(42));
572 assert_eq!(Int64(7) * Int64(6), Int64(42));
573 assert_eq!(Int128(7) * Int128(6), Int128(42));
574
575 assert_eq!(Float32(1.5) * Float32(2.0), Float32(3.0));
576 assert_eq!(Float64(1.5) * Float64(2.0), Float64(3.0));
577 }
578
579 #[test]
580 fn numeric_div_same_type() {
581 assert_eq!(Bool(true) / Bool(false), Bool(true));
582
583 assert_eq!(UInt8(42) / UInt8(6), UInt8(7));
584 assert_eq!(UInt16(42) / UInt16(6), UInt16(7));
585 assert_eq!(UInt32(42) / UInt32(6), UInt32(7));
586 assert_eq!(UInt64(42) / UInt64(6), UInt64(7));
587
588 assert_eq!(Int8(42) / Int8(6), Int8(7));
589 assert_eq!(Int16(42) / Int16(6), Int16(7));
590 assert_eq!(Int32(42) / Int32(6), Int32(7));
591 assert_eq!(Int64(42) / Int64(6), Int64(7));
592 assert_eq!(Int128(42) / Int128(6), Int128(7));
593
594 assert_eq!(Float32(7.5) / Float32(2.5), Float32(3.0));
595 assert_eq!(Float64(7.5) / Float64(2.5), Float64(3.0));
596 }
597
598 #[test]
599 fn int_div_by_zero_yields_null() {
600 assert_eq!(Int32(5) / Int32(0), Int32(5));
601 assert_eq!(UInt64(7) / UInt64(0), UInt64(7));
602 }
603
604 #[test]
606 fn vector_elementwise_add_ok() {
607 let a = make_vec(vec![Int32(1), Int32(2), Int32(3)]);
608 let b = make_vec(vec![Int32(4), Int32(5), Int32(6)]);
609 let out = make_vec(vec![Int32(5), Int32(7), Int32(9)]);
610 assert_eq!(a + b, out);
611 }
612
613 #[test]
614 fn vector_length_mismatch() {
615 let a = make_vec(vec![Int32(1), Int32(2)]);
616 let b = make_vec(vec![Int32(3)]);
617 assert_eq!(a + b, Vector(vec![Int32(4)]));
618 }
619
620 #[test]
622 fn struct_same_shape_by_order() {
623 let a = make_struct(vec![("x", Int32(1)), ("y", Int32(2))]);
625 let b = make_struct(vec![("x", Int32(3)), ("y", Int32(4))]);
626 let out = make_struct(vec![("x", Int32(4)), ("y", Int32(6))]);
627 assert_eq!(a + b, out);
628 }
629
630 #[test]
631 fn struct_length_mismatch_yields_null() {
632 let a = make_struct(vec![("x", Int32(1))]);
633 let b = make_struct(vec![("x", Int32(2)), ("y", Int32(3))]);
634 assert_eq!(a + b, Null);
635 }
636
637 #[test]
638 fn struct_field_name_mismatch_sets_field_null_under_current_rules() {
639 let a = make_struct(vec![("x", Int32(1)), ("y", Int32(2))]);
640 let b = make_struct(vec![("x", Int32(3)), ("z", Int32(9))]);
641 let expected = make_struct(vec![("x", Int32(4)), ("y", Null)]);
643 assert_eq!(a + b, expected);
644 }
645
646 #[test]
647 fn struct_align_by_name_regardless_of_order() {
648 let a = make_struct(vec![("x", Int32(1)), ("y", Int32(2))]);
649 let b = make_struct(vec![("y", Int32(4)), ("x", Int32(3))]);
650 let out = make_struct(vec![("x", Null), ("y", Null)]);
651 assert_eq!(a + b, out);
652 }
653
654 #[test]
656 fn null_propagation() {
657 assert_eq!(Null + Int32(5), Null);
658 assert_eq!(Float64(2.0) * Null, Float64(2.0));
659 assert_eq!(Null / Null, Null);
660 }
661
662 #[test]
664 fn mean_numeric_pairs() {
665 assert_eq!(mean_anyvalue(&Int32(2), &Int32(4)), Some(Int32(3)));
666 assert_eq!(mean_anyvalue(&UInt8(10), &UInt8(20)), Some(UInt8(15)));
667 assert_eq!(
668 mean_anyvalue(&Float64(1.0), &Float64(3.0)),
669 Some(Float64(2.0))
670 );
671 }
672
673 #[test]
674 fn mean_bool_is_and() {
675 assert_eq!(mean_anyvalue(&Bool(true), &Bool(false)), Some(Bool(false)));
676 assert_eq!(mean_anyvalue(&Bool(true), &Bool(true)), Some(Bool(true)));
677 }
678
679 #[test]
681 fn add_commutative_for_numeric() {
682 assert_eq!(Int64(7) + Int64(5), Int64(5) + Int64(7));
683 }
684
685 #[test]
686 fn mul_commutative_for_numeric() {
687 assert_eq!(Int16(3) * Int16(9), Int16(9) * Int16(3));
688 }
689
690 #[test]
691 fn sub_non_commutative_for_numeric() {
692 assert_ne!(Int32(10) - Int32(4), Int32(4) - Int32(10));
693 }
694}