proof_of_sql/base/database/
owned_column_operation.rs

1use super::{
2    AddOp, ArithmeticOp, ColumnOperationError, ColumnOperationResult, ComparisonOp, DivOp, EqualOp,
3    GreaterThanOp, LessThanOp, MulOp, SubOp,
4};
5use crate::base::{
6    database::{
7        slice_operation::{slice_and, slice_not, slice_or},
8        OwnedColumn,
9    },
10    scalar::Scalar,
11};
12use alloc::string::ToString;
13
14impl<S: Scalar> OwnedColumn<S> {
15    /// Element-wise NOT operation for a column
16    pub fn element_wise_not(&self) -> ColumnOperationResult<Self> {
17        match self {
18            Self::Boolean(values) => Ok(Self::Boolean(slice_not(values))),
19            _ => Err(ColumnOperationError::UnaryOperationInvalidColumnType {
20                operator: "NOT".to_string(),
21                operand_type: self.column_type(),
22            }),
23        }
24    }
25
26    /// Element-wise AND for two columns
27    pub fn element_wise_and(&self, rhs: &Self) -> ColumnOperationResult<Self> {
28        if self.len() != rhs.len() {
29            return Err(ColumnOperationError::DifferentColumnLength {
30                len_a: self.len(),
31                len_b: rhs.len(),
32            });
33        }
34        match (self, rhs) {
35            (Self::Boolean(lhs), Self::Boolean(rhs)) => Ok(Self::Boolean(slice_and(lhs, rhs))),
36            _ => Err(ColumnOperationError::BinaryOperationInvalidColumnType {
37                operator: "AND".to_string(),
38                left_type: self.column_type(),
39                right_type: rhs.column_type(),
40            }),
41        }
42    }
43
44    /// Element-wise OR for two columns
45    pub fn element_wise_or(&self, rhs: &Self) -> ColumnOperationResult<Self> {
46        if self.len() != rhs.len() {
47            return Err(ColumnOperationError::DifferentColumnLength {
48                len_a: self.len(),
49                len_b: rhs.len(),
50            });
51        }
52        match (self, rhs) {
53            (Self::Boolean(lhs), Self::Boolean(rhs)) => Ok(Self::Boolean(slice_or(lhs, rhs))),
54            _ => Err(ColumnOperationError::BinaryOperationInvalidColumnType {
55                operator: "OR".to_string(),
56                left_type: self.column_type(),
57                right_type: rhs.column_type(),
58            }),
59        }
60    }
61
62    /// Element-wise equality check for two columns
63    pub fn element_wise_eq(&self, rhs: &Self) -> ColumnOperationResult<Self> {
64        EqualOp::owned_column_element_wise_comparison(self, rhs)
65    }
66
67    /// Element-wise less than or equal to check for two columns
68    pub fn element_wise_lt(&self, rhs: &Self) -> ColumnOperationResult<Self> {
69        LessThanOp::owned_column_element_wise_comparison(self, rhs)
70    }
71
72    /// Element-wise greater than or equal to check for two columns
73    pub fn element_wise_gt(&self, rhs: &Self) -> ColumnOperationResult<Self> {
74        GreaterThanOp::owned_column_element_wise_comparison(self, rhs)
75    }
76
77    /// Element-wise addition for two columns
78    pub fn element_wise_add(&self, rhs: &OwnedColumn<S>) -> ColumnOperationResult<OwnedColumn<S>> {
79        AddOp::owned_column_element_wise_arithmetic(self, rhs)
80    }
81
82    /// Element-wise subtraction for two columns
83    pub fn element_wise_sub(&self, rhs: &OwnedColumn<S>) -> ColumnOperationResult<OwnedColumn<S>> {
84        SubOp::owned_column_element_wise_arithmetic(self, rhs)
85    }
86
87    /// Element-wise multiplication for two columns
88    pub fn element_wise_mul(&self, rhs: &OwnedColumn<S>) -> ColumnOperationResult<OwnedColumn<S>> {
89        MulOp::owned_column_element_wise_arithmetic(self, rhs)
90    }
91
92    /// Element-wise division for two columns
93    pub fn element_wise_div(&self, rhs: &OwnedColumn<S>) -> ColumnOperationResult<OwnedColumn<S>> {
94        DivOp::owned_column_element_wise_arithmetic(self, rhs)
95    }
96}
97
98#[cfg(test)]
99mod test {
100    use super::*;
101    use crate::base::{math::decimal::Precision, scalar::test_scalar::TestScalar};
102    use alloc::vec;
103
104    #[test]
105    fn we_cannot_do_binary_operation_on_columns_with_different_lengths() {
106        let lhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]);
107        let rhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false]);
108
109        let result = lhs.element_wise_and(&rhs);
110        assert!(matches!(
111            result,
112            Err(ColumnOperationError::DifferentColumnLength { .. })
113        ));
114
115        let result = lhs.element_wise_eq(&rhs);
116        assert!(matches!(
117            result,
118            Err(ColumnOperationError::DifferentColumnLength { .. })
119        ));
120
121        let result = lhs.element_wise_lt(&rhs);
122        assert!(matches!(
123            result,
124            Err(ColumnOperationError::DifferentColumnLength { .. })
125        ));
126
127        let result = lhs.element_wise_gt(&rhs);
128        assert!(matches!(
129            result,
130            Err(ColumnOperationError::DifferentColumnLength { .. })
131        ));
132
133        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
134        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2]);
135        let result = lhs.element_wise_add(&rhs);
136        assert!(matches!(
137            result,
138            Err(ColumnOperationError::DifferentColumnLength { .. })
139        ));
140
141        let lhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 2, 3]);
142        let rhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 2]);
143        let result = lhs.element_wise_add(&rhs);
144        assert!(matches!(
145            result,
146            Err(ColumnOperationError::DifferentColumnLength { .. })
147        ));
148
149        let result = lhs.element_wise_sub(&rhs);
150        assert!(matches!(
151            result,
152            Err(ColumnOperationError::DifferentColumnLength { .. })
153        ));
154
155        let result = lhs.element_wise_mul(&rhs);
156        assert!(matches!(
157            result,
158            Err(ColumnOperationError::DifferentColumnLength { .. })
159        ));
160
161        let result = lhs.element_wise_div(&rhs);
162        assert!(matches!(
163            result,
164            Err(ColumnOperationError::DifferentColumnLength { .. })
165        ));
166    }
167
168    #[test]
169    fn we_cannot_do_logical_operation_on_nonboolean_columns() {
170        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
171        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
172        let result = lhs.element_wise_and(&rhs);
173        assert!(matches!(
174            result,
175            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
176        ));
177
178        let result = lhs.element_wise_or(&rhs);
179        assert!(matches!(
180            result,
181            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
182        ));
183
184        let result = lhs.element_wise_not();
185        assert!(matches!(
186            result,
187            Err(ColumnOperationError::UnaryOperationInvalidColumnType { .. })
188        ));
189
190        let lhs = OwnedColumn::<TestScalar>::Int(vec![1, 2, 3]);
191        let rhs = OwnedColumn::<TestScalar>::Int(vec![1, 2, 3]);
192        let result = lhs.element_wise_and(&rhs);
193        assert!(matches!(
194            result,
195            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
196        ));
197
198        let result = lhs.element_wise_or(&rhs);
199        assert!(matches!(
200            result,
201            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
202        ));
203
204        let result = lhs.element_wise_not();
205        assert!(matches!(
206            result,
207            Err(ColumnOperationError::UnaryOperationInvalidColumnType { .. })
208        ));
209    }
210
211    #[test]
212    fn we_can_do_logical_operation_on_boolean_columns() {
213        let lhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false, true, false]);
214        let rhs = OwnedColumn::<TestScalar>::Boolean(vec![true, true, false, false]);
215        let result = lhs.element_wise_and(&rhs);
216        assert_eq!(
217            result,
218            Ok(OwnedColumn::<TestScalar>::Boolean(vec![
219                true, false, false, false
220            ]))
221        );
222
223        let result = lhs.element_wise_or(&rhs);
224        assert_eq!(
225            result,
226            Ok(OwnedColumn::<TestScalar>::Boolean(vec![
227                true, true, true, false
228            ]))
229        );
230
231        let result = lhs.element_wise_not();
232        assert_eq!(
233            result,
234            Ok(OwnedColumn::<TestScalar>::Boolean(vec![
235                false, true, false, true
236            ]))
237        );
238    }
239
240    #[test]
241    fn we_can_do_eq_operation() {
242        // Integers
243        let lhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 3, 2]);
244        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
245        let result = lhs.element_wise_eq(&rhs);
246        assert_eq!(
247            result,
248            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, false]))
249        );
250
251        let lhs = OwnedColumn::<TestScalar>::Int(vec![1, 3, 2]);
252        let rhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 2, 3]);
253        let result = lhs.element_wise_eq(&rhs);
254        assert_eq!(
255            result,
256            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, false]))
257        );
258
259        // Strings
260        let lhs = OwnedColumn::<TestScalar>::VarChar(
261            ["Space", "and", "Time"]
262                .iter()
263                .map(ToString::to_string)
264                .collect(),
265        );
266        let rhs = OwnedColumn::<TestScalar>::VarChar(
267            ["Space", "and", "time"]
268                .iter()
269                .map(ToString::to_string)
270                .collect(),
271        );
272        let result = lhs.element_wise_eq(&rhs);
273        assert_eq!(
274            result,
275            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, true, false]))
276        );
277
278        // Booleans
279        let lhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]);
280        let rhs = OwnedColumn::<TestScalar>::Boolean(vec![true, true, false]);
281        let result = lhs.element_wise_eq(&rhs);
282        assert_eq!(
283            result,
284            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, false]))
285        );
286
287        // Decimals
288        let lhs_scalars = [10, 2, 30].iter().map(TestScalar::from).collect();
289        let rhs_scalars = [1, 2, -3].iter().map(TestScalar::from).collect();
290        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 3, lhs_scalars);
291        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
292        let result = lhs.element_wise_eq(&rhs);
293        assert_eq!(
294            result,
295            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, false]))
296        );
297
298        // Decimals and integers
299        let lhs_scalars = [10, 2, 30].iter().map(TestScalar::from).collect();
300        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, -2, 3]);
301        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 1, lhs_scalars);
302        let result = lhs.element_wise_eq(&rhs);
303        assert_eq!(
304            result,
305            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]))
306        );
307
308        let lhs_scalars = [10, 2, 30].iter().map(TestScalar::from).collect();
309        let rhs = OwnedColumn::<TestScalar>::Int(vec![1, -2, 3]);
310        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 1, lhs_scalars);
311        let result = lhs.element_wise_eq(&rhs);
312        assert_eq!(
313            result,
314            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]))
315        );
316    }
317
318    #[test]
319    fn we_can_do_lt_operation_on_numeric_and_boolean_columns() {
320        // Booleans
321        let lhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]);
322        let rhs = OwnedColumn::<TestScalar>::Boolean(vec![true, true, false]);
323        let result = lhs.element_wise_lt(&rhs);
324        assert_eq!(
325            result,
326            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, true, false]))
327        );
328
329        // Integers
330        let lhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 3, 2]);
331        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
332        let result = lhs.element_wise_lt(&rhs);
333        assert_eq!(
334            result,
335            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, false, true]))
336        );
337
338        let lhs = OwnedColumn::<TestScalar>::Int(vec![1, 3, 2]);
339        let rhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 2, 3]);
340        let result = lhs.element_wise_lt(&rhs);
341        assert_eq!(
342            result,
343            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, false, true]))
344        );
345
346        // Decimals
347        let lhs_scalars = [10, 2, 30].iter().map(TestScalar::from).collect();
348        let rhs_scalars = [1, 24, -3].iter().map(TestScalar::from).collect();
349        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 3, lhs_scalars);
350        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
351        let result = lhs.element_wise_lt(&rhs);
352        assert_eq!(
353            result,
354            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, true, false]))
355        );
356
357        // Decimals and integers
358        let lhs_scalars = [10, -2, -30].iter().map(TestScalar::from).collect();
359        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, -20, 3]);
360        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), -1, lhs_scalars);
361        let result = lhs.element_wise_lt(&rhs);
362        assert_eq!(
363            result,
364            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, false, true]))
365        );
366
367        let lhs_scalars = [10, -2, -30].iter().map(TestScalar::from).collect();
368        let rhs = OwnedColumn::<TestScalar>::Int(vec![1, -20, 3]);
369        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), -1, lhs_scalars);
370        let result = lhs.element_wise_lt(&rhs);
371        assert_eq!(
372            result,
373            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, false, true]))
374        );
375    }
376
377    #[test]
378    fn we_can_do_ge_operation_on_numeric_and_boolean_columns() {
379        // Booleans
380        let lhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]);
381        let rhs = OwnedColumn::<TestScalar>::Boolean(vec![true, true, false]);
382        let result = lhs.element_wise_gt(&rhs);
383        assert_eq!(
384            result,
385            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, false, true]))
386        );
387
388        // Integers
389        let lhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 3, 2]);
390        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
391        let result = lhs.element_wise_gt(&rhs);
392        assert_eq!(
393            result,
394            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, true, false]))
395        );
396
397        let lhs = OwnedColumn::<TestScalar>::Int(vec![1, 3, 2]);
398        let rhs = OwnedColumn::<TestScalar>::SmallInt(vec![1, 2, 3]);
399        let result = lhs.element_wise_gt(&rhs);
400        assert_eq!(
401            result,
402            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, true, false]))
403        );
404
405        // Decimals
406        let lhs_scalars = [10, 2, 30].iter().map(TestScalar::from).collect();
407        let rhs_scalars = [1, 24, -3].iter().map(TestScalar::from).collect();
408        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 3, lhs_scalars);
409        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
410        let result = lhs.element_wise_gt(&rhs);
411        assert_eq!(
412            result,
413            Ok(OwnedColumn::<TestScalar>::Boolean(vec![false, false, true]))
414        );
415
416        // Decimals and integers
417        let lhs_scalars = [10, -2, -30].iter().map(TestScalar::from).collect();
418        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1_i8, -20, 3]);
419        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), -1, lhs_scalars);
420        let result = lhs.element_wise_gt(&rhs);
421        assert_eq!(
422            result,
423            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, false]))
424        );
425
426        let lhs_scalars = [10, -2, -30].iter().map(TestScalar::from).collect();
427        let rhs = OwnedColumn::<TestScalar>::BigInt(vec![1_i64, -20, 3]);
428        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), -1, lhs_scalars);
429        let result = lhs.element_wise_gt(&rhs);
430        assert_eq!(
431            result,
432            Ok(OwnedColumn::<TestScalar>::Boolean(vec![true, false, false]))
433        );
434    }
435
436    #[test]
437    fn we_cannot_do_comparison_on_columns_with_incompatible_types() {
438        // Strings can't be compared with other types
439        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
440        let rhs = OwnedColumn::<TestScalar>::VarChar(
441            ["Space", "and", "Time"]
442                .iter()
443                .map(ToString::to_string)
444                .collect(),
445        );
446        let result = lhs.element_wise_lt(&rhs);
447        assert!(matches!(
448            result,
449            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
450        ));
451
452        let lhs = OwnedColumn::<TestScalar>::Int(vec![1, 2, 3]);
453        let rhs = OwnedColumn::<TestScalar>::VarChar(
454            ["Space", "and", "Time"]
455                .iter()
456                .map(ToString::to_string)
457                .collect(),
458        );
459        let result = lhs.element_wise_lt(&rhs);
460        assert!(matches!(
461            result,
462            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
463        ));
464
465        let result = lhs.element_wise_gt(&rhs);
466        assert!(matches!(
467            result,
468            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
469        ));
470
471        let result = lhs.element_wise_lt(&rhs);
472        assert!(matches!(
473            result,
474            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
475        ));
476
477        // Booleans can't be compared with other types
478        let lhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]);
479        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
480        let result = lhs.element_wise_lt(&rhs);
481        assert!(matches!(
482            result,
483            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
484        ));
485
486        let lhs = OwnedColumn::<TestScalar>::Boolean(vec![true, false, true]);
487        let rhs = OwnedColumn::<TestScalar>::Int(vec![1, 2, 3]);
488        let result = lhs.element_wise_lt(&rhs);
489        assert!(matches!(
490            result,
491            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
492        ));
493
494        // Strings can not be <= or >= to each other
495        let lhs = OwnedColumn::<TestScalar>::VarChar(
496            ["Space", "and", "Time"]
497                .iter()
498                .map(ToString::to_string)
499                .collect(),
500        );
501        let rhs = OwnedColumn::<TestScalar>::VarChar(
502            ["Space", "and", "time"]
503                .iter()
504                .map(ToString::to_string)
505                .collect(),
506        );
507        let result = lhs.element_wise_lt(&rhs);
508        assert!(matches!(
509            result,
510            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
511        ));
512
513        let result = lhs.element_wise_gt(&rhs);
514        assert!(matches!(
515            result,
516            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
517        ));
518    }
519
520    #[test]
521    fn we_cannot_do_arithmetic_on_nonnumeric_columns() {
522        let lhs = OwnedColumn::<TestScalar>::VarChar(
523            ["Space", "and", "Time"]
524                .iter()
525                .map(ToString::to_string)
526                .collect(),
527        );
528        let rhs = OwnedColumn::<TestScalar>::Scalar(vec![
529            TestScalar::from(1),
530            TestScalar::from(2),
531            TestScalar::from(3),
532        ]);
533        let result = lhs.element_wise_add(&rhs);
534        assert!(matches!(
535            result,
536            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
537        ));
538
539        let result = lhs.element_wise_sub(&rhs);
540        assert!(matches!(
541            result,
542            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
543        ));
544
545        let result = lhs.element_wise_mul(&rhs);
546        assert!(matches!(
547            result,
548            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
549        ));
550
551        let result = lhs.element_wise_div(&rhs);
552        assert!(matches!(
553            result,
554            Err(ColumnOperationError::BinaryOperationInvalidColumnType { .. })
555        ));
556    }
557
558    #[test]
559    fn we_can_add_integer_columns() {
560        // lhs and rhs have the same precision
561        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![1_i8, 2, 3]);
562        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1_i8, 2, 3]);
563        let result = lhs.element_wise_add(&rhs).unwrap();
564        assert_eq!(result, OwnedColumn::<TestScalar>::TinyInt(vec![2_i8, 4, 6]));
565
566        let lhs = OwnedColumn::<TestScalar>::SmallInt(vec![1_i16, 2, 3]);
567        let rhs = OwnedColumn::<TestScalar>::SmallInt(vec![1_i16, 2, 3]);
568        let result = lhs.element_wise_add(&rhs).unwrap();
569        assert_eq!(
570            result,
571            OwnedColumn::<TestScalar>::SmallInt(vec![2_i16, 4, 6])
572        );
573
574        // lhs and rhs have different precisions
575        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![1_i8, 2, 3]);
576        let rhs = OwnedColumn::<TestScalar>::Int(vec![1_i32, 2, 3]);
577        let result = lhs.element_wise_add(&rhs).unwrap();
578        assert_eq!(result, OwnedColumn::<TestScalar>::Int(vec![2_i32, 4, 6]));
579
580        let lhs = OwnedColumn::<TestScalar>::Int128(vec![1_i128, 2, 3]);
581        let rhs = OwnedColumn::<TestScalar>::Int(vec![1_i32, 2, 3]);
582        let result = lhs.element_wise_add(&rhs).unwrap();
583        assert_eq!(
584            result,
585            OwnedColumn::<TestScalar>::Int128(vec![2_i128, 4, 6])
586        );
587    }
588
589    #[test]
590    fn we_can_add_decimal_columns() {
591        // lhs and rhs have the same precision and scale
592        let lhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
593        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
594        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, lhs_scalars);
595        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
596        let result = lhs.element_wise_add(&rhs).unwrap();
597        let expected_scalars = [2, 4, 6].iter().map(TestScalar::from).collect();
598        assert_eq!(
599            result,
600            OwnedColumn::<TestScalar>::Decimal75(Precision::new(6).unwrap(), 2, expected_scalars)
601        );
602
603        // lhs and rhs have different precisions and scales
604        let lhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
605        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
606        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, lhs_scalars);
607        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(51).unwrap(), 3, rhs_scalars);
608        let result = lhs.element_wise_add(&rhs).unwrap();
609        let expected_scalars = [11, 22, 33].iter().map(TestScalar::from).collect();
610        assert_eq!(
611            result,
612            OwnedColumn::<TestScalar>::Decimal75(Precision::new(52).unwrap(), 3, expected_scalars)
613        );
614
615        // lhs is integer and rhs is decimal
616        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![1, 2, 3]);
617        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
618        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
619        let result = lhs.element_wise_add(&rhs).unwrap();
620        let expected_scalars = [101, 202, 303].iter().map(TestScalar::from).collect();
621        assert_eq!(
622            result,
623            OwnedColumn::<TestScalar>::Decimal75(Precision::new(6).unwrap(), 2, expected_scalars)
624        );
625
626        let lhs = OwnedColumn::<TestScalar>::Int(vec![1, 2, 3]);
627        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
628        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
629        let result = lhs.element_wise_add(&rhs).unwrap();
630        let expected_scalars = [101, 202, 303].iter().map(TestScalar::from).collect();
631        assert_eq!(
632            result,
633            OwnedColumn::<TestScalar>::Decimal75(Precision::new(13).unwrap(), 2, expected_scalars)
634        );
635    }
636
637    #[test]
638    fn we_can_subtract_integer_columns() {
639        // lhs and rhs have the same precision
640        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![4_i8, 5, 2]);
641        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1_i8, 2, 3]);
642        let result = lhs.element_wise_sub(&rhs).unwrap();
643        assert_eq!(
644            result,
645            OwnedColumn::<TestScalar>::TinyInt(vec![3_i8, 3, -1])
646        );
647
648        let lhs = OwnedColumn::<TestScalar>::Int(vec![4_i32, 5, 2]);
649        let rhs = OwnedColumn::<TestScalar>::Int(vec![1_i32, 2, 3]);
650        let result = lhs.element_wise_sub(&rhs).unwrap();
651        assert_eq!(result, OwnedColumn::<TestScalar>::Int(vec![3_i32, 3, -1]));
652
653        // lhs and rhs have different precisions
654        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![4_i8, 5, 2]);
655        let rhs = OwnedColumn::<TestScalar>::BigInt(vec![1_i64, 2, 5]);
656        let result = lhs.element_wise_sub(&rhs).unwrap();
657        assert_eq!(
658            result,
659            OwnedColumn::<TestScalar>::BigInt(vec![3_i64, 3, -3])
660        );
661
662        let lhs = OwnedColumn::<TestScalar>::Int(vec![3_i32, 2, 3]);
663        let rhs = OwnedColumn::<TestScalar>::BigInt(vec![1_i64, 2, 5]);
664        let result = lhs.element_wise_sub(&rhs).unwrap();
665        assert_eq!(
666            result,
667            OwnedColumn::<TestScalar>::BigInt(vec![2_i64, 0, -2])
668        );
669    }
670
671    #[test]
672    fn we_can_subtract_decimal_columns() {
673        // lhs and rhs have the same precision and scale
674        let lhs_scalars = [4, 5, 2].iter().map(TestScalar::from).collect();
675        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
676        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, lhs_scalars);
677        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
678        let result = lhs.element_wise_sub(&rhs).unwrap();
679        let expected_scalars = [3, 3, -1].iter().map(TestScalar::from).collect();
680        assert_eq!(
681            result,
682            OwnedColumn::<TestScalar>::Decimal75(Precision::new(6).unwrap(), 2, expected_scalars)
683        );
684
685        // lhs and rhs have different precisions and scales
686        let lhs_scalars = [4, 5, 2].iter().map(TestScalar::from).collect();
687        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
688        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(25).unwrap(), 2, lhs_scalars);
689        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(51).unwrap(), 3, rhs_scalars);
690        let result = lhs.element_wise_sub(&rhs).unwrap();
691        let expected_scalars = [39, 48, 17].iter().map(TestScalar::from).collect();
692        assert_eq!(
693            result,
694            OwnedColumn::<TestScalar>::Decimal75(Precision::new(52).unwrap(), 3, expected_scalars)
695        );
696
697        // lhs is integer and rhs is decimal
698        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![4, 5, 2]);
699        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
700        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
701        let result = lhs.element_wise_sub(&rhs).unwrap();
702        let expected_scalars = [399, 498, 197].iter().map(TestScalar::from).collect();
703        assert_eq!(
704            result,
705            OwnedColumn::<TestScalar>::Decimal75(Precision::new(6).unwrap(), 2, expected_scalars)
706        );
707
708        let lhs = OwnedColumn::<TestScalar>::Int(vec![4, 5, 2]);
709        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
710        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
711        let result = lhs.element_wise_sub(&rhs).unwrap();
712        let expected_scalars = [399, 498, 197].iter().map(TestScalar::from).collect();
713        assert_eq!(
714            result,
715            OwnedColumn::<TestScalar>::Decimal75(Precision::new(13).unwrap(), 2, expected_scalars)
716        );
717    }
718
719    #[test]
720    fn we_can_multiply_integer_columns() {
721        // lhs and rhs have the same precision
722        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![4_i8, 5, -2]);
723        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1_i8, 2, 3]);
724        let result = lhs.element_wise_mul(&rhs).unwrap();
725        assert_eq!(
726            result,
727            OwnedColumn::<TestScalar>::TinyInt(vec![4_i8, 10, -6])
728        );
729
730        let lhs = OwnedColumn::<TestScalar>::BigInt(vec![4_i64, 5, -2]);
731        let rhs = OwnedColumn::<TestScalar>::BigInt(vec![1_i64, 2, 3]);
732        let result = lhs.element_wise_mul(&rhs).unwrap();
733        assert_eq!(
734            result,
735            OwnedColumn::<TestScalar>::BigInt(vec![4_i64, 10, -6])
736        );
737
738        // lhs and rhs have different precisions
739        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![3_i8, 2, 3]);
740        let rhs = OwnedColumn::<TestScalar>::Int128(vec![1_i128, 2, 5]);
741        let result = lhs.element_wise_mul(&rhs).unwrap();
742        assert_eq!(
743            result,
744            OwnedColumn::<TestScalar>::Int128(vec![3_i128, 4, 15])
745        );
746
747        let lhs = OwnedColumn::<TestScalar>::Int(vec![3_i32, 2, 3]);
748        let rhs = OwnedColumn::<TestScalar>::Int128(vec![1_i128, 2, 5]);
749        let result = lhs.element_wise_mul(&rhs).unwrap();
750        assert_eq!(
751            result,
752            OwnedColumn::<TestScalar>::Int128(vec![3_i128, 4, 15])
753        );
754    }
755
756    #[test]
757    fn we_can_multiply_decimal_columns() {
758        // lhs and rhs are both decimals
759        let lhs_scalars = [4, 5, 2].iter().map(TestScalar::from).collect();
760        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, lhs_scalars);
761        let rhs_scalars = [-1, 2, 3].iter().map(TestScalar::from).collect();
762        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
763        let result = lhs.element_wise_mul(&rhs).unwrap();
764        let expected_scalars = [-4, 10, 6].iter().map(TestScalar::from).collect();
765        assert_eq!(
766            result,
767            OwnedColumn::<TestScalar>::Decimal75(Precision::new(11).unwrap(), 4, expected_scalars)
768        );
769
770        // lhs is integer and rhs is decimal
771        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![4, 5, 2]);
772        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
773        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
774        let result = lhs.element_wise_mul(&rhs).unwrap();
775        let expected_scalars = [4, 10, 6].iter().map(TestScalar::from).collect();
776        assert_eq!(
777            result,
778            OwnedColumn::<TestScalar>::Decimal75(Precision::new(9).unwrap(), 2, expected_scalars)
779        );
780
781        let lhs = OwnedColumn::<TestScalar>::Int(vec![4, 5, 2]);
782        let rhs_scalars = [1, 2, 3].iter().map(TestScalar::from).collect();
783        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
784        let result = lhs.element_wise_mul(&rhs).unwrap();
785        let expected_scalars = [4, 10, 6].iter().map(TestScalar::from).collect();
786        assert_eq!(
787            result,
788            OwnedColumn::<TestScalar>::Decimal75(Precision::new(16).unwrap(), 2, expected_scalars)
789        );
790    }
791
792    #[test]
793    fn we_can_divide_integer_columns() {
794        // lhs and rhs have the same precision
795        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![4_i8, 5, -2]);
796        let rhs = OwnedColumn::<TestScalar>::TinyInt(vec![1_i8, 2, 3]);
797        let result = lhs.element_wise_div(&rhs).unwrap();
798        assert_eq!(result, OwnedColumn::<TestScalar>::TinyInt(vec![4_i8, 2, 0]));
799
800        let lhs = OwnedColumn::<TestScalar>::BigInt(vec![4_i64, 5, -2]);
801        let rhs = OwnedColumn::<TestScalar>::BigInt(vec![1_i64, 2, 3]);
802        let result = lhs.element_wise_div(&rhs).unwrap();
803        assert_eq!(result, OwnedColumn::<TestScalar>::BigInt(vec![4_i64, 2, 0]));
804
805        // lhs and rhs have different precisions
806        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![3_i8, 2, 3]);
807        let rhs = OwnedColumn::<TestScalar>::Int128(vec![1_i128, 2, 5]);
808        let result = lhs.element_wise_div(&rhs).unwrap();
809        assert_eq!(
810            result,
811            OwnedColumn::<TestScalar>::Int128(vec![3_i128, 1, 0])
812        );
813
814        let lhs = OwnedColumn::<TestScalar>::Int(vec![3_i32, 2, 3]);
815        let rhs = OwnedColumn::<TestScalar>::Int128(vec![1_i128, 2, 5]);
816        let result = lhs.element_wise_div(&rhs).unwrap();
817        assert_eq!(
818            result,
819            OwnedColumn::<TestScalar>::Int128(vec![3_i128, 1, 0])
820        );
821    }
822
823    #[test]
824    fn we_can_try_divide_decimal_columns() {
825        // lhs and rhs are both decimals
826        let lhs_scalars = [4, 5, 3].iter().map(TestScalar::from).collect();
827        let lhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, lhs_scalars);
828        let rhs_scalars = [-1, 2, 4].iter().map(TestScalar::from).collect();
829        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(5).unwrap(), 2, rhs_scalars);
830        let result = lhs.element_wise_div(&rhs).unwrap();
831        let expected_scalars = [-400_000_000_i128, 250_000_000, 75_000_000]
832            .iter()
833            .map(TestScalar::from)
834            .collect();
835        assert_eq!(
836            result,
837            OwnedColumn::<TestScalar>::Decimal75(Precision::new(13).unwrap(), 8, expected_scalars)
838        );
839
840        // lhs is integer and rhs is decimal
841        let lhs = OwnedColumn::<TestScalar>::TinyInt(vec![4, 5, 3]);
842        let rhs_scalars = [-1, 2, 3].iter().map(TestScalar::from).collect();
843        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(3).unwrap(), 2, rhs_scalars);
844        let result = lhs.element_wise_div(&rhs).unwrap();
845        let expected_scalars = [-400_000_000, 250_000_000, 100_000_000]
846            .iter()
847            .map(TestScalar::from)
848            .collect();
849        assert_eq!(
850            result,
851            OwnedColumn::<TestScalar>::Decimal75(Precision::new(11).unwrap(), 6, expected_scalars)
852        );
853
854        let lhs = OwnedColumn::<TestScalar>::SmallInt(vec![4, 5, 3]);
855        let rhs_scalars = [-1, 2, 3].iter().map(TestScalar::from).collect();
856        let rhs = OwnedColumn::<TestScalar>::Decimal75(Precision::new(3).unwrap(), 2, rhs_scalars);
857        let result = lhs.element_wise_div(&rhs).unwrap();
858        let expected_scalars = [-400_000_000, 250_000_000, 100_000_000]
859            .iter()
860            .map(TestScalar::from)
861            .collect();
862        assert_eq!(
863            result,
864            OwnedColumn::<TestScalar>::Decimal75(Precision::new(13).unwrap(), 6, expected_scalars)
865        );
866    }
867}