Skip to content

Commit

Permalink
feat(expr): Various trigonometric functions (#8838)
Browse files Browse the repository at this point in the history
Co-authored-by: xiangjinwu <[email protected]>
  • Loading branch information
CAJan93 and xiangjinwu authored Mar 30, 2023
1 parent bccc76d commit bf616d8
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 0 deletions.
155 changes: 155 additions & 0 deletions e2e_test/batch/functions/trigonometric_funcs.slt.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
query R
SELECT abs(sin(1) - 0.8414709848078965) < 0.000000000000001
----
t

query R
SELECT abs(cos(1) - 0.5403023058681398) < 0.000000000000001
----
t

query R
SELECT abs(tan(1) - 1.557407724654902) < 0.000000000000001
----
t

query R
SELECT abs(cot(1) - 0.6420926159343308) < 0.000000000000001
----
t

query R
SELECT abs(asin(1) - 1.5707963267948966) < 0.000000000000001
----
t

query R
SELECT abs(acos(1) - 0) < 0.000000000000001
----
t

query R
SELECT abs(atan(1) - 0.7853981633974483) < 0.000000000000001
----
t

query R
SELECT abs(sin(1.1) - 0.8912073600614354) < 0.000000000000001
----
t

query R
SELECT abs(cos(1.1) - 0.4535961214255773) < 0.000000000000001
----
t

query R
SELECT abs(tan(1.1) - 1.9647596572486525) < 0.000000000000001
----
t

query R
SELECT abs(cot(1.1) - 0.5089681052390642) < 0.000000000000001
----
t

query R
SELECT asin(1.1)
----
NaN

query R
SELECT acos(1.1)
----
NaN

query R
SELECT abs(atan(1.1) - 0.8329812666744317) < 0.000000000000001
----
t

query R
SELECT abs(sin(-1.1) - -0.8912073600614354) < 0.000000000000001
----
t

query R
SELECT abs(cos(-1.1) - 0.4535961214255773) < 0.000000000000001
----
t

query R
SELECT abs(tan(-1.1) - -1.9647596572486525) < 0.000000000000001
----
t

query R
SELECT abs(cot(-1.1) - -0.5089681052390642) < 0.000000000000001
----
t

query R
SELECT asin(-1.1)
----
NaN

query R
SELECT acos(-1.1)
----
NaN

query R
SELECT abs(atan(-1.1) - -0.8329812666744317) < 0.000000000000001
----
t

query R
SELECT abs(sin(pi()) - 0.000000000000001) < 0.000000000000001
----
t

query R
SELECT cos(pi())
----
-1

query R
SELECT abs(tan(pi())) < 0.000000000000001
----
t

query R
SELECT asin(pi())
----
NaN

query R
SELECT acos(pi())
----
NaN

query R
SELECT abs(atan(pi()) - 1.2626272556789115) < 0.000000000000001
----
t

query R
SELECT abs(atan2(1, 0) - 1.5707963267948966) < 0.000000000000001
----
t

query R
SELECT abs(atan2(1.1, 3.8) - 0.2817718672733522) < 0.000000000000001
----
t

query R
SELECT abs(atan2(-1.1, -3.8) - -2.859820786316441) < 0.000000000000001
----
t

query R
SELECT abs(atan2(pi(), -3.8) - 2.4507611878363194) < 0.000000000000001
----
t

8 changes: 8 additions & 0 deletions proto/expr.proto
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ message ExprNode {
TO_ASCII = 242;
TO_HEX = 243;
QUOTE_IDENT = 244;
SIN = 245;
COS = 246;
TAN = 247;
COT = 248;
ASIN = 249;
ACOS = 250;
ATAN = 251;
ATAN2 = 252;

// Boolean comparison
IS_TRUE = 301;
Expand Down
1 change: 1 addition & 0 deletions src/expr/src/vector_op/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub mod timestamptz;
pub mod to_char;
pub mod to_timestamp;
pub mod translate;
pub mod trigonometric;
pub mod trim;
pub mod tumble;
pub mod upper;
107 changes: 107 additions & 0 deletions src/expr/src/vector_op/trigonometric.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2023 RisingWave Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use risingwave_common::types::F64;
use risingwave_expr_macro::function;

#[function("sin(float64) -> float64")]
pub fn sin_f64(input: F64) -> F64 {
f64::sin(input.0).into()
}

#[function("cos(float64) -> float64")]
pub fn cos_f64(input: F64) -> F64 {
f64::cos(input.0).into()
}

#[function("tan(float64) -> float64")]
pub fn tan_f64(input: F64) -> F64 {
f64::tan(input.0).into()
}

#[function("cot(float64) -> float64")]
pub fn cot_f64(input: F64) -> F64 {
let res = 1.0 / f64::tan(input.0);
res.into()
}

#[function("asin(float64) -> float64")]
pub fn asin_f64(input: F64) -> F64 {
f64::asin(input.0).into()
}

#[function("acos(float64) -> float64")]
pub fn acos_f64(input: F64) -> F64 {
f64::acos(input.0).into()
}

#[function("atan(float64) -> float64")]
pub fn atan_f64(input: F64) -> F64 {
f64::atan(input.0).into()
}

#[function("atan2(float64, float64) -> float64")]
pub fn atan2_f64(input_x: F64, input_y: F64) -> F64 {
input_x.0.atan2(input_y.0).into()
}

#[cfg(test)]
mod tests {

use risingwave_common::types::F64;

use crate::vector_op::trigonometric::*;

/// numbers are equal within a rounding error
fn assert_similar(lhs: F64, rhs: F64) {
let x = F64::from(lhs.abs() - rhs.abs()).abs() <= 0.000000000000001;
assert!(x);
}

#[test]
fn test_trigonometric_funcs() {
// from https://en.wikipedia.org/wiki/Trigonometric_functions#Sum_and_difference_formulas
let x = F64::from(1);
let y = F64::from(3);
let one = F64::from(1);
assert_similar(
sin_f64(x + y),
sin_f64(x) * cos_f64(y) + cos_f64(x) * sin_f64(y),
);
assert_similar(
cos_f64(x + y),
cos_f64(x) * cos_f64(y) - sin_f64(x) * sin_f64(y),
);
assert_similar(
tan_f64(x + y),
(tan_f64(x) + tan_f64(y)) / (one - tan_f64(x) * tan_f64(y)),
);
}

#[test]
fn test_inverse_trigonometric_funcs() {
let x = F64::from(1);
let y = F64::from(3);
let two = F64::from(2);
// https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Relationships_between_trigonometric_functions_and_inverse_trigonometric_functions
assert_similar(x, sin_f64(asin_f64(x)));
assert_similar(x, cos_f64(acos_f64(x)));
assert_similar(x, tan_f64(atan_f64(x)));
// https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Two-argument_variant_of_arctangent
assert_similar(
atan2_f64(y, x),
two * atan_f64(y / (F64::from(F64::from(x.powi(2) + y.powi(2)).sqrt()) + x)),
)
}
}
9 changes: 9 additions & 0 deletions src/frontend/src/binder/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,15 @@ impl Binder {
("abs", raw_call(ExprType::Abs)),
("exp", raw_call(ExprType::Exp)),
("mod", raw_call(ExprType::Modulus)),
("sin", raw_call(ExprType::Sin)),
("cos", raw_call(ExprType::Cos)),
("tan", raw_call(ExprType::Tan)),
("cot", raw_call(ExprType::Cot)),
("asin", raw_call(ExprType::Asin)),
("acos", raw_call(ExprType::Acos)),
("atan", raw_call(ExprType::Atan)),
("atan2", raw_call(ExprType::Atan2)),

(
"to_timestamp",
dispatch_by_len(vec![
Expand Down

0 comments on commit bf616d8

Please sign in to comment.