From eea4e93c1408ef57aebdc7514af51f1acf1d3992 Mon Sep 17 00:00:00 2001 From: drun Date: Thu, 4 Jul 2024 01:07:01 +0200 Subject: [PATCH 1/8] arctanh arccosh arcsinh --- daft/daft.pyi | 6 ++ daft/expressions/expressions.py | 15 ++++ daft/series.py | 12 +++ docs/source/api_docs/expressions.rst | 3 + src/daft-core/src/array/ops/trigonometry.rs | 9 +++ src/daft-core/src/python/series.rs | 21 ++++++ src/daft-dsl/src/functions/numeric/mod.rs | 30 ++++++++ src/daft-dsl/src/python.rs | 15 ++++ tests/expressions/test_expressions.py | 23 ++++++ tests/expressions/typing/test_arithmetic.py | 27 +++++++ tests/table/test_eval.py | 83 +++++++++++++++++++++ 11 files changed, 244 insertions(+) diff --git a/daft/daft.pyi b/daft/daft.pyi index 2d13a8ff37..2e99fcb3ab 100644 --- a/daft/daft.pyi +++ b/daft/daft.pyi @@ -1036,6 +1036,9 @@ class PyExpr: def arccos(self) -> PyExpr: ... def arctan(self) -> PyExpr: ... def arctan2(self, other: PyExpr) -> PyExpr: ... + def arctanh(self) -> PyExpr: ... + def arccosh(self) -> PyExpr: ... + def arcsinh(self) -> PyExpr: ... def degrees(self) -> PyExpr: ... def radians(self) -> PyExpr: ... def log2(self) -> PyExpr: ... @@ -1225,6 +1228,9 @@ class PySeries: def arccos(self) -> PySeries: ... def arctan(self) -> PySeries: ... def arctan2(self, other: PySeries) -> PySeries: ... + def arctanh(self) -> PySeries: ... + def arccosh(self) -> PySeries: ... + def arcsinh(self) -> PySeries: ... def degrees(self) -> PySeries: ... def radians(self) -> PySeries: ... def log2(self) -> PySeries: ... diff --git a/daft/expressions/expressions.py b/daft/expressions/expressions.py index 05ab6e81e8..937e019995 100644 --- a/daft/expressions/expressions.py +++ b/daft/expressions/expressions.py @@ -434,6 +434,21 @@ def arctan2(self, other: Expression) -> Expression: expr = Expression._to_expression(other) return Expression._from_pyexpr(self._expr.arctan2(expr._expr)) + def arctanh(self) -> Expression: + """The elementwise inverse hyperbolic tangent of a numeric expression (``expr.arctanh()``)""" + expr = self._expr.arctanh() + return Expression._from_pyexpr(expr) + + def arccosh(self) -> Expression: + """The elementwise inverse hyperbolic cosine of a numeric expression (``expr.arccosh()``)""" + expr = self._expr.arccosh() + return Expression._from_pyexpr(expr) + + def arcsinh(self) -> Expression: + """The elementwise inverse hyperbolic sine of a numeric expression (``expr.arcsinh()``)""" + expr = self._expr.arcsinh() + return Expression._from_pyexpr(expr) + def radians(self) -> Expression: """The elementwise radians of a numeric expression (``expr.radians()``)""" expr = self._expr.radians() diff --git a/daft/series.py b/daft/series.py index 854b92eeba..c975d00d00 100644 --- a/daft/series.py +++ b/daft/series.py @@ -402,6 +402,18 @@ def arctan2(self, other: Series) -> Series: raise TypeError(f"expected another Series but got {type(other)}") return Series._from_pyseries(self._series.arctan2(other._series)) + def arctanh(self) -> Series: + """The elementwise inverse hyperbolic tangent of a numeric series""" + return Series._from_pyseries(self._series.arctanh()) + + def arccosh(self) -> Series: + """The elementwise inverse hyperbolic cosine of a numeric series""" + return Series._from_pyseries(self._series.arccosh()) + + def arcsinh(self) -> Series: + """The elementwise inverse hyperbolic sine of a numeric series""" + return Series._from_pyseries(self._series.arcsinh()) + def radians(self) -> Series: """The elementwise radians of a numeric series""" return Series._from_pyseries(self._series.radians()) diff --git a/docs/source/api_docs/expressions.rst b/docs/source/api_docs/expressions.rst index 27f143d882..c6aabd4ad6 100644 --- a/docs/source/api_docs/expressions.rst +++ b/docs/source/api_docs/expressions.rst @@ -60,6 +60,9 @@ Numeric Expression.arccos Expression.arctan Expression.arctan2 + Expression.arctanh + Expression.arccosh + Expression.arcsinh Expression.radians Expression.degrees Expression.log2 diff --git a/src/daft-core/src/array/ops/trigonometry.rs b/src/daft-core/src/array/ops/trigonometry.rs index 49e03924cc..834e69b455 100644 --- a/src/daft-core/src/array/ops/trigonometry.rs +++ b/src/daft-core/src/array/ops/trigonometry.rs @@ -19,6 +19,9 @@ pub enum TrigonometricFunction { ArcTan, Radians, Degrees, + ArcTanh, + ArcCosh, + ArcSinh, } impl TrigonometricFunction { @@ -34,6 +37,9 @@ impl TrigonometricFunction { ArcTan => "arctan", Radians => "radians", Degrees => "degrees", + ArcTanh => "arctanh", + ArcCosh => "arccosh", + ArcSinh => "arcsinh", } } } @@ -55,6 +61,9 @@ where ArcTan => self.apply(|v| v.atan()), Radians => self.apply(|v| v.to_radians()), Degrees => self.apply(|v| v.to_degrees()), + ArcTanh => self.apply(|v| v.atanh()), + ArcCosh => self.apply(|v| v.acosh()), + ArcSinh => self.apply(|v| v.asinh()), } } } diff --git a/src/daft-core/src/python/series.rs b/src/daft-core/src/python/series.rs index 39d616b38f..385fb8bff9 100644 --- a/src/daft-core/src/python/series.rs +++ b/src/daft-core/src/python/series.rs @@ -205,6 +205,27 @@ impl PySeries { .into()) } + pub fn arctanh(&self) -> PyResult { + Ok(self + .series + .trigonometry(&TrigonometricFunction::ArcTanh)? + .into()) + } + + pub fn arccosh(&self) -> PyResult { + Ok(self + .series + .trigonometry(&TrigonometricFunction::ArcCosh)? + .into()) + } + + pub fn arcsinh(&self) -> PyResult { + Ok(self + .series + .trigonometry(&TrigonometricFunction::ArcSinh)? + .into()) + } + pub fn log2(&self) -> PyResult { Ok(self.series.log2()?.into()) } diff --git a/src/daft-dsl/src/functions/numeric/mod.rs b/src/daft-dsl/src/functions/numeric/mod.rs index b087fcbc13..9b5b744d5c 100644 --- a/src/daft-dsl/src/functions/numeric/mod.rs +++ b/src/daft-dsl/src/functions/numeric/mod.rs @@ -49,6 +49,9 @@ pub enum NumericExpr { Log(FloatWrapper), Ln, Exp, + ArcTanh, + ArcCosh, + ArcSinh, } impl NumericExpr { @@ -77,6 +80,9 @@ impl NumericExpr { Log(_) => &LogEvaluator(log::LogFunction::Log), Ln => &LogEvaluator(log::LogFunction::Ln), Exp => &ExpEvaluator {}, + ArcTanh => &TrigonometryEvaluator(TrigonometricFunction::ArcTanh), + ArcCosh => &TrigonometryEvaluator(TrigonometricFunction::ArcCosh), + ArcSinh => &TrigonometryEvaluator(TrigonometricFunction::ArcSinh), } } } @@ -209,6 +215,30 @@ pub fn degrees(input: ExprRef) -> ExprRef { .into() } +pub fn arctanh(input: ExprRef) -> ExprRef { + Expr::Function { + func: super::FunctionExpr::Numeric(NumericExpr::ArcTanh), + inputs: vec![input], + } + .into() +} + +pub fn arccosh(input: ExprRef) -> ExprRef { + Expr::Function { + func: super::FunctionExpr::Numeric(NumericExpr::ArcCosh), + inputs: vec![input], + } + .into() +} + +pub fn arcsinh(input: ExprRef) -> ExprRef { + Expr::Function { + func: super::FunctionExpr::Numeric(NumericExpr::ArcSinh), + inputs: vec![input], + } + .into() +} + pub fn log2(input: ExprRef) -> ExprRef { Expr::Function { func: super::FunctionExpr::Numeric(NumericExpr::Log2), diff --git a/src/daft-dsl/src/python.rs b/src/daft-dsl/src/python.rs index e086de0ec7..45de2de01f 100644 --- a/src/daft-dsl/src/python.rs +++ b/src/daft-dsl/src/python.rs @@ -282,6 +282,21 @@ impl PyExpr { Ok(degrees(self.into()).into()) } + pub fn arctanh(&self) -> PyResult { + use functions::numeric::arctanh; + Ok(arctanh(self.into()).into()) + } + + pub fn arccosh(&self) -> PyResult { + use functions::numeric::arccosh; + Ok(arccosh(self.into()).into()) + } + + pub fn arcsinh(&self) -> PyResult { + use functions::numeric::arcsinh; + Ok(arcsinh(self.into()).into()) + } + pub fn log2(&self) -> PyResult { use functions::numeric::log2; Ok(log2(self.into()).into()) diff --git a/tests/expressions/test_expressions.py b/tests/expressions/test_expressions.py index cac5a21c63..3fba23a647 100644 --- a/tests/expressions/test_expressions.py +++ b/tests/expressions/test_expressions.py @@ -194,6 +194,29 @@ def test_repr_functions_atan2() -> None: copied = copy.deepcopy(y) assert repr_out == repr(copied) +def test_repr_functions_arctanh() -> None: + a = col("a") + y = a.arctanh() + repr_out = repr(y) + assert repr_out == "arctanh(col(a))" + copied = copy.deepcopy(y) + assert repr_out == repr(copied) + +def test_repr_functions_arccosh() -> None: + a = col("a") + y = a.arccosh() + repr_out = repr(y) + assert repr_out == "arccosh(col(a))" + copied = copy.deepcopy(y) + assert repr_out == repr(copied) + +def test_repr_functions_arcsinh() -> None: + a = col("a") + y = a.arcsinh() + repr_out = repr(y) + assert repr_out == "arcsinh(col(a))" + copied = copy.deepcopy(y) + assert repr_out == repr(copied) def test_repr_functions_day() -> None: a = col("a") diff --git a/tests/expressions/typing/test_arithmetic.py b/tests/expressions/typing/test_arithmetic.py index e2422c83c9..e9299f4ead 100644 --- a/tests/expressions/typing/test_arithmetic.py +++ b/tests/expressions/typing/test_arithmetic.py @@ -196,6 +196,33 @@ def test_atan2(binary_data_fixture): resolvable=is_numeric(lhs.datatype()) and is_numeric(rhs.datatype()), ) +def test_atanh(unary_data_fixture): + arg = unary_data_fixture + assert_typing_resolve_vs_runtime_behavior( + data=(unary_data_fixture,), + expr=col(arg.name()).atanh(), + run_kernel=lambda: arg.atanh(), + resolvable=is_numeric(arg.datatype()), + ) + +def test_asinh(unary_data_fixture): + arg = unary_data_fixture + assert_typing_resolve_vs_runtime_behavior( + data=(unary_data_fixture,), + expr=col(arg.name()).asinh(), + run_kernel=lambda: arg.asinh(), + resolvable=is_numeric(arg.datatype()), + ) + +def test_acosh(unary_data_fixture): + arg = unary_data_fixture + assert_typing_resolve_vs_runtime_behavior( + data=(unary_data_fixture,), + expr=col(arg.name()).acosh(), + run_kernel=lambda: arg.acosh(), + resolvable=is_numeric(arg.datatype()), + ) + def test_exp(unary_data_fixture): arg = unary_data_fixture diff --git a/tests/table/test_eval.py b/tests/table/test_eval.py index ccf9265a4b..0298ffddc6 100644 --- a/tests/table/test_eval.py +++ b/tests/table/test_eval.py @@ -366,6 +366,89 @@ def test_table_numeric_atan2_literals() -> None: is True ) +def test_table_numeric_arctanh() -> None: + table = MicroPartition.from_pydict({"a": [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, math.nan]}) + s = table.to_pandas()["a"] + np_result = np.arctanh(s) + + arct = table.eval_expression_list([col("a").arctanh()]) + assert ( + all( + x == y or (math.isnan(x) and math.isnan(y)) + for x, y in zip(arct.get_column("a").to_pylist(), np_result.to_list()) + ) + is True + ) + +def test_table_numeric_arctanh_literals() -> None: + table = MicroPartition.from_pydict({"a": [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, math.nan]}) + literals = [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, math.nan] + for litv in literals: + np_result = np.arctanh(np.repeat(litv, len(table))) + arct = table.eval_expression_list([lit(litv).arctanh()]) + assert ( + all( + x == y or (math.isnan(x) and math.isnan(y)) + for x, y in zip(arct.get_column("a").to_pylist(), np_result.to_list()) + ) + is True + ) + +def test_table_numeric_arcsinh() -> None: + table = MicroPartition.from_pydict({"a": [0.0, 1.0, 0.5, -0.5, -0.0, math.nan]}) + s = table.to_pandas()["a"] + np_result = np.arcsinh(s) + + arcs = table.eval_expression_list([col("a").arcsinh()]) + assert ( + all( + x == y or (math.isnan(x) and math.isnan(y)) + for x, y in zip(arcs.get_column("a").to_pylist(), np_result.to_list()) + ) + is True + ) + +def test_table_numeric_arcsinh_literals() -> None: + table = MicroPartition.from_pydict({"a": [0.0, 1.0, 0.5, -0.5, -0.0, math.nan]}) + literals = [0.0, 1.0, 0.5, -0.5, -0.0, math.nan] + for litv in literals: + np_result = np.arcsinh(np.repeat(litv, len(table))) + arcs = table.eval_expression_list([lit(litv).arcsinh()]) + assert ( + all( + x == y or (math.isnan(x) and math.isnan(y)) + for x, y in zip(arcs.get_column("a").to_pylist(), np_result.to_list()) + ) + is True + ) + +def test_table_numeric_arccosh() -> None: + table = MicroPartition.from_pydict({"a": [1.0, 2.0, 1.5, math.nan]}) + s = table.to_pandas()["a"] + np_result = np.arccosh(s) + + arcc = table.eval_expression_list([col("a").arccosh()]) + assert ( + all( + x == y or (math.isnan(x) and math.isnan(y)) + for x, y in zip(arcc.get_column("a").to_pylist(), np_result.to_list()) + ) + is True + ) + +def test_table_numeric_arccosh_literals() -> None: + table = MicroPartition.from_pydict({"a": [1.0, 2.0, 1.5, math.nan]}) + literals = [1.0, 2.0, 1.5, math.nan] + for litv in literals: + np_result = np.arccosh(np.repeat(litv, len(table))) + arcc = table.eval_expression_list([lit(litv).arccosh()]) + assert ( + all( + x == y or (math.isnan(x) and math.isnan(y)) + for x, y in zip(arcc.get_column("a").to_pylist(), np_result.to_list()) + ) + is True + ) def test_table_numeric_round() -> None: from decimal import ROUND_HALF_UP, Decimal From ff2a867f4fbe100068e729bf0d82614d5a388fbe Mon Sep 17 00:00:00 2001 From: drun Date: Thu, 4 Jul 2024 01:42:45 +0200 Subject: [PATCH 2/8] test fix --- tests/expressions/typing/test_arithmetic.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/expressions/typing/test_arithmetic.py b/tests/expressions/typing/test_arithmetic.py index e9299f4ead..e5c61ee7ac 100644 --- a/tests/expressions/typing/test_arithmetic.py +++ b/tests/expressions/typing/test_arithmetic.py @@ -200,8 +200,8 @@ def test_atanh(unary_data_fixture): arg = unary_data_fixture assert_typing_resolve_vs_runtime_behavior( data=(unary_data_fixture,), - expr=col(arg.name()).atanh(), - run_kernel=lambda: arg.atanh(), + expr=col(arg.name()).arctanh(), + run_kernel=lambda: arg.arctanh(), resolvable=is_numeric(arg.datatype()), ) @@ -209,8 +209,8 @@ def test_asinh(unary_data_fixture): arg = unary_data_fixture assert_typing_resolve_vs_runtime_behavior( data=(unary_data_fixture,), - expr=col(arg.name()).asinh(), - run_kernel=lambda: arg.asinh(), + expr=col(arg.name()).arcsinh(), + run_kernel=lambda: arg.arcsinh(), resolvable=is_numeric(arg.datatype()), ) @@ -218,8 +218,8 @@ def test_acosh(unary_data_fixture): arg = unary_data_fixture assert_typing_resolve_vs_runtime_behavior( data=(unary_data_fixture,), - expr=col(arg.name()).acosh(), - run_kernel=lambda: arg.acosh(), + expr=col(arg.name()).arccosh(), + run_kernel=lambda: arg.arccosh(), resolvable=is_numeric(arg.datatype()), ) From f1a4dfac5138f2065cfdcac53cdc507b665b0e82 Mon Sep 17 00:00:00 2001 From: drun Date: Thu, 4 Jul 2024 02:13:55 +0200 Subject: [PATCH 3/8] test fix --- tests/table/test_eval.py | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/tests/table/test_eval.py b/tests/table/test_eval.py index 0298ffddc6..1f9b05fa74 100644 --- a/tests/table/test_eval.py +++ b/tests/table/test_eval.py @@ -380,20 +380,6 @@ def test_table_numeric_arctanh() -> None: is True ) -def test_table_numeric_arctanh_literals() -> None: - table = MicroPartition.from_pydict({"a": [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, math.nan]}) - literals = [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, math.nan] - for litv in literals: - np_result = np.arctanh(np.repeat(litv, len(table))) - arct = table.eval_expression_list([lit(litv).arctanh()]) - assert ( - all( - x == y or (math.isnan(x) and math.isnan(y)) - for x, y in zip(arct.get_column("a").to_pylist(), np_result.to_list()) - ) - is True - ) - def test_table_numeric_arcsinh() -> None: table = MicroPartition.from_pydict({"a": [0.0, 1.0, 0.5, -0.5, -0.0, math.nan]}) s = table.to_pandas()["a"] @@ -408,19 +394,6 @@ def test_table_numeric_arcsinh() -> None: is True ) -def test_table_numeric_arcsinh_literals() -> None: - table = MicroPartition.from_pydict({"a": [0.0, 1.0, 0.5, -0.5, -0.0, math.nan]}) - literals = [0.0, 1.0, 0.5, -0.5, -0.0, math.nan] - for litv in literals: - np_result = np.arcsinh(np.repeat(litv, len(table))) - arcs = table.eval_expression_list([lit(litv).arcsinh()]) - assert ( - all( - x == y or (math.isnan(x) and math.isnan(y)) - for x, y in zip(arcs.get_column("a").to_pylist(), np_result.to_list()) - ) - is True - ) def test_table_numeric_arccosh() -> None: table = MicroPartition.from_pydict({"a": [1.0, 2.0, 1.5, math.nan]}) @@ -436,19 +409,6 @@ def test_table_numeric_arccosh() -> None: is True ) -def test_table_numeric_arccosh_literals() -> None: - table = MicroPartition.from_pydict({"a": [1.0, 2.0, 1.5, math.nan]}) - literals = [1.0, 2.0, 1.5, math.nan] - for litv in literals: - np_result = np.arccosh(np.repeat(litv, len(table))) - arcc = table.eval_expression_list([lit(litv).arccosh()]) - assert ( - all( - x == y or (math.isnan(x) and math.isnan(y)) - for x, y in zip(arcc.get_column("a").to_pylist(), np_result.to_list()) - ) - is True - ) def test_table_numeric_round() -> None: from decimal import ROUND_HALF_UP, Decimal From fdcf1f34290da29d52e52a43b0fb302e202a85ea Mon Sep 17 00:00:00 2001 From: drun Date: Thu, 4 Jul 2024 02:37:31 +0200 Subject: [PATCH 4/8] test fix --- tests/table/test_eval.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/table/test_eval.py b/tests/table/test_eval.py index 1f9b05fa74..e1b52be495 100644 --- a/tests/table/test_eval.py +++ b/tests/table/test_eval.py @@ -374,12 +374,13 @@ def test_table_numeric_arctanh() -> None: arct = table.eval_expression_list([col("a").arctanh()]) assert ( all( - x == y or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 or (math.isnan(x) and math.isnan(y)) for x, y in zip(arct.get_column("a").to_pylist(), np_result.to_list()) ) is True ) + def test_table_numeric_arcsinh() -> None: table = MicroPartition.from_pydict({"a": [0.0, 1.0, 0.5, -0.5, -0.0, math.nan]}) s = table.to_pandas()["a"] @@ -388,7 +389,7 @@ def test_table_numeric_arcsinh() -> None: arcs = table.eval_expression_list([col("a").arcsinh()]) assert ( all( - x == y or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 or (math.isnan(x) and math.isnan(y)) for x, y in zip(arcs.get_column("a").to_pylist(), np_result.to_list()) ) is True @@ -403,7 +404,7 @@ def test_table_numeric_arccosh() -> None: arcc = table.eval_expression_list([col("a").arccosh()]) assert ( all( - x == y or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 or (math.isnan(x) and math.isnan(y)) for x, y in zip(arcc.get_column("a").to_pylist(), np_result.to_list()) ) is True From e380e825c556bf8fe5d168806d88b436baf10474 Mon Sep 17 00:00:00 2001 From: drun Date: Thu, 4 Jul 2024 02:39:32 +0200 Subject: [PATCH 5/8] test fix --- tests/table/test_eval.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/table/test_eval.py b/tests/table/test_eval.py index e1b52be495..c9044a930a 100644 --- a/tests/table/test_eval.py +++ b/tests/table/test_eval.py @@ -374,7 +374,7 @@ def test_table_numeric_arctanh() -> None: arct = table.eval_expression_list([col("a").arctanh()]) assert ( all( - x - y < 1.0e-10 or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 or (x is None and y is None) or (math.isnan(x) and math.isnan(y)) for x, y in zip(arct.get_column("a").to_pylist(), np_result.to_list()) ) is True @@ -389,7 +389,7 @@ def test_table_numeric_arcsinh() -> None: arcs = table.eval_expression_list([col("a").arcsinh()]) assert ( all( - x - y < 1.0e-10 or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 or (x is None and y is None)or (math.isnan(x) and math.isnan(y)) for x, y in zip(arcs.get_column("a").to_pylist(), np_result.to_list()) ) is True @@ -404,7 +404,7 @@ def test_table_numeric_arccosh() -> None: arcc = table.eval_expression_list([col("a").arccosh()]) assert ( all( - x - y < 1.0e-10 or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 or (x is None and y is None) or (math.isnan(x) and math.isnan(y)) for x, y in zip(arcc.get_column("a").to_pylist(), np_result.to_list()) ) is True From 6a040b3fc6fbb72982331356af4d4018f7bdb94d Mon Sep 17 00:00:00 2001 From: drun Date: Thu, 4 Jul 2024 10:14:46 +0200 Subject: [PATCH 6/8] fmt --- daft/expressions/expressions.py | 4 ++-- daft/series.py | 4 ++-- tests/expressions/test_expressions.py | 4 ++++ tests/expressions/typing/test_arithmetic.py | 3 +++ tests/table/test_eval.py | 3 ++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/daft/expressions/expressions.py b/daft/expressions/expressions.py index 937e019995..e9144048d9 100644 --- a/daft/expressions/expressions.py +++ b/daft/expressions/expressions.py @@ -438,12 +438,12 @@ def arctanh(self) -> Expression: """The elementwise inverse hyperbolic tangent of a numeric expression (``expr.arctanh()``)""" expr = self._expr.arctanh() return Expression._from_pyexpr(expr) - + def arccosh(self) -> Expression: """The elementwise inverse hyperbolic cosine of a numeric expression (``expr.arccosh()``)""" expr = self._expr.arccosh() return Expression._from_pyexpr(expr) - + def arcsinh(self) -> Expression: """The elementwise inverse hyperbolic sine of a numeric expression (``expr.arcsinh()``)""" expr = self._expr.arcsinh() diff --git a/daft/series.py b/daft/series.py index c975d00d00..ff09a2a588 100644 --- a/daft/series.py +++ b/daft/series.py @@ -405,11 +405,11 @@ def arctan2(self, other: Series) -> Series: def arctanh(self) -> Series: """The elementwise inverse hyperbolic tangent of a numeric series""" return Series._from_pyseries(self._series.arctanh()) - + def arccosh(self) -> Series: """The elementwise inverse hyperbolic cosine of a numeric series""" return Series._from_pyseries(self._series.arccosh()) - + def arcsinh(self) -> Series: """The elementwise inverse hyperbolic sine of a numeric series""" return Series._from_pyseries(self._series.arcsinh()) diff --git a/tests/expressions/test_expressions.py b/tests/expressions/test_expressions.py index 3fba23a647..83e0564a4f 100644 --- a/tests/expressions/test_expressions.py +++ b/tests/expressions/test_expressions.py @@ -194,6 +194,7 @@ def test_repr_functions_atan2() -> None: copied = copy.deepcopy(y) assert repr_out == repr(copied) + def test_repr_functions_arctanh() -> None: a = col("a") y = a.arctanh() @@ -202,6 +203,7 @@ def test_repr_functions_arctanh() -> None: copied = copy.deepcopy(y) assert repr_out == repr(copied) + def test_repr_functions_arccosh() -> None: a = col("a") y = a.arccosh() @@ -210,6 +212,7 @@ def test_repr_functions_arccosh() -> None: copied = copy.deepcopy(y) assert repr_out == repr(copied) + def test_repr_functions_arcsinh() -> None: a = col("a") y = a.arcsinh() @@ -218,6 +221,7 @@ def test_repr_functions_arcsinh() -> None: copied = copy.deepcopy(y) assert repr_out == repr(copied) + def test_repr_functions_day() -> None: a = col("a") y = a.dt.day() diff --git a/tests/expressions/typing/test_arithmetic.py b/tests/expressions/typing/test_arithmetic.py index e5c61ee7ac..55ec9ac2af 100644 --- a/tests/expressions/typing/test_arithmetic.py +++ b/tests/expressions/typing/test_arithmetic.py @@ -196,6 +196,7 @@ def test_atan2(binary_data_fixture): resolvable=is_numeric(lhs.datatype()) and is_numeric(rhs.datatype()), ) + def test_atanh(unary_data_fixture): arg = unary_data_fixture assert_typing_resolve_vs_runtime_behavior( @@ -205,6 +206,7 @@ def test_atanh(unary_data_fixture): resolvable=is_numeric(arg.datatype()), ) + def test_asinh(unary_data_fixture): arg = unary_data_fixture assert_typing_resolve_vs_runtime_behavior( @@ -214,6 +216,7 @@ def test_asinh(unary_data_fixture): resolvable=is_numeric(arg.datatype()), ) + def test_acosh(unary_data_fixture): arg = unary_data_fixture assert_typing_resolve_vs_runtime_behavior( diff --git a/tests/table/test_eval.py b/tests/table/test_eval.py index c9044a930a..9566786df6 100644 --- a/tests/table/test_eval.py +++ b/tests/table/test_eval.py @@ -366,6 +366,7 @@ def test_table_numeric_atan2_literals() -> None: is True ) + def test_table_numeric_arctanh() -> None: table = MicroPartition.from_pydict({"a": [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, math.nan]}) s = table.to_pandas()["a"] @@ -389,7 +390,7 @@ def test_table_numeric_arcsinh() -> None: arcs = table.eval_expression_list([col("a").arcsinh()]) assert ( all( - x - y < 1.0e-10 or (x is None and y is None)or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 or (x is None and y is None) or (math.isnan(x) and math.isnan(y)) for x, y in zip(arcs.get_column("a").to_pylist(), np_result.to_list()) ) is True From 7b1dc0933e5c441017880116bad717292d0752ed Mon Sep 17 00:00:00 2001 From: drun Date: Fri, 5 Jul 2024 15:26:16 +0200 Subject: [PATCH 7/8] edit test --- tests/table/test_eval.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/table/test_eval.py b/tests/table/test_eval.py index 9566786df6..d7a4923b68 100644 --- a/tests/table/test_eval.py +++ b/tests/table/test_eval.py @@ -368,7 +368,7 @@ def test_table_numeric_atan2_literals() -> None: def test_table_numeric_arctanh() -> None: - table = MicroPartition.from_pydict({"a": [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, math.nan]}) + table = MicroPartition.from_pydict({"a": [0.0, 0.5, 0.9, -0.9, -0.5, -0.0, 1, -1.3, math.nan]}) s = table.to_pandas()["a"] np_result = np.arctanh(s) @@ -398,7 +398,7 @@ def test_table_numeric_arcsinh() -> None: def test_table_numeric_arccosh() -> None: - table = MicroPartition.from_pydict({"a": [1.0, 2.0, 1.5, math.nan]}) + table = MicroPartition.from_pydict({"a": [1.0, 2.0, 1.5, 0.5, math.nan]}) s = table.to_pandas()["a"] np_result = np.arccosh(s) From 7fdd9212ef289dd65b2052a506e45110a13814bb Mon Sep 17 00:00:00 2001 From: drun Date: Fri, 5 Jul 2024 15:57:07 +0200 Subject: [PATCH 8/8] inf check --- tests/table/test_eval.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/table/test_eval.py b/tests/table/test_eval.py index d7a4923b68..0c78a60326 100644 --- a/tests/table/test_eval.py +++ b/tests/table/test_eval.py @@ -375,7 +375,9 @@ def test_table_numeric_arctanh() -> None: arct = table.eval_expression_list([col("a").arctanh()]) assert ( all( - x - y < 1.0e-10 or (x is None and y is None) or (math.isnan(x) and math.isnan(y)) + x - y < 1.0e-10 + or (x is None and y is None) + or (math.isnan(x) and math.isnan(y) or math.isinf(x) and math.isinf(y)) for x, y in zip(arct.get_column("a").to_pylist(), np_result.to_list()) ) is True