136 void * coords_data,
size_t coords_size,
size_t coords_count,
140 double balance_point[3] = {0.0,0.0,0.0};
143 for (
size_t i = 0; i < coords_count; ++i) {
146 (
double*)(((
unsigned char*)coords_data) + i * coords_size);
147 balance_point[0] += coords[0];
148 balance_point[1] += coords[1];
149 balance_point[2] += coords[2];
152 if ((fabs(balance_point[0]) > 1e-9) ||
153 (fabs(balance_point[1]) > 1e-9) ||
154 (fabs(balance_point[2]) > 1e-9)) {
157 balance_point[0] = prev_gc_norm_vector[2];
158 balance_point[1] = prev_gc_norm_vector[0];
159 balance_point[2] = prev_gc_norm_vector[1];
185 for (
size_t j = begin; j < end; ++j)
199 size_t I_begin = I_FULL_size;
200 size_t U_begin = I_FULL_size + I_size;
201 size_t T_begin = I_FULL_size + I_size + U_size;
203 size_t I_end = I_begin + I_size;
204 size_t U_end = U_begin + U_size;
205 size_t T_end = T_begin + T_size;
207 while (I_end > I_begin && part_data[I_end-1].
node_type ==
I_NODE) I_end--;
208 while (U_end > U_begin && part_data[U_end-1].
node_type ==
U_NODE) U_end--;
209 while (T_end > T_begin && part_data[T_end-1].
node_type ==
T_NODE) T_end--;
211 for (
size_t i = 0; i < I_FULL_size; ++i)
219 I_begin = I_FULL_size;
220 for (
size_t i = I_begin; i < I_end; ++i)
232 U_begin = I_FULL_size + I_size;
233 T_begin = I_FULL_size + I_size + U_size;
234 for (
size_t i = U_begin; i < U_end; ++i)
245 size_t num_cell_ids,
size_t threshold,
struct sphere_part_node * parent_node,
246 double prev_gc_norm_vector[]) {
248 if (num_cell_ids == 0) {
254 part_data,
sizeof(*part_data), num_cell_ids,
260 size_t I_FULL_size = 0;
267 for (
size_t i = 0; i < num_cell_ids; ++i) {
305 max_inc_angle = inc_angle;
309 }
else if (angle.
cos < 0.0) {
325 I_size += I_FULL_size;
326 parent_node->
I_size = I_size;
327 parent_node->
U_size = U_size;
328 parent_node->
T_size = T_size;
334 parent_node->
I_angle = max_inc_angle;
348 for (
size_t i = 0; i < I_FULL_size; ++i) {
355 for (
size_t i = I_FULL_size; i < I_size; ++i) {
357 double GCp[3], bVp[3];
366 (fabs(bVp[0]) > 1e-9) || (fabs(bVp[1]) > 1e-9) ||
367 (fabs(bVp[2]) > 1e-9),
368 "ERROR(partition_data): "
369 "projected vector is nearly identical to gc_norm_vector")
380 double bnd_circle_lat_cos =
383 M_PI_2 - acos(curr_bnd_circle.
inc_angle.
sin/bnd_circle_lat_cos);
400 for (
size_t i = 0; i < I_size; ++i)
401 local_cell_ids[i] = part_data[i].local_id;
402 parent_node->
I.
list = (
void*)local_cell_ids;
405 parent_node->
I.
list = NULL;
408 local_cell_ids += I_size;
411 if (U_size <= threshold) {
413 for (
size_t i = 0; i < U_size; ++i)
414 local_cell_ids[i] = part_data[i].local_id;
415 parent_node->
U = (
void*)local_cell_ids;
424 local_cell_ids += U_size;
427 if (T_size <= threshold) {
429 for (
size_t i = 0; i < T_size; ++i)
430 local_cell_ids[i] = part_data[i].local_id;
431 parent_node->
T = (
void*)local_cell_ids;
433 local_cell_ids += T_size;
450 double prev_gc_norm_vector[],
size_t curr_tree_depth,
451 size_t * max_tree_depth,
int * list_flag) {
453 if (curr_tree_depth > *max_tree_depth) *max_tree_depth = curr_tree_depth;
471 double * curr_coordinates_xyz = &(
points[i].coordinates_xyz[0]);
477 list_flag[i] = (dot <= 0.0);
482 if (list_flag[i]) ++
U_size;
496 for (;!list_flag[j];++j);
509 if ((U_size <= threshold) || (U_size ==
num_points)) {
519 points, U_size, threshold, gc_norm_vector,
520 curr_tree_depth + 1, max_tree_depth, list_flag);
523 if ((T_size <= threshold) || (T_size ==
num_points)) {
533 points + U_size, T_size, threshold, gc_norm_vector,
534 curr_tree_depth + 1, max_tree_depth, list_flag);
545 double gc_norm_vector[3] = {0.0,0.0,1.0};
553 xmalloc(num_circles *
sizeof(*part_data));
554 for (
size_t i = 0; i < num_circles; ++i) {
568 const void * a,
const void * b) {
575 for (
int i = 0; i < 3; ++i)
590 double const scale = (double)(2 << 21);
592 size_t num_unmasked_points;
596 for (
size_t i = 0; i < num_unmasked_points; ++i) {
598 points_int32[i].
idx = i;
599 for (
size_t j = 0; j < 3; ++j)
601 (int32_t)round(coordinates_xyz[i][j] * scale);
604 num_unmasked_points = 0;
607 if (!
mask[i])
continue;
608 points_int32[num_unmasked_points].
idx = i;
609 for (
size_t j = 0; j < 3; ++j)
611 (int32_t)round(coordinates_xyz[i][j] * scale);
612 num_unmasked_points++;
617 qsort(points_int32, num_unmasked_points,
621 dummy.
idx = SIZE_MAX;
627 size_t new_num_points = 0;
628 for (
size_t i = 0; i < num_unmasked_points; ++i, ++curr) {
630 size_t curr_idx = curr->
idx;
632 prev = points_int32 + new_num_points++;
633 if (prev != curr) *prev = *curr;
634 prev_id = ids[curr_idx];
636 yac_int curr_id = ids[curr_idx];
637 if (curr_id > prev_id) {
639 prev->
idx = curr_idx;
645 for (
size_t i = 0; i < new_num_points; ++i) {
646 size_t curr_idx = points_int32[i].
idx;
667 size_t max_tree_depth = 0;
675 1, &max_tree_depth, list_flag);
706 (
double[3]){0.0,0.0,1.0}, 1, &max_tree_depth, list_flag);
719 size_t ** restrict overlap_cells,
size_t * overlap_cells_array_size,
720 size_t * restrict num_overlap_cells,
721 struct overlaps * search_interval_tree_buffer,
double prev_gc_norm_vector[]) {
728 angle.
cos = fabs(angle.
cos);
735 (*overlap_cells)[(*num_overlap_cells)+i] =
741 double GCp[3], bVp[3];
748 (fabs(bVp[0]) > 1e-9) || (fabs(bVp[1]) > 1e-9) || (fabs(bVp[2]) > 1e-9),
749 "ERROR(search_bnd_circle_I_node): "
750 "projected vector is nearly identical to gc_norm_vector")
756 double bnd_circle_lat_cos =
759 M_PI_2 - acos(bnd_circle.
inc_angle.
sin/bnd_circle_lat_cos);
769 .left = base_angle - inc_angle,
770 .right = base_angle + inc_angle},
771 search_interval_tree_buffer);
777 for (
size_t i = 0; i < search_interval_tree_buffer->
num_overlaps; ++i)
778 (*overlap_cells)[(*num_overlap_cells)+i] =
782 *num_overlap_cells += search_interval_tree_buffer->
num_overlaps;
787 *num_overlap_cells + node->
I_size);
788 memcpy(*overlap_cells + *num_overlap_cells, node->
I.
list,
789 node->
I_size *
sizeof(**overlap_cells));
790 *num_overlap_cells += node->
I_size;
797 size_t ** restrict overlap_cells,
size_t * overlap_cells_array_size,
798 size_t * restrict num_overlap_cells,
799 struct overlaps * search_interval_tree_buffer,
double prev_gc_norm_vector[]) {
804 *num_overlap_cells + node->
T_size);
805 memcpy(*overlap_cells + *num_overlap_cells, node->
T,
806 node->
T_size *
sizeof(**overlap_cells));
807 *num_overlap_cells += node->
T_size;
811 node->
T, bnd_circle, overlap_cells, overlap_cells_array_size,
812 num_overlap_cells, search_interval_tree_buffer, node->
gc_norm_vector);
818 *num_overlap_cells + node->
U_size);
819 memcpy(*overlap_cells + *num_overlap_cells, node->
U,
820 node->
U_size *
sizeof(**overlap_cells));
821 *num_overlap_cells += node->
U_size;
825 node->
U, bnd_circle, overlap_cells, overlap_cells_array_size,
826 num_overlap_cells, search_interval_tree_buffer, node->
gc_norm_vector);
830 node, bnd_circle, overlap_cells, overlap_cells_array_size,
831 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
836 size_t ** restrict overlap_cells,
size_t * overlap_cells_array_size,
837 size_t * restrict num_overlap_cells,
838 struct overlaps * search_interval_tree_buffer,
double prev_gc_norm_vector[]) {
850 *num_overlap_cells + node->
T_size);
851 memcpy(*overlap_cells + *num_overlap_cells, node->
T,
852 node->
T_size *
sizeof(**overlap_cells));
853 *num_overlap_cells += node->
T_size;
857 node->
T, bnd_circle, overlap_cells, overlap_cells_array_size,
858 num_overlap_cells, search_interval_tree_buffer,
869 *num_overlap_cells + node->
U_size);
870 memcpy(*overlap_cells + *num_overlap_cells, node->
U,
871 node->
U_size *
sizeof(**overlap_cells));
872 *num_overlap_cells += node->
U_size;
876 node->
U, bnd_circle, overlap_cells, overlap_cells_array_size,
877 num_overlap_cells, search_interval_tree_buffer,
902 if (((angle_sum.
sin < 0.0) || (angle_sum.
cos <= 0.0)) ||
903 (fabs(dot) <= angle_sum.
sin)) {
905 node, bnd_circle, overlap_cells, overlap_cells_array_size,
906 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
912 size_t ** restrict overlap_cells,
913 size_t * overlap_cells_array_size,
914 size_t * restrict num_overlap_cells,
915 struct overlaps * search_interval_tree_buffer,
916 double prev_gc_norm_vector[]) {
921 node, bnd_circle, overlap_cells, overlap_cells_array_size,
922 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
925 node, bnd_circle, overlap_cells, overlap_cells_array_size,
926 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
931 double * point_coordinates_xyz,
struct sin_cos_angle * best_angle,
932 double (**result_coordinates_xyz)[3],
933 size_t * result_coordinates_xyz_array_size,
size_t ** local_point_ids,
934 size_t * local_point_ids_array_size,
size_t total_num_local_point_ids,
935 size_t * num_local_point_ids) {
937 size_t * local_point_ids_ = *local_point_ids;
938 size_t local_point_ids_array_size_ = *local_point_ids_array_size;
939 double (*result_coordinates_xyz_)[3];
940 size_t result_coordinates_xyz_array_size_;
941 size_t num_local_point_ids_ = *num_local_point_ids;
943 if (result_coordinates_xyz != NULL) {
944 result_coordinates_xyz_ = *result_coordinates_xyz;
945 result_coordinates_xyz_array_size_ = *result_coordinates_xyz_array_size;
947 result_coordinates_xyz_, result_coordinates_xyz_array_size_,
948 total_num_local_point_ids + num_local_point_ids_ +
num_points);
949 *result_coordinates_xyz = result_coordinates_xyz_;
950 *result_coordinates_xyz_array_size = result_coordinates_xyz_array_size_;
951 result_coordinates_xyz_ += total_num_local_point_ids;
954 local_point_ids_, local_point_ids_array_size_,
955 total_num_local_point_ids + num_local_point_ids_ +
num_points);
956 *local_point_ids = local_point_ids_;
957 *local_point_ids_array_size = local_point_ids_array_size_;
958 local_point_ids_ += total_num_local_point_ids;
966 points[i].coordinates_xyz, point_coordinates_xyz);
970 if (compare > 0)
continue;
975 *best_angle = curr_angle;
976 num_local_point_ids_ = 1;
977 if (result_coordinates_xyz != NULL) {
978 result_coordinates_xyz_[0][0] =
points[i].coordinates_xyz[0];
979 result_coordinates_xyz_[0][1] =
points[i].coordinates_xyz[1];
980 result_coordinates_xyz_[0][2] =
points[i].coordinates_xyz[2];
982 local_point_ids_[0] =
points[i].idx;
986 if (result_coordinates_xyz != NULL) {
987 result_coordinates_xyz_[num_local_point_ids_][0] =
988 points[i].coordinates_xyz[0];
989 result_coordinates_xyz_[num_local_point_ids_][1] =
990 points[i].coordinates_xyz[1];
991 result_coordinates_xyz_[num_local_point_ids_][2] =
992 points[i].coordinates_xyz[2];
994 local_point_ids_[num_local_point_ids_] =
points[i].idx;
995 num_local_point_ids_++;
999 *num_local_point_ids = num_local_point_ids_;
1003 struct bounding_circle * bnd_circle,
double (**result_coordinates_xyz)[3],
1004 size_t * result_coordinates_xyz_array_size,
size_t ** local_point_ids,
1005 size_t * local_point_ids_array_size,
size_t total_num_local_point_ids,
1006 size_t * num_local_point_ids,
double * dot_stack,
1008 int * flags,
size_t curr_tree_depth) {
1010 double * point_coordinates_xyz = bnd_circle->
base_vector;
1013 double dot = dot_stack[curr_tree_depth];
1025 if ((dot < best_angle.
sin) | (best_angle.
cos <= 0.0)) {
1031 point_coordinates_xyz, &best_angle, result_coordinates_xyz,
1032 result_coordinates_xyz_array_size, local_point_ids,
1033 local_point_ids_array_size, total_num_local_point_ids,
1034 num_local_point_ids);
1044 dot_stack[curr_tree_depth] = dot;
1045 node_stack[curr_tree_depth] = node;
1046 flags[curr_tree_depth] = 0;
1059 if ((dot > - best_angle.
sin) || (best_angle.
cos <= 0.0)) {
1065 point_coordinates_xyz, &best_angle, result_coordinates_xyz,
1066 result_coordinates_xyz_array_size, local_point_ids,
1067 local_point_ids_array_size, total_num_local_point_ids,
1068 num_local_point_ids);
1078 dot_stack[curr_tree_depth] = dot;
1079 node_stack[curr_tree_depth] = node;
1080 flags[curr_tree_depth] = 0;
1088 if (curr_tree_depth == 0)
break;
1093 dot = dot_stack[curr_tree_depth];
1094 node = node_stack[curr_tree_depth];
1106 size_t ** local_point_ids,
size_t * local_point_ids_array_size,
1107 double (**result_coordinates_xyz)[3],
1108 size_t * result_coordinates_xyz_array_size,
1109 size_t total_num_local_point_ids,
size_t * num_local_point_ids) {
1117 total_num_local_point_ids + 1);
1118 (*local_point_ids)[total_num_local_point_ids] =
points[i].idx;
1119 if (result_coordinates_xyz != NULL) {
1121 *result_coordinates_xyz_array_size,
1122 total_num_local_point_ids + 1);
1123 memcpy((*result_coordinates_xyz) + total_num_local_point_ids,
1124 points[i].coordinates_xyz, 3 *
sizeof(
double));
1126 *num_local_point_ids = 1;
1136 double (*coordinates_xyz)[3],
1137 double * cos_angles,
1138 double (**result_coordinates_xyz)[3],
1139 size_t * result_coordinates_xyz_array_size,
1140 size_t ** local_point_ids,
1141 size_t * local_point_ids_array_size,
1142 size_t * num_local_point_ids) {
1144 memset(num_local_point_ids, 0,
num_points *
sizeof(*num_local_point_ids));
1146 if (search == NULL)
return;
1150 size_t total_num_local_point_ids = 0;
1161 double * curr_coordinates_xyz = coordinates_xyz[i];
1163 size_t curr_tree_depth = 0;
1165 size_t curr_num_points = 0;
1170 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
1174 dot_stack[curr_tree_depth] = dot;
1175 node_stack[curr_tree_depth] = curr_node;
1176 flags[curr_tree_depth] = 0;
1181 flags[curr_tree_depth] =
U_FLAG;
1184 if (curr_node->
U_size > 0) {
1186 curr_num_points = curr_node->
U_size;
1189 flags[curr_tree_depth] =
T_FLAG;
1192 "ERROR(yac_point_sphere_part_search_NN): "
1193 "if one branch is empty, the other has to be a leaf");
1195 curr_num_points = curr_node->
T_size;
1198 }
else curr_node = curr_node->
U;
1203 flags[curr_tree_depth] =
T_FLAG;
1206 if (curr_node->
T_size > 0) {
1208 curr_num_points = curr_node->
T_size;
1211 flags[curr_tree_depth] =
U_FLAG;
1214 "ERROR(yac_point_sphere_part_search_NN): "
1215 "if one branch is empty, the other has to be a leaf");
1217 curr_num_points = curr_node->
U_size;
1220 }
else curr_node = curr_node->
T;
1228 points, curr_num_points, curr_coordinates_xyz, local_point_ids,
1229 local_point_ids_array_size, result_coordinates_xyz,
1230 result_coordinates_xyz_array_size, total_num_local_point_ids,
1231 num_local_point_ids + i)) {
1233 if (cos_angles != NULL) cos_angles[i] = 1.0;
1238 bnd_circle.
base_vector[0] = curr_coordinates_xyz[0];
1239 bnd_circle.
base_vector[1] = curr_coordinates_xyz[1];
1240 bnd_circle.
base_vector[2] = curr_coordinates_xyz[2];
1242 bnd_circle.
sq_crd = DBL_MAX;
1246 result_coordinates_xyz, result_coordinates_xyz_array_size,
1247 local_point_ids, local_point_ids_array_size, total_num_local_point_ids,
1248 num_local_point_ids + i);
1252 &bnd_circle, result_coordinates_xyz, result_coordinates_xyz_array_size,
1253 local_point_ids, local_point_ids_array_size, total_num_local_point_ids,
1254 num_local_point_ids + i, dot_stack, node_stack, flags, curr_tree_depth);
1256 if (cos_angles != NULL) cos_angles[i] = bnd_circle.
inc_angle.
cos;
1259 total_num_local_point_ids += num_local_point_ids[i];
1275 if (ret != 0)
return ret;
1283 size_t * results_array_size) {
1298#pragma _NEC novector
1304 points[i].coordinates_xyz[0] * point_coordinates_xyz[0] +
1305 points[i].coordinates_xyz[1] * point_coordinates_xyz[1] +
1306 points[i].coordinates_xyz[2] * point_coordinates_xyz[2]);
1314 double min_cos_angle = results_[n - 1].
cos_angle;
1316 for (num_results = n;
1318 !(fabs(min_cos_angle - results_[num_results].
cos_angle) > 0.0);
1325 size_t n, double * point_coordinates_xyz,
1330 size_t num_results_ = *num_results;
1336 double min_cos_angle = results_[num_results_-1].
cos_angle;
1341 double curr_cos_angle =
1342 points[i].coordinates_xyz[0] * point_coordinates_xyz[0] +
1343 points[i].coordinates_xyz[1] * point_coordinates_xyz[1] +
1344 points[i].coordinates_xyz[2] * point_coordinates_xyz[2];
1347 if (curr_cos_angle < min_cos_angle)
continue;
1350 {.
point =
points[i], .cos_angle = curr_cos_angle};
1354 for (j = 0; j < num_results_; ++j) {
1357 &point, results_ + num_results_ - j - 1) < 0) {
1358 results_[num_results_ - j] = results_[num_results_ - j - 1];
1363 results_[num_results_ - j] = point;
1371 if (num_results_ > n) {
1373 size_t new_num_results;
1374 min_cos_angle = results_[n - 1].
cos_angle;
1376 for (new_num_results = n;
1377 (new_num_results < num_results_) &&
1378 !(fabs(min_cos_angle - results_[new_num_results].cos_angle) > 0.0);
1380 num_results_ = new_num_results;
1382 *num_results = num_results_;
1386 results_[num_results_-1].point.coordinates_xyz, point_coordinates_xyz);
1387 }
else return curr_angle;
1391 size_t n,
double * point_coordinates_xyz,
1393 size_t * num_results,
double * dot_stack,
1395 size_t curr_tree_depth) {
1399 (*results)[(*num_results)-1].point.coordinates_xyz,
1400 point_coordinates_xyz);
1405 double dot = dot_stack[curr_tree_depth];
1417 if ((dot < angle.
sin) | (angle.
cos <= 0.0)) {
1423 node->
U_size, results, results_array_size, num_results, angle);
1433 dot_stack[curr_tree_depth] = dot;
1434 node_stack[curr_tree_depth] = node;
1435 flags[curr_tree_depth] = 0;
1448 if ((dot > - angle.
sin) || (angle.
cos <= 0.0)) {
1454 node->
T_size, results, results_array_size, num_results, angle);
1464 dot_stack[curr_tree_depth] = dot;
1465 node_stack[curr_tree_depth] = node;
1466 flags[curr_tree_depth] = 0;
1474 if (curr_tree_depth == 0)
break;
1479 dot = dot_stack[curr_tree_depth];
1480 node = node_stack[curr_tree_depth];
1489 double (*coordinates_xyz)[3],
size_t n,
1490 double ** cos_angles,
1491 size_t * cos_angles_array_size,
1492 double (**result_coordinates_xyz)[3],
1493 size_t * result_coordinates_xyz_array_size,
1494 size_t ** local_point_ids,
1495 size_t * local_point_ids_array_size,
1496 size_t * num_local_point_ids) {
1500 if (cos_angles != NULL)
1505 search,
num_points, coordinates_xyz, (cos_angles!=NULL)?*cos_angles:NULL,
1506 result_coordinates_xyz, result_coordinates_xyz_array_size,
1507 local_point_ids, local_point_ids_array_size, num_local_point_ids);
1509 size_t total_num_local_points = 0;
1511 total_num_local_points += num_local_point_ids[i];
1513 if ((cos_angles != NULL) && (total_num_local_points >
num_points)) {
1516 total_num_local_points);
1518 for (
size_t i =
num_points - 1, offset = total_num_local_points - 1;
1519 i != (size_t)-1; i--) {
1521 for (
size_t j = 0; j < num_local_point_ids[i]; ++j, --offset)
1522 (*cos_angles)[offset] = (*cos_angles)[i];
1529 if (search == NULL) {
1530 memset(num_local_point_ids, 0,
num_points *
sizeof(*num_local_point_ids));
1536 size_t total_num_local_point_ids = 0;
1544 size_t results_array_size = 0;
1550 double * curr_coordinates_xyz = coordinates_xyz[i];
1552 size_t curr_tree_depth = 0;
1554 size_t curr_num_points = 0;
1559 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
1563 dot_stack[curr_tree_depth] = dot;
1564 node_stack[curr_tree_depth] = curr_node;
1565 flags[curr_tree_depth] = 0;
1570 if (curr_node->
U_size < n) {
1573 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1577 flags[curr_tree_depth] =
U_FLAG;
1578 curr_num_points = curr_node->
U_size;
1582 flags[curr_tree_depth] =
U_FLAG;
1583 curr_node = curr_node->
U;
1588 if (curr_node->
T_size < n) {
1591 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1596 flags[curr_tree_depth] =
T_FLAG;
1597 curr_num_points = curr_node->
T_size;
1602 flags[curr_tree_depth] =
T_FLAG;
1603 curr_node = curr_node->
T;
1610 assert(curr_num_points > 0);
1612 size_t num_results =
1614 n,
points, curr_num_points, curr_coordinates_xyz,
1615 &results, &results_array_size);
1619 n, curr_coordinates_xyz, &results, &results_array_size, &num_results,
1620 dot_stack, node_stack, flags, curr_tree_depth);
1624 total_num_local_point_ids + num_results);
1625 size_t * local_point_ids_ =
1626 (*local_point_ids) + total_num_local_point_ids;
1627 double * cos_angles_;
1628 if (cos_angles != NULL) {
1630 total_num_local_point_ids + num_results);
1631 cos_angles_ = (*cos_angles) + total_num_local_point_ids;
1635 double (*result_coordinates_xyz_)[3];
1636 if (result_coordinates_xyz != NULL) {
1638 *result_coordinates_xyz_array_size,
1639 total_num_local_point_ids + num_results);
1640 result_coordinates_xyz_ =
1641 (*result_coordinates_xyz) + total_num_local_point_ids;
1643 result_coordinates_xyz_ = NULL;
1646 for (
size_t j = 0; j < num_results; ++j) {
1648 local_point_ids_[j] = results[j].
point.
idx;
1649 if (cos_angles_ != NULL) cos_angles_[j] = results[j].
cos_angle;
1650 if (result_coordinates_xyz_ != NULL) {
1657 num_local_point_ids[i] = num_results;
1658 total_num_local_point_ids += num_results;
1670 size_t n,
size_t ** local_point_ids,
size_t * local_point_ids_array_size,
1671 size_t * num_local_point_ids) {
1673 if (num_bnd_circles == 0)
return;
1675 if (search == NULL) {
1677 num_local_point_ids, 0, num_bnd_circles *
sizeof(*num_local_point_ids));
1683 size_t total_num_local_point_ids = 0;
1691 size_t results_array_size = 0;
1693 for (
size_t i = 0; i < num_bnd_circles; ++i) {
1697 double * curr_coordinates_xyz = bnd_circles[i].
base_vector;
1699 size_t curr_tree_depth = 0;
1701 size_t curr_num_points = 0;
1706 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
1710 dot_stack[curr_tree_depth] = dot;
1711 node_stack[curr_tree_depth] = curr_node;
1712 flags[curr_tree_depth] = 0;
1717 if (curr_node->
U_size < n) {
1720 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1724 flags[curr_tree_depth] =
U_FLAG;
1725 curr_num_points = curr_node->
U_size;
1729 flags[curr_tree_depth] =
U_FLAG;
1730 curr_node = curr_node->
U;
1735 if (curr_node->
T_size < n) {
1738 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1743 flags[curr_tree_depth] =
T_FLAG;
1744 curr_num_points = curr_node->
T_size;
1749 flags[curr_tree_depth] =
T_FLAG;
1750 curr_node = curr_node->
T;
1758 curr_num_points > 0,
1759 "ERROR(yac_point_sphere_part_search_NNN_bnd_circle): "
1760 "insufficient number of points");
1762 size_t num_results =
1764 n,
points, curr_num_points, curr_coordinates_xyz,
1765 &results, &results_array_size);
1769 n, curr_coordinates_xyz, &results, &results_array_size, &num_results,
1770 dot_stack, node_stack, flags, curr_tree_depth);
1772 for (; num_results > 0; --num_results)
1773 if (results[num_results-1].cos_angle >= bnd_circles[i].inc_angle.cos)
1778 total_num_local_point_ids + num_results);
1779 size_t * local_point_ids_ =
1780 (*local_point_ids) + total_num_local_point_ids;
1782 for (
size_t j = 0; j < num_results; ++j)
1783 local_point_ids_[j] = results[j].point.idx;
1785 num_local_point_ids[i] = num_results;
1786 total_num_local_point_ids += num_results;
1808 "ERRROR(yac_point_sphere_part_search_NNN_ubound): "
1809 "invalid point sphere part search (has to be != NULL)");
1811 n > 0,
"ERROR(yac_point_sphere_part_search_NNN_ubound): "
1812 "invalid n (has to be > 0)")
1815 size_t temp_angles_array_size = 0;
1823 double * curr_coordinates_xyz = coordinates_xyz[i];
1826 size_t curr_num_points = 0;
1831 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
1838 if (curr_node->
U_size < n) {
1840 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1844 curr_num_points = curr_node->
U_size;
1848 curr_node = curr_node->
U;
1853 if (curr_node->
T_size < n) {
1855 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1860 curr_num_points = curr_node->
T_size;
1865 curr_node = curr_node->
T;
1871 curr_num_points >= n,
1872 "ERROR(yac_point_sphere_part_search_NNN_ubound): "
1873 "failed to find a sufficient number of points");
1882 curr_coordinates_xyz,
points[0].coordinates_xyz);
1883 for (
size_t j = 1; j < curr_num_points; ++j) {
1886 curr_coordinates_xyz,
points[j].coordinates_xyz);
1888 best_angle = curr_angle;
1890 angles[i] = best_angle;
1896 temp_angles, temp_angles_array_size, curr_num_points);
1897 for (
size_t j = 0; j < curr_num_points; ++j)
1900 curr_coordinates_xyz,
points[j].coordinates_xyz);
1903 temp_angles, curr_num_points,
sizeof(*temp_angles),
1906 angles[i] = temp_angles[n-1];
1915 size_t ** overlap_cells,
1916 size_t * overlap_cells_array_size,
1917 size_t * num_overlap_cells,
1918 struct overlaps * search_interval_tree_buffer,
1919 double prev_gc_norm_vector[]) {
1931 *num_overlap_cells + node->
T_size);
1932 memcpy(*overlap_cells + *num_overlap_cells, node->
T,
1933 node->
T_size *
sizeof(**overlap_cells));
1934 *num_overlap_cells += node->
T_size;
1938 overlap_cells_array_size, num_overlap_cells,
1949 *num_overlap_cells + node->
U_size);
1950 memcpy(*overlap_cells + *num_overlap_cells, node->
U,
1951 node->
U_size *
sizeof(**overlap_cells));
1952 *num_overlap_cells += node->
U_size;
1956 overlap_cells_array_size, num_overlap_cells,
1968 double GCp[3], bVp[3];
1975 if ((fabs(bVp[0]) > 1e-9) || (fabs(bVp[1]) > 1e-9) ||
1976 (fabs(bVp[2]) > 1e-9)) {
1979 search_interval.
left=base_angle;
1980 search_interval.
right=base_angle;
1982 search_interval.
left = -M_PI;
1983 search_interval.
right = M_PI;
1989 search_interval, search_interval_tree_buffer);
1992 *num_overlap_cells +
1995 for (
size_t i = 0; i < search_interval_tree_buffer->
num_overlaps;
1997 (*overlap_cells)[(*num_overlap_cells)+i] =
2002 *num_overlap_cells += search_interval_tree_buffer->
num_overlaps;
2007 *num_overlap_cells + node->
I_size);
2008 memcpy(*overlap_cells + *num_overlap_cells, node->
I.
list,
2009 node->
I_size *
sizeof(**overlap_cells));
2010 *num_overlap_cells += node->
I_size;
2017 size_t count,
size_t ** cells,
size_t * num_cells_per_coordinate) {
2021 size_t * temp_search_results = NULL;
2022 size_t temp_search_results_array_size = 0;
2023 size_t num_temp_search_results = 0;
2025 struct overlaps search_interval_tree_buffer = {0, 0, NULL};
2028 num_cells_per_coordinate, 0, count *
sizeof(*num_cells_per_coordinate));
2029 size_t * cells_ = NULL;
2030 size_t cells_array_size = 0;
2034 for (
size_t i = 0; i < count; ++i) {
2036 double * curr_coordinates_xyz = &(coordinates_xyz[i][0]);
2038 num_temp_search_results = 0;
2040 double gc_norm_vector[3] = {0.0,0.0,1.0};
2042 search_point(base_node, curr_coordinates_xyz, &temp_search_results,
2043 &temp_search_results_array_size, &num_temp_search_results,
2044 &search_interval_tree_buffer, gc_norm_vector);
2047 cells_, cells_array_size,
num_cells + num_temp_search_results);
2049 memcpy(cells_ +
num_cells, temp_search_results,
2050 num_temp_search_results *
sizeof(*temp_search_results));
2051 num_cells_per_coordinate[i] = num_temp_search_results;
2055 free(temp_search_results);
2056 free(search_interval_tree_buffer.
overlap_iv);
2063 size_t count,
size_t ** cells,
size_t * num_cells_per_bnd_circle) {
2067 size_t * temp_search_results = NULL;
2068 size_t temp_search_results_array_size = 0;
2069 size_t num_temp_search_results = 0;
2071 struct overlaps search_interval_tree_buffer = {0, 0, NULL};
2074 num_cells_per_bnd_circle, 0, count *
sizeof(*num_cells_per_bnd_circle));
2075 size_t * cells_ = NULL;
2076 size_t cells_array_size = 0;
2080 for (
size_t i = 0; i < count; ++i) {
2082 num_temp_search_results = 0;
2084 double gc_norm_vector[3] = {0.0,0.0,1.0};
2087 &temp_search_results_array_size, &num_temp_search_results,
2088 &search_interval_tree_buffer, gc_norm_vector);
2091 cells_, cells_array_size,
num_cells + num_temp_search_results);
2093 memcpy(cells_ +
num_cells, temp_search_results,
2094 num_temp_search_results *
sizeof(*temp_search_results));
2095 num_cells_per_bnd_circle[i] = num_temp_search_results;
2099 free(temp_search_results);
2100 free(search_interval_tree_buffer.
overlap_iv);
2138 if (search == NULL)
return;
2147 if (search == NULL)
return;
#define YAC_ASSERT(exp, msg)
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
static double clamp_abs_one(double val)
static const struct sin_cos_angle SIN_COS_ZERO
static int points_are_identically(double const *a, double const *b)
static const struct sin_cos_angle SIN_COS_M_PI
static struct sin_cos_angle sum_angles_no_check(struct sin_cos_angle a, struct sin_cos_angle b)
static void crossproduct_kahan(double const a[], double const b[], double cross[])
static const struct sin_cos_angle SIN_COS_M_PI_2
static int compare_angles(struct sin_cos_angle a, struct sin_cos_angle b)
static void normalise_vector(double v[])
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_search_interval_tree(struct interval_node tree[], size_t num_nodes, struct interval query, struct overlaps *overlaps)
void yac_generate_interval_tree(struct interval_node intervals[], size_t num_nodes)
#define xrealloc(ptr, size)
static int leaf_contains_matching_point(struct point_id_xyz *points, size_t num_points, double coordinate_xyz[3], size_t **local_point_ids, size_t *local_point_ids_array_size, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t total_num_local_point_ids, size_t *num_local_point_ids)
static size_t initial_point_bnd_search_NNN(size_t n, struct point_id_xyz *points, size_t num_points, double *point_coordinates_xyz, struct point_id_xyz_angle **results, size_t *results_array_size)
static void search_point(struct sphere_part_node *node, double point[], size_t **overlap_cells, size_t *overlap_cells_array_size, size_t *num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
static int compare_point_idx_xyz(void const *a, void const *b)
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)
static size_t swap_node_type(struct temp_partition_data *part_data, size_t i, int node_type, size_t begin, size_t end)
static void check_leaf_NN(struct point_id_xyz *points, size_t num_points, double *point_coordinates_xyz, struct sin_cos_angle *best_angle, 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 total_num_local_point_ids, size_t *num_local_point_ids)
static struct point_id_xyz * get_unique_points(size_t *num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids, int const *mask)
void yac_bnd_sphere_part_search_do_bnd_circle_search(struct bnd_sphere_part_search *search, struct bounding_circle *bnd_circles, size_t count, size_t **cells, size_t *num_cells_per_bnd_circle)
static void compute_gc_norm_vector(void *coords_data, size_t coords_size, size_t coords_count, double prev_gc_norm_vector[], double gc_norm_vector[])
static struct point_sphere_part_node * partition_point_data(struct point_id_xyz *points, size_t num_points, size_t threshold, double prev_gc_norm_vector[], size_t curr_tree_depth, size_t *max_tree_depth, int *list_flag)
static void point_search_NN(struct bounding_circle *bnd_circle, 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 total_num_local_point_ids, size_t *num_local_point_ids, double *dot_stack, struct point_sphere_part_node **node_stack, int *flags, size_t curr_tree_depth)
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)
struct bnd_sphere_part_search * yac_bnd_sphere_part_search_new(struct bounding_circle *circles, size_t num_circles)
static void search_bnd_circle_I_node(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
static void search_big_bnd_circle(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
TODO change to iterative implementation and allocate overlap_cells first.
static void sort_partition_data(struct temp_partition_data *part_data, size_t I_FULL_size, size_t I_size, size_t U_size, size_t T_size)
static void partition_data(size_t *local_cell_ids, struct temp_partition_data *part_data, size_t num_cell_ids, size_t threshold, struct sphere_part_node *parent_node, double prev_gc_norm_vector[])
void yac_delete_point_sphere_part_search(struct point_sphere_part_search *search)
struct point_sphere_part_search * yac_point_sphere_part_search_mask_new(size_t num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids, int const *mask)
void yac_bnd_sphere_part_search_delete(struct bnd_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)
static struct sin_cos_angle check_leaf_NNN(size_t n, double *point_coordinates_xyz, struct point_id_xyz *points, size_t num_points, struct point_id_xyz_angle **results, size_t *results_array_size, size_t *num_results, struct sin_cos_angle curr_angle)
static int compare_angles_(void const *a, void const *b)
static struct sphere_part_node * get_sphere_part_node()
static void free_sphere_part_tree(struct sphere_part_node tree)
static int compare_point_id_xyz_angle(const void *a, const void *b)
void yac_bnd_sphere_part_search_do_point_search(struct bnd_sphere_part_search *search, yac_coordinate_pointer coordinates_xyz, size_t count, size_t **cells, size_t *num_cells_per_coordinate)
static void search_small_bnd_circle(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
static void swap_partition_data(struct temp_partition_data *a, struct temp_partition_data *b)
static void init_sphere_part_node(struct sphere_part_node *node)
static void search_bnd_circle(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
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)
static void free_point_sphere_part_tree(struct point_sphere_part_node *tree)
static int compare_points_int32_coord(const void *a, const void *b)
static void point_search_NNN(size_t n, double *point_coordinates_xyz, struct point_id_xyz_angle **results, size_t *results_array_size, size_t *num_results, double *dot_stack, struct point_sphere_part_node **node_stack, int *flags, size_t curr_tree_depth)
algorithm for searching cells and points on a grid
struct sphere_part_node base_node
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
struct point_id_xyz point
int32_t coordinate_xyz[3]
double coordinates_xyz[3]
struct point_sphere_part_node base_node
struct point_id_xyz * points
struct sin_cos_angle I_angle
struct bounding_circle bnd_circle
struct interval_node * head_node
static struct user_input_data_points ** points
double const (* yac_const_coordinate_pointer)[3]
double(* yac_coordinate_pointer)[3]