Skip to content

Commit c16da25

Browse files
authored
feat: support missing functions non-finite (#19)
* feat: support missing functions non-finite * test: add tests
1 parent 2be6ebe commit c16da25

File tree

2 files changed

+81
-9
lines changed

2 files changed

+81
-9
lines changed

lib/complex.ex

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,11 @@ defmodule Complex do
10411041

10421042
def asin(n) when is_number(n), do: :math.asin(n)
10431043

1044+
def asin(n) when is_non_finite_number(n), do: :nan
1045+
1046+
def asin(%Complex{re: re, im: im}) when is_non_finite_number(re) or is_non_finite_number(im),
1047+
do: new(:nan, :nan)
1048+
10441049
def asin(z = %Complex{}) do
10451050
i = new(0.0, 1.0)
10461051
# result = -i*ln(i*z + sqrt(1.0-z*z))
@@ -1110,6 +1115,11 @@ defmodule Complex do
11101115

11111116
def acos(n) when is_number(n), do: :math.acos(n)
11121117

1118+
def acos(n) when is_non_finite_number(n), do: :nan
1119+
1120+
def acos(%Complex{re: re, im: im}) when is_non_finite_number(re) or is_non_finite_number(im),
1121+
do: new(:nan, :nan)
1122+
11131123
def acos(z = %Complex{}) do
11141124
i = new(0.0, 1.0)
11151125
one = new(1.0, 0.0)
@@ -1137,7 +1147,7 @@ defmodule Complex do
11371147

11381148
def tan(n) when is_number(n), do: :math.tan(n)
11391149

1140-
def tan(z = %Complex{}) do
1150+
def tan(z) do
11411151
divide(sin(z), cos(z))
11421152
end
11431153

@@ -1233,13 +1243,12 @@ defmodule Complex do
12331243
%Complex{im: -2.962299212953233e-16, re: 0.45765755436028577}
12341244
12351245
"""
1236-
@spec cot(t) :: t
1237-
@spec cot(number) :: number
1246+
@spec cot(t | number | non_finite_number) :: t | number | non_finite_number
12381247
def cot(z)
12391248

12401249
def cot(n) when is_number(n), do: 1 / :math.tan(n)
12411250

1242-
def cot(z = %Complex{}) do
1251+
def cot(z) do
12431252
divide(cos(z), sin(z))
12441253
end
12451254

@@ -1260,13 +1269,16 @@ defmodule Complex do
12601269
%Complex{im: 2.9999999999999996, re: 1.9999999999999993}
12611270
12621271
"""
1263-
@spec acot(t) :: t
1264-
@spec acot(number) :: number
1272+
@spec acot(t | number | non_finite_number) :: t | number | non_finite_number
12651273
def acot(z)
12661274

12671275
def acot(n) when is_number(n), do: :math.atan(1 / n)
12681276

1269-
def acot(z = %Complex{}) do
1277+
def acot(:infinity), do: 0
1278+
def acot(:neg_infinity), do: :math.pi()
1279+
def acot(:nan), do: :nan
1280+
1281+
def acot(z) do
12701282
i = new(0.0, 1.0)
12711283
# result = 0.5*i*(ln(1-i/z)-ln(1+i/z))
12721284
t1 = multiply(new(0.5, 0.0), i)
@@ -1318,6 +1330,10 @@ defmodule Complex do
13181330
:math.acos(1 / n)
13191331
end
13201332

1333+
def asec(:infinity), do: :math.pi() / 2
1334+
def asec(:neg_infinity), do: 3 * :math.pi() / 2
1335+
def asec(:nan), do: :nan
1336+
13211337
def asec(z = %Complex{}) do
13221338
i = new(0.0, 1.0)
13231339
# result = -i*ln(i*sqrt(1-1/(z*z))+1/z)
@@ -1367,11 +1383,13 @@ defmodule Complex do
13671383
%Complex{im: 3.0, re: 1.9999999999999993}
13681384
13691385
"""
1370-
@spec acsc(t) :: t
1371-
@spec acsc(number) :: number
1386+
@spec acsc(t | number | non_finite_number) :: t | number | non_finite_number
13721387
def acsc(z)
13731388

13741389
def acsc(n) when is_number(n), do: :math.asin(1 / n)
1390+
def acsc(:infinity), do: 0
1391+
def acsc(:neg_infinity), do: -:math.pi()
1392+
def acsc(:nan), do: :nan
13751393

13761394
def acsc(z = %Complex{}) do
13771395
i = new(0.0, 1.0)
@@ -1445,6 +1463,10 @@ defmodule Complex do
14451463
end
14461464
end
14471465

1466+
def asinh(:infinity), do: :infinity
1467+
def asinh(:neg_infinity), do: :neg_infinity
1468+
def asinh(:nan), do: :nan
1469+
14481470
def asinh(z) do
14491471
# result = ln(z+sqrt(z*z+1))
14501472
# result = ln(z+sqrt(t1))
@@ -1506,6 +1528,13 @@ defmodule Complex do
15061528
end
15071529
end
15081530

1531+
def acosh(:infinity), do: :infinity
1532+
1533+
def acosh(:neg_infinity),
1534+
do: raise(ArithmeticError, "Complex.acosh(:neg_infinity) is undefined")
1535+
1536+
def acosh(:nan), do: :nan
1537+
15091538
def acosh(z) do
15101539
# result = ln(z+sqrt(z*z-1))
15111540
# result = ln(z+sqrt(t1))

test/complex_test.exs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,49 @@ defmodule ComplexTest do
662662
assert_close Complex.acoth(1.0049698), a
663663
end
664664

665+
test "trig and hyperbolic trig functions non-finite" do
666+
for n <- [:infinity, :neg_infinity, :nan] do
667+
assert Complex.asin(n) == :nan
668+
assert Complex.asin(Complex.new(n)) == Complex.new(:nan, :nan)
669+
assert Complex.asin(Complex.new(n, 1)) == Complex.new(:nan, :nan)
670+
assert Complex.asin(Complex.new(1, n)) == Complex.new(:nan, :nan)
671+
assert Complex.asin(Complex.new(0, n)) == Complex.new(:nan, :nan)
672+
assert Complex.acos(n) == :nan
673+
assert Complex.acos(Complex.new(n)) == Complex.new(:nan, :nan)
674+
assert Complex.acos(Complex.new(n, 1)) == Complex.new(:nan, :nan)
675+
assert Complex.acos(Complex.new(1, n)) == Complex.new(:nan, :nan)
676+
assert Complex.acos(Complex.new(0, n)) == Complex.new(:nan, :nan)
677+
assert Complex.tan(Complex.new(n)) == Complex.new(:nan, :nan)
678+
assert Complex.tan(Complex.new(n, 1)) == Complex.new(:nan, :nan)
679+
assert Complex.tan(Complex.new(1, n)) == Complex.new(:nan, :nan)
680+
assert Complex.tan(Complex.new(0, n)) == Complex.new(:nan, :nan)
681+
assert Complex.cot(Complex.new(n)) == Complex.new(:nan, :nan)
682+
assert Complex.cot(Complex.new(n, 1)) == Complex.new(:nan, :nan)
683+
assert Complex.cot(Complex.new(1, n)) == Complex.new(:nan, :nan)
684+
assert Complex.cot(Complex.new(0, n)) == Complex.new(:nan, :nan)
685+
assert Complex.asinh(n) == n
686+
end
687+
688+
assert Complex.acot(:infinity) == 0
689+
assert Complex.acot(:neg_infinity) == :math.pi()
690+
assert Complex.acot(:nan) == :nan
691+
692+
assert Complex.asec(:infinity) == :math.pi() / 2
693+
assert Complex.asec(:neg_infinity) == 3 * :math.pi() / 2
694+
assert Complex.asec(:nan) == :nan
695+
696+
assert Complex.acsc(:infinity) == 0
697+
assert Complex.acsc(:neg_infinity) == -:math.pi()
698+
assert Complex.acsc(:nan) == :nan
699+
700+
assert Complex.acosh(:infinity) == :infinity
701+
assert Complex.acosh(:nan) == :nan
702+
703+
assert_raise ArithmeticError, "Complex.acosh(:neg_infinity) is undefined", fn ->
704+
Complex.acosh(:neg_infinity)
705+
end
706+
end
707+
665708
for {m, f} <- [{Kernel, :inspect}, {String.Chars.Complex, :to_string}, {Complex, :to_string}] do
666709
test "#{m}.#{f}/1" do
667710
assert "1.0+1.0i" == apply(unquote(m), unquote(f), [Complex.new(1.0, 1.0)])

0 commit comments

Comments
 (0)