1#include "duckdb/function/scalar/math_functions.hpp"
2#include "duckdb/common/vector_operations/vector_operations.hpp"
3#include "duckdb/function/scalar/trigonometric_functions.hpp"
4
5#include <algorithm>
6#include <cmath>
7
8using namespace std;
9
10namespace duckdb {
11
12template <class TR, class OP> static scalar_function_t GetScalarIntegerUnaryFunctionFixedReturn(SQLType type) {
13 switch (type.id) {
14 case SQLTypeId::TINYINT:
15 return ScalarFunction::UnaryFunction<int8_t, TR, OP>;
16 case SQLTypeId::SMALLINT:
17 return ScalarFunction::UnaryFunction<int16_t, TR, OP>;
18 case SQLTypeId::INTEGER:
19 return ScalarFunction::UnaryFunction<int32_t, TR, OP>;
20 case SQLTypeId::BIGINT:
21 return ScalarFunction::UnaryFunction<int64_t, TR, OP>;
22 default:
23 throw NotImplementedException("Unimplemented type for GetScalarIntegerUnaryFunctionFixedReturn");
24 }
25}
26
27struct UnaryDoubleWrapper {
28 template <class FUNC, class OP, class INPUT_TYPE, class RESULT_TYPE>
29 static inline RESULT_TYPE Operation(FUNC fun, INPUT_TYPE input, nullmask_t &nullmask, idx_t idx) {
30 RESULT_TYPE result = OP::template Operation<INPUT_TYPE, RESULT_TYPE>(input);
31 if (std::isnan(result) || std::isinf(result) || errno != 0) {
32 errno = 0;
33 nullmask[idx] = true;
34 return 0;
35 }
36 return result;
37 }
38};
39
40template <class T, class OP>
41static void UnaryDoubleFunctionWrapper(DataChunk &input, ExpressionState &state, Vector &result) {
42 assert(input.column_count() >= 1);
43 errno = 0;
44 UnaryExecutor::Execute<T, T, OP, true, UnaryDoubleWrapper>(input.data[0], result, input.size());
45}
46
47struct BinaryDoubleWrapper {
48 template <class FUNC, class OP, class TA, class TB, class TR>
49 static inline TR Operation(FUNC fun, TA left, TB right, nullmask_t &nullmask, idx_t idx) {
50 TR result = OP::template Operation<TA, TB, TR>(left, right);
51 if (std::isnan(result) || std::isinf(result) || errno != 0) {
52 errno = 0;
53 nullmask[idx] = true;
54 return 0;
55 }
56 return result;
57 }
58};
59
60template <class T, class OP>
61static void BinaryDoubleFunctionWrapper(DataChunk &input, ExpressionState &state, Vector &result) {
62 assert(input.column_count() >= 2);
63 errno = 0;
64 BinaryExecutor::Execute<T, T, T, OP, true, BinaryDoubleWrapper>(input.data[0], input.data[1], result, input.size());
65}
66
67//===--------------------------------------------------------------------===//
68// abs
69//===--------------------------------------------------------------------===//
70struct AbsOperator {
71 template <class TA, class TR> static inline TR Operation(TA left) {
72 return left < 0 ? left * -1 : left;
73 }
74};
75
76void AbsFun::RegisterFunction(BuiltinFunctions &set) {
77 ScalarFunctionSet abs("abs");
78 for (auto &type : SQLType::NUMERIC) {
79 abs.AddFunction(ScalarFunction({type}, type, ScalarFunction::GetScalarUnaryFunction<AbsOperator>(type)));
80 }
81 set.AddFunction(abs);
82}
83
84//===--------------------------------------------------------------------===//
85// bit_count
86//===--------------------------------------------------------------------===//
87struct BitCntOperator {
88 template <class TA, class TR> static inline TR Operation(TA input) {
89 using TU = typename make_unsigned<TA>::type;
90 TR count = 0;
91 for (auto value = TU(input); value > 0; value >>= 1) {
92 count += TR(value & 1);
93 }
94 return count;
95 }
96};
97
98void BitCountFun::RegisterFunction(BuiltinFunctions &set) {
99 ScalarFunctionSet functions("bit_count");
100 for (auto &type : SQLType::INTEGRAL) {
101 functions.AddFunction(ScalarFunction({type}, SQLType::TINYINT,
102 GetScalarIntegerUnaryFunctionFixedReturn<int8_t, BitCntOperator>(type)));
103 }
104 set.AddFunction(functions);
105}
106
107//===--------------------------------------------------------------------===//
108// sign
109//===--------------------------------------------------------------------===//
110struct SignOperator {
111 template <class TA, class TR> static inline TR Operation(TA left) {
112 if (left == TA(0))
113 return 0;
114 else if (left > TA(0))
115 return 1;
116 else
117 return -1;
118 }
119};
120
121void SignFun::RegisterFunction(BuiltinFunctions &set) {
122 ScalarFunctionSet sign("sign");
123 for (auto &type : SQLType::NUMERIC) {
124 sign.AddFunction(ScalarFunction({type}, SQLType::TINYINT,
125 ScalarFunction::GetScalarUnaryFunctionFixedReturn<int8_t, SignOperator>(type)));
126 }
127 set.AddFunction(sign);
128}
129
130//===--------------------------------------------------------------------===//
131// ceil
132//===--------------------------------------------------------------------===//
133struct CeilOperator {
134 template <class TA, class TR> static inline TR Operation(TA left) {
135 return ceil(left);
136 }
137};
138
139void CeilFun::RegisterFunction(BuiltinFunctions &set) {
140 ScalarFunctionSet ceil("ceil");
141 for (auto &type : SQLType::NUMERIC) {
142 scalar_function_t func;
143 if (type.IsIntegral()) {
144 // ceil on integral type is a nop
145 func = ScalarFunction::NopFunction;
146 } else {
147 func = ScalarFunction::GetScalarUnaryFunction<CeilOperator>(type);
148 }
149 ceil.AddFunction(ScalarFunction({type}, type, func));
150 }
151 set.AddFunction(ceil);
152 ceil.name = "ceiling";
153 set.AddFunction(ceil);
154}
155
156//===--------------------------------------------------------------------===//
157// floor
158//===--------------------------------------------------------------------===//
159struct FloorOperator {
160 template <class TA, class TR> static inline TR Operation(TA left) {
161 return floor(left);
162 }
163};
164
165void FloorFun::RegisterFunction(BuiltinFunctions &set) {
166 ScalarFunctionSet floor("floor");
167 for (auto &type : SQLType::NUMERIC) {
168 scalar_function_t func;
169 if (type.IsIntegral()) {
170 // floor on integral type is a nop
171 func = ScalarFunction::NopFunction;
172 } else {
173 func = ScalarFunction::GetScalarUnaryFunction<FloorOperator>(type);
174 }
175 floor.AddFunction(ScalarFunction({type}, type, func));
176 }
177 set.AddFunction(floor);
178}
179
180//===--------------------------------------------------------------------===//
181// round
182//===--------------------------------------------------------------------===//
183struct RoundOperator {
184 template <class TA, class TB, class TR> static inline TR Operation(TA input, TB precision) {
185 if (precision < 0) {
186 precision = 0;
187 }
188 double modifier = pow(10, precision);
189 double rounded_value = (round(input * modifier)) / modifier;
190 if (std::isinf(rounded_value) || std::isnan(rounded_value)) {
191 return input;
192 }
193 return rounded_value;
194 }
195};
196
197void RoundFun::RegisterFunction(BuiltinFunctions &set) {
198 ScalarFunctionSet round("round");
199 for (auto &type : SQLType::NUMERIC) {
200 scalar_function_t func;
201 if (type.IsIntegral()) {
202 // round on integral type is a nop
203 func = ScalarFunction::NopFunction;
204 } else if (type.id == SQLTypeId::FLOAT) {
205 func = ScalarFunction::BinaryFunction<float, int32_t, float, RoundOperator>;
206 } else {
207 assert(type.id == SQLTypeId::DOUBLE || type.id == SQLTypeId::DECIMAL);
208 func = ScalarFunction::BinaryFunction<double, int32_t, double, RoundOperator>;
209 }
210 round.AddFunction(ScalarFunction({type, SQLType::INTEGER}, type, func));
211 }
212 set.AddFunction(round);
213}
214
215//===--------------------------------------------------------------------===//
216// exp
217//===--------------------------------------------------------------------===//
218struct ExpOperator {
219 template <class TA, class TR> static inline TR Operation(TA left) {
220 return exp(left);
221 }
222};
223
224void ExpFun::RegisterFunction(BuiltinFunctions &set) {
225 set.AddFunction(
226 ScalarFunction("exp", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, ExpOperator>));
227}
228
229//===--------------------------------------------------------------------===//
230// pow
231//===--------------------------------------------------------------------===//
232struct PowOperator {
233 template <class TA, class TB, class TR> static inline TR Operation(TA base, TB exponent) {
234 return pow(base, exponent);
235 }
236};
237
238void PowFun::RegisterFunction(BuiltinFunctions &set) {
239 ScalarFunction power_function("pow", {SQLType::DOUBLE, SQLType::DOUBLE}, SQLType::DOUBLE,
240 BinaryDoubleFunctionWrapper<double, PowOperator>);
241 set.AddFunction(power_function);
242 power_function.name = "power";
243 set.AddFunction(power_function);
244}
245
246//===--------------------------------------------------------------------===//
247// sqrt
248//===--------------------------------------------------------------------===//
249struct SqrtOperator {
250 template <class TA, class TR> static inline TR Operation(TA left) {
251 return sqrt(left);
252 }
253};
254
255void SqrtFun::RegisterFunction(BuiltinFunctions &set) {
256 set.AddFunction(
257 ScalarFunction("sqrt", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, SqrtOperator>));
258}
259
260//===--------------------------------------------------------------------===//
261// cbrt
262//===--------------------------------------------------------------------===//
263struct CbRtOperator {
264 template <class TA, class TR> static inline TR Operation(TA left) {
265 return cbrt(left);
266 }
267};
268
269void CbrtFun::RegisterFunction(BuiltinFunctions &set) {
270 set.AddFunction(
271 ScalarFunction("cbrt", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, CbRtOperator>));
272}
273
274//===--------------------------------------------------------------------===//
275// ln
276//===--------------------------------------------------------------------===//
277
278struct LnOperator {
279 template <class TA, class TR> static inline TR Operation(TA left) {
280 return log(left);
281 }
282};
283
284void LnFun::RegisterFunction(BuiltinFunctions &set) {
285 set.AddFunction(
286 ScalarFunction("ln", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, LnOperator>));
287}
288
289//===--------------------------------------------------------------------===//
290// log
291//===--------------------------------------------------------------------===//
292struct Log10Operator {
293 template <class TA, class TR> static inline TR Operation(TA left) {
294 return log10(left);
295 }
296};
297
298void Log10Fun::RegisterFunction(BuiltinFunctions &set) {
299 set.AddFunction({"log10", "log"}, ScalarFunction({SQLType::DOUBLE}, SQLType::DOUBLE,
300 UnaryDoubleFunctionWrapper<double, Log10Operator>));
301}
302
303//===--------------------------------------------------------------------===//
304// log2
305//===--------------------------------------------------------------------===//
306struct Log2Operator {
307 template <class TA, class TR> static inline TR Operation(TA left) {
308 return log2(left);
309 }
310};
311
312void Log2Fun::RegisterFunction(BuiltinFunctions &set) {
313 set.AddFunction(
314 ScalarFunction("log2", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, Log2Operator>));
315}
316
317//===--------------------------------------------------------------------===//
318// pi
319//===--------------------------------------------------------------------===//
320Value pi_value = Value::DOUBLE(PI);
321
322static void pi_function(DataChunk &args, ExpressionState &state, Vector &result) {
323 assert(args.column_count() == 0);
324 result.Reference(pi_value);
325}
326
327void PiFun::RegisterFunction(BuiltinFunctions &set) {
328 set.AddFunction(ScalarFunction("pi", {}, SQLType::DOUBLE, pi_function));
329}
330
331//===--------------------------------------------------------------------===//
332// degrees
333//===--------------------------------------------------------------------===//
334struct DegreesOperator {
335 template <class TA, class TR> static inline TR Operation(TA left) {
336 return left * (180 / PI);
337 }
338};
339
340void DegreesFun::RegisterFunction(BuiltinFunctions &set) {
341 set.AddFunction(ScalarFunction("degrees", {SQLType::DOUBLE}, SQLType::DOUBLE,
342 UnaryDoubleFunctionWrapper<double, DegreesOperator>));
343}
344
345//===--------------------------------------------------------------------===//
346// radians
347//===--------------------------------------------------------------------===//
348struct RadiansOperator {
349 template <class TA, class TR> static inline TR Operation(TA left) {
350 return left * (PI / 180);
351 }
352};
353
354void RadiansFun::RegisterFunction(BuiltinFunctions &set) {
355 set.AddFunction(ScalarFunction("radians", {SQLType::DOUBLE}, SQLType::DOUBLE,
356 UnaryDoubleFunctionWrapper<double, RadiansOperator>));
357}
358
359//===--------------------------------------------------------------------===//
360// sin
361//===--------------------------------------------------------------------===//
362struct SinOperator {
363 template <class TA, class TR> static inline TR Operation(TA input) {
364 return sin(input);
365 }
366};
367
368void SinFun::RegisterFunction(BuiltinFunctions &set) {
369 set.AddFunction(
370 ScalarFunction("sin", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, SinOperator>));
371}
372
373//===--------------------------------------------------------------------===//
374// cos
375//===--------------------------------------------------------------------===//
376struct CosOperator {
377 template <class TA, class TR> static inline TR Operation(TA input) {
378 return (double)cos(input);
379 }
380};
381
382void CosFun::RegisterFunction(BuiltinFunctions &set) {
383 set.AddFunction(
384 ScalarFunction("cos", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, CosOperator>));
385}
386
387//===--------------------------------------------------------------------===//
388// tan
389//===--------------------------------------------------------------------===//
390struct TanOperator {
391 template <class TA, class TR> static inline TR Operation(TA input) {
392 return (double)tan(input);
393 }
394};
395
396void TanFun::RegisterFunction(BuiltinFunctions &set) {
397 set.AddFunction(
398 ScalarFunction("tan", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, TanOperator>));
399}
400
401//===--------------------------------------------------------------------===//
402// asin
403//===--------------------------------------------------------------------===//
404struct ASinOperator {
405 template <class TA, class TR> static inline TR Operation(TA input) {
406 if (input < -1 || input > 1) {
407 throw Exception("ASIN is undefined outside [-1,1]");
408 }
409 return (double)asin(input);
410 }
411};
412
413void AsinFun::RegisterFunction(BuiltinFunctions &set) {
414 set.AddFunction(
415 ScalarFunction("asin", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, ASinOperator>));
416}
417
418//===--------------------------------------------------------------------===//
419// atan
420//===--------------------------------------------------------------------===//
421struct ATanOperator {
422 template <class TA, class TR> static inline TR Operation(TA input) {
423 return (double)atan(input);
424 }
425};
426
427void AtanFun::RegisterFunction(BuiltinFunctions &set) {
428 set.AddFunction(
429 ScalarFunction("atan", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, ATanOperator>));
430}
431
432//===--------------------------------------------------------------------===//
433// atan2
434//===--------------------------------------------------------------------===//
435struct ATan2 {
436 template <class TA, class TB, class TR> static inline TR Operation(TA left, TB right) {
437 return (double)atan2(left, right);
438 }
439};
440
441void Atan2Fun::RegisterFunction(BuiltinFunctions &set) {
442 set.AddFunction(ScalarFunction("atan2", {SQLType::DOUBLE, SQLType::DOUBLE}, SQLType::DOUBLE,
443 BinaryDoubleFunctionWrapper<double, ATan2>));
444}
445
446//===--------------------------------------------------------------------===//
447// acos
448//===--------------------------------------------------------------------===//
449struct ACos {
450 template <class TA, class TR> static inline TR Operation(TA input) {
451 return (double)acos(input);
452 }
453};
454
455void AcosFun::RegisterFunction(BuiltinFunctions &set) {
456 set.AddFunction(
457 ScalarFunction("acos", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, ACos>));
458}
459
460//===--------------------------------------------------------------------===//
461// cot
462//===--------------------------------------------------------------------===//
463struct CotOperator {
464 template <class TA, class TR> static inline TR Operation(TA input) {
465 return 1.0 / (double)tan(input);
466 }
467};
468
469void CotFun::RegisterFunction(BuiltinFunctions &set) {
470 set.AddFunction(
471 ScalarFunction("cot", {SQLType::DOUBLE}, SQLType::DOUBLE, UnaryDoubleFunctionWrapper<double, CotOperator>));
472}
473
474} // namespace duckdb
475