Skip to main content

reifydb_routine/function/math/
clamp.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use num_traits::ToPrimitive;
5use reifydb_core::value::column::{ColumnWithName, buffer::ColumnBuffer, columns::Columns};
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::routine::{Function, FunctionKind, Routine, RoutineInfo, context::FunctionContext, error::RoutineError};
18
19pub struct Clamp {
20	info: RoutineInfo,
21}
22
23impl Default for Clamp {
24	fn default() -> Self {
25		Self::new()
26	}
27}
28
29impl Clamp {
30	pub fn new() -> Self {
31		Self {
32			info: RoutineInfo::new("math::clamp"),
33		}
34	}
35}
36
37fn convert_column_to_type(data: &ColumnBuffer, target: Type, row_count: usize) -> ColumnBuffer {
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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::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			ColumnBuffer::decimal_with_bitvec(result, bitvec)
248		}
249		_ => data.clone(),
250	}
251}
252
253fn get_as_i8(data: &ColumnBuffer, i: usize) -> i8 {
254	match data {
255		ColumnBuffer::Int1(c) => c.get(i).copied().unwrap_or(0),
256		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as i8).unwrap_or(0),
257		_ => 0,
258	}
259}
260
261fn get_as_u8(data: &ColumnBuffer, i: usize) -> u8 {
262	match data {
263		ColumnBuffer::Uint1(c) => c.get(i).copied().unwrap_or(0),
264		ColumnBuffer::Int1(c) => c.get(i).map(|&v| v as u8).unwrap_or(0),
265		_ => 0,
266	}
267}
268
269fn get_as_i16(data: &ColumnBuffer, i: usize) -> i16 {
270	match data {
271		ColumnBuffer::Int1(c) => c.get(i).map(|&v| v as i16).unwrap_or(0),
272		ColumnBuffer::Int2(c) => c.get(i).copied().unwrap_or(0),
273		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as i16).unwrap_or(0),
274		_ => 0,
275	}
276}
277
278fn get_as_i32(data: &ColumnBuffer, i: usize) -> i32 {
279	match data {
280		ColumnBuffer::Int1(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
281		ColumnBuffer::Int2(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
282		ColumnBuffer::Int4(c) => c.get(i).copied().unwrap_or(0),
283		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
284		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as i32).unwrap_or(0),
285		_ => 0,
286	}
287}
288
289fn get_as_i64(data: &ColumnBuffer, i: usize) -> i64 {
290	match data {
291		ColumnBuffer::Int1(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
292		ColumnBuffer::Int2(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
293		ColumnBuffer::Int4(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
294		ColumnBuffer::Int8(c) => c.get(i).copied().unwrap_or(0),
295		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
296		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
297		ColumnBuffer::Uint4(c) => c.get(i).map(|&v| v as i64).unwrap_or(0),
298		_ => 0,
299	}
300}
301
302fn get_as_i128(data: &ColumnBuffer, i: usize) -> i128 {
303	match data {
304		ColumnBuffer::Int1(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
305		ColumnBuffer::Int2(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
306		ColumnBuffer::Int4(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
307		ColumnBuffer::Int8(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
308		ColumnBuffer::Int16(c) => c.get(i).copied().unwrap_or(0),
309		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
310		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
311		ColumnBuffer::Uint4(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
312		ColumnBuffer::Uint8(c) => c.get(i).map(|&v| v as i128).unwrap_or(0),
313		_ => 0,
314	}
315}
316
317fn get_as_u16(data: &ColumnBuffer, i: usize) -> u16 {
318	match data {
319		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as u16).unwrap_or(0),
320		ColumnBuffer::Uint2(c) => c.get(i).copied().unwrap_or(0),
321		_ => 0,
322	}
323}
324
325fn get_as_u32(data: &ColumnBuffer, i: usize) -> u32 {
326	match data {
327		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as u32).unwrap_or(0),
328		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as u32).unwrap_or(0),
329		ColumnBuffer::Uint4(c) => c.get(i).copied().unwrap_or(0),
330		_ => 0,
331	}
332}
333
334fn get_as_u64(data: &ColumnBuffer, i: usize) -> u64 {
335	match data {
336		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as u64).unwrap_or(0),
337		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as u64).unwrap_or(0),
338		ColumnBuffer::Uint4(c) => c.get(i).map(|&v| v as u64).unwrap_or(0),
339		ColumnBuffer::Uint8(c) => c.get(i).copied().unwrap_or(0),
340		_ => 0,
341	}
342}
343
344fn get_as_u128(data: &ColumnBuffer, i: usize) -> u128 {
345	match data {
346		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
347		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
348		ColumnBuffer::Uint4(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
349		ColumnBuffer::Uint8(c) => c.get(i).map(|&v| v as u128).unwrap_or(0),
350		ColumnBuffer::Uint16(c) => c.get(i).copied().unwrap_or(0),
351		_ => 0,
352	}
353}
354
355fn get_as_f32(data: &ColumnBuffer, i: usize) -> f32 {
356	match data {
357		ColumnBuffer::Int1(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
358		ColumnBuffer::Int2(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
359		ColumnBuffer::Int4(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
360		ColumnBuffer::Int8(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
361		ColumnBuffer::Int16(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
362		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
363		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
364		ColumnBuffer::Uint4(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
365		ColumnBuffer::Uint8(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
366		ColumnBuffer::Uint16(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
367		ColumnBuffer::Float4(c) => c.get(i).copied().unwrap_or(0.0),
368		ColumnBuffer::Float8(c) => c.get(i).map(|&v| v as f32).unwrap_or(0.0),
369		ColumnBuffer::Int {
370			container,
371			..
372		} => container.get(i).map(|v| v.0.to_f32().unwrap_or(0.0)).unwrap_or(0.0),
373		ColumnBuffer::Uint {
374			container,
375			..
376		} => container.get(i).map(|v| v.0.to_f32().unwrap_or(0.0)).unwrap_or(0.0),
377		ColumnBuffer::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: &ColumnBuffer, i: usize) -> f64 {
386	match data {
387		ColumnBuffer::Int1(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
388		ColumnBuffer::Int2(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
389		ColumnBuffer::Int4(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
390		ColumnBuffer::Int8(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
391		ColumnBuffer::Int16(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
392		ColumnBuffer::Uint1(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
393		ColumnBuffer::Uint2(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
394		ColumnBuffer::Uint4(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
395		ColumnBuffer::Uint8(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
396		ColumnBuffer::Uint16(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
397		ColumnBuffer::Float4(c) => c.get(i).map(|&v| v as f64).unwrap_or(0.0),
398		ColumnBuffer::Float8(c) => c.get(i).copied().unwrap_or(0.0),
399		ColumnBuffer::Int {
400			container,
401			..
402		} => container.get(i).map(|v| v.0.to_f64().unwrap_or(0.0)).unwrap_or(0.0),
403		ColumnBuffer::Uint {
404			container,
405			..
406		} => container.get(i).map(|v| v.0.to_f64().unwrap_or(0.0)).unwrap_or(0.0),
407		ColumnBuffer::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	if matches!(left, Type::Float4 | Type::Float8 | Type::Decimal)
417		|| matches!(right, Type::Float4 | Type::Float8 | Type::Decimal)
418	{
419		return Type::Decimal;
420	}
421	if left == Type::Int || right == Type::Int {
422		return Type::Int16;
423	}
424	if left == Type::Uint || right == Type::Uint {
425		if matches!(left, Type::Int1 | Type::Int2 | Type::Int4 | Type::Int8 | Type::Int16)
426			|| matches!(right, Type::Int1 | Type::Int2 | Type::Int4 | Type::Int8 | Type::Int16)
427		{
428			return Type::Int16;
429		}
430		return Type::Uint16;
431	}
432	Type::promote(left, right)
433}
434
435fn promote_numeric_types(a: Type, b: Type, c: Type) -> Type {
436	promote_two(promote_two(a, b), c)
437}
438
439impl<'a> Routine<FunctionContext<'a>> for Clamp {
440	fn info(&self) -> &RoutineInfo {
441		&self.info
442	}
443
444	fn return_type(&self, input_types: &[Type]) -> Type {
445		if input_types.len() >= 3
446			&& input_types[0].is_number()
447			&& input_types[1].is_number()
448			&& input_types[2].is_number()
449		{
450			promote_numeric_types(input_types[0].clone(), input_types[1].clone(), input_types[2].clone())
451		} else {
452			Type::Float8
453		}
454	}
455
456	fn execute(&self, ctx: &mut FunctionContext<'a>, args: &Columns) -> Result<Columns, RoutineError> {
457		if args.len() != 3 {
458			return Err(RoutineError::FunctionArityMismatch {
459				function: ctx.fragment.clone(),
460				expected: 3,
461				actual: args.len(),
462			});
463		}
464
465		let val_col = &args[0];
466		let min_col = &args[1];
467		let max_col = &args[2];
468
469		let (v_data, v_bv) = val_col.unwrap_option();
470		let (lo_data, lo_bv) = min_col.unwrap_option();
471		let (hi_data, hi_bv) = max_col.unwrap_option();
472		let row_count = v_data.len();
473
474		let result_data = match (v_data, lo_data, hi_data) {
475			(ColumnBuffer::Int1(v), ColumnBuffer::Int1(lo), ColumnBuffer::Int1(hi)) => {
476				let mut result = Vec::with_capacity(row_count);
477				let mut res_bitvec = Vec::with_capacity(row_count);
478				for i in 0..row_count {
479					match (v.get(i), lo.get(i), hi.get(i)) {
480						(Some(&val), Some(&min), Some(&max)) => {
481							result.push(val.clamp(min, max));
482							res_bitvec.push(true);
483						}
484						_ => {
485							result.push(0);
486							res_bitvec.push(false);
487						}
488					}
489				}
490				ColumnBuffer::int1_with_bitvec(result, res_bitvec)
491			}
492			(ColumnBuffer::Int2(v), ColumnBuffer::Int2(lo), ColumnBuffer::Int2(hi)) => {
493				let mut result = Vec::with_capacity(row_count);
494				let mut res_bitvec = Vec::with_capacity(row_count);
495				for i in 0..row_count {
496					match (v.get(i), lo.get(i), hi.get(i)) {
497						(Some(&val), Some(&min), Some(&max)) => {
498							result.push(val.clamp(min, max));
499							res_bitvec.push(true);
500						}
501						_ => {
502							result.push(0);
503							res_bitvec.push(false);
504						}
505					}
506				}
507				ColumnBuffer::int2_with_bitvec(result, res_bitvec)
508			}
509			(ColumnBuffer::Int4(v), ColumnBuffer::Int4(lo), ColumnBuffer::Int4(hi)) => {
510				let mut result = Vec::with_capacity(row_count);
511				let mut res_bitvec = Vec::with_capacity(row_count);
512				for i in 0..row_count {
513					match (v.get(i), lo.get(i), hi.get(i)) {
514						(Some(&val), Some(&min), Some(&max)) => {
515							result.push(val.clamp(min, max));
516							res_bitvec.push(true);
517						}
518						_ => {
519							result.push(0);
520							res_bitvec.push(false);
521						}
522					}
523				}
524				ColumnBuffer::int4_with_bitvec(result, res_bitvec)
525			}
526			(ColumnBuffer::Int8(v), ColumnBuffer::Int8(lo), ColumnBuffer::Int8(hi)) => {
527				let mut result = Vec::with_capacity(row_count);
528				let mut res_bitvec = Vec::with_capacity(row_count);
529				for i in 0..row_count {
530					match (v.get(i), lo.get(i), hi.get(i)) {
531						(Some(&val), Some(&min), Some(&max)) => {
532							result.push(val.clamp(min, max));
533							res_bitvec.push(true);
534						}
535						_ => {
536							result.push(0);
537							res_bitvec.push(false);
538						}
539					}
540				}
541				ColumnBuffer::int8_with_bitvec(result, res_bitvec)
542			}
543			(ColumnBuffer::Int16(v), ColumnBuffer::Int16(lo), ColumnBuffer::Int16(hi)) => {
544				let mut result = Vec::with_capacity(row_count);
545				let mut res_bitvec = Vec::with_capacity(row_count);
546				for i in 0..row_count {
547					match (v.get(i), lo.get(i), hi.get(i)) {
548						(Some(&val), Some(&min), Some(&max)) => {
549							result.push(val.clamp(min, max));
550							res_bitvec.push(true);
551						}
552						_ => {
553							result.push(0);
554							res_bitvec.push(false);
555						}
556					}
557				}
558				ColumnBuffer::int16_with_bitvec(result, res_bitvec)
559			}
560			(ColumnBuffer::Uint1(v), ColumnBuffer::Uint1(lo), ColumnBuffer::Uint1(hi)) => {
561				let mut result = Vec::with_capacity(row_count);
562				let mut res_bitvec = Vec::with_capacity(row_count);
563				for i in 0..row_count {
564					match (v.get(i), lo.get(i), hi.get(i)) {
565						(Some(&val), Some(&min), Some(&max)) => {
566							result.push(val.clamp(min, max));
567							res_bitvec.push(true);
568						}
569						_ => {
570							result.push(0);
571							res_bitvec.push(false);
572						}
573					}
574				}
575				ColumnBuffer::uint1_with_bitvec(result, res_bitvec)
576			}
577			(ColumnBuffer::Uint2(v), ColumnBuffer::Uint2(lo), ColumnBuffer::Uint2(hi)) => {
578				let mut result = Vec::with_capacity(row_count);
579				let mut res_bitvec = Vec::with_capacity(row_count);
580				for i in 0..row_count {
581					match (v.get(i), lo.get(i), hi.get(i)) {
582						(Some(&val), Some(&min), Some(&max)) => {
583							result.push(val.clamp(min, max));
584							res_bitvec.push(true);
585						}
586						_ => {
587							result.push(0);
588							res_bitvec.push(false);
589						}
590					}
591				}
592				ColumnBuffer::uint2_with_bitvec(result, res_bitvec)
593			}
594			(ColumnBuffer::Uint4(v), ColumnBuffer::Uint4(lo), ColumnBuffer::Uint4(hi)) => {
595				let mut result = Vec::with_capacity(row_count);
596				let mut res_bitvec = Vec::with_capacity(row_count);
597				for i in 0..row_count {
598					match (v.get(i), lo.get(i), hi.get(i)) {
599						(Some(&val), Some(&min), Some(&max)) => {
600							result.push(val.clamp(min, max));
601							res_bitvec.push(true);
602						}
603						_ => {
604							result.push(0);
605							res_bitvec.push(false);
606						}
607					}
608				}
609				ColumnBuffer::uint4_with_bitvec(result, res_bitvec)
610			}
611			(ColumnBuffer::Uint8(v), ColumnBuffer::Uint8(lo), ColumnBuffer::Uint8(hi)) => {
612				let mut result = Vec::with_capacity(row_count);
613				let mut res_bitvec = Vec::with_capacity(row_count);
614				for i in 0..row_count {
615					match (v.get(i), lo.get(i), hi.get(i)) {
616						(Some(&val), Some(&min), Some(&max)) => {
617							result.push(val.clamp(min, max));
618							res_bitvec.push(true);
619						}
620						_ => {
621							result.push(0);
622							res_bitvec.push(false);
623						}
624					}
625				}
626				ColumnBuffer::uint8_with_bitvec(result, res_bitvec)
627			}
628			(ColumnBuffer::Uint16(v), ColumnBuffer::Uint16(lo), ColumnBuffer::Uint16(hi)) => {
629				let mut result = Vec::with_capacity(row_count);
630				let mut res_bitvec = Vec::with_capacity(row_count);
631				for i in 0..row_count {
632					match (v.get(i), lo.get(i), hi.get(i)) {
633						(Some(&val), Some(&min), Some(&max)) => {
634							result.push(val.clamp(min, max));
635							res_bitvec.push(true);
636						}
637						_ => {
638							result.push(0);
639							res_bitvec.push(false);
640						}
641					}
642				}
643				ColumnBuffer::uint16_with_bitvec(result, res_bitvec)
644			}
645			(ColumnBuffer::Float4(v), ColumnBuffer::Float4(lo), ColumnBuffer::Float4(hi)) => {
646				let mut result = Vec::with_capacity(row_count);
647				let mut res_bitvec = Vec::with_capacity(row_count);
648				for i in 0..row_count {
649					match (v.get(i), lo.get(i), hi.get(i)) {
650						(Some(&val), Some(&min), Some(&max)) => {
651							result.push(val.clamp(min, max));
652							res_bitvec.push(true);
653						}
654						_ => {
655							result.push(0.0);
656							res_bitvec.push(false);
657						}
658					}
659				}
660				ColumnBuffer::float4_with_bitvec(result, res_bitvec)
661			}
662			(ColumnBuffer::Float8(v), ColumnBuffer::Float8(lo), ColumnBuffer::Float8(hi)) => {
663				let mut result = Vec::with_capacity(row_count);
664				let mut res_bitvec = Vec::with_capacity(row_count);
665				for i in 0..row_count {
666					match (v.get(i), lo.get(i), hi.get(i)) {
667						(Some(&val), Some(&min), Some(&max)) => {
668							result.push(val.clamp(min, max));
669							res_bitvec.push(true);
670						}
671						_ => {
672							result.push(0.0);
673							res_bitvec.push(false);
674						}
675					}
676				}
677				ColumnBuffer::float8_with_bitvec(result, res_bitvec)
678			}
679			(
680				ColumnBuffer::Int {
681					container: v_container,
682					max_bytes,
683				},
684				ColumnBuffer::Int {
685					container: lo_container,
686					..
687				},
688				ColumnBuffer::Int {
689					container: hi_container,
690					..
691				},
692			) => {
693				let mut result = Vec::with_capacity(row_count);
694				let mut res_bitvec = Vec::with_capacity(row_count);
695				for i in 0..row_count {
696					match (v_container.get(i), lo_container.get(i), hi_container.get(i)) {
697						(Some(val), Some(lo), Some(hi)) => {
698							let v = val.0.to_f64().unwrap_or(0.0);
699							let l = lo.0.to_f64().unwrap_or(0.0);
700							let h = hi.0.to_f64().unwrap_or(0.0);
701							result.push(Int::from(v.clamp(l, h) as i64));
702							res_bitvec.push(true);
703						}
704						_ => {
705							result.push(Int::default());
706							res_bitvec.push(false);
707						}
708					}
709				}
710				ColumnBuffer::Int {
711					container: NumberContainer::new(result),
712					max_bytes: *max_bytes,
713				}
714			}
715			(
716				ColumnBuffer::Uint {
717					container: v_container,
718					max_bytes,
719				},
720				ColumnBuffer::Uint {
721					container: lo_container,
722					..
723				},
724				ColumnBuffer::Uint {
725					container: hi_container,
726					..
727				},
728			) => {
729				let mut result = Vec::with_capacity(row_count);
730				let mut res_bitvec = Vec::with_capacity(row_count);
731				for i in 0..row_count {
732					match (v_container.get(i), lo_container.get(i), hi_container.get(i)) {
733						(Some(val), Some(lo), Some(hi)) => {
734							let v = val.0.to_f64().unwrap_or(0.0);
735							let l = lo.0.to_f64().unwrap_or(0.0);
736							let h = hi.0.to_f64().unwrap_or(0.0);
737							result.push(Uint::from(v.clamp(l, h) as u64));
738							res_bitvec.push(true);
739						}
740						_ => {
741							result.push(Uint::default());
742							res_bitvec.push(false);
743						}
744					}
745				}
746				ColumnBuffer::Uint {
747					container: NumberContainer::new(result),
748					max_bytes: *max_bytes,
749				}
750			}
751			(
752				ColumnBuffer::Decimal {
753					container: v_container,
754					precision,
755					scale,
756				},
757				ColumnBuffer::Decimal {
758					container: lo_container,
759					..
760				},
761				ColumnBuffer::Decimal {
762					container: hi_container,
763					..
764				},
765			) => {
766				let mut result = Vec::with_capacity(row_count);
767				let mut res_bitvec = Vec::with_capacity(row_count);
768				for i in 0..row_count {
769					match (v_container.get(i), lo_container.get(i), hi_container.get(i)) {
770						(Some(val), Some(lo), Some(hi)) => {
771							let v = val.0.to_f64().unwrap_or(0.0);
772							let l = lo.0.to_f64().unwrap_or(0.0);
773							let h = hi.0.to_f64().unwrap_or(0.0);
774							result.push(Decimal::from(v.clamp(l, h)));
775							res_bitvec.push(true);
776						}
777						_ => {
778							result.push(Decimal::default());
779							res_bitvec.push(false);
780						}
781					}
782				}
783				ColumnBuffer::Decimal {
784					container: NumberContainer::new(result),
785					precision: *precision,
786					scale: *scale,
787				}
788			}
789			// Mixed-type fallback: promote all to Decimal or recursion
790			_ => {
791				let v_type = v_data.get_type();
792				let lo_type = lo_data.get_type();
793				let hi_type = hi_data.get_type();
794
795				if !v_type.is_number() {
796					return Err(RoutineError::FunctionInvalidArgumentType {
797						function: ctx.fragment.clone(),
798						argument_index: 0,
799						expected: InputTypes::numeric().expected_at(0).to_vec(),
800						actual: v_type,
801					});
802				}
803				if !lo_type.is_number() {
804					return Err(RoutineError::FunctionInvalidArgumentType {
805						function: ctx.fragment.clone(),
806						argument_index: 1,
807						expected: InputTypes::numeric().expected_at(0).to_vec(),
808						actual: lo_type,
809					});
810				}
811				if !hi_type.is_number() {
812					return Err(RoutineError::FunctionInvalidArgumentType {
813						function: ctx.fragment.clone(),
814						argument_index: 2,
815						expected: InputTypes::numeric().expected_at(0).to_vec(),
816						actual: hi_type,
817					});
818				}
819
820				let promoted = promote_numeric_types(v_type, lo_type, hi_type);
821				let pv = convert_column_to_type(v_data, promoted.clone(), row_count);
822				let plo = convert_column_to_type(lo_data, promoted.clone(), row_count);
823				let phi = convert_column_to_type(hi_data, promoted, row_count);
824
825				let val_col = ColumnWithName::new(Fragment::internal("val"), pv);
826				let min_col = ColumnWithName::new(Fragment::internal("min"), plo);
827				let max_col = ColumnWithName::new(Fragment::internal("max"), phi);
828				let promoted_columns = Columns::new(vec![val_col, min_col, max_col]);
829
830				return self.call(ctx, &promoted_columns);
831			}
832		};
833
834		let combined_bitvec = match (v_bv, lo_bv, hi_bv) {
835			(Some(v), Some(lo), Some(hi)) => Some(v.and(lo).and(hi)),
836			(Some(v), Some(lo), None) => Some(v.and(lo)),
837			(Some(v), None, Some(hi)) => Some(v.and(hi)),
838			(None, Some(lo), Some(hi)) => Some(lo.and(hi)),
839			(Some(v), None, None) => Some(v.clone()),
840			(None, Some(lo), None) => Some(lo.clone()),
841			(None, None, Some(hi)) => Some(hi.clone()),
842			(None, None, None) => None,
843		};
844
845		let final_data = if let Some(bv) = combined_bitvec {
846			ColumnBuffer::Option {
847				inner: Box::new(result_data),
848				bitvec: bv,
849			}
850		} else {
851			result_data
852		};
853
854		Ok(Columns::new(vec![ColumnWithName::new(ctx.fragment.clone(), final_data)]))
855	}
856}
857
858impl Function for Clamp {
859	fn kinds(&self) -> &[FunctionKind] {
860		&[FunctionKind::Scalar]
861	}
862}