1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package s1
16
17 import (
18 "math"
19 "testing"
20 )
21
22 func TestChordAngleBasics(t *testing.T) {
23 var zeroChord ChordAngle
24 tests := []struct {
25 a, b ChordAngle
26 lessThan bool
27 equal bool
28 }{
29 {NegativeChordAngle, NegativeChordAngle, false, true},
30 {NegativeChordAngle, zeroChord, true, false},
31 {NegativeChordAngle, StraightChordAngle, true, false},
32 {NegativeChordAngle, InfChordAngle(), true, false},
33
34 {zeroChord, zeroChord, false, true},
35 {zeroChord, StraightChordAngle, true, false},
36 {zeroChord, InfChordAngle(), true, false},
37
38 {StraightChordAngle, StraightChordAngle, false, true},
39 {StraightChordAngle, InfChordAngle(), true, false},
40
41 {InfChordAngle(), InfChordAngle(), false, true},
42 {InfChordAngle(), StraightChordAngle, false, false},
43 }
44
45 for _, test := range tests {
46 if got := test.a < test.b; got != test.lessThan {
47 t.Errorf("%v should be less than %v", test.a, test.b)
48 }
49 if got := test.a == test.b; got != test.equal {
50 t.Errorf("%v should be equal to %v", test.a, test.b)
51 }
52 }
53 }
54
55 func TestChordAngleAngleEquality(t *testing.T) {
56 var zeroAngle Angle
57 var zeroChord ChordAngle
58
59 if InfAngle() != InfChordAngle().Angle() {
60 t.Errorf("Infinite ChordAngle to Angle = %v, want %v", InfChordAngle().Angle(), InfAngle())
61 }
62
63 oneEighty := 180 * Degree
64 if oneEighty != StraightChordAngle.Angle() {
65 t.Errorf("Right ChordAngle to degrees = %v, want %v", StraightChordAngle.Angle(), oneEighty)
66 }
67
68 if zeroAngle != zeroChord.Angle() {
69 t.Errorf("Zero ChordAngle to Angle = %v, want %v", zeroChord.Angle(), zeroAngle)
70 }
71
72 d := RightChordAngle.Angle().Degrees()
73 if !float64Near(90, d, 1e-13) {
74 t.Errorf("Right ChordAngle to degrees = %v, want %v", d, 90)
75 }
76
77 }
78
79 func TestChordAngleIsFunctions(t *testing.T) {
80 var zeroChord ChordAngle
81 tests := []struct {
82 have ChordAngle
83 isNegative bool
84 isZero bool
85 isInf bool
86 isSpecial bool
87 }{
88 {zeroChord, false, true, false, false},
89 {NegativeChordAngle, true, false, false, true},
90 {StraightChordAngle, false, false, false, false},
91 {InfChordAngle(), false, false, true, true},
92 }
93
94 for _, test := range tests {
95 if got := test.have < 0; got != test.isNegative {
96 t.Errorf("%v.isNegative() = %t, want %t", test.have, got, test.isNegative)
97 }
98 if got := test.have == 0; got != test.isZero {
99 t.Errorf("%v.isZero() = %t, want %t", test.have, got, test.isZero)
100 }
101 if got := test.have.IsInfinity(); got != test.isInf {
102 t.Errorf("%v.IsInfinity() = %t, want %t", test.have, got, test.isInf)
103 }
104 if got := test.have.isSpecial(); got != test.isSpecial {
105 t.Errorf("%v.isSpecial() = %t, want %t", test.have, got, test.isSpecial)
106 }
107 }
108 }
109
110 func TestChordAngleSuccessor(t *testing.T) {
111 if got, want := NegativeChordAngle.Successor(), ChordAngle(0.0); got != want {
112 t.Errorf("NegativeChordAngle.Successor() = %v, want %v", got, want)
113 }
114 if got, want := StraightChordAngle.Successor(), InfChordAngle(); got != want {
115 t.Errorf("StraightChordAngle.Successor() = %v, want %v", got, want)
116 }
117 if got, want := InfChordAngle().Successor(), InfChordAngle(); got != want {
118 t.Errorf("InfChordAngle.Successor() = %v, want %v", got, want)
119 }
120 x := NegativeChordAngle
121 for i := 0; i < 10; i++ {
122 if x >= x.Successor() {
123 t.Errorf("%d. %0.24f >= %0.24f.Successor() = %0.24f, want <", i, x, x, x.Successor())
124 }
125 x = x.Successor()
126 }
127 }
128
129 func TestChordAnglePredecessor(t *testing.T) {
130 if got, want := InfChordAngle().Predecessor(), StraightChordAngle; got != want {
131 t.Errorf("InfChordAngle.Predecessor() = %v, want %v", got, want)
132 }
133 if got, want := (ChordAngle(0)).Predecessor(), NegativeChordAngle; got != want {
134 t.Errorf("Zero ChordAngle.Predecessor() = %v, want %v", got, want)
135 }
136 if got, want := NegativeChordAngle.Predecessor(), NegativeChordAngle; got != want {
137 t.Errorf("NegativeChordAngle.Predecessor() = %v, want %v", got, want)
138 }
139 x := InfChordAngle()
140 for i := 0; i < 10; i++ {
141 if x <= x.Predecessor() {
142 t.Errorf("%v <= %v.Predecessor() = %v, want <", x, x, x.Predecessor())
143 }
144 x = x.Predecessor()
145 }
146 }
147
148 func TestChordAngleFromAngle(t *testing.T) {
149 for _, angle := range []float64{0, 1, -1, math.Pi} {
150 if got := ChordAngleFromAngle(Angle(angle)).Angle().Radians(); got != angle {
151 t.Errorf("ChordAngleFromAngle(Angle(%v)) = %v, want %v", angle, got, angle)
152 }
153 }
154
155 if got := ChordAngleFromAngle(Angle(math.Pi)); got != StraightChordAngle {
156 t.Errorf("a ChordAngle from an Angle of π = %v, want %v", got, StraightChordAngle)
157 }
158
159 if InfAngle() != ChordAngleFromAngle(InfAngle()).Angle() {
160 t.Errorf("converting infinite Angle to ChordAngle should yield infinite Angle")
161 }
162 }
163
164 func TestChordAngleArithmetic(t *testing.T) {
165 var (
166 zero ChordAngle
167 degree30 = ChordAngleFromAngle(30 * Degree)
168 degree60 = ChordAngleFromAngle(60 * Degree)
169 degree90 = ChordAngleFromAngle(90 * Degree)
170 degree120 = ChordAngleFromAngle(120 * Degree)
171 degree180 = StraightChordAngle
172 )
173
174 addTests := []struct {
175 a, b ChordAngle
176 want ChordAngle
177 }{
178 {zero, zero, zero},
179 {degree60, zero, degree60},
180 {zero, degree60, degree60},
181 {degree30, degree60, degree90},
182 {degree60, degree30, degree90},
183 {degree180, zero, degree180},
184 {degree60, degree30, degree90},
185 {degree90, degree90, degree180},
186 {degree120, degree90, degree180},
187 {degree120, degree120, degree180},
188 {degree30, degree180, degree180},
189 {degree180, degree180, degree180},
190 }
191
192 subTests := []struct {
193 a, b ChordAngle
194 want ChordAngle
195 }{
196 {zero, zero, zero},
197 {degree60, degree60, zero},
198 {degree180, degree180, zero},
199 {zero, degree60, zero},
200 {degree30, degree90, zero},
201 {degree90, degree30, degree60},
202 {degree90, degree60, degree30},
203 {degree180, zero, degree180},
204 }
205
206 for _, test := range addTests {
207 if got := float64(test.a.Add(test.b)); !float64Eq(got, float64(test.want)) {
208 t.Errorf("%v.Add(%v) = %0.24f, want %0.24f", test.a.Angle().Degrees(), test.b.Angle().Degrees(), got, test.want)
209 }
210 }
211 for _, test := range subTests {
212 if got := float64(test.a.Sub(test.b)); !float64Eq(got, float64(test.want)) {
213 t.Errorf("%v.Sub(%v) = %0.24f, want %0.24f", test.a.Angle().Degrees(), test.b.Angle().Degrees(), got, test.want)
214 }
215 }
216 }
217
218 func TestChordAngleTrigonometry(t *testing.T) {
219
220
221
222 const epsilon = 1e-14
223 const iters = 40
224 for iter := 0; iter <= iters; iter++ {
225 radians := math.Pi * float64(iter) / float64(iters)
226 angle := ChordAngleFromAngle(Angle(radians))
227 if !float64Near(math.Sin(radians), angle.Sin(), epsilon) {
228 t.Errorf("(%d/%d)*π. %v.Sin() = %v, want %v", iter, iters, angle, angle.Sin(), math.Sin(radians))
229 }
230 if !float64Near(math.Cos(radians), angle.Cos(), epsilon) {
231 t.Errorf("(%d/%d)*π. %v.Cos() = %v, want %v", iter, iters, angle, angle.Cos(), math.Cos(radians))
232 }
233
234
235
236 if !float64Near(math.Atan(math.Tan(radians)), math.Atan(angle.Tan()), epsilon) {
237 t.Errorf("(%d/%d)*π. %v.Tan() = %v, want %v", iter, iters, angle, angle.Tan(), math.Tan(radians))
238 }
239 }
240
241
242 angle90 := ChordAngleFromSquaredLength(2)
243 angle180 := ChordAngleFromSquaredLength(4)
244 if !float64Eq(1, angle90.Sin()) {
245 t.Errorf("%v.Sin() = %v, want 1", angle90, angle90.Sin())
246 }
247 if !float64Eq(0, angle90.Cos()) {
248 t.Errorf("%v.Cos() = %v, want 0", angle90, angle90.Cos())
249 }
250 if !math.IsInf(angle90.Tan(), 0) {
251 t.Errorf("%v.Tan() should be infinite, but was not.", angle90)
252 }
253 if !float64Eq(0, angle180.Sin()) {
254 t.Errorf("%v.Sin() = %v, want 0", angle180, angle180.Sin())
255 }
256 if !float64Eq(-1, angle180.Cos()) {
257 t.Errorf("%v.Cos() = %v, want -1", angle180, angle180.Cos())
258 }
259 if !float64Eq(0, angle180.Tan()) {
260 t.Errorf("%v.Tan() = %v, want 0", angle180, angle180.Tan())
261 }
262 }
263
264 func TestChordAngleExpanded(t *testing.T) {
265 var zero ChordAngle
266
267 tests := []struct {
268 have ChordAngle
269 add float64
270 want ChordAngle
271 }{
272 {NegativeChordAngle, 5, NegativeChordAngle.Expanded(5)},
273 {InfChordAngle(), -5, InfChordAngle()},
274 {StraightChordAngle, 5, ChordAngleFromSquaredLength(5)},
275 {zero, -5, zero},
276 {ChordAngleFromSquaredLength(1.25), 0.25, ChordAngleFromSquaredLength(1.5)},
277 {ChordAngleFromSquaredLength(0.75), 0.25, ChordAngleFromSquaredLength(1)},
278 }
279
280 for _, test := range tests {
281 if got := test.have.Expanded(test.add); got != test.want {
282 t.Errorf("%v.Expanded(%v) = %v, want %v", test.have, test.add, got, test.want)
283 }
284 }
285 }
286
View as plain text