reifydb_engine/function/math/scalar/
power.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use reifydb_core::value::column::ColumnData;
5
6use crate::function::{ScalarFunction, ScalarFunctionContext};
7
8pub struct Power;
9
10impl Power {
11	pub fn new() -> Self {
12		Self {}
13	}
14}
15
16impl ScalarFunction for Power {
17	fn scalar(&self, ctx: ScalarFunctionContext) -> crate::Result<ColumnData> {
18		let columns = ctx.columns;
19		let row_count = ctx.row_count;
20
21		if columns.len() < 2 {
22			return Ok(ColumnData::int4(Vec::<i32>::new()));
23		}
24
25		let base_column = columns.get(0).unwrap();
26		let exponent_column = columns.get(1).unwrap();
27
28		match (base_column.data(), exponent_column.data()) {
29			(ColumnData::Int1(base_container), ColumnData::Int1(exp_container)) => {
30				let mut result = Vec::with_capacity(row_count);
31
32				for row_idx in 0..row_count {
33					let base = base_container.get(row_idx);
34					let exp = exp_container.get(row_idx);
35
36					let power_result = match (base, exp) {
37						(Some(&base_val), Some(&exp_val)) => {
38							if exp_val < 0 {
39								0 // Integer power with negative exponent results in 0
40							} else {
41								(base_val as i32).pow(exp_val as u32)
42							}
43						}
44						_ => 0, // If either value is undefined, result is 0
45					};
46
47					result.push(power_result);
48				}
49
50				Ok(ColumnData::int4(result))
51			}
52			(ColumnData::Int2(base_container), ColumnData::Int2(exp_container)) => {
53				let mut result = Vec::with_capacity(row_count);
54
55				for row_idx in 0..row_count {
56					let base = base_container.get(row_idx);
57					let exp = exp_container.get(row_idx);
58
59					let power_result = match (base, exp) {
60						(Some(&base_val), Some(&exp_val)) => {
61							if exp_val < 0 {
62								0 // Integer power with negative exponent results in 0
63							} else {
64								(base_val as i32).pow(exp_val as u32)
65							}
66						}
67						_ => 0, // If either value is undefined, result is 0
68					};
69
70					result.push(power_result);
71				}
72
73				Ok(ColumnData::int4(result))
74			}
75			(ColumnData::Int4(base_container), ColumnData::Int4(exp_container)) => {
76				let mut result = Vec::with_capacity(row_count);
77
78				for row_idx in 0..row_count {
79					let base = base_container.get(row_idx);
80					let exp = exp_container.get(row_idx);
81
82					let power_result = match (base, exp) {
83						(Some(&base_val), Some(&exp_val)) => {
84							if exp_val < 0 {
85								0 // Integer power with negative exponent results in 0
86							} else {
87								base_val.saturating_pow(exp_val as u32)
88							}
89						}
90						_ => 0, // If either value is undefined, result is 0
91					};
92
93					result.push(power_result);
94				}
95
96				Ok(ColumnData::int4(result))
97			}
98			(ColumnData::Int8(base_container), ColumnData::Int8(exp_container)) => {
99				let mut result = Vec::with_capacity(row_count);
100
101				for row_idx in 0..row_count {
102					let base = base_container.get(row_idx);
103					let exp = exp_container.get(row_idx);
104
105					let power_result = match (base, exp) {
106						(Some(&base_val), Some(&exp_val)) => {
107							if exp_val < 0 {
108								0 // Integer power with negative exponent results in 0
109							} else {
110								base_val.saturating_pow(exp_val as u32)
111							}
112						}
113						_ => 0, // If either value is undefined, result is 0
114					};
115
116					result.push(power_result);
117				}
118
119				Ok(ColumnData::int8(result))
120			}
121			_ => unimplemented!("Power function currently supports matching integer types only"),
122		}
123	}
124}