21static void utest_random_test(
size_t const num_points);
22static void utest_zero_point_test();
23static void utest_single_point_test();
24static void utest_empty_branch_test(
size_t num_points);
25static void utest_zero_balance_point();
26static void utest_duplicated_point_test();
32 for (
size_t i = 0;
i < 10; ++
i) {
34 utest_random_test(10);
35 utest_random_test(100);
36 utest_random_test(650);
38 utest_zero_point_test();
39 utest_single_point_test();
40 utest_empty_branch_test(4);
41 utest_empty_branch_test(128);
42 utest_zero_balance_point();
43 utest_duplicated_point_test();
70 double (*xyz_coordinates)[3],
size_t num_points,
size_t ** local_point_ids,
71 size_t * local_point_ids_array_size,
75 search,
num_points, xyz_coordinates, n, NULL, NULL, NULL, NULL,
76 local_point_ids, local_point_ids_array_size, num_local_point_ids);
79 for (
size_t j = 0, offset = 0; j <
num_points; ++j) {
83 size_t ref_num_local_points = 1, m = 0;
84 for (; (ref_num_local_points <
num_points); ++ref_num_local_points)
86 curr_distances[ref_num_local_points-1].
distance,
87 curr_distances[ref_num_local_points].
distance))
90 if (num_local_point_ids[j] != ref_num_local_points) {
91 PUT_ERR(
"wrong number of local points found\n");
95 size_t num_matching_points = 0;
96 for (
size_t k = 0; k < ref_num_local_points; ++k)
97 for (
size_t l = 0; l < ref_num_local_points; ++l)
98 if (curr_distances[k].
index == (*local_point_ids)[offset+l])
99 ++num_matching_points;
101 if (num_matching_points != ref_num_local_points)
104 offset += ref_num_local_points;
116 search,
num_points, xyz_coordinates, n, angles);
138 size_t cut_off = n / 2;
144 sizeof(*xyz_coordinates));
153 size_t * local_point_ids = NULL;
154 size_t local_point_ids_array_size = 0;
155 size_t * num_local_point_ids =
156 malloc(
num_points *
sizeof(*num_local_point_ids));
159 search,
num_points, bnd_circles, n, &local_point_ids,
160 &local_point_ids_array_size, num_local_point_ids);
165 size_t ref_num_local_point_ids = (i <
num_points / 2)?(n / 2 + 1):n;
166 double ref_distance =
170 i *
num_points + ref_num_local_point_ids].distance == ref_distance);
171 ++ref_num_local_point_ids);
173 if (ref_num_local_point_ids != num_local_point_ids[i])
176 for (
size_t j = 0; j < num_local_point_ids[i]; ++j) {
178 for (
size_t k = 0; (k < num_local_point_ids[i]) && !match_flag; ++k)
180 distances[i *
num_points + k].index == local_point_ids[offset + j];
181 if (!match_flag)
PUT_ERR(
"wrong result");
183 offset += num_local_point_ids[i];
186 free(local_point_ids);
187 free(num_local_point_ids);
192 double x_coordinate = 2.0 * M_PI * (((double)rand()) / ((
double)RAND_MAX));
193 double y_coordinate = M_PI * (((double)rand()) / ((
double)RAND_MAX)) - M_PI_2;
194 LLtoXYZ(x_coordinate, y_coordinate, point);
200 double angle = M_PI_2 * (((double)rand()) / ((
double)RAND_MAX));
205static void utest_random_test(
size_t const num_points) {
207 double (*coordinates_xyz)[3];
208 double (*coordinates_xyz_a)[3];
209 double (*coordinates_xyz_b)[3];
215 coordinates_xyz_a = coordinates_xyz;
216 coordinates_xyz_b = coordinates_xyz +
num_points;
218 size_t * local_point_ids = NULL;
219 size_t local_point_ids_array_size = 0;
220 size_t * num_local_point_ids =
249 for (
size_t n = 1; n < 16; ++n)
251 search, n, coordinates_xyz_b,
num_points, &local_point_ids,
252 &local_point_ids_array_size, num_local_point_ids, distances);
256 search,
num_points, coordinates_xyz_b, n, distances);
260 search,
num_points, coordinates_xyz_b, n, distances);
265 free(local_point_ids);
266 free(num_local_point_ids);
269 free(coordinates_xyz);
272static void utest_single_point_test() {
275 double xyz_coordinate[1][3];
277 double x_coordinate = 0, y_coordinate = 0;
279 LLtoXYZ(x_coordinate, y_coordinate, xyz_coordinate[0]);
285 double x_coordinates[] = {0.0,90.0,180.0,-90.0, 0.0, 0.0};
286 double y_coordinates[] = {0.0, 0.0, 0.0, 0.0,90.0,-90.0};
287 size_t num_points =
sizeof(x_coordinates) /
sizeof(x_coordinates[0]);
290 LLtoXYZ_deg(x_coordinates[i], y_coordinates[i], xyz_coordinates[i]);
292 size_t * local_point_ids = NULL;
293 size_t local_point_ids_array_size = 0;
294 size_t * num_local_point_ids =
298 search,
num_points, xyz_coordinates, NULL, NULL, NULL, &local_point_ids,
299 &local_point_ids_array_size, num_local_point_ids);
302 if ((num_local_point_ids[i] != 1) || (local_point_ids[i] != 0))
303 PUT_ERR(
"utest_single_point_test: wrong result\n");
307 search,
num_points, xyz_coordinates, 1, angles);
313 xyz_coordinate[0], xyz_coordinates[i])) != 0)
316 free(local_point_ids);
317 free(num_local_point_ids);
321static void utest_zero_point_test() {
326 double x_coordinates[] = {0.0,90.0,180.0,-90.0, 0.0, 0.0};
327 double y_coordinates[] = {0.0, 0.0, 0.0, 0.0,90.0,-90.0};
328 size_t num_points =
sizeof(x_coordinates) /
sizeof(x_coordinates[0]);
331 LLtoXYZ_deg(x_coordinates[i], y_coordinates[i], xyz_coordinates[i]);
333 size_t * local_point_ids = NULL;
334 size_t local_point_ids_array_size = 0;
335 size_t * num_local_point_ids =
339 num_local_point_ids[i] = (
size_t)-1;
341 search,
num_points, xyz_coordinates, NULL, NULL, NULL, &local_point_ids,
342 &local_point_ids_array_size, num_local_point_ids);
345 if (num_local_point_ids[i] != 0)
PUT_ERR(
"utest_zero_point_test: wrong result\n");
348 num_local_point_ids[i] = (
size_t)-1;
350 search,
num_points, xyz_coordinates, 16, NULL, NULL, NULL, NULL,
351 &local_point_ids, &local_point_ids_array_size, num_local_point_ids);
354 if (num_local_point_ids[i] != 0)
PUT_ERR(
"utest_zero_point_test: wrong result\n");
356 free(local_point_ids);
357 free(num_local_point_ids);
361static void utest_empty_branch_test(
size_t num_points_a) {
364 malloc(num_points_a *
sizeof(*xyz_coordinates_a));
365 yac_int * global_ids = malloc(num_points_a *
sizeof(*global_ids));
366 for (
size_t i = 0;
i < num_points_a; ++
i) {
367 LLtoXYZ_deg(0.0, -5.0 + (10.0 / (
double)num_points_a) * (
double)i,
368 xyz_coordinates_a[i]);
378 double x_coordinates_b[] = {-1.0,-1.0, 1.0,1.0};
379 double y_coordinates_b[] = {-1.0, 1.0,-1.0,1.0};
380 size_t num_points_b =
sizeof(x_coordinates_b) /
sizeof(x_coordinates_b[0]);
381 double xyz_coordinates_b[num_points_b][3];
382 for (
size_t i = 0;
i < num_points_b; ++
i)
383 LLtoXYZ_deg(x_coordinates_b[i], y_coordinates_b[i], xyz_coordinates_b[i]);
385 size_t * local_point_ids = NULL;
386 size_t local_point_ids_array_size = 0;
387 size_t * num_local_point_ids =
388 xmalloc(num_points_b *
sizeof(*num_local_point_ids));
392 for (
size_t i = 0;
i < num_points_b; ++
i) {
394 for (
size_t j = 0; j < num_points_a; ++j) {
396 distances[
i * num_points_a + j].
distance =
398 distances[
i * num_points_a + j].
index = j;
400 qsort(distances + i * num_points_a, num_points_a,
sizeof(*distances),
404 for (
size_t i = 0;
i < num_points_b; ++
i)
405 num_local_point_ids[i] = (
size_t)-1;
407 search, num_points_b, xyz_coordinates_b, NULL, NULL, NULL,
408 &local_point_ids, &local_point_ids_array_size, num_local_point_ids);
411 for (
size_t j = 0, offset = 0; j < num_points_b; ++j) {
413 struct distance_index * curr_distances = distances + j * num_points_a;
415 size_t ref_num_local_points;
416 for (ref_num_local_points = 1;
417 (ref_num_local_points < num_points_a); ++ref_num_local_points)
419 curr_distances[ref_num_local_points-1].
distance,
420 curr_distances[ref_num_local_points].
distance))
break;
422 if (num_local_point_ids[j] != ref_num_local_points) {
423 PUT_ERR(
"wrong number of local points found\n");
427 size_t num_matching_points = 0;
428 for (
size_t k = 0; k < ref_num_local_points; ++k)
429 for (
size_t l = 0; l < ref_num_local_points; ++l)
430 if (curr_distances[k].
index == local_point_ids[offset+l])
431 ++num_matching_points;
433 if (num_matching_points != ref_num_local_points)
436 offset += ref_num_local_points;
438 free(local_point_ids);
439 free(num_local_point_ids);
444 search, num_points_b, xyz_coordinates_b, 1, angles);
447 for (
size_t j = 0; j < num_points_b; ++j) {
451 for (
size_t i = 0;
i < num_points_a; ++
i) {
455 xyz_coordinates_a[i], xyz_coordinates_b[j]);
458 min_angle = curr_angle;
465 free(xyz_coordinates_a);
470static void utest_zero_balance_point() {
474 double x_coordinate = 0, y_coordinate = 0;
475 double xyz_coordinate[6][3] =
479 yac_int global_ids[6] = {0,1,2,3,4,5};
480 LLtoXYZ(x_coordinate, y_coordinate, xyz_coordinate[0]);
488static void utest_duplicated_point_test() {
492 double x_coordinates[] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
493 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,
494 2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,
495 3.0,3.0,3.0,3.0,3.0,3.0,3.0,3.0,3.0,3.0,
496 4.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0,
498 double y_coordinates[] = {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,
499 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,
500 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,
501 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,
502 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,
504 enum {
NUM_POINTS =
sizeof(x_coordinates) /
sizeof(x_coordinates[0])};
507 0,1,2,3,4,5,6,7,8,9,
508 10,11,12,13,14,15,16,17,18,19,
509 20,21,22,23,24,25,26,27,28,29,
510 30,31,32,33,34,35,36,37,38,39,
511 40,41,42,43,44,45,46,47,48,49,
514 LLtoXYZ_deg(x_coordinates[i], y_coordinates[i], xyz_coordinates[i]);
523 double x_coordinates[] = {1.0,1.0,2.0,2.0,2.0,3.0,3.0,2.1,0.1};
524 double y_coordinates[] = {1.0,8.0,3.0,4.0,5.0,1.0,8.0,4.0,0.0};
525 enum {
NUM_POINTS =
sizeof(x_coordinates) /
sizeof(x_coordinates[0])};
528 LLtoXYZ_deg(x_coordinates[i], y_coordinates[i], xyz_coordinates[i]);
530 size_t * local_point_ids = NULL;
531 size_t local_point_ids_array_size = 0;
534 double (*result_coordinates_xyz)[3] = NULL;
535 size_t result_coordinates_xyz_array_size = 0;
539 &result_coordinates_xyz, &result_coordinates_xyz_array_size,
540 &local_point_ids, &local_point_ids_array_size, num_local_point_ids);
543 {{11}, {18}, {23}, {52}, {25}, {31}, {38}, {52}, {0}};
544 size_t ref_num_local_point_ids[
NUM_POINTS] = {1,1,1,1,1,1,1,1,1};
545 double ref_x_coordinates[
NUM_POINTS] = {1.0,1.0,2.0,2.0,2.0,3.0,3.0,2.0,0.0};
546 double ref_y_coordinates[
NUM_POINTS] = {1.0,8.0,3.0,4.0,5.0,1.0,8.0,4.0,0.0};
547 double ref_result_coordinates_xyz[
NUM_POINTS][3][3];
550 for (
size_t j = 0; j < ref_num_local_point_ids[
i]; ++j)
552 ref_x_coordinates[i], ref_y_coordinates[i],
553 ref_result_coordinates_xyz[i][j]);
556 offset += num_local_point_ids[
i++]) {
558 if (num_local_point_ids[i] != ref_num_local_point_ids[i]) {
559 PUT_ERR(
"ERROR in yac_point_sphere_part_search_NN (num_local_point_ids)");
562 for (
size_t j = 0; j < ref_num_local_point_ids[
i]; ++j) {
565 result_coordinates_xyz[offset+j],
566 ref_result_coordinates_xyz[i][j]))
567 PUT_ERR(
"ERROR in yac_point_sphere_part_search_NN "
568 "(result_coordinates_xyz)");
569 if (local_point_ids[offset+j] != ref_local_point_ids[i][j])
570 PUT_ERR(
"ERROR in yac_point_sphere_part_search_NN (local_point_ids)");
575 free(local_point_ids);
576 free(result_coordinates_xyz);
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
static int points_are_identically(double const *a, double const *b)
static const struct sin_cos_angle SIN_COS_M_PI
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
static int compare_angles(struct sin_cos_angle a, struct sin_cos_angle b)
static double get_vector_angle(double const a[3], double const b[3])
static struct sin_cos_angle sin_cos_angle_new(double sin, double cos)
void yac_point_sphere_part_search_NNN_ubound(struct point_sphere_part_search *search, size_t num_points, yac_coordinate_pointer coordinates_xyz, size_t n, struct sin_cos_angle *angles)
void yac_point_sphere_part_search_NNN_bnd_circle(struct point_sphere_part_search *search, size_t num_bnd_circles, struct bounding_circle *bnd_circles, size_t n, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
void yac_delete_point_sphere_part_search(struct point_sphere_part_search *search)
struct point_sphere_part_search * yac_point_sphere_part_search_new(size_t num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids)
void yac_point_sphere_part_search_NN(struct point_sphere_part_search *search, size_t num_points, double(*coordinates_xyz)[3], double *cos_angles, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
void yac_point_sphere_part_search_NNN(struct point_sphere_part_search *search, size_t num_points, double(*coordinates_xyz)[3], size_t n, double **cos_angles, size_t *cos_angles_array_size, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
algorithm for searching cells and points on a grid
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
int double_are_unequal(double a, double b)
static int compare_distance_index(const void *a, const void *b)
static void point_sphere_test_NNN(struct point_sphere_part_search *search, size_t n, double(*xyz_coordinates)[3], size_t num_points, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids, struct distance_index *distances)
static void gen_random_bnd_circle(struct bounding_circle *circle)
static void gen_random_point(double *point)
static void point_sphere_test_NNN_bnd_circle(struct point_sphere_part_search *search, size_t num_points, yac_coordinate_pointer xyz_coordinates, size_t n, struct distance_index *distances)
static void point_sphere_test_NNN_ubound(struct point_sphere_part_search *search, size_t num_points, yac_coordinate_pointer xyz_coordinates, size_t n, struct distance_index *distances)
static void LLtoXYZ(double lon, double lat, double p_out[])
double const (* yac_const_coordinate_pointer)[3]
double(* yac_coordinate_pointer)[3]