datafusion_functions/math/
iszero.rs1use std::any::Any;
19use std::sync::Arc;
20
21use arrow::array::{ArrayRef, AsArray, BooleanArray};
22use arrow::datatypes::DataType::{Boolean, Float32, Float64};
23use arrow::datatypes::{DataType, Float32Type, Float64Type};
24
25use datafusion_common::{exec_err, Result};
26use datafusion_expr::TypeSignature::Exact;
27use datafusion_expr::{
28 ColumnarValue, Documentation, ScalarFunctionArgs, ScalarUDFImpl, Signature,
29 Volatility,
30};
31use datafusion_macros::user_doc;
32
33use crate::utils::make_scalar_function;
34
35#[user_doc(
36 doc_section(label = "Math Functions"),
37 description = "Returns true if a given number is +0.0 or -0.0 otherwise returns false.",
38 syntax_example = "iszero(numeric_expression)",
39 standard_argument(name = "numeric_expression", prefix = "Numeric")
40)]
41#[derive(Debug)]
42pub struct IsZeroFunc {
43 signature: Signature,
44}
45
46impl Default for IsZeroFunc {
47 fn default() -> Self {
48 IsZeroFunc::new()
49 }
50}
51
52impl IsZeroFunc {
53 pub fn new() -> Self {
54 use DataType::*;
55 Self {
56 signature: Signature::one_of(
57 vec![Exact(vec![Float32]), Exact(vec![Float64])],
58 Volatility::Immutable,
59 ),
60 }
61 }
62}
63
64impl ScalarUDFImpl for IsZeroFunc {
65 fn as_any(&self) -> &dyn Any {
66 self
67 }
68
69 fn name(&self) -> &str {
70 "iszero"
71 }
72
73 fn signature(&self) -> &Signature {
74 &self.signature
75 }
76
77 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
78 Ok(Boolean)
79 }
80
81 fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
82 make_scalar_function(iszero, vec![])(&args.args)
83 }
84
85 fn documentation(&self) -> Option<&Documentation> {
86 self.doc()
87 }
88}
89
90pub fn iszero(args: &[ArrayRef]) -> Result<ArrayRef> {
92 match args[0].data_type() {
93 Float64 => Ok(Arc::new(BooleanArray::from_unary(
94 args[0].as_primitive::<Float64Type>(),
95 |x| x == 0.0,
96 )) as ArrayRef),
97
98 Float32 => Ok(Arc::new(BooleanArray::from_unary(
99 args[0].as_primitive::<Float32Type>(),
100 |x| x == 0.0,
101 )) as ArrayRef),
102
103 other => exec_err!("Unsupported data type {other:?} for function iszero"),
104 }
105}
106
107#[cfg(test)]
108mod test {
109 use std::sync::Arc;
110
111 use arrow::array::{ArrayRef, Float32Array, Float64Array};
112
113 use datafusion_common::cast::as_boolean_array;
114
115 use crate::math::iszero::iszero;
116
117 #[test]
118 fn test_iszero_f64() {
119 let args: Vec<ArrayRef> =
120 vec![Arc::new(Float64Array::from(vec![1.0, 0.0, 3.0, -0.0]))];
121
122 let result = iszero(&args).expect("failed to initialize function iszero");
123 let booleans =
124 as_boolean_array(&result).expect("failed to initialize function iszero");
125
126 assert_eq!(booleans.len(), 4);
127 assert!(!booleans.value(0));
128 assert!(booleans.value(1));
129 assert!(!booleans.value(2));
130 assert!(booleans.value(3));
131 }
132
133 #[test]
134 fn test_iszero_f32() {
135 let args: Vec<ArrayRef> =
136 vec![Arc::new(Float32Array::from(vec![1.0, 0.0, 3.0, -0.0]))];
137
138 let result = iszero(&args).expect("failed to initialize function iszero");
139 let booleans =
140 as_boolean_array(&result).expect("failed to initialize function iszero");
141
142 assert_eq!(booleans.len(), 4);
143 assert!(!booleans.value(0));
144 assert!(booleans.value(1));
145 assert!(!booleans.value(2));
146 assert!(booleans.value(3));
147 }
148}