1use std::any::Any;
21
22use super::power::PowerFunc;
23
24use crate::utils::{
25 calculate_binary_math, decimal32_to_i32, decimal64_to_i64, decimal128_to_i128,
26};
27use arrow::array::{Array, ArrayRef};
28use arrow::datatypes::{
29 DataType, Decimal32Type, Decimal64Type, Decimal128Type, Decimal256Type, Float16Type,
30 Float32Type, Float64Type,
31};
32use arrow::error::ArrowError;
33use arrow_buffer::i256;
34use datafusion_common::types::NativeType;
35use datafusion_common::{
36 Result, ScalarValue, exec_err, internal_err, plan_datafusion_err, plan_err,
37};
38use datafusion_expr::expr::ScalarFunction;
39use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyInfo};
40use datafusion_expr::sort_properties::{ExprProperties, SortProperties};
41use datafusion_expr::{
42 Coercion, ColumnarValue, Documentation, Expr, ScalarFunctionArgs, ScalarUDF,
43 TypeSignature, TypeSignatureClass, lit,
44};
45use datafusion_expr::{ScalarUDFImpl, Signature, Volatility};
46use datafusion_macros::user_doc;
47use num_traits::Float;
48
49#[user_doc(
50 doc_section(label = "Math Functions"),
51 description = "Returns the base-x logarithm of a number. Can either provide a specified base, or if omitted then takes the base-10 of a number.",
52 syntax_example = r#"log(base, numeric_expression)
53log(numeric_expression)"#,
54 sql_example = r#"```sql
55> SELECT log(10);
56+---------+
57| log(10) |
58+---------+
59| 1.0 |
60+---------+
61```"#,
62 standard_argument(name = "base", prefix = "Base numeric"),
63 standard_argument(name = "numeric_expression", prefix = "Numeric")
64)]
65#[derive(Debug, PartialEq, Eq, Hash)]
66pub struct LogFunc {
67 signature: Signature,
68}
69
70impl Default for LogFunc {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl LogFunc {
77 pub fn new() -> Self {
78 let as_float = Coercion::new_implicit(
80 TypeSignatureClass::Float,
81 vec![TypeSignatureClass::Numeric],
82 NativeType::Float64,
83 );
84 Self {
85 signature: Signature::one_of(
86 vec![
89 TypeSignature::Coercible(vec![Coercion::new_exact(
91 TypeSignatureClass::Decimal,
92 )]),
93 TypeSignature::Coercible(vec![as_float.clone()]),
94 TypeSignature::Coercible(vec![
96 as_float.clone(),
97 Coercion::new_exact(TypeSignatureClass::Decimal),
98 ]),
99 TypeSignature::Coercible(vec![as_float.clone(), as_float.clone()]),
100 ],
101 Volatility::Immutable,
102 ),
103 }
104 }
105}
106
107fn log_decimal32(value: i32, scale: i8, base: f64) -> Result<f64, ArrowError> {
110 if !base.is_finite() || base.trunc() != base {
111 return Err(ArrowError::ComputeError(format!(
112 "Log cannot use non-integer base: {base}"
113 )));
114 }
115 if (base as u32) < 2 {
116 return Err(ArrowError::ComputeError(format!(
117 "Log base must be greater than 1: {base}"
118 )));
119 }
120
121 if value <= 0 {
123 return Ok(f64::NAN);
124 }
125
126 if scale < 0 {
127 let actual_value = (value as f64) * 10.0_f64.powi(-(scale as i32));
128 Ok(actual_value.log(base))
129 } else {
130 let unscaled_value = decimal32_to_i32(value, scale)?;
131 if unscaled_value <= 0 {
132 return Ok(f64::NAN);
133 }
134 let log_value: u32 = unscaled_value.ilog(base as i32);
135 Ok(log_value as f64)
136 }
137}
138
139fn log_decimal64(value: i64, scale: i8, base: f64) -> Result<f64, ArrowError> {
142 if !base.is_finite() || base.trunc() != base {
143 return Err(ArrowError::ComputeError(format!(
144 "Log cannot use non-integer base: {base}"
145 )));
146 }
147 if (base as u32) < 2 {
148 return Err(ArrowError::ComputeError(format!(
149 "Log base must be greater than 1: {base}"
150 )));
151 }
152
153 if value <= 0 {
154 return Ok(f64::NAN);
155 }
156
157 if scale < 0 {
158 let actual_value = (value as f64) * 10.0_f64.powi(-(scale as i32));
159 Ok(actual_value.log(base))
160 } else {
161 let unscaled_value = decimal64_to_i64(value, scale)?;
162 if unscaled_value <= 0 {
163 return Ok(f64::NAN);
164 }
165 let log_value: u32 = unscaled_value.ilog(base as i64);
166 Ok(log_value as f64)
167 }
168}
169
170fn log_decimal128(value: i128, scale: i8, base: f64) -> Result<f64, ArrowError> {
173 if !base.is_finite() || base.trunc() != base {
174 return Err(ArrowError::ComputeError(format!(
175 "Log cannot use non-integer base: {base}"
176 )));
177 }
178 if (base as u32) < 2 {
179 return Err(ArrowError::ComputeError(format!(
180 "Log base must be greater than 1: {base}"
181 )));
182 }
183
184 if value <= 0 {
185 return Ok(f64::NAN);
187 }
188
189 if scale < 0 {
190 let actual_value = (value as f64) * 10.0_f64.powi(-(scale as i32));
191 Ok(actual_value.log(base))
192 } else {
193 let unscaled_value = decimal128_to_i128(value, scale)?;
194 if unscaled_value <= 0 {
195 return Ok(f64::NAN);
196 }
197 let log_value: u32 = unscaled_value.ilog(base as i128);
198 Ok(log_value as f64)
199 }
200}
201
202fn log_decimal256(value: i256, scale: i8, base: f64) -> Result<f64, ArrowError> {
205 match value.to_i128() {
206 Some(value) => log_decimal128(value, scale, base),
207 None => Err(ArrowError::NotYetImplemented(format!(
208 "Log of Decimal256 larger than Decimal128 is not yet supported: {value}"
209 ))),
210 }
211}
212
213impl ScalarUDFImpl for LogFunc {
214 fn as_any(&self) -> &dyn Any {
215 self
216 }
217 fn name(&self) -> &str {
218 "log"
219 }
220
221 fn signature(&self) -> &Signature {
222 &self.signature
223 }
224
225 fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
226 match &arg_types.last().ok_or(plan_datafusion_err!("No args"))? {
228 DataType::Float16 => Ok(DataType::Float16),
229 DataType::Float32 => Ok(DataType::Float32),
230 _ => Ok(DataType::Float64),
231 }
232 }
233
234 fn output_ordering(&self, input: &[ExprProperties]) -> Result<SortProperties> {
235 let (base_sort_properties, num_sort_properties) = if input.len() == 1 {
236 (SortProperties::Singleton, input[0].sort_properties)
238 } else {
239 (input[0].sort_properties, input[1].sort_properties)
240 };
241 match (num_sort_properties, base_sort_properties) {
242 (first @ SortProperties::Ordered(num), SortProperties::Ordered(base))
243 if num.descending != base.descending
244 && num.nulls_first == base.nulls_first =>
245 {
246 Ok(first)
247 }
248 (
249 first @ (SortProperties::Ordered(_) | SortProperties::Singleton),
250 SortProperties::Singleton,
251 ) => Ok(first),
252 (SortProperties::Singleton, second @ SortProperties::Ordered(_)) => {
253 Ok(-second)
254 }
255 _ => Ok(SortProperties::Unordered),
256 }
257 }
258
259 fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
261 if args.arg_fields.iter().any(|a| a.data_type().is_null()) {
262 return ColumnarValue::Scalar(ScalarValue::Null)
263 .cast_to(args.return_type(), None);
264 }
265
266 let (base, value) = if args.args.len() == 2 {
267 (args.args[0].clone(), &args.args[1])
268 } else {
269 (
271 ColumnarValue::Scalar(ScalarValue::new_ten(args.return_type())?),
272 &args.args[0],
273 )
274 };
275 let value = value.to_array(args.number_rows)?;
276
277 let output: ArrayRef = match value.data_type() {
278 DataType::Float16 => {
279 calculate_binary_math::<Float16Type, Float16Type, Float16Type, _>(
280 &value,
281 &base,
282 |value, base| Ok(value.log(base)),
283 )?
284 }
285 DataType::Float32 => {
286 calculate_binary_math::<Float32Type, Float32Type, Float32Type, _>(
287 &value,
288 &base,
289 |value, base| Ok(value.log(base)),
290 )?
291 }
292 DataType::Float64 => {
293 calculate_binary_math::<Float64Type, Float64Type, Float64Type, _>(
294 &value,
295 &base,
296 |value, base| Ok(value.log(base)),
297 )?
298 }
299 DataType::Decimal32(_, scale) => {
300 calculate_binary_math::<Decimal32Type, Float64Type, Float64Type, _>(
301 &value,
302 &base,
303 |value, base| log_decimal32(value, *scale, base),
304 )?
305 }
306 DataType::Decimal64(_, scale) => {
307 calculate_binary_math::<Decimal64Type, Float64Type, Float64Type, _>(
308 &value,
309 &base,
310 |value, base| log_decimal64(value, *scale, base),
311 )?
312 }
313 DataType::Decimal128(_, scale) => {
314 calculate_binary_math::<Decimal128Type, Float64Type, Float64Type, _>(
315 &value,
316 &base,
317 |value, base| log_decimal128(value, *scale, base),
318 )?
319 }
320 DataType::Decimal256(_, scale) => {
321 calculate_binary_math::<Decimal256Type, Float64Type, Float64Type, _>(
322 &value,
323 &base,
324 |value, base| log_decimal256(value, *scale, base),
325 )?
326 }
327 other => {
328 return exec_err!("Unsupported data type {other:?} for function log");
329 }
330 };
331
332 Ok(ColumnarValue::Array(output))
333 }
334
335 fn documentation(&self) -> Option<&Documentation> {
336 self.doc()
337 }
338
339 fn simplify(
344 &self,
345 mut args: Vec<Expr>,
346 info: &dyn SimplifyInfo,
347 ) -> Result<ExprSimplifyResult> {
348 let mut arg_types = args
349 .iter()
350 .map(|arg| info.get_data_type(arg))
351 .collect::<Result<Vec<_>>>()?;
352 let return_type = self.return_type(&arg_types)?;
353
354 if arg_types.iter().any(|dt| dt.is_null()) {
356 return Ok(ExprSimplifyResult::Simplified(lit(
357 ScalarValue::Null.cast_to(&return_type)?
358 )));
359 }
360
361 let num_args = args.len();
365 if num_args != 1 && num_args != 2 {
366 return plan_err!("Expected log to have 1 or 2 arguments, got {num_args}");
367 }
368
369 match arg_types.last().unwrap() {
370 DataType::Decimal32(_, scale)
371 | DataType::Decimal64(_, scale)
372 | DataType::Decimal128(_, scale)
373 | DataType::Decimal256(_, scale)
374 if *scale < 0 =>
375 {
376 return Ok(ExprSimplifyResult::Original(args));
377 }
378 _ => (),
379 };
380
381 let number = args.pop().unwrap();
382 let number_datatype = arg_types.pop().unwrap();
383 let base = if let Some(base) = args.pop() {
385 base
386 } else {
387 lit(ScalarValue::new_ten(&number_datatype)?)
388 };
389
390 match number {
391 Expr::Literal(value, _)
392 if value == ScalarValue::new_one(&number_datatype)? =>
393 {
394 Ok(ExprSimplifyResult::Simplified(lit(ScalarValue::new_zero(
395 &info.get_data_type(&base)?,
396 )?)))
397 }
398 Expr::ScalarFunction(ScalarFunction { func, mut args })
399 if is_pow(&func) && args.len() == 2 && base == args[0] =>
400 {
401 let b = args.pop().unwrap(); Ok(ExprSimplifyResult::Simplified(b))
403 }
404 number => {
405 if number == base {
406 Ok(ExprSimplifyResult::Simplified(lit(ScalarValue::new_one(
407 &number_datatype,
408 )?)))
409 } else {
410 let args = match num_args {
411 1 => vec![number],
412 2 => vec![base, number],
413 _ => {
414 return internal_err!(
415 "Unexpected number of arguments in log::simplify"
416 );
417 }
418 };
419 Ok(ExprSimplifyResult::Original(args))
420 }
421 }
422 }
423 }
424}
425
426fn is_pow(func: &ScalarUDF) -> bool {
428 func.inner().as_any().downcast_ref::<PowerFunc>().is_some()
429}
430
431#[cfg(test)]
432mod tests {
433 use std::collections::HashMap;
434 use std::sync::Arc;
435
436 use super::*;
437
438 use arrow::array::{
439 Date32Array, Decimal128Array, Decimal256Array, Float32Array, Float64Array,
440 };
441 use arrow::compute::SortOptions;
442 use arrow::datatypes::{DECIMAL256_MAX_PRECISION, Field};
443 use datafusion_common::DFSchema;
444 use datafusion_common::cast::{as_float32_array, as_float64_array};
445 use datafusion_common::config::ConfigOptions;
446 use datafusion_expr::execution_props::ExecutionProps;
447 use datafusion_expr::simplify::SimplifyContext;
448
449 #[test]
450 fn test_log_decimal_native() {
451 let value = 10_i128.pow(35);
452 assert_eq!((value as f64).log2(), 116.26748332105768);
453 assert_eq!(
454 log_decimal128(value, 0, 2.0).unwrap(),
455 116.0
458 );
459 }
460
461 #[test]
462 fn test_log_invalid_base_type() {
463 let arg_fields = vec![
464 Field::new("b", DataType::Date32, false).into(),
465 Field::new("n", DataType::Float64, false).into(),
466 ];
467 let args = ScalarFunctionArgs {
468 args: vec![
469 ColumnarValue::Array(Arc::new(Date32Array::from(vec![5, 10, 15, 20]))), ColumnarValue::Array(Arc::new(Float64Array::from(vec![
471 10.0, 100.0, 1000.0, 10000.0,
472 ]))), ],
474 arg_fields,
475 number_rows: 4,
476 return_field: Field::new("f", DataType::Float64, true).into(),
477 config_options: Arc::new(ConfigOptions::default()),
478 };
479 let result = LogFunc::new().invoke_with_args(args);
480 assert!(result.is_err());
481 assert_eq!(
482 result.unwrap_err().to_string().lines().next().unwrap(),
483 "Arrow error: Cast error: Casting from Date32 to Float64 not supported"
484 );
485 }
486
487 #[test]
488 fn test_log_invalid_value() {
489 let arg_field = Field::new("a", DataType::Date32, false).into();
490 let args = ScalarFunctionArgs {
491 args: vec![
492 ColumnarValue::Array(Arc::new(Date32Array::from(vec![10]))), ],
494 arg_fields: vec![arg_field],
495 number_rows: 1,
496 return_field: Field::new("f", DataType::Float64, true).into(),
497 config_options: Arc::new(ConfigOptions::default()),
498 };
499
500 let result = LogFunc::new().invoke_with_args(args);
501 result.expect_err("expected error");
502 }
503
504 #[test]
505 fn test_log_scalar_f32_unary() {
506 let arg_field = Field::new("a", DataType::Float32, false).into();
507 let args = ScalarFunctionArgs {
508 args: vec![
509 ColumnarValue::Scalar(ScalarValue::Float32(Some(10.0))), ],
511 arg_fields: vec![arg_field],
512 number_rows: 1,
513 return_field: Field::new("f", DataType::Float32, true).into(),
514 config_options: Arc::new(ConfigOptions::default()),
515 };
516 let result = LogFunc::new()
517 .invoke_with_args(args)
518 .expect("failed to initialize function log");
519
520 match result {
521 ColumnarValue::Array(arr) => {
522 let floats = as_float32_array(&arr)
523 .expect("failed to convert result to a Float32Array");
524
525 assert_eq!(floats.len(), 1);
526 assert!((floats.value(0) - 1.0).abs() < 1e-10);
527 }
528 ColumnarValue::Scalar(_) => {
529 panic!("Expected an array value")
530 }
531 }
532 }
533
534 #[test]
535 fn test_log_scalar_f64_unary() {
536 let arg_field = Field::new("a", DataType::Float64, false).into();
537 let args = ScalarFunctionArgs {
538 args: vec![
539 ColumnarValue::Scalar(ScalarValue::Float64(Some(10.0))), ],
541 arg_fields: vec![arg_field],
542 number_rows: 1,
543 return_field: Field::new("f", DataType::Float64, true).into(),
544 config_options: Arc::new(ConfigOptions::default()),
545 };
546 let result = LogFunc::new()
547 .invoke_with_args(args)
548 .expect("failed to initialize function log");
549
550 match result {
551 ColumnarValue::Array(arr) => {
552 let floats = as_float64_array(&arr)
553 .expect("failed to convert result to a Float64Array");
554
555 assert_eq!(floats.len(), 1);
556 assert!((floats.value(0) - 1.0).abs() < 1e-10);
557 }
558 ColumnarValue::Scalar(_) => {
559 panic!("Expected an array value")
560 }
561 }
562 }
563
564 #[test]
565 fn test_log_scalar_f32() {
566 let arg_fields = vec![
567 Field::new("a", DataType::Float32, false).into(),
568 Field::new("a", DataType::Float32, false).into(),
569 ];
570 let args = ScalarFunctionArgs {
571 args: vec![
572 ColumnarValue::Scalar(ScalarValue::Float32(Some(2.0))), ColumnarValue::Scalar(ScalarValue::Float32(Some(32.0))), ],
575 arg_fields,
576 number_rows: 1,
577 return_field: Field::new("f", DataType::Float32, true).into(),
578 config_options: Arc::new(ConfigOptions::default()),
579 };
580 let result = LogFunc::new()
581 .invoke_with_args(args)
582 .expect("failed to initialize function log");
583
584 match result {
585 ColumnarValue::Array(arr) => {
586 let floats = as_float32_array(&arr)
587 .expect("failed to convert result to a Float32Array");
588
589 assert_eq!(floats.len(), 1);
590 assert!((floats.value(0) - 5.0).abs() < 1e-10);
591 }
592 ColumnarValue::Scalar(_) => {
593 panic!("Expected an array value")
594 }
595 }
596 }
597
598 #[test]
599 fn test_log_scalar_f64() {
600 let arg_fields = vec![
601 Field::new("a", DataType::Float64, false).into(),
602 Field::new("a", DataType::Float64, false).into(),
603 ];
604 let args = ScalarFunctionArgs {
605 args: vec![
606 ColumnarValue::Scalar(ScalarValue::Float64(Some(2.0))), ColumnarValue::Scalar(ScalarValue::Float64(Some(64.0))), ],
609 arg_fields,
610 number_rows: 1,
611 return_field: Field::new("f", DataType::Float64, true).into(),
612 config_options: Arc::new(ConfigOptions::default()),
613 };
614 let result = LogFunc::new()
615 .invoke_with_args(args)
616 .expect("failed to initialize function log");
617
618 match result {
619 ColumnarValue::Array(arr) => {
620 let floats = as_float64_array(&arr)
621 .expect("failed to convert result to a Float64Array");
622
623 assert_eq!(floats.len(), 1);
624 assert!((floats.value(0) - 6.0).abs() < 1e-10);
625 }
626 ColumnarValue::Scalar(_) => {
627 panic!("Expected an array value")
628 }
629 }
630 }
631
632 #[test]
633 fn test_log_f64_unary() {
634 let arg_field = Field::new("a", DataType::Float64, false).into();
635 let args = ScalarFunctionArgs {
636 args: vec![
637 ColumnarValue::Array(Arc::new(Float64Array::from(vec![
638 10.0, 100.0, 1000.0, 10000.0,
639 ]))), ],
641 arg_fields: vec![arg_field],
642 number_rows: 4,
643 return_field: Field::new("f", DataType::Float64, true).into(),
644 config_options: Arc::new(ConfigOptions::default()),
645 };
646 let result = LogFunc::new()
647 .invoke_with_args(args)
648 .expect("failed to initialize function log");
649
650 match result {
651 ColumnarValue::Array(arr) => {
652 let floats = as_float64_array(&arr)
653 .expect("failed to convert result to a Float64Array");
654
655 assert_eq!(floats.len(), 4);
656 assert!((floats.value(0) - 1.0).abs() < 1e-10);
657 assert!((floats.value(1) - 2.0).abs() < 1e-10);
658 assert!((floats.value(2) - 3.0).abs() < 1e-10);
659 assert!((floats.value(3) - 4.0).abs() < 1e-10);
660 }
661 ColumnarValue::Scalar(_) => {
662 panic!("Expected an array value")
663 }
664 }
665 }
666
667 #[test]
668 fn test_log_f32_unary() {
669 let arg_field = Field::new("a", DataType::Float32, false).into();
670 let args = ScalarFunctionArgs {
671 args: vec![
672 ColumnarValue::Array(Arc::new(Float32Array::from(vec![
673 10.0, 100.0, 1000.0, 10000.0,
674 ]))), ],
676 arg_fields: vec![arg_field],
677 number_rows: 4,
678 return_field: Field::new("f", DataType::Float32, true).into(),
679 config_options: Arc::new(ConfigOptions::default()),
680 };
681 let result = LogFunc::new()
682 .invoke_with_args(args)
683 .expect("failed to initialize function log");
684
685 match result {
686 ColumnarValue::Array(arr) => {
687 let floats = as_float32_array(&arr)
688 .expect("failed to convert result to a Float64Array");
689
690 assert_eq!(floats.len(), 4);
691 assert!((floats.value(0) - 1.0).abs() < 1e-10);
692 assert!((floats.value(1) - 2.0).abs() < 1e-10);
693 assert!((floats.value(2) - 3.0).abs() < 1e-10);
694 assert!((floats.value(3) - 4.0).abs() < 1e-10);
695 }
696 ColumnarValue::Scalar(_) => {
697 panic!("Expected an array value")
698 }
699 }
700 }
701
702 #[test]
703 fn test_log_f64() {
704 let arg_fields = vec![
705 Field::new("a", DataType::Float64, false).into(),
706 Field::new("a", DataType::Float64, false).into(),
707 ];
708 let args = ScalarFunctionArgs {
709 args: vec![
710 ColumnarValue::Array(Arc::new(Float64Array::from(vec![
711 2.0, 2.0, 3.0, 5.0, 5.0,
712 ]))), ColumnarValue::Array(Arc::new(Float64Array::from(vec![
714 8.0, 4.0, 81.0, 625.0, -123.0,
715 ]))), ],
717 arg_fields,
718 number_rows: 5,
719 return_field: Field::new("f", DataType::Float64, true).into(),
720 config_options: Arc::new(ConfigOptions::default()),
721 };
722 let result = LogFunc::new()
723 .invoke_with_args(args)
724 .expect("failed to initialize function log");
725
726 match result {
727 ColumnarValue::Array(arr) => {
728 let floats = as_float64_array(&arr)
729 .expect("failed to convert result to a Float64Array");
730
731 assert_eq!(floats.len(), 5);
732 assert!((floats.value(0) - 3.0).abs() < 1e-10);
733 assert!((floats.value(1) - 2.0).abs() < 1e-10);
734 assert!((floats.value(2) - 4.0).abs() < 1e-10);
735 assert!((floats.value(3) - 4.0).abs() < 1e-10);
736 assert!(floats.value(4).is_nan());
737 }
738 ColumnarValue::Scalar(_) => {
739 panic!("Expected an array value")
740 }
741 }
742 }
743
744 #[test]
745 fn test_log_f32() {
746 let arg_fields = vec![
747 Field::new("a", DataType::Float32, false).into(),
748 Field::new("a", DataType::Float32, false).into(),
749 ];
750 let args = ScalarFunctionArgs {
751 args: vec![
752 ColumnarValue::Array(Arc::new(Float32Array::from(vec![
753 2.0, 2.0, 3.0, 5.0,
754 ]))), ColumnarValue::Array(Arc::new(Float32Array::from(vec![
756 8.0, 4.0, 81.0, 625.0,
757 ]))), ],
759 arg_fields,
760 number_rows: 4,
761 return_field: Field::new("f", DataType::Float32, true).into(),
762 config_options: Arc::new(ConfigOptions::default()),
763 };
764 let result = LogFunc::new()
765 .invoke_with_args(args)
766 .expect("failed to initialize function log");
767
768 match result {
769 ColumnarValue::Array(arr) => {
770 let floats = as_float32_array(&arr)
771 .expect("failed to convert result to a Float32Array");
772
773 assert_eq!(floats.len(), 4);
774 assert!((floats.value(0) - 3.0).abs() < f32::EPSILON);
775 assert!((floats.value(1) - 2.0).abs() < f32::EPSILON);
776 assert!((floats.value(2) - 4.0).abs() < f32::EPSILON);
777 assert!((floats.value(3) - 4.0).abs() < f32::EPSILON);
778 }
779 ColumnarValue::Scalar(_) => {
780 panic!("Expected an array value")
781 }
782 }
783 }
784 #[test]
785 fn test_log_simplify_errors() {
787 let props = ExecutionProps::new();
788 let schema =
789 Arc::new(DFSchema::new_with_metadata(vec![], HashMap::new()).unwrap());
790 let context = SimplifyContext::new(&props).with_schema(schema);
791 let _ = LogFunc::new().simplify(vec![], &context).unwrap_err();
793 let _ = LogFunc::new()
795 .simplify(vec![lit(1), lit(2), lit(3)], &context)
796 .unwrap_err();
797 }
798
799 #[test]
800 fn test_log_simplify_original() {
802 let props = ExecutionProps::new();
803 let schema =
804 Arc::new(DFSchema::new_with_metadata(vec![], HashMap::new()).unwrap());
805 let context = SimplifyContext::new(&props).with_schema(schema);
806 let result = LogFunc::new().simplify(vec![lit(2)], &context).unwrap();
808 let ExprSimplifyResult::Original(args) = result else {
809 panic!("Expected ExprSimplifyResult::Original")
810 };
811 assert_eq!(args.len(), 1);
812 assert_eq!(args[0], lit(2));
813 let result = LogFunc::new()
815 .simplify(vec![lit(2), lit(3)], &context)
816 .unwrap();
817 let ExprSimplifyResult::Original(args) = result else {
818 panic!("Expected ExprSimplifyResult::Original")
819 };
820 assert_eq!(args.len(), 2);
821 assert_eq!(args[0], lit(2));
822 assert_eq!(args[1], lit(3));
823 }
824
825 #[test]
826 fn test_log_output_ordering() {
827 let orders = [
829 ExprProperties::new_unknown(),
830 ExprProperties::new_unknown().with_order(SortProperties::Ordered(
831 SortOptions {
832 descending: false,
833 nulls_first: true,
834 },
835 )),
836 ExprProperties::new_unknown().with_order(SortProperties::Ordered(
837 SortOptions {
838 descending: true,
839 nulls_first: true,
840 },
841 )),
842 ExprProperties::new_unknown().with_order(SortProperties::Singleton),
843 ];
844
845 let log = LogFunc::new();
846
847 for order in orders.iter().cloned() {
849 let result = log.output_ordering(std::slice::from_ref(&order)).unwrap();
850 assert_eq!(result, order.sort_properties);
851 }
852
853 let mut results = Vec::with_capacity(orders.len() * orders.len());
855 for base_order in orders.iter() {
856 for num_order in orders.iter().cloned() {
857 let result = log
858 .output_ordering(&[base_order.clone(), num_order])
859 .unwrap();
860 results.push(result);
861 }
862 }
863 let expected = [
864 SortProperties::Unordered,
866 SortProperties::Unordered,
867 SortProperties::Unordered,
868 SortProperties::Unordered,
869 SortProperties::Unordered,
871 SortProperties::Unordered,
873 SortProperties::Ordered(SortOptions {
875 descending: true,
876 nulls_first: true,
877 }),
878 SortProperties::Ordered(SortOptions {
880 descending: true,
881 nulls_first: true,
882 }),
883 SortProperties::Unordered,
885 SortProperties::Ordered(SortOptions {
887 descending: false,
888 nulls_first: true,
889 }),
890 SortProperties::Unordered,
892 SortProperties::Ordered(SortOptions {
894 descending: false,
895 nulls_first: true,
896 }),
897 SortProperties::Unordered,
899 SortProperties::Ordered(SortOptions {
901 descending: false,
902 nulls_first: true,
903 }),
904 SortProperties::Ordered(SortOptions {
906 descending: true,
907 nulls_first: true,
908 }),
909 SortProperties::Singleton,
911 ];
912 assert_eq!(results, expected);
913
914 let base_order = ExprProperties::new_unknown().with_order(
916 SortProperties::Ordered(SortOptions {
917 descending: true,
918 nulls_first: true,
919 }),
920 );
921 let num_order = ExprProperties::new_unknown().with_order(
922 SortProperties::Ordered(SortOptions {
923 descending: false,
924 nulls_first: false,
925 }),
926 );
927 assert_eq!(
928 log.output_ordering(&[base_order, num_order]).unwrap(),
929 SortProperties::Unordered
930 );
931 }
932
933 #[test]
934 fn test_log_scalar_decimal128_unary() {
935 let arg_field = Field::new("a", DataType::Decimal128(38, 0), false).into();
936 let args = ScalarFunctionArgs {
937 args: vec![
938 ColumnarValue::Scalar(ScalarValue::Decimal128(Some(10), 38, 0)), ],
940 arg_fields: vec![arg_field],
941 number_rows: 1,
942 return_field: Field::new("f", DataType::Decimal128(38, 0), true).into(),
943 config_options: Arc::new(ConfigOptions::default()),
944 };
945 let result = LogFunc::new()
946 .invoke_with_args(args)
947 .expect("failed to initialize function log");
948
949 match result {
950 ColumnarValue::Array(arr) => {
951 let floats = as_float64_array(&arr)
952 .expect("failed to convert result to a Decimal128Array");
953 assert_eq!(floats.len(), 1);
954 assert!((floats.value(0) - 1.0).abs() < 1e-10);
955 }
956 ColumnarValue::Scalar(_) => {
957 panic!("Expected an array value")
958 }
959 }
960 }
961
962 #[test]
963 fn test_log_scalar_decimal128() {
964 let arg_fields = vec![
965 Field::new("b", DataType::Float64, false).into(),
966 Field::new("x", DataType::Decimal128(38, 0), false).into(),
967 ];
968 let args = ScalarFunctionArgs {
969 args: vec![
970 ColumnarValue::Scalar(ScalarValue::Float64(Some(2.0))), ColumnarValue::Scalar(ScalarValue::Decimal128(Some(64), 38, 0)), ],
973 arg_fields,
974 number_rows: 1,
975 return_field: Field::new("f", DataType::Float64, true).into(),
976 config_options: Arc::new(ConfigOptions::default()),
977 };
978 let result = LogFunc::new()
979 .invoke_with_args(args)
980 .expect("failed to initialize function log");
981
982 match result {
983 ColumnarValue::Array(arr) => {
984 let floats = as_float64_array(&arr)
985 .expect("failed to convert result to a Float64Array");
986
987 assert_eq!(floats.len(), 1);
988 assert!((floats.value(0) - 6.0).abs() < 1e-10);
989 }
990 ColumnarValue::Scalar(_) => {
991 panic!("Expected an array value")
992 }
993 }
994 }
995
996 #[test]
997 fn test_log_decimal128_unary() {
998 let arg_field = Field::new("a", DataType::Decimal128(38, 0), false).into();
999 let args = ScalarFunctionArgs {
1000 args: vec![
1001 ColumnarValue::Array(Arc::new(
1002 Decimal128Array::from(vec![10, 100, 1000, 10000, 12600, -123])
1003 .with_precision_and_scale(38, 0)
1004 .unwrap(),
1005 )), ],
1007 arg_fields: vec![arg_field],
1008 number_rows: 6,
1009 return_field: Field::new("f", DataType::Float64, true).into(),
1010 config_options: Arc::new(ConfigOptions::default()),
1011 };
1012 let result = LogFunc::new()
1013 .invoke_with_args(args)
1014 .expect("failed to initialize function log");
1015
1016 match result {
1017 ColumnarValue::Array(arr) => {
1018 let floats = as_float64_array(&arr)
1019 .expect("failed to convert result to a Float64Array");
1020
1021 assert_eq!(floats.len(), 6);
1022 assert!((floats.value(0) - 1.0).abs() < 1e-10);
1023 assert!((floats.value(1) - 2.0).abs() < 1e-10);
1024 assert!((floats.value(2) - 3.0).abs() < 1e-10);
1025 assert!((floats.value(3) - 4.0).abs() < 1e-10);
1026 assert!((floats.value(4) - 4.0).abs() < 1e-10); assert!(floats.value(5).is_nan());
1028 }
1029 ColumnarValue::Scalar(_) => {
1030 panic!("Expected an array value")
1031 }
1032 }
1033 }
1034
1035 #[test]
1036 fn test_log_decimal128_base_decimal() {
1037 for base in [
1039 ScalarValue::Decimal128(Some(i128::from(2)), 38, 0),
1040 ScalarValue::Decimal128(Some(i128::from(2000)), 38, 3),
1041 ] {
1042 let arg_fields = vec![
1043 Field::new("b", DataType::Decimal128(38, 0), false).into(),
1044 Field::new("x", DataType::Decimal128(38, 0), false).into(),
1045 ];
1046 let args = ScalarFunctionArgs {
1047 args: vec![
1048 ColumnarValue::Scalar(base), ColumnarValue::Scalar(ScalarValue::Decimal128(Some(64), 38, 0)), ],
1051 arg_fields,
1052 number_rows: 1,
1053 return_field: Field::new("f", DataType::Float64, true).into(),
1054 config_options: Arc::new(ConfigOptions::default()),
1055 };
1056 let result = LogFunc::new()
1057 .invoke_with_args(args)
1058 .expect("failed to initialize function log");
1059
1060 match result {
1061 ColumnarValue::Array(arr) => {
1062 let floats = as_float64_array(&arr)
1063 .expect("failed to convert result to a Float64Array");
1064
1065 assert_eq!(floats.len(), 1);
1066 assert!((floats.value(0) - 6.0).abs() < 1e-10);
1067 }
1068 ColumnarValue::Scalar(_) => {
1069 panic!("Expected an array value")
1070 }
1071 }
1072 }
1073 }
1074
1075 #[test]
1076 fn test_log_decimal128_value_scale() {
1077 for value in [
1079 ScalarValue::Decimal128(Some(i128::from(1000)), 38, 0),
1080 ScalarValue::Decimal128(Some(i128::from(10000)), 38, 1),
1081 ScalarValue::Decimal128(Some(i128::from(1000000)), 38, 3),
1082 ] {
1083 let arg_fields = vec![
1084 Field::new("b", DataType::Decimal128(38, 0), false).into(),
1085 Field::new("x", DataType::Decimal128(38, 0), false).into(),
1086 ];
1087 let args = ScalarFunctionArgs {
1088 args: vec![
1089 ColumnarValue::Scalar(value), ],
1091 arg_fields,
1092 number_rows: 1,
1093 return_field: Field::new("f", DataType::Float64, true).into(),
1094 config_options: Arc::new(ConfigOptions::default()),
1095 };
1096 let result = LogFunc::new()
1097 .invoke_with_args(args)
1098 .expect("failed to initialize function log");
1099
1100 match result {
1101 ColumnarValue::Array(arr) => {
1102 let floats = as_float64_array(&arr)
1103 .expect("failed to convert result to a Float64Array");
1104
1105 assert_eq!(floats.len(), 1);
1106 assert!((floats.value(0) - 3.0).abs() < 1e-10);
1107 }
1108 ColumnarValue::Scalar(_) => {
1109 panic!("Expected an array value")
1110 }
1111 }
1112 }
1113 }
1114
1115 #[test]
1116 fn test_log_decimal256_unary() {
1117 let arg_field = Field::new(
1118 "a",
1119 DataType::Decimal256(DECIMAL256_MAX_PRECISION, 0),
1120 false,
1121 )
1122 .into();
1123 let args = ScalarFunctionArgs {
1124 args: vec![
1125 ColumnarValue::Array(Arc::new(
1126 Decimal256Array::from(vec![
1127 Some(i256::from(10)),
1128 Some(i256::from(100)),
1129 Some(i256::from(1000)),
1130 Some(i256::from(10000)),
1131 Some(i256::from(12600)),
1132 Some(i256::from_i128(i128::MAX) - i256::from(1000)),
1134 Some(i256::from(-123)),
1136 ])
1137 .with_precision_and_scale(DECIMAL256_MAX_PRECISION, 0)
1138 .unwrap(),
1139 )), ],
1141 arg_fields: vec![arg_field],
1142 number_rows: 7,
1143 return_field: Field::new("f", DataType::Float64, true).into(),
1144 config_options: Arc::new(ConfigOptions::default()),
1145 };
1146 let result = LogFunc::new()
1147 .invoke_with_args(args)
1148 .expect("failed to initialize function log");
1149
1150 match result {
1151 ColumnarValue::Array(arr) => {
1152 let floats = as_float64_array(&arr)
1153 .expect("failed to convert result to a Float64Array");
1154
1155 assert_eq!(floats.len(), 7);
1156 eprintln!("floats {:?}", &floats);
1157 assert!((floats.value(0) - 1.0).abs() < 1e-10);
1158 assert!((floats.value(1) - 2.0).abs() < 1e-10);
1159 assert!((floats.value(2) - 3.0).abs() < 1e-10);
1160 assert!((floats.value(3) - 4.0).abs() < 1e-10);
1161 assert!((floats.value(4) - 4.0).abs() < 1e-10); assert!((floats.value(5) - 38.0).abs() < 1e-10);
1163 assert!(floats.value(6).is_nan());
1164 }
1165 ColumnarValue::Scalar(_) => {
1166 panic!("Expected an array value")
1167 }
1168 }
1169 }
1170
1171 #[test]
1172 fn test_log_decimal128_wrong_base() {
1173 let arg_fields = vec![
1174 Field::new("b", DataType::Float64, false).into(),
1175 Field::new("x", DataType::Decimal128(38, 0), false).into(),
1176 ];
1177 let args = ScalarFunctionArgs {
1178 args: vec![
1179 ColumnarValue::Scalar(ScalarValue::Float64(Some(-2.0))), ColumnarValue::Scalar(ScalarValue::Decimal128(Some(64), 38, 0)), ],
1182 arg_fields,
1183 number_rows: 1,
1184 return_field: Field::new("f", DataType::Float64, true).into(),
1185 config_options: Arc::new(ConfigOptions::default()),
1186 };
1187 let result = LogFunc::new().invoke_with_args(args);
1188 assert!(result.is_err());
1189 assert_eq!(
1190 "Arrow error: Compute error: Log base must be greater than 1: -2",
1191 result.unwrap_err().to_string().lines().next().unwrap()
1192 );
1193 }
1194
1195 #[test]
1196 fn test_log_decimal256_error() {
1197 let arg_field = Field::new("a", DataType::Decimal256(38, 0), false).into();
1198 let args = ScalarFunctionArgs {
1199 args: vec![
1200 ColumnarValue::Array(Arc::new(Decimal256Array::from(vec![
1201 Some(i256::from_i128(i128::MAX) + i256::from(1000)),
1203 ]))), ],
1205 arg_fields: vec![arg_field],
1206 number_rows: 1,
1207 return_field: Field::new("f", DataType::Float64, true).into(),
1208 config_options: Arc::new(ConfigOptions::default()),
1209 };
1210 let result = LogFunc::new().invoke_with_args(args);
1211 assert!(result.is_err());
1212 assert_eq!(
1213 result.unwrap_err().to_string().lines().next().unwrap(),
1214 "Arrow error: Not yet implemented: Log of Decimal256 larger than Decimal128 is not yet supported: 170141183460469231731687303715884106727"
1215 );
1216 }
1217}