Skip to content

Commit d14b905

Browse files
committed
Acos throws if argument out of range. More test cases.
1 parent b6a8a01 commit d14b905

File tree

2 files changed

+66
-70
lines changed

2 files changed

+66
-70
lines changed

src/Fix64.cs

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -708,70 +708,67 @@ public static Fix64 Tan(Fix64 x) {
708708
/// Returns the arccos of of the specified number, calculated using Atan and Sqrt
709709
/// This function has at least 7 decimals of accuracy.
710710
/// </summary>
711-
public static Fix64 Acos(Fix64 x)
712-
{
713-
if (x.RawValue == 0)
714-
return Fix64.PiOver2;
711+
public static Fix64 Acos(Fix64 x) {
712+
if (x < -One || x > One) {
713+
throw new ArgumentOutOfRangeException(nameof(x));
714+
}
715+
716+
if (x.RawValue == 0) return PiOver2;
715717

716-
Fix64 result = Fix64.Atan(Fix64.Sqrt(One - x * x) / x);
717-
if (x.RawValue < 0)
718-
return result + Fix64.Pi;
719-
else
720-
return result;
718+
var result = Atan(Sqrt(One - x * x) / x);
719+
return x.RawValue < 0 ? result + Pi : result;
721720
}
722721

723722
/// <summary>
724723
/// Returns the arctan of of the specified number, calculated using Euler series
725724
/// This function has at least 7 decimals of accuracy.
726725
/// </summary>
727-
public static Fix64 Atan(Fix64 z)
728-
{
729-
if (z.RawValue == 0)
730-
return Zero;
726+
public static Fix64 Atan(Fix64 z) {
727+
if (z.RawValue == 0) return Zero;
731728

732729
// Force positive values for argument
733730
// Atan(-z) = -Atan(z).
734-
bool neg = (z.RawValue < 0);
735-
if (neg) z = -z;
731+
var neg = z.RawValue < 0;
732+
if (neg) {
733+
z = -z;
734+
}
736735

737736
Fix64 result;
737+
var two = (Fix64)2;
738+
var three = (Fix64)3;
738739

739-
if (z == One)
740-
result = Pi/(Fix64)4;
741-
else
742-
{
743-
bool invert = z > One;
744-
if (invert) z = One / z;
745-
746-
result = One;
747-
Fix64 term = One;
748-
749-
Fix64 zSq = z * z;
750-
Fix64 zSq2 = zSq * (Fix64)2;
751-
Fix64 zSqPlusOne = zSq + One;
752-
Fix64 zSq12 = zSqPlusOne * (Fix64)2;
753-
Fix64 dividend = zSq2;
754-
Fix64 divisor = zSqPlusOne * (Fix64)3;
755-
756-
for (int i = 2; i < 30; i++)
757-
{
758-
term *= dividend / divisor;
759-
result += term;
760-
761-
dividend += zSq2;
762-
divisor += zSq12;
763-
764-
if (term.RawValue == 0)
765-
break;
766-
}
740+
bool invert = z > One;
741+
if (invert) z = One / z;
742+
743+
result = One;
744+
var term = One;
767745

768-
result = result * z / zSqPlusOne;
746+
var zSq = z * z;
747+
var zSq2 = zSq * two;
748+
var zSqPlusOne = zSq + One;
749+
var zSq12 = zSqPlusOne * two;
750+
var dividend = zSq2;
751+
var divisor = zSqPlusOne * three;
769752

770-
if (invert)
771-
result = PiOver2 - result;
753+
for (var i = 2; i < 30; ++i) {
754+
term *= dividend / divisor;
755+
result += term;
756+
757+
dividend += zSq2;
758+
divisor += zSq12;
759+
760+
if (term.RawValue == 0) break;
761+
}
762+
763+
result = result * z / zSqPlusOne;
764+
765+
if (invert) {
766+
result = PiOver2 - result;
772767
}
773768

774-
if (neg) result = -result;
769+
if (neg) {
770+
result = -result;
771+
}
775772
return result;
776773
}
777774

tests/Fix64Tests.cs

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -580,14 +580,16 @@ public void FastSin()
580580
}
581581

582582
[Fact]
583-
public void Acos()
584-
{
583+
public void Acos() {
585584
var maxDelta = 0.00000001m;
586585
var deltas = new List<decimal>();
587586

587+
Assert.Equal(Fix64.Zero, Fix64.Acos(Fix64.One));
588+
Assert.Equal(Fix64.PiOver2, Fix64.Acos(Fix64.Zero));
589+
Assert.Equal(Fix64.Pi, Fix64.Acos(-Fix64.One));
590+
588591
// Precision
589-
for (var x = -1.0; x < 1.0; x += 0.001)
590-
{
592+
for (var x = -1.0; x < 1.0; x += 0.001) {
591593
var xf = (Fix64)x;
592594
var actual = (decimal)Fix64.Acos(xf);
593595
var expected = (decimal)Math.Acos((double)xf);
@@ -596,20 +598,19 @@ public void Acos()
596598
Assert.True(delta <= maxDelta, string.Format("Precision: Acos({0}): expected {1} but got {2}", xf, expected, actual));
597599
}
598600

599-
for (int i = 0; i < m_testCases.Length; ++i)
600-
{
601+
for (int i = 0; i < m_testCases.Length; ++i) {
601602
var b = Fix64.FromRaw(m_testCases[i]);
602603

603-
if (b < -Fix64.One)
604-
continue;
605-
if (b > Fix64.One)
606-
continue;
607-
608-
var expected = (decimal)Math.Acos((double)b);
609-
var actual = (decimal)Fix64.Acos(b);
610-
var delta = Math.Abs(expected - actual);
611-
deltas.Add(delta);
612-
Assert.True(delta <= maxDelta, string.Format("Acos({0}) = expected {1} but got {2}", b, expected, actual));
604+
if (b < -Fix64.One || b > Fix64.One) {
605+
Assert.Throws<ArgumentOutOfRangeException>(() => Fix64.Acos(b));
606+
}
607+
else {
608+
var expected = (decimal)Math.Acos((double)b);
609+
var actual = (decimal)Fix64.Acos(b);
610+
var delta = Math.Abs(expected - actual);
611+
deltas.Add(delta);
612+
Assert.True(delta <= maxDelta, string.Format("Acos({0}) = expected {1} but got {2}", b, expected, actual));
613+
}
613614
}
614615
Console.WriteLine("Max error: {0} ({1} times precision)", deltas.Max(), deltas.Max() / Fix64.Precision);
615616
Console.WriteLine("Average precision: {0} ({1} times precision)", deltas.Average(), deltas.Average() / Fix64.Precision);
@@ -703,14 +704,14 @@ public void Tan()
703704
}
704705

705706
[Fact]
706-
public void Atan()
707-
{
707+
public void Atan() {
708708
var maxDelta = 0.00000001m;
709709
var deltas = new List<decimal>();
710710

711+
Assert.Equal(Fix64.Zero, Fix64.Atan(Fix64.Zero));
712+
711713
// Precision
712-
for (var x = -1.0; x < 1.0; x += 0.0001)
713-
{
714+
for (var x = -1.0; x < 1.0; x += 0.0001) {
714715
var xf = (Fix64)x;
715716
var actual = (decimal)Fix64.Atan(xf);
716717
var expected = (decimal)Math.Atan((double)xf);
@@ -720,8 +721,7 @@ public void Atan()
720721
}
721722

722723
// Scalability and edge cases
723-
foreach (var x in m_testCases)
724-
{
724+
foreach (var x in m_testCases) {
725725
var xf = (Fix64)x;
726726
var actual = (decimal)Fix64.Atan(xf);
727727
var expected = (decimal)Math.Atan((double)xf);
@@ -732,7 +732,6 @@ public void Atan()
732732
Console.WriteLine("Max error: {0} ({1} times precision)", deltas.Max(), deltas.Max() / Fix64.Precision);
733733
Console.WriteLine("Average precision: {0} ({1} times precision)", deltas.Average(), deltas.Average() / Fix64.Precision);
734734
}
735-
736735
//[Fact]
737736
public void AtanBenchmark()
738737
{

0 commit comments

Comments
 (0)