Skip to main content

reifydb_routine/function/math/
power.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use num_traits::ToPrimitive;
5use reifydb_core::value::column::{Column, columns::Columns, data::ColumnData};
6use reifydb_type::{
7	fragment::Fragment,
8	value::{
9		container::number::NumberContainer,
10		decimal::Decimal,
11		int::Int,
12		r#type::{Type, input_types::InputTypes},
13		uint::Uint,
14	},
15};
16
17use crate::function::{Function, FunctionCapability, FunctionContext, FunctionInfo, error::FunctionError};
18
19pub struct Power {
20	info: FunctionInfo,
21}
22
23impl Default for Power {
24	fn default() -> Self {
25		Self::new()
26	}
27}
28
29impl Power {
30	pub fn new() -> Self {
31		Self {
32			info: FunctionInfo::new("math::power"),
33		}
34	}
35}
36
37fn convert_column_to_type(data: &ColumnData, target: Type, row_count: usize) -> ColumnData {
38	match target {
39		Type::Int1 => {
40			let mut result = Vec::with_capacity(row_count);
41			let mut bitvec = Vec::with_capacity(row_count);
42			for i in 0..row_count {
43				if data.is_defined(i) {
44					result.push(get_as_i8(data, i));
45					bitvec.push(true);
46				} else {
47					result.push(0);
48					bitvec.push(false);
49				}
50			}
51			ColumnData::int1_with_bitvec(result, bitvec)
52		}
53		Type::Int2 => {
54			let mut result = Vec::with_capacity(row_count);
55			let mut bitvec = Vec::with_capacity(row_count);
56			for i in 0..row_count {
57				if data.is_defined(i) {
58					result.push(get_as_i16(data, i));
59					bitvec.push(true);
60				} else {
61					result.push(0);
62					bitvec.push(false);
63				}
64			}
65			ColumnData::int2_with_bitvec(result, bitvec)
66		}
67		Type::Int4 => {
68			let mut result = Vec::with_capacity(row_count);
69			let mut bitvec = Vec::with_capacity(row_count);
70			for i in 0..row_count {
71				if data.is_defined(i) {
72					result.push(get_as_i32(data, i));
73					bitvec.push(true);
74				} else {
75					result.push(0);
76					bitvec.push(false);
77				}
78			}
79			ColumnData::int4_with_bitvec(result, bitvec)
80		}
81		Type::Int8 => {
82			let mut result = Vec::with_capacity(row_count);
83			let mut bitvec = Vec::with_capacity(row_count);
84			for i in 0..row_count {
85				if data.is_defined(i) {
86					result.push(get_as_i64(data, i));
87					bitvec.push(true);
88				} else {
89					result.push(0);
90					bitvec.push(false);
91				}
92			}
93			ColumnData::int8_with_bitvec(result, bitvec)
94		}
95		Type::Int16 => {
96			let mut result = Vec::with_capacity(row_count);
97			let mut bitvec = Vec::with_capacity(row_count);
98			for i in 0..row_count {
99				if data.is_defined(i) {
100					result.push(get_as_i128(data, i));
101					bitvec.push(true);
102				} else {
103					result.push(0);
104					bitvec.push(false);
105				}
106			}
107			ColumnData::int16_with_bitvec(result, bitvec)
108		}
109		Type::Uint1 => {
110			let mut result = Vec::with_capacity(row_count);
111			let mut bitvec = Vec::with_capacity(row_count);
112			for i in 0..row_count {
113				if data.is_defined(i) {
114					result.push(get_as_u8(data, i));
115					bitvec.push(true);
116				} else {
117					result.push(0);
118					bitvec.push(false);
119				}
120			}
121			ColumnData::uint1_with_bitvec(result, bitvec)
122		}
123		Type::Uint2 => {
124			let mut result = Vec::with_capacity(row_count);
125			let mut bitvec = Vec::with_capacity(row_count);
126			for i in 0..row_count {
127				if data.is_defined(i) {
128					result.push(get_as_u16(data, i));
129					bitvec.push(true);
130				} else {
131					result.push(0);
132					bitvec.push(false);
133				}
134			}
135			ColumnData::uint2_with_bitvec(result, bitvec)
136		}
137		Type::Uint4 => {
138			let mut result = Vec::with_capacity(row_count);
139			let mut bitvec = Vec::with_capacity(row_count);
140			for i in 0..row_count {
141				if data.is_defined(i) {
142					result.push(get_as_u32(data, i));
143					bitvec.push(true);
144				} else {
145					result.push(0);
146					bitvec.push(false);
147				}
148			}
149			ColumnData::uint4_with_bitvec(result, bitvec)
150		}
151		Type::Uint8 => {
152			let mut result = Vec::with_capacity(row_count);
153			let mut bitvec = Vec::with_capacity(row_count);
154			for i in 0..row_count {
155				if data.is_defined(i) {
156					result.push(get_as_u64(data, i));
157					bitvec.push(true);
158				} else {
159					result.push(0);
160					bitvec.push(false);
161				}
162			}
163			ColumnData::uint8_with_bitvec(result, bitvec)
164		}
165		Type::Uint16 => {
166			let mut result = Vec::with_capacity(row_count);
167			let mut bitvec = Vec::with_capacity(row_count);
168			for i in 0..row_count {
169				if data.is_defined(i) {
170					result.push(get_as_u128(data, i));
171					bitvec.push(true);
172				} else {
173					result.push(0);
174					bitvec.push(false);
175				}
176			}
177			ColumnData::uint16_with_bitvec(result, bitvec)
178		}
179		Type::Float4 => {
180			let mut result = Vec::with_capacity(row_count);
181			let mut bitvec = Vec::with_capacity(row_count);
182			for i in 0..row_count {
183				if data.is_defined(i) {
184					result.push(get_as_f32(data, i));
185					bitvec.push(true);
186				} else {
187					result.push(0.0);
188					bitvec.push(false);
189				}
190			}
191			ColumnData::float4_with_bitvec(result, bitvec)
192		}
193		Type::Float8 => {
194			let mut result = Vec::with_capacity(row_count);
195			let mut bitvec = Vec::with_capacity(row_count);
196			for i in 0..row_count {
197				if data.is_defined(i) {
198					result.push(get_as_f64(data, i));
199					bitvec.push(true);
200				} else {
201					result.push(0.0);
202					bitvec.push(false);
203				}
204			}
205			ColumnData::float8_with_bitvec(result, bitvec)
206		}
207		Type::Int => {
208			let mut result = Vec::with_capacity(row_count);
209			let mut bitvec = Vec::with_capacity(row_count);
210			for i in 0..row_count {
211				if data.is_defined(i) {
212					result.push(Int::from(get_as_i128(data, i)));
213					bitvec.push(true);
214				} else {
215					result.push(Int::default());
216					bitvec.push(false);
217				}
218			}
219			ColumnData::int_with_bitvec(result, bitvec)
220		}
221		Type::Uint => {
222			let mut result = Vec::with_capacity(row_count);
223			let mut bitvec = Vec::with_capacity(row_count);
224			for i in 0..row_count {
225				if data.is_defined(i) {
226					result.push(Uint::from(get_as_u128(data, i)));
227					bitvec.push(true);
228				} else {
229					result.push(Uint::default());
230					bitvec.push(false);
231				}
232			}
233			ColumnData::uint_with_bitvec(result, bitvec)
234		}
235		Type::Decimal => {
236			let mut result = Vec::with_capacity(row_count);
237			let mut bitvec = Vec::with_capacity(row_count);
238			for i in 0..row_count {
239				if data.is_defined(i) {
240					result.push(Decimal::from(get_as_f64(data, i)));
241					bitvec.push(true);
242				} else {
243					result.push(Decimal::default());
244					bitvec.push(false);
245				}
246			}
247			ColumnData::decimal_with_bitvec(result, bitvec)
248		}
249		_ => data.clone(),
250	}
251}
252
253fn get_as_i8(data: &ColumnData, i: usize) -> i8 {
254	match data {
255		ColumnData::Int1(c) => c.get(i).copied().unwrap_or(0),
256		ColumnData::Uint1(c) => c.get(i).map(|&v| v as i8).unwrap_or(0),
257		_ => 0,
258	}
259}
260
261fn get_as_u8(data: &ColumnData, i: usize) -> u8 {
262	match data {
263		ColumnData::Uint1(c) => c.get(i).copied().unwrap_or(0),
264		ColumnData::Int1(c) => c.get(i).map(|&v| v as u8).unwrap_or(0),
265		_ => 0,
266	}
267}
268
269fn get_as_i16(data: &ColumnData, i: usize) -> i16 {
270	match data {
271		ColumnData::Int1(c) => c.get(i).map(|&v| v as i16).unwrap_or(0),
272		ColumnData::Int2(c) => c.get(i).copied().unwrap_or(0),
273		ColumnData::Uint1(c) => c.get(i).map(|&v| v as i16).unwrap_or(0),
274		_ => 0,
275	}
276}
277
278fn get_as_i32(data: &ColumnData, i: usize) -> i32 {
279	match data {
280		ColumnData::Int1(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
281		ColumnData::Int2(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
282		ColumnData::Int4(c) => c.get(i).copied().unwrap_or(0),
283		ColumnData::Uint1(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
284		ColumnData::Uint2(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
285		_ => 0,
286	}
287}
288
289fn get_as_i64(data: &ColumnData, i: usize) -> i64 {
290	match data {
291		ColumnData::Int1(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
292		ColumnData::Int2(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
293		ColumnData::Int4(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
294		ColumnData::Int8(c) => c.get(i).copied().unwrap_or(0),
295		ColumnData::Uint1(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
296		ColumnData::Uint2(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
297		ColumnData::Uint4(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
298		_ => 0,
299	}
300}
301
302fn get_as_i128(data: &ColumnData, i: usize) -> i128 {
303	match data {
304		ColumnData::Int1(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
305		ColumnData::Int2(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
306		ColumnData::Int4(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
307		ColumnData::Int8(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
308		ColumnData::Int16(c) => c.get(i).copied().unwrap_or(0),
309		ColumnData::Uint1(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
310		ColumnData::Uint2(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
311		ColumnData::Uint4(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
312		ColumnData::Uint8(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
313		_ => 0,
314	}
315}
316
317fn get_as_u16(data: &ColumnData, i: usize) -> u16 {
318	match data {
319		ColumnData::Uint1(c) => c.get(i).map(|&v| v as u16).unwrap_or(0),
320		ColumnData::Uint2(c) => c.get(i).copied().unwrap_or(0),
321		_ => 0,
322	}
323}
324
325fn get_as_u32(data: &ColumnData, i: usize) -> u32 {
326	match data {
327		ColumnData::Uint1(c) => c.get(i).map(|&v| v as u32).unwrap_or(0),
328		ColumnData::Uint2(c) => c.get(i).map(|&v| v as u32).unwrap_or(0),
329		ColumnData::Uint4(c) => c.get(i).copied().unwrap_or(0),
330		_ => 0,
331	}
332}
333
334fn get_as_u64(data: &ColumnData, i: usize) -> u64 {
335	match data {
336		ColumnData::Uint1(c) => c.get(i).map(|&v| v as u64).unwrap_or(0),
337		ColumnData::Uint2(c) => c.get(i).map(|&v| v as u64).unwrap_or(0),
338		ColumnData::Uint4(c) => c.get(i).map(|&v| v as u64).unwrap_or(0),
339		ColumnData::Uint8(c) => c.get(i).copied().unwrap_or(0),
340		_ => 0,
341	}
342}
343
344fn get_as_u128(data: &ColumnData, i: usize) -> u128 {
345	match data {
346		ColumnData::Uint1(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
347		ColumnData::Uint2(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
348		ColumnData::Uint4(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
349		ColumnData::Uint8(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
350		ColumnData::Uint16(c) => c.get(i).copied().unwrap_or(0),
351		_ => 0,
352	}
353}
354
355fn get_as_f32(data: &ColumnData, i: usize) -> f32 {
356	match data {
357		ColumnData::Int1(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
358		ColumnData::Int2(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
359		ColumnData::Int4(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
360		ColumnData::Int8(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
361		ColumnData::Int16(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
362		ColumnData::Uint1(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
363		ColumnData::Uint2(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
364		ColumnData::Uint4(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
365		ColumnData::Uint8(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
366		ColumnData::Uint16(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
367		ColumnData::Float4(c) => c.get(i).copied().unwrap_or(0.0),
368		ColumnData::Float8(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
369		ColumnData::Int {
370			container,
371			..
372		} => container.get(i).map(|v| v.0.to_f32().unwrap_or(0.0)).unwrap_or(0.0),
373		ColumnData::Uint {
374			container,
375			..
376		} => container.get(i).map(|v| v.0.to_f32().unwrap_or(0.0)).unwrap_or(0.0),
377		ColumnData::Decimal {
378			container,
379			..
380		} => container.get(i).map(|v| v.0.to_f32().unwrap_or(0.0)).unwrap_or(0.0),
381		_ => 0.0,
382	}
383}
384
385fn get_as_f64(data: &ColumnData, i: usize) -> f64 {
386	match data {
387		ColumnData::Int1(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
388		ColumnData::Int2(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
389		ColumnData::Int4(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
390		ColumnData::Int8(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
391		ColumnData::Int16(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
392		ColumnData::Uint1(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
393		ColumnData::Uint2(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
394		ColumnData::Uint4(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
395		ColumnData::Uint8(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
396		ColumnData::Uint16(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
397		ColumnData::Float4(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
398		ColumnData::Float8(c) => c.get(i).copied().unwrap_or(0.0),
399		ColumnData::Int {
400			container,
401			..
402		} => container.get(i).map(|v| v.0.to_f64().unwrap_or(0.0)).unwrap_or(0.0),
403		ColumnData::Uint {
404			container,
405			..
406		} => container.get(i).map(|v| v.0.to_f64().unwrap_or(0.0)).unwrap_or(0.0),
407		ColumnData::Decimal {
408			container,
409			..
410		} => container.get(i).map(|v| v.0.to_f64().unwrap_or(0.0)).unwrap_or(0.0),
411		_ => 0.0,
412	}
413}
414
415fn promote_two(left: Type, right: Type) -> Type {
416	// Known-side-wins symmetric: (X, Any) and (Any, X) yield X when X is numeric;
417	// (Any, Any) yields Any. Runs BEFORE canonicalization so `power(Int, none)`
418	// preserves `Int` rather than falling into the Int→Int16 overflow-guard
419	// branch (no value exists to overflow when the exponent is null).
420	if matches!(left, Type::Any) && matches!(right, Type::Any) {
421		return Type::Any;
422	}
423	if matches!(left, Type::Any) && right.is_number() {
424		return right;
425	}
426	if left.is_number() && matches!(right, Type::Any) {
427		return left;
428	}
429	if matches!(left, Type::Float4 | Type::Float8 | Type::Decimal)
430		|| matches!(right, Type::Float4 | Type::Float8 | Type::Decimal)
431	{
432		return Type::Decimal;
433	}
434	if left == Type::Int || right == Type::Int {
435		return Type::Int16;
436	}
437	if left == Type::Uint || right == Type::Uint {
438		if matches!(left, Type::Int1 | Type::Int2 | Type::Int4 | Type::Int8 | Type::Int16)
439			|| matches!(right, Type::Int1 | Type::Int2 | Type::Int4 | Type::Int8 | Type::Int16)
440		{
441			return Type::Int16;
442		}
443		return Type::Uint16;
444	}
445	Type::promote(left, right)
446}
447
448impl Function for Power {
449	fn info(&self) -> &FunctionInfo {
450		&self.info
451	}
452
453	fn capabilities(&self) -> &[FunctionCapability] {
454		&[FunctionCapability::Scalar]
455	}
456
457	fn return_type(&self, input_types: &[Type]) -> Type {
458		if input_types.len() >= 2 {
459			promote_two(input_types[0].clone(), input_types[1].clone())
460		} else {
461			Type::Float8
462		}
463	}
464
465	fn execute(&self, ctx: &FunctionContext, args: &Columns) -> Result<Columns, FunctionError> {
466		if args.len() != 2 {
467			return Err(FunctionError::ArityMismatch {
468				function: ctx.fragment.clone(),
469				expected: 2,
470				actual: args.len(),
471			});
472		}
473
474		let base_column = &args[0];
475		let exponent_column = &args[1];
476
477		let (base_data, base_bv) = base_column.data().unwrap_option();
478		let (exp_data, exp_bv) = exponent_column.data().unwrap_option();
479		let row_count = base_data.len();
480
481		let result_data = match (base_data, exp_data) {
482			(ColumnData::Int1(base), ColumnData::Int1(exp)) => {
483				let mut result = Vec::with_capacity(row_count);
484				let mut res_bitvec = Vec::with_capacity(row_count);
485				for i in 0..row_count {
486					match (base.get(i), exp.get(i)) {
487						(Some(&b), Some(&e)) => {
488							result.push(if e < 0 {
489								0
490							} else {
491								(b as i32).pow(e as u32)
492							});
493							res_bitvec.push(true);
494						}
495						_ => {
496							result.push(0);
497							res_bitvec.push(false);
498						}
499					}
500				}
501				ColumnData::int4_with_bitvec(result, res_bitvec)
502			}
503			(ColumnData::Int2(base), ColumnData::Int2(exp)) => {
504				let mut result = Vec::with_capacity(row_count);
505				let mut res_bitvec = Vec::with_capacity(row_count);
506				for i in 0..row_count {
507					match (base.get(i), exp.get(i)) {
508						(Some(&b), Some(&e)) => {
509							result.push(if e < 0 {
510								0
511							} else {
512								(b as i32).pow(e as u32)
513							});
514							res_bitvec.push(true);
515						}
516						_ => {
517							result.push(0);
518							res_bitvec.push(false);
519						}
520					}
521				}
522				ColumnData::int4_with_bitvec(result, res_bitvec)
523			}
524			(ColumnData::Int4(base), ColumnData::Int4(exp)) => {
525				let mut result = Vec::with_capacity(row_count);
526				let mut res_bitvec = Vec::with_capacity(row_count);
527				for i in 0..row_count {
528					match (base.get(i), exp.get(i)) {
529						(Some(&b), Some(&e)) => {
530							result.push(if e < 0 {
531								0
532							} else {
533								b.saturating_pow(e as u32)
534							});
535							res_bitvec.push(true);
536						}
537						_ => {
538							result.push(0);
539							res_bitvec.push(false);
540						}
541					}
542				}
543				ColumnData::int4_with_bitvec(result, res_bitvec)
544			}
545			(ColumnData::Int8(base), ColumnData::Int8(exp)) => {
546				let mut result = Vec::with_capacity(row_count);
547				let mut res_bitvec = Vec::with_capacity(row_count);
548				for i in 0..row_count {
549					match (base.get(i), exp.get(i)) {
550						(Some(&b), Some(&e)) => {
551							result.push(if e < 0 {
552								0
553							} else {
554								b.saturating_pow(e as u32)
555							});
556							res_bitvec.push(true);
557						}
558						_ => {
559							result.push(0);
560							res_bitvec.push(false);
561						}
562					}
563				}
564				ColumnData::int8_with_bitvec(result, res_bitvec)
565			}
566			(ColumnData::Int16(base), ColumnData::Int16(exp)) => {
567				let mut result = Vec::with_capacity(row_count);
568				let mut res_bitvec = Vec::with_capacity(row_count);
569				for i in 0..row_count {
570					match (base.get(i), exp.get(i)) {
571						(Some(&b), Some(&e)) => {
572							result.push(if e < 0 {
573								0
574							} else {
575								b.saturating_pow(e as u32)
576							});
577							res_bitvec.push(true);
578						}
579						_ => {
580							result.push(0);
581							res_bitvec.push(false);
582						}
583					}
584				}
585				ColumnData::int16_with_bitvec(result, res_bitvec)
586			}
587			(ColumnData::Float4(base), ColumnData::Float4(exp)) => {
588				let mut result = Vec::with_capacity(row_count);
589				let mut res_bitvec = Vec::with_capacity(row_count);
590				for i in 0..row_count {
591					match (base.get(i), exp.get(i)) {
592						(Some(&b), Some(&e)) => {
593							result.push(b.powf(e));
594							res_bitvec.push(true);
595						}
596						_ => {
597							result.push(0.0);
598							res_bitvec.push(false);
599						}
600					}
601				}
602				ColumnData::float4_with_bitvec(result, res_bitvec)
603			}
604			(ColumnData::Float8(base), ColumnData::Float8(exp)) => {
605				let mut result = Vec::with_capacity(row_count);
606				let mut res_bitvec = Vec::with_capacity(row_count);
607				for i in 0..row_count {
608					match (base.get(i), exp.get(i)) {
609						(Some(&b), Some(&e)) => {
610							result.push(b.powf(e));
611							res_bitvec.push(true);
612						}
613						_ => {
614							result.push(0.0);
615							res_bitvec.push(false);
616						}
617					}
618				}
619				ColumnData::float8_with_bitvec(result, res_bitvec)
620			}
621			(ColumnData::Uint1(base), ColumnData::Uint1(exp)) => {
622				let mut result = Vec::with_capacity(row_count);
623				let mut res_bitvec = Vec::with_capacity(row_count);
624				for i in 0..row_count {
625					match (base.get(i), exp.get(i)) {
626						(Some(&b), Some(&e)) => {
627							result.push((b as u32).saturating_pow(e as u32));
628							res_bitvec.push(true);
629						}
630						_ => {
631							result.push(0);
632							res_bitvec.push(false);
633						}
634					}
635				}
636				ColumnData::uint4_with_bitvec(result, res_bitvec)
637			}
638			(ColumnData::Uint2(base), ColumnData::Uint2(exp)) => {
639				let mut result = Vec::with_capacity(row_count);
640				let mut res_bitvec = Vec::with_capacity(row_count);
641				for i in 0..row_count {
642					match (base.get(i), exp.get(i)) {
643						(Some(&b), Some(&e)) => {
644							result.push((b as u32).saturating_pow(e as u32));
645							res_bitvec.push(true);
646						}
647						_ => {
648							result.push(0);
649							res_bitvec.push(false);
650						}
651					}
652				}
653				ColumnData::uint4_with_bitvec(result, res_bitvec)
654			}
655			(ColumnData::Uint4(base), ColumnData::Uint4(exp)) => {
656				let mut result = Vec::with_capacity(row_count);
657				let mut res_bitvec = Vec::with_capacity(row_count);
658				for i in 0..row_count {
659					match (base.get(i), exp.get(i)) {
660						(Some(&b), Some(&e)) => {
661							result.push(b.saturating_pow(e));
662							res_bitvec.push(true);
663						}
664						_ => {
665							result.push(0);
666							res_bitvec.push(false);
667						}
668					}
669				}
670				ColumnData::uint4_with_bitvec(result, res_bitvec)
671			}
672			(ColumnData::Uint8(base), ColumnData::Uint8(exp)) => {
673				let mut result = Vec::with_capacity(row_count);
674				let mut res_bitvec = Vec::with_capacity(row_count);
675				for i in 0..row_count {
676					match (base.get(i), exp.get(i)) {
677						(Some(&b), Some(&e)) => {
678							result.push(b.saturating_pow(e as u32));
679							res_bitvec.push(true);
680						}
681						_ => {
682							result.push(0);
683							res_bitvec.push(false);
684						}
685					}
686				}
687				ColumnData::uint8_with_bitvec(result, res_bitvec)
688			}
689			(ColumnData::Uint16(base), ColumnData::Uint16(exp)) => {
690				let mut result = Vec::with_capacity(row_count);
691				let mut res_bitvec = Vec::with_capacity(row_count);
692				for i in 0..row_count {
693					match (base.get(i), exp.get(i)) {
694						(Some(&b), Some(&e)) => {
695							result.push(b.saturating_pow(e as u32));
696							res_bitvec.push(true);
697						}
698						_ => {
699							result.push(0);
700							res_bitvec.push(false);
701						}
702					}
703				}
704				ColumnData::uint16_with_bitvec(result, res_bitvec)
705			}
706			(
707				ColumnData::Int {
708					container: base,
709					max_bytes,
710				},
711				ColumnData::Int {
712					container: exp,
713					..
714				},
715			) => {
716				let mut result = Vec::with_capacity(row_count);
717				let mut res_bitvec = Vec::with_capacity(row_count);
718				for i in 0..row_count {
719					match (base.get(i), exp.get(i)) {
720						(Some(b), Some(e)) => {
721							let b_val = b.0.to_f64().unwrap_or(0.0);
722							let e_val = e.0.to_f64().unwrap_or(0.0);
723							result.push(Int::from(b_val.powf(e_val) as i64));
724							res_bitvec.push(true);
725						}
726						_ => {
727							result.push(Int::default());
728							res_bitvec.push(false);
729						}
730					}
731				}
732				ColumnData::Int {
733					container: NumberContainer::new(result),
734					max_bytes: *max_bytes,
735				}
736			}
737			(
738				ColumnData::Uint {
739					container: base,
740					max_bytes,
741				},
742				ColumnData::Uint {
743					container: exp,
744					..
745				},
746			) => {
747				let mut result = Vec::with_capacity(row_count);
748				let mut res_bitvec = Vec::with_capacity(row_count);
749				for i in 0..row_count {
750					match (base.get(i), exp.get(i)) {
751						(Some(b), Some(e)) => {
752							let b_val = b.0.to_f64().unwrap_or(0.0);
753							let e_val = e.0.to_f64().unwrap_or(0.0);
754							result.push(Uint::from(b_val.powf(e_val) as u64));
755							res_bitvec.push(true);
756						}
757						_ => {
758							result.push(Uint::default());
759							res_bitvec.push(false);
760						}
761					}
762				}
763				ColumnData::Uint {
764					container: NumberContainer::new(result),
765					max_bytes: *max_bytes,
766				}
767			}
768			(
769				ColumnData::Decimal {
770					container: base,
771					precision,
772					scale,
773				},
774				ColumnData::Decimal {
775					container: exp,
776					..
777				},
778			) => {
779				let mut result = Vec::with_capacity(row_count);
780				let mut res_bitvec = Vec::with_capacity(row_count);
781				for i in 0..row_count {
782					match (base.get(i), exp.get(i)) {
783						(Some(b), Some(e)) => {
784							let b_val = b.0.to_f64().unwrap_or(0.0);
785							let e_val = e.0.to_f64().unwrap_or(0.0);
786							result.push(Decimal::from(b_val.powf(e_val)));
787							res_bitvec.push(true);
788						}
789						_ => {
790							result.push(Decimal::default());
791							res_bitvec.push(false);
792						}
793					}
794				}
795				ColumnData::Decimal {
796					container: NumberContainer::new(result),
797					precision: *precision,
798					scale: *scale,
799				}
800			}
801			// Mixed-type case: promote both columns to a common type and recurse
802			_ => {
803				let base_type = base_data.get_type();
804				let exp_type = exp_data.get_type();
805
806				if !base_type.is_number() || !exp_type.is_number() {
807					return Err(FunctionError::InvalidArgumentType {
808						function: ctx.fragment.clone(),
809						argument_index: 0,
810						expected: InputTypes::numeric().expected_at(0).to_vec(),
811						actual: base_type,
812					});
813				}
814
815				let promoted_type = promote_two(base_type, exp_type);
816				let promoted_base = convert_column_to_type(base_data, promoted_type.clone(), row_count);
817				let promoted_exp = convert_column_to_type(exp_data, promoted_type, row_count);
818
819				let base_col = Column::new(Fragment::internal("base"), promoted_base);
820				let exp_col = Column::new(Fragment::internal("exp"), promoted_exp);
821				let promoted_columns = Columns::new(vec![base_col, exp_col]);
822
823				return self.call(ctx, &promoted_columns);
824			}
825		};
826
827		let combined_bitvec = match (base_bv, exp_bv) {
828			(Some(b), Some(e)) => Some(b.and(e)),
829			(Some(b), None) => Some(b.clone()),
830			(None, Some(e)) => Some(e.clone()),
831			(None, None) => None,
832		};
833
834		let final_data = if let Some(bv) = combined_bitvec {
835			ColumnData::Option {
836				inner: Box::new(result_data),
837				bitvec: bv,
838			}
839		} else {
840			result_data
841		};
842
843		Ok(Columns::new(vec![Column::new(ctx.fragment.clone(), final_data)]))
844	}
845}