xcoll 0.5.4__py3-none-any.whl → 0.5.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of xcoll might be problematic. Click here for more details.

@@ -1,953 +0,0 @@
1
- #include <stdint.h>
2
- #ifndef XOBJ_TYPEDEF_GeomCInit
3
- #define XOBJ_TYPEDEF_GeomCInit
4
- typedef struct GeomCInit_s * GeomCInit;
5
- static inline GeomCInit GeomCInit_getp(GeomCInit restrict obj){
6
- int64_t offset=0;
7
- return (GeomCInit)(( char*) obj+offset);
8
- }
9
- #endif
10
- // copyright ############################### #
11
- // This file is part of the Xcoll package. #
12
- // Copyright (c) CERN, 2024. #
13
- // ######################################### #
14
-
15
- #ifndef XCOLL_GEOM_DEFINES_H
16
- #define XCOLL_GEOM_DEFINES_H
17
- #include <math.h>
18
- #include <stdio.h>
19
- #include <stdint.h>
20
- #include <stdlib.h>
21
-
22
- #define XC_EPSILON 1.e-12
23
- #define XC_S_MAX 1.e21
24
-
25
-
26
- #endif /* XCOLL_GEOM_DEFINES_H */
27
- // copyright ############################### #
28
- // This file is part of the Xcoll package. #
29
- // Copyright (c) CERN, 2024. #
30
- // ######################################### #
31
-
32
- #ifndef XCOLL_GEOM_SORT_H
33
- #define XCOLL_GEOM_SORT_H
34
-
35
- #pragma GCC diagnostic push
36
- #pragma GCC diagnostic ignored "-Warray-bounds"
37
-
38
- #ifdef MAX
39
- #undef MAX
40
- #pragma message ("Xcoll geometry: Compiler macro MAX redefined")
41
- #endif
42
- #define MAX(x, y) ({const __typeof__ (x) _x = (x); \
43
- const __typeof__ (y) _y = (y); \
44
- _x > _y ? _x : _y; })
45
- #ifdef MIN
46
- #undef MIN
47
- #pragma message ("Xcoll geometry: Compiler macro MIN redefined")
48
- #endif
49
- #define MIN(x, y) ({const __typeof__ (x) _x = (x); \
50
- const __typeof__ (y) _y = (y); \
51
- _x < _y ? _x : _y; })
52
- #ifdef SWAP
53
- #error "Xcoll geometry: Compiler macro SWAP already defined!"
54
- #endif
55
- #define SWAP(d,x,y) ({const __typeof__(*d) _x = MIN(d[x], d[y]); \
56
- const __typeof__(*d) _y = MAX(d[x], d[y]); \
57
- d[x] = _x; d[y] = _y; })
58
-
59
-
60
- // Fast methods
61
- // ------------
62
-
63
- static inline void sort_array_of_2_double(double* d){
64
- SWAP(d, 0, 1);
65
- }
66
-
67
- static inline void sort_array_of_3_double(double* d){
68
- SWAP(d, 0, 1); SWAP(d, 1, 2); SWAP(d, 0, 1);
69
- }
70
-
71
- static inline void sort_array_of_4_double(double* d){
72
- SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
73
- }
74
-
75
- static inline void sort_array_of_5_double(double* d){
76
- SWAP(d, 0, 1); SWAP(d, 3, 4); SWAP(d, 2, 4); SWAP(d, 2, 3); SWAP(d, 1, 4);
77
- SWAP(d, 0, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
78
- }
79
-
80
- static inline void sort_array_of_6_double(double* d){
81
- SWAP(d, 1, 2); SWAP(d, 4, 5); SWAP(d, 0, 2); SWAP(d, 3, 5); SWAP(d, 0, 1);
82
- SWAP(d, 3, 4); SWAP(d, 1, 4); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3);
83
- SWAP(d, 2, 4); SWAP(d, 2, 3);
84
- }
85
-
86
- static inline void sort_array_of_7_double(double* d){
87
- SWAP(d, 1, 2); SWAP(d, 3, 4); SWAP(d, 5, 6); SWAP(d, 0, 2); SWAP(d, 3, 5);
88
- SWAP(d, 4, 6); SWAP(d, 0, 1); SWAP(d, 4, 5); SWAP(d, 2, 6); SWAP(d, 0, 4);
89
- SWAP(d, 1, 5); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3); SWAP(d, 2, 4);
90
- SWAP(d, 2, 3);
91
- }
92
-
93
- static inline void sort_array_of_8_double(double* d){
94
- SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 4, 5); SWAP(d, 6, 7); SWAP(d, 0, 2);
95
- SWAP(d, 1, 3); SWAP(d, 4, 6); SWAP(d, 5, 7); SWAP(d, 1, 2); SWAP(d, 5, 6);
96
- SWAP(d, 0, 4); SWAP(d, 3, 7); SWAP(d, 1, 5); SWAP(d, 2, 6); SWAP(d, 1, 4);
97
- SWAP(d, 3, 6); SWAP(d, 2, 4); SWAP(d, 3, 5); SWAP(d, 3, 4);
98
- }
99
-
100
- static inline void sort_array_of_2_int64(int64_t* d){
101
- SWAP(d, 0, 1);
102
- }
103
-
104
- static inline void sort_array_of_3_int64(int64_t* d){
105
- SWAP(d, 0, 1); SWAP(d, 1, 2); SWAP(d, 0, 1);
106
- }
107
-
108
- static inline void sort_array_of_4_int64(int64_t* d){
109
- SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
110
- }
111
-
112
- static inline void sort_array_of_5_int64(int64_t* d){
113
- SWAP(d, 0, 1); SWAP(d, 3, 4); SWAP(d, 2, 4); SWAP(d, 2, 3); SWAP(d, 1, 4);
114
- SWAP(d, 0, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
115
- }
116
-
117
- static inline void sort_array_of_6_int64(int64_t* d){
118
- SWAP(d, 1, 2); SWAP(d, 4, 5); SWAP(d, 0, 2); SWAP(d, 3, 5); SWAP(d, 0, 1);
119
- SWAP(d, 3, 4); SWAP(d, 1, 4); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3);
120
- SWAP(d, 2, 4); SWAP(d, 2, 3);
121
- }
122
-
123
- static inline void sort_array_of_7_int64(int64_t* d){
124
- SWAP(d, 1, 2); SWAP(d, 3, 4); SWAP(d, 5, 6); SWAP(d, 0, 2); SWAP(d, 3, 5);
125
- SWAP(d, 4, 6); SWAP(d, 0, 1); SWAP(d, 4, 5); SWAP(d, 2, 6); SWAP(d, 0, 4);
126
- SWAP(d, 1, 5); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3); SWAP(d, 2, 4);
127
- SWAP(d, 2, 3);
128
- }
129
-
130
- static inline void sort_array_of_8_int64(int64_t* d){
131
- SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 4, 5); SWAP(d, 6, 7); SWAP(d, 0, 2);
132
- SWAP(d, 1, 3); SWAP(d, 4, 6); SWAP(d, 5, 7); SWAP(d, 1, 2); SWAP(d, 5, 6);
133
- SWAP(d, 0, 4); SWAP(d, 3, 7); SWAP(d, 1, 5); SWAP(d, 2, 6); SWAP(d, 1, 4);
134
- SWAP(d, 3, 6); SWAP(d, 2, 4); SWAP(d, 3, 5); SWAP(d, 3, 4);
135
- }
136
-
137
-
138
- // Generic methods
139
- // ---------------
140
-
141
- int cmpfunc_double(const void * a, const void * b) {
142
- return ( *(double*)a - *(double*)b );
143
- }
144
-
145
- static inline void sort_array_of_double(double* arr, int64_t length){
146
- switch(length){
147
- case 2:
148
- sort_array_of_2_double(arr);
149
- break;
150
- case 3:
151
- sort_array_of_3_double(arr);
152
- break;
153
- case 4:
154
- sort_array_of_4_double(arr);
155
- break;
156
- case 5:
157
- sort_array_of_5_double(arr);
158
- break;
159
- case 6:
160
- sort_array_of_6_double(arr);
161
- break;
162
- case 7:
163
- sort_array_of_7_double(arr);
164
- break;
165
- case 8:
166
- sort_array_of_8_double(arr);
167
- break;
168
- default:
169
- qsort(arr, length, sizeof(double), cmpfunc_double);
170
- }
171
- }
172
-
173
- int cmpfunc_int64(const void * a, const void * b) {
174
- return ( *(int64_t*)a - *(int64_t*)b );
175
- }
176
-
177
- static inline void sort_array_of_int64(int64_t* arr, int64_t length){
178
- switch(length){
179
- case 2:
180
- sort_array_of_2_int64(arr);
181
- break;
182
- case 3:
183
- sort_array_of_3_int64(arr);
184
- break;
185
- case 4:
186
- sort_array_of_4_int64(arr);
187
- break;
188
- case 5:
189
- sort_array_of_5_int64(arr);
190
- break;
191
- case 6:
192
- sort_array_of_6_int64(arr);
193
- break;
194
- case 7:
195
- sort_array_of_7_int64(arr);
196
- break;
197
- case 8:
198
- sort_array_of_8_int64(arr);
199
- break;
200
- default:
201
- qsort(arr, length, sizeof(int64_t), cmpfunc_int64);
202
- }
203
- }
204
-
205
- #pragma GCC diagnostic pop
206
- #endif /* XCOLL_GEOM_SORT_H */
207
- // copyright ############################### #
208
- // This file is part of the Xcoll package. #
209
- // Copyright (c) CERN, 2024. #
210
- // ######################################### #
211
-
212
- #ifndef XCOLL_GEOM_METHODS_H
213
- #define XCOLL_GEOM_METHODS_H
214
-
215
- // This function calculates the overlap between an array and a given interval.
216
- // The array comes in pairs of points, e.g. in-out-in-out... or out-in-out-in...
217
- // IMPORTANT:
218
- // The array and interval are assumed to be sorted!
219
- // Furthermore, the array should have one extra slot allocated at the end, in case it needs to be expanded..
220
- // This is always true for the arrays created by get_s, as we create them with 2*n_segments slots.
221
- static inline
222
- void calculate_overlap_array_interval(double* arr, int8_t* length, double* interval){
223
- if (arr[0] > interval[1]){
224
- // No overlap
225
- *length = 0;
226
- }
227
- if ((*length)%2 == 1){
228
- // Special case: last interval of array is open until infinity,
229
- // so we add an extra point at the end to represent infinity.
230
- arr[*length] = XC_S_MAX*0.1;
231
- (*length)++;
232
- } else if (arr[*length-1] < interval[0]){
233
- // No overlap
234
- *length = 0;
235
- }
236
- int8_t i_start = 0;
237
- // Find the start of overlap
238
- for (int8_t i=0; i<*length; i++){
239
- if (arr[i] >= interval[0]){
240
- if (i%2 == 0){
241
- // This is the first point of overlap
242
- i_start = i;
243
- } else {
244
- // The vertical restriction is the first point of overlap
245
- i_start = i-1;
246
- arr[i_start] = interval[0];
247
- }
248
- break;
249
- }
250
- }
251
- // Find the end of overlap
252
- int8_t i_stop = *length - 1;
253
- for (int8_t i=0; i<*length; i++){
254
- if (arr[i] >= interval[1]){
255
- if (i%2 == 0){
256
- // The previous point is the last point of overlap
257
- i_stop = i-1;
258
- } else {
259
- // The vertical restriction is the first point of overlap
260
- i_stop = i;
261
- arr[i_stop] = interval[1];
262
- }
263
- break;
264
- }
265
- }
266
- *length = i_stop - i_start + 1;
267
- if (i_start > 0){
268
- for (int8_t i=0; i<*length; i++){
269
- arr[i] = arr[i+i_start];
270
- }
271
- }
272
- }
273
-
274
-
275
- #endif /* XCOLL_GEOM_METHODS_H */
276
- #ifndef XOBJ_TYPEDEF_LineSegment
277
- #define XOBJ_TYPEDEF_LineSegment
278
- typedef struct LineSegment_s * LineSegment;
279
- static inline LineSegment LineSegment_getp(LineSegment restrict obj){
280
- int64_t offset=0;
281
- return (LineSegment)(( char*) obj+offset);
282
- }
283
- static inline double LineSegment_get_s1(const LineSegment restrict obj){
284
- int64_t offset=0;
285
- return *( double*)(( char*) obj+offset);
286
- }
287
- static inline void LineSegment_set_s1(LineSegment restrict obj, double value){
288
- int64_t offset=0;
289
- *( double*)(( char*) obj+offset)=value;
290
- }
291
- static inline double* LineSegment_getp_s1(LineSegment restrict obj){
292
- int64_t offset=0;
293
- return ( double*)(( char*) obj+offset);
294
- }
295
- static inline double LineSegment_get_x1(const LineSegment restrict obj){
296
- int64_t offset=0;
297
- offset+=8;
298
- return *( double*)(( char*) obj+offset);
299
- }
300
- static inline void LineSegment_set_x1(LineSegment restrict obj, double value){
301
- int64_t offset=0;
302
- offset+=8;
303
- *( double*)(( char*) obj+offset)=value;
304
- }
305
- static inline double* LineSegment_getp_x1(LineSegment restrict obj){
306
- int64_t offset=0;
307
- offset+=8;
308
- return ( double*)(( char*) obj+offset);
309
- }
310
- static inline double LineSegment_get_s2(const LineSegment restrict obj){
311
- int64_t offset=0;
312
- offset+=16;
313
- return *( double*)(( char*) obj+offset);
314
- }
315
- static inline void LineSegment_set_s2(LineSegment restrict obj, double value){
316
- int64_t offset=0;
317
- offset+=16;
318
- *( double*)(( char*) obj+offset)=value;
319
- }
320
- static inline double* LineSegment_getp_s2(LineSegment restrict obj){
321
- int64_t offset=0;
322
- offset+=16;
323
- return ( double*)(( char*) obj+offset);
324
- }
325
- static inline double LineSegment_get_x2(const LineSegment restrict obj){
326
- int64_t offset=0;
327
- offset+=24;
328
- return *( double*)(( char*) obj+offset);
329
- }
330
- static inline void LineSegment_set_x2(LineSegment restrict obj, double value){
331
- int64_t offset=0;
332
- offset+=24;
333
- *( double*)(( char*) obj+offset)=value;
334
- }
335
- static inline double* LineSegment_getp_x2(LineSegment restrict obj){
336
- int64_t offset=0;
337
- offset+=24;
338
- return ( double*)(( char*) obj+offset);
339
- }
340
- #endif
341
-
342
- static inline
343
- void LineSegment_crossing_drift(LineSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
344
- // Get segment data
345
- double s1 = LineSegment_get_s1(seg);
346
- double x1 = LineSegment_get_x1(seg);
347
- double s2 = LineSegment_get_s2(seg);
348
- double x2 = LineSegment_get_x2(seg);
349
- double denom = (x2 - x1) - (s2 - s1)*m;
350
- if (fabs(denom) < XC_EPSILON){
351
- // Trajectory is parallel to the segment
352
- if (fabs((x0 - x1)/(s0 - s1) - m) < XC_EPSILON){
353
- // Trajectory overlaps with the segment
354
- // TODO: This is situational; we should return s1 if get_s_first and current_s if after current_s
355
- // For now we hit twice (because we go nor IN nor OUT)
356
- s[*n_hit] = s1;
357
- (*n_hit)++;
358
- s[*n_hit] = s2;
359
- (*n_hit)++;
360
- } else {
361
- // No crossing
362
- return;
363
- }
364
- } else {
365
- double t = (x0 - x1 - (s0 - s1)*m) / denom;
366
- if (t >= 0 && t <= 1){
367
- s[*n_hit] = s1*(1-t) + s2*t;
368
- (*n_hit)++;
369
- }
370
- }
371
- }
372
-
373
- #ifndef XOBJ_TYPEDEF_HalfOpenLineSegment
374
- #define XOBJ_TYPEDEF_HalfOpenLineSegment
375
- typedef struct HalfOpenLineSegment_s * HalfOpenLineSegment;
376
- static inline HalfOpenLineSegment HalfOpenLineSegment_getp(HalfOpenLineSegment restrict obj){
377
- int64_t offset=0;
378
- return (HalfOpenLineSegment)(( char*) obj+offset);
379
- }
380
- static inline double HalfOpenLineSegment_get_s(const HalfOpenLineSegment restrict obj){
381
- int64_t offset=0;
382
- return *( double*)(( char*) obj+offset);
383
- }
384
- static inline void HalfOpenLineSegment_set_s(HalfOpenLineSegment restrict obj, double value){
385
- int64_t offset=0;
386
- *( double*)(( char*) obj+offset)=value;
387
- }
388
- static inline double* HalfOpenLineSegment_getp_s(HalfOpenLineSegment restrict obj){
389
- int64_t offset=0;
390
- return ( double*)(( char*) obj+offset);
391
- }
392
- static inline double HalfOpenLineSegment_get_x(const HalfOpenLineSegment restrict obj){
393
- int64_t offset=0;
394
- offset+=8;
395
- return *( double*)(( char*) obj+offset);
396
- }
397
- static inline void HalfOpenLineSegment_set_x(HalfOpenLineSegment restrict obj, double value){
398
- int64_t offset=0;
399
- offset+=8;
400
- *( double*)(( char*) obj+offset)=value;
401
- }
402
- static inline double* HalfOpenLineSegment_getp_x(HalfOpenLineSegment restrict obj){
403
- int64_t offset=0;
404
- offset+=8;
405
- return ( double*)(( char*) obj+offset);
406
- }
407
- static inline double HalfOpenLineSegment_get_t(const HalfOpenLineSegment restrict obj){
408
- int64_t offset=0;
409
- offset+=16;
410
- return *( double*)(( char*) obj+offset);
411
- }
412
- static inline void HalfOpenLineSegment_set_t(HalfOpenLineSegment restrict obj, double value){
413
- int64_t offset=0;
414
- offset+=16;
415
- *( double*)(( char*) obj+offset)=value;
416
- }
417
- static inline double* HalfOpenLineSegment_getp_t(HalfOpenLineSegment restrict obj){
418
- int64_t offset=0;
419
- offset+=16;
420
- return ( double*)(( char*) obj+offset);
421
- }
422
- #endif
423
-
424
- static inline
425
- void HalfOpenLineSegment_crossing_drift(HalfOpenLineSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
426
- // Get segment data
427
- double s1 = HalfOpenLineSegment_get_s(seg);
428
- double x1 = HalfOpenLineSegment_get_x(seg);
429
- double s2 = s1 + cos(HalfOpenLineSegment_get_t(seg));
430
- double x2 = x1 + sin(HalfOpenLineSegment_get_t(seg));
431
- double denom = (x2 - x1) - (s2 - s1)*m;
432
- if (fabs(denom) < XC_EPSILON){
433
- // Trajectory is parallel to the segment
434
- if (fabs((x0 - x1)/(s0 - s1) - m) < XC_EPSILON){
435
- // Trajectory overlaps with the segment
436
- // TODO: This is situational; we should return s1 if get_s_first and current_s if after current_s
437
- // For now we hit twice (because we go nor IN nor OUT)
438
- s[*n_hit] = s1;
439
- (*n_hit)++;
440
- s[*n_hit] = s2;
441
- (*n_hit)++;
442
- } else {
443
- // No hit
444
- return;
445
- }
446
- } else {
447
- double t = (x0 - x1 - (s0 - s1)*m) / denom;
448
- if (t >= 0){ // We do not check for t<=1 as it is a half-open segment
449
- s[*n_hit] = s1*(1-t) + s2*t;
450
- (*n_hit)++;
451
- }
452
- }
453
- }
454
-
455
- #ifndef XOBJ_TYPEDEF_CircularSegment
456
- #define XOBJ_TYPEDEF_CircularSegment
457
- typedef struct CircularSegment_s * CircularSegment;
458
- static inline CircularSegment CircularSegment_getp(CircularSegment restrict obj){
459
- int64_t offset=0;
460
- return (CircularSegment)(( char*) obj+offset);
461
- }
462
- static inline double CircularSegment_get_R(const CircularSegment restrict obj){
463
- int64_t offset=0;
464
- return *( double*)(( char*) obj+offset);
465
- }
466
- static inline void CircularSegment_set_R(CircularSegment restrict obj, double value){
467
- int64_t offset=0;
468
- *( double*)(( char*) obj+offset)=value;
469
- }
470
- static inline double* CircularSegment_getp_R(CircularSegment restrict obj){
471
- int64_t offset=0;
472
- return ( double*)(( char*) obj+offset);
473
- }
474
- static inline double CircularSegment_get_s(const CircularSegment restrict obj){
475
- int64_t offset=0;
476
- offset+=8;
477
- return *( double*)(( char*) obj+offset);
478
- }
479
- static inline void CircularSegment_set_s(CircularSegment restrict obj, double value){
480
- int64_t offset=0;
481
- offset+=8;
482
- *( double*)(( char*) obj+offset)=value;
483
- }
484
- static inline double* CircularSegment_getp_s(CircularSegment restrict obj){
485
- int64_t offset=0;
486
- offset+=8;
487
- return ( double*)(( char*) obj+offset);
488
- }
489
- static inline double CircularSegment_get_x(const CircularSegment restrict obj){
490
- int64_t offset=0;
491
- offset+=16;
492
- return *( double*)(( char*) obj+offset);
493
- }
494
- static inline void CircularSegment_set_x(CircularSegment restrict obj, double value){
495
- int64_t offset=0;
496
- offset+=16;
497
- *( double*)(( char*) obj+offset)=value;
498
- }
499
- static inline double* CircularSegment_getp_x(CircularSegment restrict obj){
500
- int64_t offset=0;
501
- offset+=16;
502
- return ( double*)(( char*) obj+offset);
503
- }
504
- static inline double CircularSegment_get_t1(const CircularSegment restrict obj){
505
- int64_t offset=0;
506
- offset+=24;
507
- return *( double*)(( char*) obj+offset);
508
- }
509
- static inline void CircularSegment_set_t1(CircularSegment restrict obj, double value){
510
- int64_t offset=0;
511
- offset+=24;
512
- *( double*)(( char*) obj+offset)=value;
513
- }
514
- static inline double* CircularSegment_getp_t1(CircularSegment restrict obj){
515
- int64_t offset=0;
516
- offset+=24;
517
- return ( double*)(( char*) obj+offset);
518
- }
519
- static inline double CircularSegment_get_t2(const CircularSegment restrict obj){
520
- int64_t offset=0;
521
- offset+=32;
522
- return *( double*)(( char*) obj+offset);
523
- }
524
- static inline void CircularSegment_set_t2(CircularSegment restrict obj, double value){
525
- int64_t offset=0;
526
- offset+=32;
527
- *( double*)(( char*) obj+offset)=value;
528
- }
529
- static inline double* CircularSegment_getp_t2(CircularSegment restrict obj){
530
- int64_t offset=0;
531
- offset+=32;
532
- return ( double*)(( char*) obj+offset);
533
- }
534
- #endif
535
-
536
- static inline
537
- void CircularSegment_crossing_drift(CircularSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
538
- // Get segment data
539
- double R = CircularSegment_get_R(seg);
540
- double sC = CircularSegment_get_s(seg);
541
- double xC = CircularSegment_get_x(seg);
542
- double t1 = CircularSegment_get_t1(seg);
543
- double t2 = CircularSegment_get_t2(seg);
544
- // Calculate crossings
545
- int8_t reversed = 0;
546
- if (t2 < t1){
547
- reversed = 1;
548
- }
549
- double a = 1 + m*m;
550
- double bb = sC - m*(x0 - xC - m*s0); // This is -b/2 with b from the quadratic formula
551
- double c = sC*sC + (x0 - xC - m*s0)*(x0 - xC - m*s0) - R*R;
552
- double disc = bb*bb - a*c; // This is 2*discriminant**2
553
- if (disc < 0){
554
- // No crossing
555
- return;
556
- }
557
- for (int8_t i = 0; i < 2; i++) {
558
- double sgnD = i*2-1; // negative and positive solutions; if multiplicity 2, we add the same solution twice
559
- double new_s = (bb + sgnD*sqrt(fabs(disc)))/a;
560
- double new_x = x0 + (new_s - s0)*m;
561
- double t = atan2(new_x - xC, new_s - sC);
562
- if (reversed){
563
- // t2 < t1, so we are looking at the inverted region of angles
564
- if (t1 >= t || t >= t2){
565
- s[*n_hit] = new_s;
566
- (*n_hit)++;
567
- }
568
- } else {
569
- if (t1 <= t && t <= t2){
570
- s[*n_hit] = new_s;
571
- (*n_hit)++;
572
- }
573
- }
574
- }
575
- }
576
-
577
- #ifndef XOBJ_TYPEDEF_BezierSegment
578
- #define XOBJ_TYPEDEF_BezierSegment
579
- typedef struct BezierSegment_s * BezierSegment;
580
- static inline BezierSegment BezierSegment_getp(BezierSegment restrict obj){
581
- int64_t offset=0;
582
- return (BezierSegment)(( char*) obj+offset);
583
- }
584
- static inline double BezierSegment_get_s1(const BezierSegment restrict obj){
585
- int64_t offset=0;
586
- return *( double*)(( char*) obj+offset);
587
- }
588
- static inline void BezierSegment_set_s1(BezierSegment restrict obj, double value){
589
- int64_t offset=0;
590
- *( double*)(( char*) obj+offset)=value;
591
- }
592
- static inline double* BezierSegment_getp_s1(BezierSegment restrict obj){
593
- int64_t offset=0;
594
- return ( double*)(( char*) obj+offset);
595
- }
596
- static inline double BezierSegment_get_x1(const BezierSegment restrict obj){
597
- int64_t offset=0;
598
- offset+=8;
599
- return *( double*)(( char*) obj+offset);
600
- }
601
- static inline void BezierSegment_set_x1(BezierSegment restrict obj, double value){
602
- int64_t offset=0;
603
- offset+=8;
604
- *( double*)(( char*) obj+offset)=value;
605
- }
606
- static inline double* BezierSegment_getp_x1(BezierSegment restrict obj){
607
- int64_t offset=0;
608
- offset+=8;
609
- return ( double*)(( char*) obj+offset);
610
- }
611
- static inline double BezierSegment_get_s2(const BezierSegment restrict obj){
612
- int64_t offset=0;
613
- offset+=16;
614
- return *( double*)(( char*) obj+offset);
615
- }
616
- static inline void BezierSegment_set_s2(BezierSegment restrict obj, double value){
617
- int64_t offset=0;
618
- offset+=16;
619
- *( double*)(( char*) obj+offset)=value;
620
- }
621
- static inline double* BezierSegment_getp_s2(BezierSegment restrict obj){
622
- int64_t offset=0;
623
- offset+=16;
624
- return ( double*)(( char*) obj+offset);
625
- }
626
- static inline double BezierSegment_get_x2(const BezierSegment restrict obj){
627
- int64_t offset=0;
628
- offset+=24;
629
- return *( double*)(( char*) obj+offset);
630
- }
631
- static inline void BezierSegment_set_x2(BezierSegment restrict obj, double value){
632
- int64_t offset=0;
633
- offset+=24;
634
- *( double*)(( char*) obj+offset)=value;
635
- }
636
- static inline double* BezierSegment_getp_x2(BezierSegment restrict obj){
637
- int64_t offset=0;
638
- offset+=24;
639
- return ( double*)(( char*) obj+offset);
640
- }
641
- static inline double BezierSegment_get_cs1(const BezierSegment restrict obj){
642
- int64_t offset=0;
643
- offset+=32;
644
- return *( double*)(( char*) obj+offset);
645
- }
646
- static inline void BezierSegment_set_cs1(BezierSegment restrict obj, double value){
647
- int64_t offset=0;
648
- offset+=32;
649
- *( double*)(( char*) obj+offset)=value;
650
- }
651
- static inline double* BezierSegment_getp_cs1(BezierSegment restrict obj){
652
- int64_t offset=0;
653
- offset+=32;
654
- return ( double*)(( char*) obj+offset);
655
- }
656
- static inline double BezierSegment_get_cx1(const BezierSegment restrict obj){
657
- int64_t offset=0;
658
- offset+=40;
659
- return *( double*)(( char*) obj+offset);
660
- }
661
- static inline void BezierSegment_set_cx1(BezierSegment restrict obj, double value){
662
- int64_t offset=0;
663
- offset+=40;
664
- *( double*)(( char*) obj+offset)=value;
665
- }
666
- static inline double* BezierSegment_getp_cx1(BezierSegment restrict obj){
667
- int64_t offset=0;
668
- offset+=40;
669
- return ( double*)(( char*) obj+offset);
670
- }
671
- static inline double BezierSegment_get_cs2(const BezierSegment restrict obj){
672
- int64_t offset=0;
673
- offset+=48;
674
- return *( double*)(( char*) obj+offset);
675
- }
676
- static inline void BezierSegment_set_cs2(BezierSegment restrict obj, double value){
677
- int64_t offset=0;
678
- offset+=48;
679
- *( double*)(( char*) obj+offset)=value;
680
- }
681
- static inline double* BezierSegment_getp_cs2(BezierSegment restrict obj){
682
- int64_t offset=0;
683
- offset+=48;
684
- return ( double*)(( char*) obj+offset);
685
- }
686
- static inline double BezierSegment_get_cx2(const BezierSegment restrict obj){
687
- int64_t offset=0;
688
- offset+=56;
689
- return *( double*)(( char*) obj+offset);
690
- }
691
- static inline void BezierSegment_set_cx2(BezierSegment restrict obj, double value){
692
- int64_t offset=0;
693
- offset+=56;
694
- *( double*)(( char*) obj+offset)=value;
695
- }
696
- static inline double* BezierSegment_getp_cx2(BezierSegment restrict obj){
697
- int64_t offset=0;
698
- offset+=56;
699
- return ( double*)(( char*) obj+offset);
700
- }
701
- #endif
702
-
703
- static inline
704
- void _hit_s_bezier(BezierSegment seg, double t, double multiplicity, int8_t* n_hit, double* s){
705
- double s1 = BezierSegment_get_s1(seg);
706
- double s2 = BezierSegment_get_s2(seg);
707
- double cs1 = BezierSegment_get_cs1(seg);
708
- double cs2 = BezierSegment_get_cs2(seg);
709
- double new_s = (1-t)*(1-t)*(1-t)*s1 + 3*(1-t)*(1-t)*t*cs1 + 3*(1-t)*t*t*cs2 + t*t*t*s2;
710
- for (int8_t i = 0; i < multiplicity; i++) {
711
- s[*n_hit] = new_s;
712
- (*n_hit)++;
713
- }
714
- }
715
-
716
- static inline
717
- void BezierSegment_crossing_drift(BezierSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
718
- // Get segment data
719
- double s1 = BezierSegment_get_s1(seg);
720
- double x1 = BezierSegment_get_x1(seg);
721
- double s2 = BezierSegment_get_s2(seg);
722
- double x2 = BezierSegment_get_x2(seg);
723
- double cs1 = BezierSegment_get_cs1(seg);
724
- double cx1 = BezierSegment_get_cx1(seg);
725
- double cs2 = BezierSegment_get_cs2(seg);
726
- double cx2 = BezierSegment_get_cx2(seg);
727
- // The Bézier curve is defined by the parametric equations (with t in [0, 1]):
728
- // s(t) = (1-t)^3*s1 + 3(1-t)^2*t*cs1 + 3(1-t)*t^2*cs2 + t^3*s2
729
- // x(t) = (1-t)^3*x1 + 3(1-t)^2*t*cx1 + 3(1-t)*t^2*cx2 + t^3*x2
730
- // Plug the parametric eqs into the drift trajectory x(t) = m*(s(t) - s0) + x0 and solve for t
731
- // The solutions for t (which we get by Cardano's method) are valid if in [0, 1]
732
- double a = (m*s1 - x1) - (m*s2 - x2) - 3*(m*cs1 - cx1) + 3*(m*cs2 - cx2);
733
- double b = 6*(m*cs1 - cx1) - 3*(m*cs2 - cx2) - 3*(m*s1 - x1);
734
- double c = 3*(m*s1 - x1) - 3*(m*cs1 - cx1);
735
- double d = (m*s0 - x0) - (m*s1 - x1);
736
- double t;
737
- // Edge cases
738
- if (fabs(a) < XC_EPSILON){
739
- if (fabs(b) < XC_EPSILON){
740
- if (fabs(c) < XC_EPSILON){
741
- if (fabs(d) < XC_EPSILON){
742
- // The trajectory is on the Bézier curve
743
- // TODO: This cannot happen because we don't have a cubic trajectory.
744
- // Adapt if these ever would be implemented.
745
- return;
746
- } else {
747
- // No solutions
748
- return;
749
- }
750
- } else {
751
- // This is a linear equation
752
- t = -d/c;
753
- if (0 <= t && t <= 1){
754
- _hit_s_bezier(seg, t, 1, n_hit, s);
755
- }
756
- }
757
- } else {
758
- // This is a quadratic equation
759
- double disc = c*c - 4*b*d;
760
- if (disc < 0){
761
- // No solutions
762
- return;
763
- }
764
- for (int8_t i = 0; i < 2; i++) {
765
- double sgnD = i*2-1; // negative and positive solutions; if multiplicity 2, we add the same solution twice
766
- t = (-c + sgnD*sqrt(fabs(disc)))/(2*b);
767
- if (0 <= t && t <= 1){
768
- _hit_s_bezier(seg, t, 1, n_hit, s);
769
- }
770
- }
771
- }
772
- } else {
773
- // Full cubic equation. Coefficients for the depressed cubic t^3 + p*t + q = 0:
774
- double p = (3*a*c - b*b)/(3*a*a);
775
- double q = (2*b*b*b - 9*a*b*c + 27*a*a*d)/(27*a*a*a);
776
- double disc = -p*p*p/27 - q*q/4; // This is the discriminant of the depressed cubic but divided by (4*27)
777
- if (fabs(disc) < XC_EPSILON){
778
- if (fabs(p) < XC_EPSILON){
779
- // One real root with multiplicity 3
780
- t = -b/(3*a);
781
- if (0 <= t && t <= 1){
782
- _hit_s_bezier(seg, t, 3, n_hit, s);
783
- }
784
- } else {
785
- // Two real roots (one simple and one with multiplicity 2)
786
- t = 3*q/p - b/(3*a);
787
- if (0 <= t && t <= 1){
788
- _hit_s_bezier(seg, t, 1, n_hit, s);
789
- }
790
- t = -3*q/(2*p) - b/(3*a);
791
- if (0 <= t && t <= 1){
792
- _hit_s_bezier(seg, t, 2, n_hit, s);
793
- }
794
- }
795
- } else if (disc < 0){
796
- // One real root
797
- t = cbrt(-q/2 + sqrt(fabs(disc))) + cbrt(-q/2 - sqrt(fabs(disc))) - b/(3*a);
798
- if (0 <= t && t <= 1){
799
- _hit_s_bezier(seg, t, 1, n_hit, s);
800
- }
801
- } else {
802
- // Three real roots
803
- double phi = acos(3*q/(2*p)*sqrt(fabs(3/p)));
804
- t = 2*sqrt(fabs(p/3))*cos(phi/3) - b/(3*a);
805
- if (0 <= t && t <= 1){
806
- _hit_s_bezier(seg, t, 1, n_hit, s);
807
- }
808
- t = 2*sqrt(fabs(p/3))*cos((phi + 2*M_PI)/3) - b/(3*a);
809
- if (0 <= t && t <= 1){
810
- _hit_s_bezier(seg, t, 1, n_hit, s);
811
- }
812
- t = 2*sqrt(fabs(p/3))*cos((phi + 4*M_PI)/3) - b/(3*a);
813
- if (0 <= t && t <= 1){
814
- _hit_s_bezier(seg, t, 1, n_hit, s);
815
- }
816
- }
817
- }
818
- }
819
-
820
- #ifndef XOBJ_TYPEDEF_Segment
821
- #define XOBJ_TYPEDEF_Segment
822
- typedef struct Segment_s * Segment;
823
- enum Segment_e{Segment_LineSegment_t,Segment_HalfOpenLineSegment_t,Segment_CircularSegment_t,Segment_BezierSegment_t};
824
- static inline Segment Segment_getp(Segment restrict obj){
825
- int64_t offset=0;
826
- return (Segment)(( char*) obj+offset);
827
- }
828
- static inline int64_t Segment_typeid(const Segment restrict obj){
829
- int64_t offset=0;
830
- offset+=8;
831
- return *( int64_t*)(( char*) obj+offset);
832
- }
833
- static inline void* Segment_member(const Segment restrict obj){
834
- int64_t offset=0;
835
- offset+=*( int64_t*)(( char*) obj+offset);
836
- return ( void*)(( char*) obj+offset);
837
- }
838
- static inline void Segment_crossing_drift(const Segment restrict obj, int8_t* restrict n_hit, double* restrict s, double s0, double x0, double m){
839
- void* member = Segment_member(obj);
840
- switch (Segment_typeid(obj)){
841
- #ifndef SEGMENT_SKIP_LINESEGMENT
842
- case Segment_LineSegment_t:
843
- return LineSegment_crossing_drift((LineSegment) member,n_hit,s,s0,x0,m);
844
- break;
845
- #endif
846
- #ifndef SEGMENT_SKIP_HALFOPENLINESEGMENT
847
- case Segment_HalfOpenLineSegment_t:
848
- return HalfOpenLineSegment_crossing_drift((HalfOpenLineSegment) member,n_hit,s,s0,x0,m);
849
- break;
850
- #endif
851
- #ifndef SEGMENT_SKIP_CIRCULARSEGMENT
852
- case Segment_CircularSegment_t:
853
- return CircularSegment_crossing_drift((CircularSegment) member,n_hit,s,s0,x0,m);
854
- break;
855
- #endif
856
- #ifndef SEGMENT_SKIP_BEZIERSEGMENT
857
- case Segment_BezierSegment_t:
858
- return BezierSegment_crossing_drift((BezierSegment) member,n_hit,s,s0,x0,m);
859
- break;
860
- #endif
861
- }
862
- return;
863
- }
864
- #endif
865
- #ifndef XOBJ_TYPEDEF_ArrNSegment
866
- #define XOBJ_TYPEDEF_ArrNSegment
867
- typedef struct ArrNSegment_s * ArrNSegment;
868
- static inline ArrNSegment ArrNSegment_getp(ArrNSegment restrict obj){
869
- int64_t offset=0;
870
- return (ArrNSegment)(( char*) obj+offset);
871
- }
872
- static inline int64_t ArrNSegment_len(ArrNSegment restrict obj){
873
- int64_t offset=0;
874
- int64_t* arr = ( int64_t*)(( char*) obj+offset);
875
- return arr[1];
876
- }
877
- static inline Segment ArrNSegment_getp1(ArrNSegment restrict obj, int64_t i0){
878
- int64_t offset=0;
879
- offset+=16+i0*16;
880
- return (Segment)(( char*) obj+offset);
881
- }
882
- static inline int64_t ArrNSegment_typeid(const ArrNSegment restrict obj, int64_t i0){
883
- int64_t offset=0;
884
- offset+=16+i0*16;
885
- offset+=8;
886
- return *( int64_t*)(( char*) obj+offset);
887
- }
888
- static inline void* ArrNSegment_member(const ArrNSegment restrict obj, int64_t i0){
889
- int64_t offset=0;
890
- offset+=16+i0*16;
891
- offset+=*( int64_t*)(( char*) obj+offset);
892
- return ( void*)(( char*) obj+offset);
893
- }
894
- #endif
895
- #ifndef XOBJ_TYPEDEF_Segments
896
- #define XOBJ_TYPEDEF_Segments
897
- typedef struct Segments_s * Segments;
898
- static inline Segments Segments_getp(Segments restrict obj){
899
- int64_t offset=0;
900
- return (Segments)(( char*) obj+offset);
901
- }
902
- static inline ArrNSegment Segments_getp_data(Segments restrict obj){
903
- int64_t offset=0;
904
- offset+=8;
905
- return (ArrNSegment)(( char*) obj+offset);
906
- }
907
- static inline int64_t Segments_len_data(Segments restrict obj){
908
- int64_t offset=0;
909
- offset+=8;
910
- int64_t* arr = ( int64_t*)(( char*) obj+offset);
911
- return arr[1];
912
- }
913
- static inline Segment Segments_getp1_data(Segments restrict obj, int64_t i0){
914
- int64_t offset=0;
915
- offset+=8;
916
- offset+=16+i0*16;
917
- return (Segment)(( char*) obj+offset);
918
- }
919
- static inline int64_t Segments_typeid_data(const Segments restrict obj, int64_t i0){
920
- int64_t offset=0;
921
- offset+=8;
922
- offset+=16+i0*16;
923
- offset+=8;
924
- return *( int64_t*)(( char*) obj+offset);
925
- }
926
- static inline void* Segments_member_data(const Segments restrict obj, int64_t i0){
927
- int64_t offset=0;
928
- offset+=8;
929
- offset+=16+i0*16;
930
- offset+=*( int64_t*)(( char*) obj+offset);
931
- return ( void*)(( char*) obj+offset);
932
- }
933
- #endif
934
-
935
- static inline
936
- void Segments_crossing_drift(Segments segs, int8_t* n_hit, double* s, double s0, double x0, double m){
937
- int64_t n_segments = Segments_len_data(segs);
938
- for (int8_t i=0; i<n_segments;i++) {
939
- Segment seg = Segments_getp1_data(segs, i);
940
- Segment_crossing_drift(seg, n_hit, s, s0, x0, m);
941
- }
942
- sort_array_of_double(s, (int64_t) *n_hit);
943
- }
944
-
945
- static inline
946
- void Segments_crossing_drift_vlimit(Segments segs, int8_t* n_hit, double* s, double s0, double x0, double m){
947
- int64_t n_segments = Segments_len_data(segs);
948
- for (int8_t i=0; i<n_segments;i++) {
949
- Segment seg = Segments_getp1_data(segs, i);
950
- Segment_crossing_drift(seg, n_hit, s, s0, x0, m);
951
- }
952
- sort_array_of_double(s, (int64_t) *n_hit);
953
- }