Skip to content

Commit f8928e2

Browse files
authored
Fix precision of BigMath.sin(x,prec) and BigMath.cos(x,prec) for large x (#346)
For large x, sin and cos is calculated: sin(x) = sin(x % (2*PI)) cos(x) = cos(x % (2*PI)) When x is large, PI(prec) is not precise enough to calculate `x%(2*PI)`. Extra precision is needed.
1 parent 2f9a424 commit f8928e2

File tree

2 files changed

+6
-2
lines changed

2 files changed

+6
-2
lines changed

lib/bigdecimal/math.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ def sin(x, prec)
6161
one = BigDecimal("1")
6262
two = BigDecimal("2")
6363
x = -x if neg = x < 0
64-
if x > (twopi = two * BigMath.PI(prec))
64+
if x > 6
65+
twopi = two * BigMath.PI(prec + x.exponent)
6566
if x > 30
6667
x %= twopi
6768
else
@@ -105,7 +106,8 @@ def cos(x, prec)
105106
one = BigDecimal("1")
106107
two = BigDecimal("2")
107108
x = -x if x < 0
108-
if x > (twopi = two * BigMath.PI(prec))
109+
if x > 6
110+
twopi = two * BigMath.PI(prec + x.exponent)
109111
if x > 30
110112
x %= twopi
111113
else

test/bigdecimal/test_bigmath.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def test_sin
4949
assert_in_delta(SQRT3 / 2, sin(PI(100) / 3, 100), BigDecimal("1e-100"))
5050
assert_in_delta(SQRT2 / 2, sin(PI(100) / 4, 100), BigDecimal("1e-100"))
5151
assert_fixed_point_precision {|n| sin(BigDecimal("1"), n) }
52+
assert_fixed_point_precision {|n| sin(BigDecimal("1e50"), n) }
5253
assert_fixed_point_precision {|n| sin(BigDecimal("1e-30"), n) }
5354
assert_fixed_point_precision {|n| sin(BigDecimal(PI(50)), n) }
5455
assert_fixed_point_precision {|n| sin(BigDecimal(PI(50) * 100), n) }
@@ -70,6 +71,7 @@ def test_cos
7071
assert_in_delta(SQRT3 / 2, cos(PI(100) / 6, 100), BigDecimal("1e-100"))
7172
assert_in_delta(SQRT2 / 2, cos(PI(100) / 4, 100), BigDecimal("1e-100"))
7273
assert_fixed_point_precision {|n| cos(BigDecimal("1"), n) }
74+
assert_fixed_point_precision {|n| cos(BigDecimal("1e50"), n) }
7375
assert_fixed_point_precision {|n| cos(BigDecimal(PI(50) / 2), n) }
7476
assert_fixed_point_precision {|n| cos(BigDecimal(PI(50) * 201 / 2), n) }
7577
end

0 commit comments

Comments
 (0)