From 8a0d94542f891e7329222966f0d03fc95e70d073 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Fri, 12 May 2023 14:09:52 +0200 Subject: [PATCH 01/14] acosd implementation draft --- .../functions/trigonometric_funcs.slt.part | 45 +++++++++++++++++++ proto/expr.proto | 1 + src/expr/src/vector_op/trigonometric.rs | 43 ++++++++++++++++++ src/frontend/src/binder/expr/function.rs | 1 + src/frontend/src/expr/pure.rs | 1 + src/tests/regress/data/sql/float8.sql | 12 ++--- 6 files changed, 97 insertions(+), 6 deletions(-) diff --git a/e2e_test/batch/functions/trigonometric_funcs.slt.part b/e2e_test/batch/functions/trigonometric_funcs.slt.part index cd4b8e47ba2b1..8c7da6d21bb80 100644 --- a/e2e_test/batch/functions/trigonometric_funcs.slt.part +++ b/e2e_test/batch/functions/trigonometric_funcs.slt.part @@ -524,3 +524,48 @@ query R SELECT abs(abs(asind(-0.5) + 30)) < 1e-14 ---- t + +query R +SELECT abs(acosd(-1) - 180.0) < 1e-14 +---- +t + +query R +SELECT abs(acosd(-0.75) - 138.59037789072914) < 1e-14 +---- +t + +query R +SELECT abs(acosd(-0.5) - 120.00000000000001) < 1e-14 +---- +t + +query R +SELECT abs(acosd(-0.25) - 104.47751218592992) < 1e-14 +---- +t + +query R +SELECT abs(acosd(0) - 90.0) < 1e-14 +---- +t + +query R +SELECT abs(acosd(0.25) - 75.52248781407008) < 1e-14 +---- +t + +query R +SELECT abs(acosd(0.5) - 59.99999999999999) < 1e-14 +---- +t + +query R +SELECT abs(acosd(0.75) - 41.40962210927086) < 1e-14 +---- +t + +query R +SELECT abs(acosd(1) - 0.0) < 1e-14 +---- +t diff --git a/proto/expr.proto b/proto/expr.proto index 75c91931679a6..14c3be9187975 100644 --- a/proto/expr.proto +++ b/proto/expr.proto @@ -119,6 +119,7 @@ message ExprNode { SQRT = 258; DEGREES = 259; RADIANS = 260; + ACOSD = 261; // Boolean comparison IS_TRUE = 301; diff --git a/src/expr/src/vector_op/trigonometric.rs b/src/expr/src/vector_op/trigonometric.rs index 9887834a4bcba..457a4acb0e038 100644 --- a/src/expr/src/vector_op/trigonometric.rs +++ b/src/expr/src/vector_op/trigonometric.rs @@ -65,6 +65,7 @@ static ONE_MINUS_COSD_60: f64 = 0.499_999_999_999_999_9; static TAND_45: f64 = 1.0; static COTD_45: f64 = 1.0; static ASIN_0_5: f64 = 0.523_598_775_598_298_8; +static ACOS_0_5: f64 = 1.047_197_551_196_597_6; // returns the cosine of an angle that lies between 0 and 60 degrees. This will return exactly 1 // when xi s 0, and exactly 0.5 when x is 60 degrees. @@ -314,6 +315,43 @@ pub fn asind_f64(input: F64) -> F64 { result.into() } +// returns the inverse cosine of x in degrees, for x in the range [0, 1]. The result is an angle in +// the first quadrant --- [0, 90] degrees. For the 3 special case inputs (0, 0.5 and 1), this +// function will return exact values (0, 60 and 90 degrees respectively). +fn acosd_q1(x: f64) -> f64 { + // Stitch together inverse sine and cosine functions for the ranges [0, 0.5] and (0.5, 1]. Each + // expression below is guaranteed to return exactly 60 for x=0.5, so the result is a continuous + // monotonic function over the full range. + if x <= 0.5 { + let asin_x = f64::asin(x); + 90.0 - (asin_x / ASIN_0_5) * 30.0 + } else { + let acos_x = f64::acos(x); + (acos_x / ACOS_0_5) * 60.0 + } +} + +#[function("acosd(float64) -> float64")] +pub fn acosd_f64(input: F64) -> F64 { + let arg1 = input.0; + + // Return NaN if input is NaN or Infinite. Slightly different from PSQL implementation + if input.0.is_nan() || input.0.is_infinite() { + return F64::from(f64::NAN); + } + + let result = if arg1 >= 0.0 { + acosd_q1(arg1) + } else { + 90.0 + asind_q1(-arg1) + }; + + if result.is_infinite() { + return F64::from(f64::NAN); + } + result.into() +} + #[function("degrees(float64) -> float64")] pub fn degrees_f64(input: F64) -> F64 { input.0.to_degrees().into() @@ -338,6 +376,9 @@ mod tests { /// numbers are equal within a rounding error fn assert_similar(lhs: F64, rhs: F64) { + if lhs == F64::from(f64::NAN) && rhs == F64::from(f64::NAN) { + return; + } let x = (lhs.0 - rhs.0).abs() <= precision(); assert!(x, "{:?} != {:?}", lhs.0, rhs.0); } @@ -433,6 +474,8 @@ mod tests { assert_similar(asind_f64(F64::from(0.5)), F64::from(30)); assert_similar(asind_f64(F64::from(1)), F64::from(90)); + // TODO: write some tests here for cosd here, matching the exact values + // exact matches assert!(tand_f64(F64::from(-270)).0.is_infinite()); assert_eq!(tand_f64(F64::from(-180)), 0.0); diff --git a/src/frontend/src/binder/expr/function.rs b/src/frontend/src/binder/expr/function.rs index a147e97803e85..cead16f5e9480 100644 --- a/src/frontend/src/binder/expr/function.rs +++ b/src/frontend/src/binder/expr/function.rs @@ -436,6 +436,7 @@ impl Binder { ("cotd", raw_call(ExprType::Cotd)), ("tand", raw_call(ExprType::Tand)), ("asind", raw_call(ExprType::Asind)), + ("acosd", raw_call(ExprType::Acosd)), ("degrees", raw_call(ExprType::Degrees)), ("radians", raw_call(ExprType::Radians)), ("sqrt", raw_call(ExprType::Sqrt)), diff --git a/src/frontend/src/expr/pure.rs b/src/frontend/src/expr/pure.rs index e87a72fd7e861..919ccdf990ab9 100644 --- a/src/frontend/src/expr/pure.rs +++ b/src/frontend/src/expr/pure.rs @@ -155,6 +155,7 @@ impl ExprVisitor for ImpureAnalyzer { | expr_node::Type::Cosd | expr_node::Type::Cotd | expr_node::Type::Asind + | expr_node::Type::Acosd | expr_node::Type::Decode | expr_node::Type::Encode | expr_node::Type::Sha1 diff --git a/src/tests/regress/data/sql/float8.sql b/src/tests/regress/data/sql/float8.sql index 17e4e61235564..3d389f5716e28 100644 --- a/src/tests/regress/data/sql/float8.sql +++ b/src/tests/regress/data/sql/float8.sql @@ -284,12 +284,12 @@ FROM (VALUES (0), (60), (90), (120), (180), --@ FROM (VALUES (0), (45), (90), (135), (180), --@ (225), (270), (315), (360)) AS t(x); ---@ SELECT x, ---@ asind(x), ---@ asind(x) IN (-90,-30,0,30,90) AS asind_exact, ---@ acosd(x), ---@ acosd(x) IN (0,60,90,120,180) AS acosd_exact ---@ FROM (VALUES (-1), (-0.5), (0), (0.5), (1)) AS t(x); +SELECT x, + asind(x), + asind(x) IN (-90,-30,0,30,90) AS asind_exact, + acosd(x), + acosd(x) IN (0,60,90,120,180) AS acosd_exact +FROM (VALUES (-1), (-0.5), (0), (0.5), (1)) AS t(x); --@ SELECT x, --@ atand(x), From e8383d473732d1bd1cb3eb8ee747c738ae8692f2 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Fri, 12 May 2023 14:38:25 +0200 Subject: [PATCH 02/14] simplify if else statement --- src/expr/src/vector_op/trigonometric.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/expr/src/vector_op/trigonometric.rs b/src/expr/src/vector_op/trigonometric.rs index 457a4acb0e038..7c148d21b2b71 100644 --- a/src/expr/src/vector_op/trigonometric.rs +++ b/src/expr/src/vector_op/trigonometric.rs @@ -65,7 +65,7 @@ static ONE_MINUS_COSD_60: f64 = 0.499_999_999_999_999_9; static TAND_45: f64 = 1.0; static COTD_45: f64 = 1.0; static ASIN_0_5: f64 = 0.523_598_775_598_298_8; -static ACOS_0_5: f64 = 1.047_197_551_196_597_6; +static ACOS_0_5: f64 = 1.047_197_551_196_597_6; // TODO: maybe this num is incorrect? // returns the cosine of an angle that lies between 0 and 60 degrees. This will return exactly 1 // when xi s 0, and exactly 0.5 when x is 60 degrees. @@ -324,11 +324,10 @@ fn acosd_q1(x: f64) -> f64 { // monotonic function over the full range. if x <= 0.5 { let asin_x = f64::asin(x); - 90.0 - (asin_x / ASIN_0_5) * 30.0 - } else { - let acos_x = f64::acos(x); - (acos_x / ACOS_0_5) * 60.0 + return 90.0 - (asin_x / ASIN_0_5) * 30.0; } + let acos_x = f64::acos(x); + (acos_x / ACOS_0_5) * 60.0 } #[function("acosd(float64) -> float64")] @@ -336,7 +335,7 @@ pub fn acosd_f64(input: F64) -> F64 { let arg1 = input.0; // Return NaN if input is NaN or Infinite. Slightly different from PSQL implementation - if input.0.is_nan() || input.0.is_infinite() { + if input.0.is_nan() || input.0.is_infinite() || arg1 < -1.0 || arg1 > 1.0 { return F64::from(f64::NAN); } @@ -385,6 +384,8 @@ mod tests { #[test] fn test_degrees() { + let ACOS_0_5_local = f64::acos(0.5); + let d = F64::from(180); let pi = F64::from(PI); From 8d8e0a21f391d46284bf56e8af04aa1d1f03fd7e Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Wed, 17 May 2023 15:13:58 +0100 Subject: [PATCH 03/14] fix bug + reduce accuracy --- .../functions/trigonometric_funcs.slt.part | 2 +- src/expr/src/vector_op/trigonometric.rs | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/e2e_test/batch/functions/trigonometric_funcs.slt.part b/e2e_test/batch/functions/trigonometric_funcs.slt.part index 8c7da6d21bb80..0665de5f4ed04 100644 --- a/e2e_test/batch/functions/trigonometric_funcs.slt.part +++ b/e2e_test/batch/functions/trigonometric_funcs.slt.part @@ -536,7 +536,7 @@ SELECT abs(acosd(-0.75) - 138.59037789072914) < 1e-14 t query R -SELECT abs(acosd(-0.5) - 120.00000000000001) < 1e-14 +SELECT abs(acosd(-0.5) - 120.0) < 1e-14 ---- t diff --git a/src/expr/src/vector_op/trigonometric.rs b/src/expr/src/vector_op/trigonometric.rs index 7c148d21b2b71..6277b2dfc21cb 100644 --- a/src/expr/src/vector_op/trigonometric.rs +++ b/src/expr/src/vector_op/trigonometric.rs @@ -58,6 +58,7 @@ pub fn atan2_f64(input_x: F64, input_y: F64) -> F64 { // Radians per degree, a.k.a. PI / 180 static RADIANS_PER_DEGREE: f64 = 0.017_453_292_519_943_295; + // Constants we use to get more accurate results. // See PSQL: https://github.com/postgres/postgres/blob/78ec02d612a9b69039ec2610740f738968fe144d/src/backend/utils/adt/float.c#L2024 static SIND_30: f64 = 0.499_999_999_999_999_94; @@ -65,7 +66,7 @@ static ONE_MINUS_COSD_60: f64 = 0.499_999_999_999_999_9; static TAND_45: f64 = 1.0; static COTD_45: f64 = 1.0; static ASIN_0_5: f64 = 0.523_598_775_598_298_8; -static ACOS_0_5: f64 = 1.047_197_551_196_597_6; // TODO: maybe this num is incorrect? +static ACOS_0_5: f64 = 1.047_197_551_196_597_6; // returns the cosine of an angle that lies between 0 and 60 degrees. This will return exactly 1 // when xi s 0, and exactly 0.5 when x is 60 degrees. @@ -286,7 +287,7 @@ pub fn asind_q1(x: f64) -> f64 { } let acos_x = f64::acos(x); - 90.0 - (acos_x / ASIN_0_5) * 60.0 + 90.0 - (acos_x / ACOS_0_5) * 60.0 } #[function("asind(float64) -> float64")] @@ -299,7 +300,7 @@ pub fn asind_f64(input: F64) -> F64 { } // Return NaN if input is out of range. Slightly different from PSQL implementation - if input.0 < -1.0 || input.0 > 1.0 { + if !(-1.0..=1.0).contains(&arg1) { return F64::from(f64::NAN); } @@ -335,7 +336,7 @@ pub fn acosd_f64(input: F64) -> F64 { let arg1 = input.0; // Return NaN if input is NaN or Infinite. Slightly different from PSQL implementation - if input.0.is_nan() || input.0.is_infinite() || arg1 < -1.0 || arg1 > 1.0 { + if input.0.is_nan() || input.0.is_infinite() || !(-1.0..=1.0).contains(&arg1) { return F64::from(f64::NAN); } @@ -370,7 +371,7 @@ mod tests { use crate::vector_op::trigonometric::*; fn precision() -> f64 { - 1e-13 + 1e-12 } /// numbers are equal within a rounding error @@ -384,8 +385,6 @@ mod tests { #[test] fn test_degrees() { - let ACOS_0_5_local = f64::acos(0.5); - let d = F64::from(180); let pi = F64::from(PI); @@ -473,9 +472,16 @@ mod tests { assert_similar(asind_f64(F64::from(-0.5)), F64::from(-30)); assert_similar(asind_f64(F64::from(0)), F64::from(0)); assert_similar(asind_f64(F64::from(0.5)), F64::from(30)); + assert_similar(asind_f64(F64::from(0.75)), F64::from(48.590377890729)); assert_similar(asind_f64(F64::from(1)), F64::from(90)); - // TODO: write some tests here for cosd here, matching the exact values + // acosd + assert_eq!(acosd_f64(F64::from(-1)), F64::from(180)); + assert_similar(acosd_f64(F64::from(-0.75)), F64::from(138.59037789072914)); + assert_eq!(acosd_f64(F64::from(-0.5)), F64::from(120)); + assert_eq!(acosd_f64(F64::from(0.0)), F64::from(90)); + assert_eq!(acosd_f64(F64::from(0.5)), F64::from(60)); + assert_eq!(acosd_f64(F64::from(1)), F64::from(0)); // exact matches assert!(tand_f64(F64::from(-270)).0.is_infinite()); From 2cec3f5a39afd2d7a0caa4b59fabee78140ae086 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Wed, 17 May 2023 15:39:48 +0100 Subject: [PATCH 04/14] retrigger --- src/expr/src/vector_op/trigonometric.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/expr/src/vector_op/trigonometric.rs b/src/expr/src/vector_op/trigonometric.rs index 427c1079964a4..4b03b9ae61cfd 100644 --- a/src/expr/src/vector_op/trigonometric.rs +++ b/src/expr/src/vector_op/trigonometric.rs @@ -450,7 +450,6 @@ mod tests { tand_f64(F64::from(-10)), ); assert_similar(tan_f64(50_f64.to_radians().into()), tand_f64(F64::from(50))); - // we get slightly different result here, which is why I reduce the required accuracy assert!( (tan_f64(250_f64.to_radians().into()) - tand_f64(F64::from(250))) .0 From 40cec342f9ad1f2be2676245fe97dd7bf6cf3e24 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Thu, 18 May 2023 11:45:35 +0100 Subject: [PATCH 05/14] use lazy_static for constants --- src/expr/Cargo.toml | 1 + src/expr/src/vector_op/trigonometric.rs | 82 +++++++++++++++++++------ 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/expr/Cargo.toml b/src/expr/Cargo.toml index a8025d2dc8dd9..0f1dccbcc7501 100644 --- a/src/expr/Cargo.toml +++ b/src/expr/Cargo.toml @@ -30,6 +30,7 @@ futures-async-stream = { workspace = true } futures-util = "0.3" hex = "0.4.3" itertools = "0.10" +lazy_static = "1" md5 = "0.7.0" num-traits = "0.2" ouroboros = "0.15" diff --git a/src/expr/src/vector_op/trigonometric.rs b/src/expr/src/vector_op/trigonometric.rs index 4b03b9ae61cfd..b1688b3d38ea2 100644 --- a/src/expr/src/vector_op/trigonometric.rs +++ b/src/expr/src/vector_op/trigonometric.rs @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::f64::consts::PI; + +use lazy_static::lazy_static; use risingwave_common::types::F64; use risingwave_expr_macro::function; @@ -56,32 +59,73 @@ pub fn atan2_f64(input_x: F64, input_y: F64) -> F64 { input_x.0.atan2(input_y.0).into() } -// Radians per degree, a.k.a. PI / 180 -static RADIANS_PER_DEGREE: f64 = 0.017_453_292_519_943_295; - // Constants we use to get more accurate results. +// Depend on the machine and have to be evaluated at runtime // See PSQL: https://github.com/postgres/postgres/blob/78ec02d612a9b69039ec2610740f738968fe144d/src/backend/utils/adt/float.c#L2024 -static SIND_30: f64 = 0.499_999_999_999_999_94; -static ONE_MINUS_COSD_60: f64 = 0.499_999_999_999_999_9; -static TAND_45: f64 = 1.0; -static COTD_45: f64 = 1.0; -static ASIN_0_5: f64 = 0.523_598_775_598_298_8; -static ACOS_0_5: f64 = 1.047_197_551_196_597_6; +fn sind_30() -> f64 { + lazy_static! { + static ref SIND_30: f64 = f64::sin(30.0 * radians_per_degree()); + } + *SIND_30 +} + +fn one_minus_cosd_60() -> f64 { + lazy_static! { + static ref ONE_MINUS_COSD_60: f64 = 1.0 - f64::cos(60.0 * radians_per_degree()); + } + *ONE_MINUS_COSD_60 +} + +fn tand_45() -> f64 { + lazy_static! { + static ref TAND_45: f64 = f64::tan(45.0 * radians_per_degree()); + } + *TAND_45 +} + +fn cotd_45() -> f64 { + lazy_static! { + static ref COTD_45: f64 = + f64::cos(45.0 * radians_per_degree()) / f64::sin(45.0 * radians_per_degree()); + } + *COTD_45 +} + +fn asin_0_5() -> f64 { + lazy_static! { + static ref ASIN_0_5: f64 = f64::asin(0.5); + } + *ASIN_0_5 +} + +fn acos_0_5() -> f64 { + lazy_static! { + static ref ACOS_0_5: f64 = f64::acos(0.5); + } + *ACOS_0_5 +} + +fn radians_per_degree() -> f64 { + lazy_static! { + static ref RADIANS_PER_DEGREE: f64 = PI / 180.0; + } + *RADIANS_PER_DEGREE +} // returns the cosine of an angle that lies between 0 and 60 degrees. This will return exactly 1 // when xi s 0, and exactly 0.5 when x is 60 degrees. fn cosd_0_to_60(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let one_minus_cos_x: f64 = 1.0 - f64::cos(x * RADIANS_PER_DEGREE); - 1.0 - (one_minus_cos_x / ONE_MINUS_COSD_60) / 2.0 + let one_minus_cos_x: f64 = 1.0 - f64::cos(x * radians_per_degree()); + 1.0 - (one_minus_cos_x / one_minus_cosd_60()) / 2.0 } // returns the sine of an angle that lies between 0 and 30 degrees. This will return exactly 0 when // x is 0, and exactly 0.5 when x is 30 degrees. fn sind_0_to_30(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let sin_x = f64::sin(x * RADIANS_PER_DEGREE); - (sin_x / SIND_30) / 2.0 + let sin_x = f64::sin(x * radians_per_degree()); + (sin_x / sind_30()) / 2.0 } // returns the cosine of an angle in the first quadrant (0 to 90 degrees). @@ -219,7 +263,7 @@ pub fn cotd_f64(input: F64) -> F64 { } let cot_arg1 = cosd_q1(arg1) / sind_q1(arg1); - let result = sign * (cot_arg1 / COTD_45); + let result = sign * (cot_arg1 / cotd_45()); // On some machines we get cotd(270) = minus zero, but this isn't always // true. For portability, and because the user constituency for this @@ -259,7 +303,7 @@ pub fn tand_f64(input: F64) -> F64 { } let tan_arg1 = sind_q1(arg1) / cosd_q1(arg1); - let result = sign * (tan_arg1 / TAND_45); + let result = sign * (tan_arg1 / tand_45()); // On some machines we get tand(180) = minus zero, but this isn't always true. For portability, // and because the user constituency for this function probably doesn't want minus zero, force @@ -278,11 +322,11 @@ pub fn asind_q1(x: f64) -> f64 { // monotonic functionover the full range. if x <= 0.5 { let asin_x = f64::asin(x); - return (asin_x / ASIN_0_5) * 30.0; + return (asin_x / asin_0_5()) * 30.0; } let acos_x = f64::acos(x); - 90.0 - (acos_x / ACOS_0_5) * 60.0 + 90.0 - (acos_x / acos_0_5()) * 60.0 } #[function("asind(float64) -> float64")] @@ -320,10 +364,10 @@ fn acosd_q1(x: f64) -> f64 { // monotonic function over the full range. if x <= 0.5 { let asin_x = f64::asin(x); - return 90.0 - (asin_x / ASIN_0_5) * 30.0; + return 90.0 - (asin_x / asin_0_5()) * 30.0; } let acos_x = f64::acos(x); - (acos_x / ACOS_0_5) * 60.0 + (acos_x / acos_0_5()) * 60.0 } #[function("acosd(float64) -> float64")] From 758b173f481525060598d3e701ac331f837f6676 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Thu, 18 May 2023 11:49:49 +0100 Subject: [PATCH 06/14] lazy_static in cargo file --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index 37f10089c8623..bb52347e71d81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6089,6 +6089,7 @@ dependencies = [ "futures-util", "hex", "itertools", + "lazy_static", "madsim-tokio", "md5", "num-traits", From ee70fbe82067d93662565b108a09c3b2d7b99623 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Thu, 27 Jun 2024 13:17:03 +0200 Subject: [PATCH 07/14] fix cargo file --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3fe6abc8787ba..e2c75a4d84171 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,7 +143,7 @@ arrow-cast-iceberg = { package = "arrow-cast", version = "52" } # After apache/iceberg-rust#411 is merged, we move to the upstream version. iceberg = { git = "https://github.com/risingwavelabs/iceberg-rust.git", rev = "0c6e133e6f4655ff9ce4ad57b577dc7f692dd902" } iceberg-catalog-rest = { git = "https://github.com/risingwavelabs/iceberg-rust.git", rev = "0c6e133e6f4655ff9ce4ad57b577dc7f692dd902" } -arrow-array = "50" +arrow-array = "52" arrow-arith = "50" arrow-cast = "50" arrow-schema = "50" From e4b7b688ff8e7d274dc0455aec1ec81784bf4b7d Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Thu, 27 Jun 2024 13:22:52 +0200 Subject: [PATCH 08/14] Fix cargo file --- Cargo.lock | 4 ---- Cargo.toml | 2 +- src/batch/Cargo.toml | 1 - src/common/Cargo.toml | 2 -- src/connector/Cargo.toml | 1 - 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37ba94e3fc3a3..ebf5f9d75b68c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10634,7 +10634,6 @@ version = "1.11.0-alpha" dependencies = [ "anyhow", "arrow-array 50.0.0", - "arrow-array 52.0.0", "arrow-schema 50.0.0", "assert_matches", "async-recursion", @@ -10786,9 +10785,7 @@ dependencies = [ "ahash 0.8.11", "anyhow", "arc-swap", - "arrow-array 48.0.1", "arrow-array 50.0.0", - "arrow-array 52.0.0", "arrow-buffer 48.0.1", "arrow-buffer 50.0.0", "arrow-buffer 52.0.0", @@ -11096,7 +11093,6 @@ dependencies = [ "anyhow", "apache-avro 0.16.0", "arrow-array 50.0.0", - "arrow-array 52.0.0", "arrow-row 50.0.0", "arrow-schema 50.0.0", "arrow-schema 52.0.0", diff --git a/Cargo.toml b/Cargo.toml index e2c75a4d84171..3fe6abc8787ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,7 +143,7 @@ arrow-cast-iceberg = { package = "arrow-cast", version = "52" } # After apache/iceberg-rust#411 is merged, we move to the upstream version. iceberg = { git = "https://github.com/risingwavelabs/iceberg-rust.git", rev = "0c6e133e6f4655ff9ce4ad57b577dc7f692dd902" } iceberg-catalog-rest = { git = "https://github.com/risingwavelabs/iceberg-rust.git", rev = "0c6e133e6f4655ff9ce4ad57b577dc7f692dd902" } -arrow-array = "52" +arrow-array = "50" arrow-arith = "50" arrow-cast = "50" arrow-schema = "50" diff --git a/src/batch/Cargo.toml b/src/batch/Cargo.toml index ef4badfe07666..2ca8ed1be4e77 100644 --- a/src/batch/Cargo.toml +++ b/src/batch/Cargo.toml @@ -16,7 +16,6 @@ normal = ["workspace-hack"] [dependencies] anyhow = "1" arrow-array = { workspace = true } -arrow-array-iceberg = { workspace = true } arrow-schema = { workspace = true } assert_matches = "1" async-recursion = "1" diff --git a/src/common/Cargo.toml b/src/common/Cargo.toml index ae6f67faf3aac..ba295b56f02ca 100644 --- a/src/common/Cargo.toml +++ b/src/common/Cargo.toml @@ -18,8 +18,6 @@ ahash = "0.8" anyhow = "1" arc-swap = "1" arrow-array = { workspace = true } -arrow-array-deltalake = { workspace = true } -arrow-array-iceberg = { workspace = true } arrow-buffer = { workspace = true } arrow-buffer-deltalake = { workspace = true } arrow-buffer-iceberg = { workspace = true } diff --git a/src/connector/Cargo.toml b/src/connector/Cargo.toml index 3d8bf618eca58..257b930556c94 100644 --- a/src/connector/Cargo.toml +++ b/src/connector/Cargo.toml @@ -17,7 +17,6 @@ normal = ["workspace-hack"] anyhow = "1" apache-avro = { workspace = true } arrow-array = { workspace = true } -arrow-array-iceberg = { workspace = true } arrow-row = { workspace = true } arrow-schema = { workspace = true } arrow-schema-iceberg = { workspace = true } From 090bc43fd6ecdfcee78c1e93c83d1912391f8caf Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Thu, 27 Jun 2024 14:44:23 +0200 Subject: [PATCH 09/14] remove lazy_static --- Cargo.lock | 46 ++++++------- src/batch/Cargo.toml | 1 + src/common/Cargo.toml | 2 + src/connector/Cargo.toml | 1 + src/expr/impl/Cargo.toml | 1 - src/expr/impl/src/scalar/trigonometric.rs | 81 ++++++----------------- 6 files changed, 46 insertions(+), 86 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebf5f9d75b68c..80cfce6eb09dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -926,9 +926,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cb6d108605c5489fff1ef9c520656946ad05ed0de3ea6d26d56bcb34bdb8c5" dependencies = [ "anyhow", - "arrow-array 52.0.0", - "arrow-buffer 52.0.0", - "arrow-schema 52.0.0", + "arrow-array 50.0.0", + "arrow-buffer 50.0.0", + "arrow-schema 50.0.0", "atomic-time", "rquickjs", ] @@ -939,10 +939,10 @@ version = "0.0.1" source = "git+https://github.com/risingwavelabs/arrow-udf.git?rev=fa36365#fa3636559de986aa592da6e8b3fbfac7bdd4bb78" dependencies = [ "anyhow", - "arrow-array 52.0.0", - "arrow-buffer 52.0.0", - "arrow-data 52.0.0", - "arrow-schema 52.0.0", + "arrow-array 50.0.0", + "arrow-buffer 50.0.0", + "arrow-data 50.0.0", + "arrow-schema 50.0.0", "arrow-udf-js-deno-runtime", "async-trait", "deno_core", @@ -990,10 +990,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4506efc6fbc200c083add2a7ed4e3616a859941a745e922320ae7051d90d12ec" dependencies = [ "anyhow", - "arrow-array 52.0.0", - "arrow-buffer 52.0.0", - "arrow-ipc 52.0.0", - "arrow-schema 52.0.0", + "arrow-array 50.0.0", + "arrow-buffer 50.0.0", + "arrow-ipc 50.0.0", + "arrow-schema 50.0.0", "lazy_static", "pyo3", "pyo3-build-config", @@ -1006,9 +1006,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb829e25925161d93617d4b053bae03fe51e708f2cce088d85df856011d4f369" dependencies = [ "anyhow", - "arrow-array 52.0.0", - "arrow-ipc 52.0.0", - "arrow-schema 52.0.0", + "arrow-array 50.0.0", + "arrow-ipc 50.0.0", + "arrow-schema 50.0.0", "async-trait", "base64 0.22.0", "genawaiter", @@ -5898,7 +5898,7 @@ dependencies = [ "http 0.2.9", "thiserror", "tokio", - "tonic 0.11.0", + "tonic 0.10.2", "tower", "tracing", "trust-dns-resolver 0.23.2", @@ -7098,11 +7098,11 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin 0.9.8", + "spin 0.5.2", ] [[package]] @@ -9929,7 +9929,7 @@ dependencies = [ "indoc", "libc", "memoffset", - "parking_lot 0.12.1", + "parking_lot 0.11.2", "portable-atomic", "pyo3-build-config", "pyo3-ffi", @@ -10634,6 +10634,7 @@ version = "1.11.0-alpha" dependencies = [ "anyhow", "arrow-array 50.0.0", + "arrow-array 52.0.0", "arrow-schema 50.0.0", "assert_matches", "async-recursion", @@ -10785,7 +10786,9 @@ dependencies = [ "ahash 0.8.11", "anyhow", "arc-swap", + "arrow-array 48.0.1", "arrow-array 50.0.0", + "arrow-array 52.0.0", "arrow-buffer 48.0.1", "arrow-buffer 50.0.0", "arrow-buffer 52.0.0", @@ -11093,6 +11096,7 @@ dependencies = [ "anyhow", "apache-avro 0.16.0", "arrow-array 50.0.0", + "arrow-array 52.0.0", "arrow-row 50.0.0", "arrow-schema 50.0.0", "arrow-schema 52.0.0", @@ -11412,7 +11416,6 @@ dependencies = [ "icelake", "itertools 0.12.1", "jsonbb", - "lazy_static", "linkme", "madsim-tokio", "md5", @@ -15396,10 +15399,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost 0.12.1", - "rustls-pemfile 2.1.1", - "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", "tokio-stream", "tower", "tower-layer", diff --git a/src/batch/Cargo.toml b/src/batch/Cargo.toml index 2ca8ed1be4e77..ef4badfe07666 100644 --- a/src/batch/Cargo.toml +++ b/src/batch/Cargo.toml @@ -16,6 +16,7 @@ normal = ["workspace-hack"] [dependencies] anyhow = "1" arrow-array = { workspace = true } +arrow-array-iceberg = { workspace = true } arrow-schema = { workspace = true } assert_matches = "1" async-recursion = "1" diff --git a/src/common/Cargo.toml b/src/common/Cargo.toml index ba295b56f02ca..ae6f67faf3aac 100644 --- a/src/common/Cargo.toml +++ b/src/common/Cargo.toml @@ -18,6 +18,8 @@ ahash = "0.8" anyhow = "1" arc-swap = "1" arrow-array = { workspace = true } +arrow-array-deltalake = { workspace = true } +arrow-array-iceberg = { workspace = true } arrow-buffer = { workspace = true } arrow-buffer-deltalake = { workspace = true } arrow-buffer-iceberg = { workspace = true } diff --git a/src/connector/Cargo.toml b/src/connector/Cargo.toml index 257b930556c94..3d8bf618eca58 100644 --- a/src/connector/Cargo.toml +++ b/src/connector/Cargo.toml @@ -17,6 +17,7 @@ normal = ["workspace-hack"] anyhow = "1" apache-avro = { workspace = true } arrow-array = { workspace = true } +arrow-array-iceberg = { workspace = true } arrow-row = { workspace = true } arrow-schema = { workspace = true } arrow-schema-iceberg = { workspace = true } diff --git a/src/expr/impl/Cargo.toml b/src/expr/impl/Cargo.toml index 8e7cb36dc27fc..0f69c91e34162 100644 --- a/src/expr/impl/Cargo.toml +++ b/src/expr/impl/Cargo.toml @@ -50,7 +50,6 @@ hex = "0.4" icelake = { workspace = true } itertools = { workspace = true } jsonbb = { workspace = true } -lazy_static = "1.5.0" linkme = { version = "0.3", features = ["used_linker"] } md5 = "0.7" moka = { version = "0.12", features = ["sync"] } diff --git a/src/expr/impl/src/scalar/trigonometric.rs b/src/expr/impl/src/scalar/trigonometric.rs index f5ea625d7d2f3..b00078dc3bd5a 100644 --- a/src/expr/impl/src/scalar/trigonometric.rs +++ b/src/expr/impl/src/scalar/trigonometric.rs @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::f64::consts::PI; - -use lazy_static::lazy_static; use risingwave_common::types::F64; use risingwave_expr::function; @@ -98,73 +95,33 @@ pub fn atanh_f64(input: F64) -> F64 { f64::atanh(input.0).into() } +// Radians per degree, a.k.a. PI / 180 +static RADIANS_PER_DEGREE: f64 = 0.017_453_292_519_943_295; // Constants we use to get more accurate results. +// TODO: use lazy_static // Depend on the machine and have to be evaluated at runtime // See PSQL: https://github.com/postgres/postgres/blob/78ec02d612a9b69039ec2610740f738968fe144d/src/backend/utils/adt/float.c#L2024 -fn sind_30() -> f64 { - lazy_static! { - static ref SIND_30: f64 = f64::sin(30.0 * radians_per_degree()); - } - *SIND_30 -} - -fn one_minus_cosd_60() -> f64 { - lazy_static! { - static ref ONE_MINUS_COSD_60: f64 = 1.0 - f64::cos(60.0 * radians_per_degree()); - } - *ONE_MINUS_COSD_60 -} - -fn tand_45() -> f64 { - lazy_static! { - static ref TAND_45: f64 = f64::tan(45.0 * radians_per_degree()); - } - *TAND_45 -} - -fn cotd_45() -> f64 { - lazy_static! { - static ref COTD_45: f64 = - f64::cos(45.0 * radians_per_degree()) / f64::sin(45.0 * radians_per_degree()); - } - *COTD_45 -} - -fn asin_0_5() -> f64 { - lazy_static! { - static ref ASIN_0_5: f64 = f64::asin(0.5); - } - *ASIN_0_5 -} - -fn acos_0_5() -> f64 { - lazy_static! { - static ref ACOS_0_5: f64 = f64::acos(0.5); - } - *ACOS_0_5 -} - -fn radians_per_degree() -> f64 { - lazy_static! { - static ref RADIANS_PER_DEGREE: f64 = PI / 180.0; - } - *RADIANS_PER_DEGREE -} +static SIND_30: f64 = 0.499_999_999_999_999_94; +static ONE_MINUS_COSD_60: f64 = 0.499_999_999_999_999_9; +static TAND_45: f64 = 1.0; +static COTD_45: f64 = 1.0; +static ASIN_0_5: f64 = 0.523_598_775_598_298_8; +static ACOS_0_5: f64 = 1.047_197_551_196_597_6; // returns the cosine of an angle that lies between 0 and 60 degrees. This will return exactly 1 // when xi s 0, and exactly 0.5 when x is 60 degrees. fn cosd_0_to_60(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let one_minus_cos_x: f64 = 1.0 - f64::cos(x * radians_per_degree()); - 1.0 - (one_minus_cos_x / one_minus_cosd_60()) / 2.0 + let one_minus_cos_x: f64 = 1.0 - f64::cos(x * RADIANS_PER_DEGREE); + 1.0 - (one_minus_cos_x / ONE_MINUS_COSD_60) / 2.0 } // returns the sine of an angle that lies between 0 and 30 degrees. This will return exactly 0 when // x is 0, and exactly 0.5 when x is 30 degrees. fn sind_0_to_30(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let sin_x = f64::sin(x * radians_per_degree()); - (sin_x / sind_30()) / 2.0 + let sin_x = f64::sin(x * RADIANS_PER_DEGREE); + (sin_x / SIND_30) / 2.0 } // returns the cosine of an angle in the first quadrant (0 to 90 degrees). @@ -302,7 +259,7 @@ pub fn cotd_f64(input: F64) -> F64 { } let cot_arg1 = cosd_q1(arg1) / sind_q1(arg1); - let result = sign * (cot_arg1 / cotd_45()); + let result = sign * (cot_arg1 / COTD_45); // On some machines we get cotd(270) = minus zero, but this isn't always // true. For portability, and because the user constituency for this @@ -342,7 +299,7 @@ pub fn tand_f64(input: F64) -> F64 { } let tan_arg1 = sind_q1(arg1) / cosd_q1(arg1); - let result = sign * (tan_arg1 / tand_45()); + let result = sign * (tan_arg1 / TAND_45); // On some machines we get tand(180) = minus zero, but this isn't always true. For portability, // and because the user constituency for this function probably doesn't want minus zero, force @@ -361,11 +318,11 @@ pub fn asind_q1(x: f64) -> f64 { // monotonic functionover the full range. if x <= 0.5 { let asin_x = f64::asin(x); - return (asin_x / asin_0_5()) * 30.0; + return (asin_x / ASIN_0_5) * 30.0; } let acos_x = f64::acos(x); - 90.0 - (acos_x / acos_0_5()) * 60.0 + 90.0 - (acos_x / ACOS_0_5) * 60.0 } #[function("asind(float8) -> float8")] @@ -403,10 +360,10 @@ fn acosd_q1(x: f64) -> f64 { // monotonic function over the full range. if x <= 0.5 { let asin_x = f64::asin(x); - return 90.0 - (asin_x / asin_0_5()) * 30.0; + return 90.0 - (asin_x / ASIN_0_5) * 30.0; } let acos_x = f64::acos(x); - (acos_x / acos_0_5()) * 60.0 + (acos_x / ACOS_0_5) * 60.0 } #[function("acosd(float8) -> float8")] From 80a9c340ec4b4a097f0e3b8fb2d94eead1351562 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Thu, 27 Jun 2024 19:10:43 +0200 Subject: [PATCH 10/14] try more precise --- src/expr/impl/src/scalar/trigonometric.rs | 58 +++++++++++++++-------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/expr/impl/src/scalar/trigonometric.rs b/src/expr/impl/src/scalar/trigonometric.rs index b00078dc3bd5a..02a7e88d4b459 100644 --- a/src/expr/impl/src/scalar/trigonometric.rs +++ b/src/expr/impl/src/scalar/trigonometric.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::f64::consts::PI; + use risingwave_common::types::F64; use risingwave_expr::function; @@ -95,33 +97,51 @@ pub fn atanh_f64(input: F64) -> F64 { f64::atanh(input.0).into() } -// Radians per degree, a.k.a. PI / 180 -static RADIANS_PER_DEGREE: f64 = 0.017_453_292_519_943_295; // Constants we use to get more accurate results. -// TODO: use lazy_static // Depend on the machine and have to be evaluated at runtime // See PSQL: https://github.com/postgres/postgres/blob/78ec02d612a9b69039ec2610740f738968fe144d/src/backend/utils/adt/float.c#L2024 -static SIND_30: f64 = 0.499_999_999_999_999_94; -static ONE_MINUS_COSD_60: f64 = 0.499_999_999_999_999_9; -static TAND_45: f64 = 1.0; -static COTD_45: f64 = 1.0; -static ASIN_0_5: f64 = 0.523_598_775_598_298_8; -static ACOS_0_5: f64 = 1.047_197_551_196_597_6; +fn sind_30() -> f64 { + f64::sin(30.0 * radians_per_degree()) +} + +fn one_minus_cosd_60() -> f64 { + 1.0 - f64::cos(60.0 * radians_per_degree()) +} + +fn tand_45() -> f64 { + f64::tan(45.0 * radians_per_degree()) +} + +fn cotd_45() -> f64 { + f64::cos(45.0 * radians_per_degree()) / f64::sin(45.0 * radians_per_degree()) +} + +fn asin_0_5() -> f64 { + f64::asin(0.5) +} + +fn acos_0_5() -> f64 { + f64::acos(0.5) +} + +fn radians_per_degree() -> f64 { + PI / 180.0 +} // returns the cosine of an angle that lies between 0 and 60 degrees. This will return exactly 1 // when xi s 0, and exactly 0.5 when x is 60 degrees. fn cosd_0_to_60(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let one_minus_cos_x: f64 = 1.0 - f64::cos(x * RADIANS_PER_DEGREE); - 1.0 - (one_minus_cos_x / ONE_MINUS_COSD_60) / 2.0 + let one_minus_cos_x: f64 = 1.0 - f64::cos(x * radians_per_degree()); + 1.0 - (one_minus_cos_x / one_minus_cosd_60()) / 2.0 } // returns the sine of an angle that lies between 0 and 30 degrees. This will return exactly 0 when // x is 0, and exactly 0.5 when x is 30 degrees. fn sind_0_to_30(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let sin_x = f64::sin(x * RADIANS_PER_DEGREE); - (sin_x / SIND_30) / 2.0 + let sin_x = f64::sin(x * radians_per_degree()); + (sin_x / sind_30()) / 2.0 } // returns the cosine of an angle in the first quadrant (0 to 90 degrees). @@ -259,7 +279,7 @@ pub fn cotd_f64(input: F64) -> F64 { } let cot_arg1 = cosd_q1(arg1) / sind_q1(arg1); - let result = sign * (cot_arg1 / COTD_45); + let result = sign * (cot_arg1 / cotd_45()); // On some machines we get cotd(270) = minus zero, but this isn't always // true. For portability, and because the user constituency for this @@ -299,7 +319,7 @@ pub fn tand_f64(input: F64) -> F64 { } let tan_arg1 = sind_q1(arg1) / cosd_q1(arg1); - let result = sign * (tan_arg1 / TAND_45); + let result = sign * (tan_arg1 / tand_45()); // On some machines we get tand(180) = minus zero, but this isn't always true. For portability, // and because the user constituency for this function probably doesn't want minus zero, force @@ -318,11 +338,11 @@ pub fn asind_q1(x: f64) -> f64 { // monotonic functionover the full range. if x <= 0.5 { let asin_x = f64::asin(x); - return (asin_x / ASIN_0_5) * 30.0; + return (asin_x / asin_0_5()) * 30.0; } let acos_x = f64::acos(x); - 90.0 - (acos_x / ACOS_0_5) * 60.0 + 90.0 - (acos_x / acos_0_5()) * 60.0 } #[function("asind(float8) -> float8")] @@ -360,10 +380,10 @@ fn acosd_q1(x: f64) -> f64 { // monotonic function over the full range. if x <= 0.5 { let asin_x = f64::asin(x); - return 90.0 - (asin_x / ASIN_0_5) * 30.0; + return 90.0 - (asin_x / asin_0_5()) * 30.0; } let acos_x = f64::acos(x); - (acos_x / ACOS_0_5) * 60.0 + (acos_x / acos_0_5()) * 60.0 } #[function("acosd(float8) -> float8")] From 716133007232193205164a6473634f4b949613bf Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Thu, 27 Jun 2024 19:20:12 +0200 Subject: [PATCH 11/14] rm duplicate import --- src/expr/impl/src/scalar/trigonometric.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/expr/impl/src/scalar/trigonometric.rs b/src/expr/impl/src/scalar/trigonometric.rs index 02a7e88d4b459..47ad047766711 100644 --- a/src/expr/impl/src/scalar/trigonometric.rs +++ b/src/expr/impl/src/scalar/trigonometric.rs @@ -419,8 +419,6 @@ pub fn radians_f64(input: F64) -> F64 { #[cfg(test)] mod tests { - use std::f64::consts::PI; - use risingwave_common::types::FloatExt; use crate::scalar::trigonometric::*; From ace278fbb1df71a64570bac73fcc495f12ee60d4 Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Fri, 28 Jun 2024 09:52:32 +0200 Subject: [PATCH 12/14] hardcode edge cases --- src/expr/impl/src/scalar/trigonometric.rs | 68 +++++++++++++++++++---- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/src/expr/impl/src/scalar/trigonometric.rs b/src/expr/impl/src/scalar/trigonometric.rs index 47ad047766711..b4b1db192f490 100644 --- a/src/expr/impl/src/scalar/trigonometric.rs +++ b/src/expr/impl/src/scalar/trigonometric.rs @@ -97,42 +97,46 @@ pub fn atanh_f64(input: F64) -> F64 { f64::atanh(input.0).into() } +static DEGREE_THIRTY: f64 = 30.0; +static DEGREE_FORTY_FIVE: f64 = 45.0; +static DEGREE_SIXTY: f64 = 60.0; +static DEGREE_ONE_HALF: f64 = 0.5; +static DEGREE_ONE: f64 = 1.0; +static RADIANS_PER_DEGREE: f64 = 0.017_453_292_519_943_295_769_2; + // Constants we use to get more accurate results. // Depend on the machine and have to be evaluated at runtime // See PSQL: https://github.com/postgres/postgres/blob/78ec02d612a9b69039ec2610740f738968fe144d/src/backend/utils/adt/float.c#L2024 fn sind_30() -> f64 { - f64::sin(30.0 * radians_per_degree()) + f64::sin(DEGREE_THIRTY * RADIANS_PER_DEGREE) } fn one_minus_cosd_60() -> f64 { - 1.0 - f64::cos(60.0 * radians_per_degree()) + DEGREE_ONE - f64::cos(DEGREE_SIXTY * RADIANS_PER_DEGREE) } fn tand_45() -> f64 { - f64::tan(45.0 * radians_per_degree()) + f64::tan(DEGREE_FORTY_FIVE * RADIANS_PER_DEGREE) } fn cotd_45() -> f64 { - f64::cos(45.0 * radians_per_degree()) / f64::sin(45.0 * radians_per_degree()) + f64::cos(DEGREE_FORTY_FIVE * RADIANS_PER_DEGREE) + / f64::sin(DEGREE_FORTY_FIVE * RADIANS_PER_DEGREE) } fn asin_0_5() -> f64 { - f64::asin(0.5) + f64::asin(DEGREE_ONE_HALF) } fn acos_0_5() -> f64 { - f64::acos(0.5) -} - -fn radians_per_degree() -> f64 { - PI / 180.0 + f64::acos(DEGREE_ONE_HALF) } // returns the cosine of an angle that lies between 0 and 60 degrees. This will return exactly 1 // when xi s 0, and exactly 0.5 when x is 60 degrees. fn cosd_0_to_60(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let one_minus_cos_x: f64 = 1.0 - f64::cos(x * radians_per_degree()); + let one_minus_cos_x: f64 = 1.0 - f64::cos(x * RADIANS_PER_DEGREE); 1.0 - (one_minus_cos_x / one_minus_cosd_60()) / 2.0 } @@ -140,7 +144,7 @@ fn cosd_0_to_60(x: f64) -> f64 { // x is 0, and exactly 0.5 when x is 30 degrees. fn sind_0_to_30(x: f64) -> f64 { // https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c - let sin_x = f64::sin(x * radians_per_degree()); + let sin_x = f64::sin(x * RADIANS_PER_DEGREE); (sin_x / sind_30()) / 2.0 } @@ -260,6 +264,20 @@ pub fn cotd_f64(input: F64) -> F64 { let mut arg1 = input.0 % 360.0; let mut sign = 1.0; + // hardcoding exact results. + if arg1 == 45.0 { + return F64::from(1.0); + } + if arg1 == 135.0 { + return F64::from(-1.0); + } + if arg1 == 225. { + return F64::from(1.0); + } + if arg1 == 315.0 { + return F64::from(-1.0); + } + if arg1 < 0.0 { // cotd(-x) = -cotd(x) arg1 = -arg1; @@ -300,6 +318,20 @@ pub fn tand_f64(input: F64) -> F64 { let mut arg1 = input.0 % 360.0; let mut sign = 1.0; + // hardcoding exact results. + if arg1 == 45.0 { + return F64::from(1.0); + } + if arg1 == 135.0 { + return F64::from(-1.0); + } + if arg1 == 225. { + return F64::from(1.0); + } + if arg1 == 315.0 { + return F64::from(-1.0); + } + if arg1 < 0.0 { // tand(-x) = -tand(x) arg1 = -arg1; @@ -644,4 +676,16 @@ mod tests { atanh_f64(F64::from(x.powi(2) - 1.0) / F64::from(x.powi(2) + 1.0)), ); } + + #[test] + fn test_exact() { + assert_eq!(cotd_f64(F64::from(135.0)).0, -1.0); + assert_eq!(cotd_f64(F64::from(225.0)).0, 1.0); + assert_eq!(cotd_f64(F64::from(315.0)).0, -1.0); + assert_eq!(cotd_f64(F64::from(45.0)).0, 1.0); + assert_eq!(tand_f64(F64::from(45.0)).0, 1.0); + assert_eq!(tand_f64(F64::from(135.0)).0, -1.0); + assert_eq!(tand_f64(F64::from(225.0)).0, 1.0); + assert_eq!(tand_f64(F64::from(315.0)).0, -1.0); + } } From d62369681f64d46068bf39f6fc9fc6eea81e2d7c Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Fri, 28 Jun 2024 11:33:41 +0200 Subject: [PATCH 13/14] risedev c --- src/expr/impl/src/scalar/trigonometric.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/expr/impl/src/scalar/trigonometric.rs b/src/expr/impl/src/scalar/trigonometric.rs index b4b1db192f490..2dbaba23228f3 100644 --- a/src/expr/impl/src/scalar/trigonometric.rs +++ b/src/expr/impl/src/scalar/trigonometric.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::f64::consts::PI; - use risingwave_common::types::F64; use risingwave_expr::function; @@ -102,7 +100,7 @@ static DEGREE_FORTY_FIVE: f64 = 45.0; static DEGREE_SIXTY: f64 = 60.0; static DEGREE_ONE_HALF: f64 = 0.5; static DEGREE_ONE: f64 = 1.0; -static RADIANS_PER_DEGREE: f64 = 0.017_453_292_519_943_295_769_2; +static RADIANS_PER_DEGREE: f64 = 0.017_453_292_519_943_295; // Constants we use to get more accurate results. // Depend on the machine and have to be evaluated at runtime From be412e2bb805d28e6c393946e8a8f22174c3a4ee Mon Sep 17 00:00:00 2001 From: CAJan93 Date: Fri, 28 Jun 2024 15:48:18 +0200 Subject: [PATCH 14/14] use pi --- src/expr/impl/src/scalar/trigonometric.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expr/impl/src/scalar/trigonometric.rs b/src/expr/impl/src/scalar/trigonometric.rs index 2dbaba23228f3..325fc85538ffe 100644 --- a/src/expr/impl/src/scalar/trigonometric.rs +++ b/src/expr/impl/src/scalar/trigonometric.rs @@ -475,7 +475,7 @@ mod tests { #[test] fn test_degrees() { let d = F64::from(180); - let pi = F64::from(PI); + let pi = F64::from(core::f64::consts::PI); // sind assert_similar(sin_f64(50_f64.to_radians().into()), sind_f64(F64::from(50)));