YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_angle.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdlib.h>
6#include <stdio.h>
7#include "geometry.h"
8#include "tests.h"
9
15#ifndef M_SQRT3_4
16#define M_SQRT3_4 (0.866025403784438646764) /* sqrt(0.75) */
17#endif
18
19#define NUM_TESTS (1000)
20
21static void utest_generate_rand_angle(
22 double * angle, struct sin_cos_angle * sin_cos_angle);
23
24static struct sin_cos_angle utest_compute_sin_cos_angle(double angle);
25static int utest_compare_double(double a, double b);
26static int utest_compare_size_t(size_t a, size_t b);
27static void utest_check_angle_sum_sub(
28 struct sin_cos_angle a, struct sin_cos_angle b,
29 double ref_sum, double ref_sub);
30static void utest_check_compare_angles(double dble_angle_a, double dble_angle_b,
31 struct sin_cos_angle sin_cos_angle_a,
32 struct sin_cos_angle sin_cos_angle_b);
33
34int main (void) {
35
36 srand(1337);
37
39 double angle;
40
41 // multiples of PI
42 double angles[] = {0.0, 0.24, 0.26, 0.5, 0.8, 1.0, 1.1, 1.5, 1.6, 1.9};
43 for (size_t i = 0; i < sizeof(angles) / sizeof(angles[0]); ++i)
44 angles[i] *= M_PI;
45
46 struct sin_cos_angle sin_cos_angles[] =
47 {(struct sin_cos_angle){.sin = 0.0, .cos = 1.0}, // 0PI
48 (struct sin_cos_angle){.sin = yac_angle_tol, .cos = 1.0}, // 0PI + tol
49 (struct sin_cos_angle){.sin = 0.5, .cos = M_SQRT3_4}, // PI/6
50 (struct sin_cos_angle){.sin = M_SQRT1_2-yac_angle_tol,
51 .cos = M_SQRT1_2+yac_angle_tol}, // PI/4 - tol
52 (struct sin_cos_angle){.sin = M_SQRT1_2, .cos = M_SQRT1_2}, // PI/4
53 (struct sin_cos_angle){.sin = M_SQRT1_2+yac_angle_tol,
54 .cos = M_SQRT1_2-yac_angle_tol}, // PI/4 + tol
55 (struct sin_cos_angle){.sin = M_SQRT3_4, .cos = 0.5}, // PI/3
56 (struct sin_cos_angle){.sin = 1.0, .cos = yac_angle_tol}, // PI/2 - tol
57 (struct sin_cos_angle){.sin = 1.0, .cos = 0.0}, // PI/2
58 (struct sin_cos_angle){.sin = 1.0, .cos = - yac_angle_tol}, // PI/2 + tol
59 (struct sin_cos_angle){.sin = M_SQRT3_4, .cos = -0.5}, // 2PI/3
60 (struct sin_cos_angle){.sin = M_SQRT1_2+yac_angle_tol,
61 .cos = -M_SQRT1_2+yac_angle_tol}, // 3PI/4 - tol
62 (struct sin_cos_angle){.sin = M_SQRT1_2, .cos = -M_SQRT1_2}, // 3PI/4
63 (struct sin_cos_angle){.sin = M_SQRT1_2-yac_angle_tol,
64 .cos = -M_SQRT1_2-yac_angle_tol}, // 3PI/4 + tol
65 (struct sin_cos_angle){.sin = 0.5, .cos = -M_SQRT3_4}, // 5PI/6
66 (struct sin_cos_angle){.sin = yac_angle_tol, .cos = -1.0}, // PI/2 - tol
67 (struct sin_cos_angle){.sin = 0.0, .cos = -1.0}, // PI/2
68 (struct sin_cos_angle){.sin = -yac_angle_tol, .cos = -1.0}, // PI/2 + tol
69 (struct sin_cos_angle){.sin = -0.5, .cos = -M_SQRT3_4}, // 7PI/6
70 (struct sin_cos_angle){.sin = -M_SQRT1_2+yac_angle_tol,
71 .cos = -M_SQRT1_2-yac_angle_tol}, // 5PI/4 - tol
72 (struct sin_cos_angle){.sin = -M_SQRT1_2, .cos = -M_SQRT1_2}, // 5PI/4
73 (struct sin_cos_angle){.sin = -M_SQRT1_2-yac_angle_tol,
74 .cos = -M_SQRT1_2+yac_angle_tol}, // 5PI/4 + tol
75 (struct sin_cos_angle){.sin = -M_SQRT3_4, .cos = -0.5}, // 4PI/3
76 (struct sin_cos_angle){.sin = -1.0, .cos = -yac_angle_tol}, // 3PI/2 - tol
77 (struct sin_cos_angle){.sin = -1.0, .cos = 0.0}, // 3PI/2
78 (struct sin_cos_angle){.sin = -1.0, .cos = yac_angle_tol}, // 3PI/2 + tol
79
80 (struct sin_cos_angle){.sin = -M_SQRT3_4, .cos = 0.5}, // 5PI/3
81 (struct sin_cos_angle){.sin = -M_SQRT1_2-yac_angle_tol,
82 .cos = M_SQRT1_2-yac_angle_tol}, // 7PI/4 - tol
83 (struct sin_cos_angle){.sin = -M_SQRT1_2, .cos = M_SQRT1_2}, // 7PI/4
84 (struct sin_cos_angle){.sin = -M_SQRT1_2+yac_angle_tol,
85 .cos = M_SQRT1_2+yac_angle_tol}, // 7PI/4 + tol
86 (struct sin_cos_angle){.sin = -0.5, .cos = M_SQRT3_4}, // 11PI/6
87 (struct sin_cos_angle){.sin = -yac_angle_tol, .cos = 1.0} // 2PI - tol
88 };
89
90 { // test routine compute_angle
91 for (size_t i = 0; i < sizeof(angles) / sizeof(angles[0]); ++i)
92 if (fabs(compute_angle(utest_compute_sin_cos_angle(angles[i])) - angles[i]) >
94 PUT_ERR("error in compute_angle");
95
96 for (size_t i = 0; i < NUM_TESTS; ++i) {
97 double temp_angle;
98 utest_generate_rand_angle(&temp_angle, &sin_cos_angle);
99 if (fabs(temp_angle - compute_angle(sin_cos_angle)) > yac_angle_tol)
100 PUT_ERR("error in compute_angle");
101 }
102 }
103
104 { // test routine compare_angles and sin_cos_angle_to_dble
105 for (size_t i = 0; i < sizeof(angles)/sizeof(angles[0]); ++i) {
106 for (size_t j = 0; j < sizeof(angles)/sizeof(angles[0]); ++j) {
107 struct sin_cos_angle temp_sin_cos_angles[2] =
108 {utest_compute_sin_cos_angle(angles[i]), utest_compute_sin_cos_angle(angles[j])};
109 utest_check_compare_angles(
110 angles[i], angles[j], temp_sin_cos_angles[0], temp_sin_cos_angles[1]);
111 }
112 }
113
114 for (size_t i = 0; i < NUM_TESTS; ++i) {
115 double temp_angles[2];
116 struct sin_cos_angle temp_sin_cos_angles[2];
117 for (size_t j = 0; j < 2; ++j)
118 utest_generate_rand_angle(&(temp_angles[j]), &(temp_sin_cos_angles[j]));
119 for (size_t j = 0; j < 2; ++j)
120 for (size_t k = 0; k < 2; ++k)
121 utest_check_compare_angles(temp_angles[j], temp_angles[k],
122 temp_sin_cos_angles[j], temp_sin_cos_angles[k]);
123 }
124
125 for (size_t i = 0; i < sizeof(sin_cos_angles)/sizeof(sin_cos_angles[0]); ++i) {
126 for (size_t j = 0; j < sizeof(sin_cos_angles)/sizeof(sin_cos_angles[0]); ++j) {
127 double temp[2] = {sin_cos_angle_to_dble(sin_cos_angles[i]),
128 sin_cos_angle_to_dble(sin_cos_angles[j])};
129 int compare_ij = utest_compare_size_t(i, j);
130 if ((compare_ij != compare_angles(sin_cos_angles[i], sin_cos_angles[j])) ||
131 (compare_ij != utest_compare_double(temp[0], temp[1])))
132 PUT_ERR("error in compare_angles");
133 }
134 }
135 }
136
137 { // test routine sum_angles, sub_angles
138 for (size_t i = 0; i < sizeof(angles)/sizeof(angles[0]); ++i) {
139 for (size_t j = 0; j < sizeof(angles)/sizeof(angles[0]); ++j) {
140 struct sin_cos_angle temp_sin_cos_angles[2] =
141 {utest_compute_sin_cos_angle(angles[i]), utest_compute_sin_cos_angle(angles[j])};
142 utest_check_angle_sum_sub(temp_sin_cos_angles[0], temp_sin_cos_angles[1],
143 angles[i] + angles[j], angles[i] - angles[j]);
144 }
145 }
146
147 for (size_t i = 0; i < NUM_TESTS; ++i) {
148 double temp_angles[2];
149 struct sin_cos_angle temp_sin_cos_angles[2];
150 for (size_t j = 0; j < 2; ++j)
151 utest_generate_rand_angle(&(temp_angles[j]), &(temp_sin_cos_angles[j]));
152 for (size_t j = 0; j < 2; ++j)
153 for (size_t k = 0; k < 2; ++k)
154 utest_check_angle_sum_sub(
155 temp_sin_cos_angles[j], temp_sin_cos_angles[k],
156 temp_angles[j] + temp_angles[k], temp_angles[j] - temp_angles[k]);
157 }
158 }
159
160 { // test routine half_angle
161 for (size_t i = 0; i < sizeof(angles)/sizeof(angles[0]); ++i)
162 if (fabs(angles[i] * 0.5 -
163 compute_angle(half_angle(utest_compute_sin_cos_angle(angles[i])))) >
165 PUT_ERR("error in half_angle");
166
167 for (size_t i = 0; i < NUM_TESTS; ++i) {
168 utest_generate_rand_angle(&angle, &sin_cos_angle);
169 if (fabs(angle * 0.5 -
171 PUT_ERR("error in half_angle");
172 }
173 }
174
175 { // test routine quarter_angle
176 for (size_t i = 0; i < sizeof(angles)/sizeof(angles[0]); ++i)
177 if (fabs(angles[i] * 0.25 -
178 compute_angle(quarter_angle(utest_compute_sin_cos_angle(angles[i])))) >
180 PUT_ERR("error in quarter_angle");
181
182 if (fabs(M_PI * 0.25 - compute_angle(quarter_angle(SIN_COS_M_PI))) >
183 yac_angle_tol) PUT_ERR("error in quarter_angle");
184
185 for (size_t i = 0; i < NUM_TESTS; ++i) {
186 utest_generate_rand_angle(&angle, &sin_cos_angle);
187 if (fabs(angle * 0.25 -
189 PUT_ERR("error in quarter_angle");
190 }
191 }
192
193 return TEST_EXIT_CODE;
194}
195
196static void utest_generate_rand_angle(
197 double * angle, struct sin_cos_angle * sin_cos_angle) {
198
199 *angle = (2.0 * M_PI) * ((double)rand() / (double)RAND_MAX);
200 *sin_cos_angle = utest_compute_sin_cos_angle(*angle);
201}
202
203static struct sin_cos_angle utest_compute_sin_cos_angle(double angle) {
204
205 double sin_angle = sin(angle);
206 double cos_angle = cos(angle);
207 return sin_cos_angle_new(sin_angle, cos_angle);
208}
209
210static int utest_compare_double(double a, double b) {
211
212 return (a > b) - (a < b);
213}
214
215static int utest_compare_size_t(size_t a, size_t b) {
216
217 return (a > b) - (a < b);
218}
219
220static void utest_check_angle_sum_sub(
221 struct sin_cos_angle a, struct sin_cos_angle b,
222 double ref_sum, double ref_sub) {
223
224 struct sin_cos_angle sum;
225 int big_sum = sum_angles(a, b, &sum);
226
227 double angle_sum = compute_angle(sum) + ((big_sum)?(2.0*M_PI):0.0);
228
229 if (fabs(angle_sum - ref_sum) > yac_angle_tol) PUT_ERR("error sum_angles");
230
231 struct sin_cos_angle sub;
232 int neg = sub_angles(a, b, &sub);
233
234 double angle_sub = compute_angle(sub) - ((neg)?(2.0*M_PI):0.0);
235
236 if (fabs(angle_sub - ref_sub) > yac_angle_tol) PUT_ERR("error sub_angles");
237}
238
239static void utest_check_compare_angles(double dble_angle_a, double dble_angle_b,
240 struct sin_cos_angle sin_cos_angle_a,
241 struct sin_cos_angle sin_cos_angle_b) {
242
243 int ret = utest_compare_double(dble_angle_a, dble_angle_b);
244 if (ret != compare_angles(sin_cos_angle_a, sin_cos_angle_b))
245 PUT_ERR("error in compare_angles");
246 double temp[2] = {sin_cos_angle_to_dble(sin_cos_angle_a),
247 sin_cos_angle_to_dble(sin_cos_angle_b)};
248 if (ret != utest_compare_double(temp[0], temp[1]))
249 PUT_ERR("error in sin_cos_angle_to_dble");
250}
251
static const struct sin_cos_angle SIN_COS_M_PI
Definition geometry.h:41
static double sin_cos_angle_to_dble(struct sin_cos_angle angle)
Definition geometry.h:451
static struct sin_cos_angle quarter_angle(struct sin_cos_angle angle)
Definition geometry.h:563
static int compare_angles(struct sin_cos_angle a, struct sin_cos_angle b)
Definition geometry.h:374
static int sub_angles(struct sin_cos_angle a, struct sin_cos_angle b, struct sin_cos_angle *restrict sub)
Definition geometry.h:504
static double compute_angle(struct sin_cos_angle angle)
return angles in the range of [0;2PI[
Definition geometry.h:518
#define yac_angle_tol
Definition geometry.h:26
static int sum_angles(struct sin_cos_angle a, struct sin_cos_angle b, struct sin_cos_angle *restrict sum)
Definition geometry.h:480
static struct sin_cos_angle sin_cos_angle_new(double sin, double cos)
Definition geometry.h:351
static struct sin_cos_angle half_angle(struct sin_cos_angle angle)
Definition geometry.h:546
double sin
Definition geometry.h:33
double cos
Definition geometry.h:33
#define M_SQRT3_4
Definition test_angle.c:16
#define NUM_TESTS
Definition test_angle.c:19
#define TEST_EXIT_CODE
Definition tests.h:14
#define PUT_ERR(string)
Definition tests.h:10