@tty-pt/islet 0.0.0-stage → 1.3.1

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.
@@ -0,0 +1,696 @@
1
+ #ifndef POINT_H
2
+ #define POINT_H
3
+
4
+ /**
5
+ * @file point.h
6
+ * @brief Point arithmetic and utility functions for spatial operations.
7
+ *
8
+ * Provides helper functions for manipulating multi-dimensional points
9
+ * represented as int16_t arrays. These are building blocks for spatial
10
+ * operations in libislet.
11
+ *
12
+ * All functions are per-dimension specializations (point_copy_1..4, etc.).
13
+ * There is no runtime dimension argument: pick the function matching the
14
+ * dimension count, so the compiler sees fully unrolled bodies.
15
+ *
16
+ * The 2D x 32-bit config (int32_t lanes, morton_set_2_32 / islet_*_2_32)
17
+ * has its own same-shaped family (point_add_2_32, etc.).
18
+ *
19
+ * Prefer the config objects (pointcfg.h: Point1_2..Point4_2, Point2_4)
20
+ * in application code; these inlines remain the tight-loop fast path.
21
+ *
22
+ * @note No bounds checking is performed for efficiency. Caller must ensure
23
+ * arrays have sufficient space for the dimension count used.
24
+ *
25
+ * @see islet_core
26
+ * @see islet_morton
27
+ */
28
+
29
+ #include <stdint.h>
30
+ #include <stdio.h>
31
+
32
+ /** @defgroup islet_point Point utilities
33
+ * @brief Arithmetic and helper functions for int16_t coordinate points.
34
+ *
35
+ * These functions operate on points represented as arrays of int16_t
36
+ * coordinates. They provide common vector operations (add, subtract,
37
+ * min, max), utility functions (copy, set, volume), and spatial
38
+ * indexing helpers.
39
+ *
40
+ * Memory Safety:
41
+ * - All arrays must have at least as many elements as the dimension
42
+ * count implied by the function name (1..4)
43
+ * - No bounds checking is performed for performance
44
+ * - Caller is responsible for ensuring valid memory access
45
+ * - Output arrays may alias input arrays unless noted otherwise
46
+ *
47
+ * Overflow Behavior:
48
+ * - All arithmetic follows standard int16_t overflow semantics (wrapping)
49
+ * - Large multiplications (e.g., point_vol) may overflow
50
+ * - No overflow detection or saturation is provided
51
+ *
52
+ * @see islet_core
53
+ * @{
54
+ */
55
+
56
+ /**
57
+ * @brief Add two points component-wise.
58
+ *
59
+ * Performs vector addition: tar[i] = orig[i] + tr[i] for each dimension.
60
+ * Overflow follows standard int16_t arithmetic (wrapping at -32768/32767).
61
+ *
62
+ * @param[out] tar Output point. May alias orig or tr for in-place operations.
63
+ * @param[in] orig First operand (addend). Array of int16_t.
64
+ * @param[in] tr Second operand (addend). Array of int16_t.
65
+ *
66
+ * @note No overflow detection. 32767 + 1 = -32768 (standard int16_t wrapping).
67
+ *
68
+ * Example:
69
+ * @code
70
+ * int16_t a[3] = {10, 20, 30};
71
+ * int16_t b[3] = {1, 2, 3};
72
+ * int16_t result[3];
73
+ * point_add_3(result, a, b); // result = {11, 22, 33}
74
+ * @endcode
75
+ *
76
+ * @see point_sub_3
77
+ */
78
+ static inline void
79
+ point_add_1(int16_t *tar, int16_t *orig, int16_t *tr)
80
+ {
81
+ tar[0] = (int16_t)(orig[0] + tr[0]);
82
+ }
83
+
84
+ /**
85
+ * @brief 2D vector addition. See point_add_1() for the family docs.
86
+ */
87
+ static inline void
88
+ point_add_2(int16_t *tar, int16_t *orig, int16_t *tr)
89
+ {
90
+ tar[0] = (int16_t)(orig[0] + tr[0]);
91
+ tar[1] = (int16_t)(orig[1] + tr[1]);
92
+ }
93
+
94
+ /**
95
+ * @brief 3D vector addition. See point_add_1() for the family docs.
96
+ */
97
+ static inline void
98
+ point_add_3(int16_t *tar, int16_t *orig, int16_t *tr)
99
+ {
100
+ tar[0] = (int16_t)(orig[0] + tr[0]);
101
+ tar[1] = (int16_t)(orig[1] + tr[1]);
102
+ tar[2] = (int16_t)(orig[2] + tr[2]);
103
+ }
104
+
105
+ /**
106
+ * @brief 4D vector addition. See point_add_1() for the family docs.
107
+ */
108
+ static inline void
109
+ point_add_4(int16_t *tar, int16_t *orig, int16_t *tr)
110
+ {
111
+ tar[0] = (int16_t)(orig[0] + tr[0]);
112
+ tar[1] = (int16_t)(orig[1] + tr[1]);
113
+ tar[2] = (int16_t)(orig[2] + tr[2]);
114
+ tar[3] = (int16_t)(orig[3] + tr[3]);
115
+ }
116
+
117
+ /**
118
+ * @brief Subtract two points component-wise.
119
+ *
120
+ * Performs vector subtraction: tar[i] = orig[i] - tr[i] for each dimension.
121
+ * Overflow follows standard int16_t arithmetic (wrapping at -32768/32767).
122
+ *
123
+ * @param[out] tar Output point. May alias orig or tr for in-place operations.
124
+ * @param[in] orig Minuend (value to subtract from). Array of int16_t.
125
+ * @param[in] tr Subtrahend (value to subtract). Array of int16_t.
126
+ *
127
+ * @note No overflow detection. -32768 - 1 = 32767 (standard int16_t wrapping).
128
+ *
129
+ * Example (compute delta):
130
+ * @code
131
+ * int16_t end[3] = {100, 200, 300};
132
+ * int16_t start[3] = {50, 60, 70};
133
+ * int16_t delta[3];
134
+ * point_sub_3(delta, end, start); // delta = {50, 140, 230}
135
+ * @endcode
136
+ *
137
+ * @see point_add_3
138
+ */
139
+ static inline void
140
+ point_sub_1(int16_t *tar, int16_t *orig, int16_t *tr)
141
+ {
142
+ tar[0] = (int16_t)(orig[0] - tr[0]);
143
+ }
144
+
145
+ /**
146
+ * @brief 2D vector subtraction. See point_sub_1() for the family docs.
147
+ */
148
+ static inline void
149
+ point_sub_2(int16_t *tar, int16_t *orig, int16_t *tr)
150
+ {
151
+ tar[0] = (int16_t)(orig[0] - tr[0]);
152
+ tar[1] = (int16_t)(orig[1] - tr[1]);
153
+ }
154
+
155
+ /**
156
+ * @brief 3D vector subtraction. See point_sub_1() for the family docs.
157
+ */
158
+ static inline void
159
+ point_sub_3(int16_t *tar, int16_t *orig, int16_t *tr)
160
+ {
161
+ tar[0] = (int16_t)(orig[0] - tr[0]);
162
+ tar[1] = (int16_t)(orig[1] - tr[1]);
163
+ tar[2] = (int16_t)(orig[2] - tr[2]);
164
+ }
165
+
166
+ /**
167
+ * @brief 4D vector subtraction. See point_sub_1() for the family docs.
168
+ */
169
+ static inline void
170
+ point_sub_4(int16_t *tar, int16_t *orig, int16_t *tr)
171
+ {
172
+ tar[0] = (int16_t)(orig[0] - tr[0]);
173
+ tar[1] = (int16_t)(orig[1] - tr[1]);
174
+ tar[2] = (int16_t)(orig[2] - tr[2]);
175
+ tar[3] = (int16_t)(orig[3] - tr[3]);
176
+ }
177
+
178
+ /**
179
+ * @brief Compute component-wise minimum of two points.
180
+ *
181
+ * For each dimension i, sets tar[i] to the smaller of a[i] and b[i].
182
+ * Useful for computing bounding box minimum corners or clamping operations.
183
+ *
184
+ * @param[out] tar Output point (minimum per component). May alias a or b.
185
+ * @param[in] a First operand. Array of int16_t.
186
+ * @param[in] b Second operand. Array of int16_t.
187
+ *
188
+ * @note Comparison uses signed int16_t ordering (-32768 is minimum value).
189
+ *
190
+ * @see point_max_3
191
+ */
192
+ static inline void
193
+ point_min_1(int16_t *tar, int16_t *a, int16_t *b)
194
+ {
195
+ tar[0] = a[0] < b[0] ? a[0] : b[0];
196
+ }
197
+
198
+ /**
199
+ * @brief 2D component-wise minimum. See point_min_1() for the family docs.
200
+ */
201
+ static inline void
202
+ point_min_2(int16_t *tar, int16_t *a, int16_t *b)
203
+ {
204
+ tar[0] = a[0] < b[0] ? a[0] : b[0];
205
+ tar[1] = a[1] < b[1] ? a[1] : b[1];
206
+ }
207
+
208
+ /**
209
+ * @brief 3D component-wise minimum. See point_min_1() for the family docs.
210
+ */
211
+ static inline void
212
+ point_min_3(int16_t *tar, int16_t *a, int16_t *b)
213
+ {
214
+ tar[0] = a[0] < b[0] ? a[0] : b[0];
215
+ tar[1] = a[1] < b[1] ? a[1] : b[1];
216
+ tar[2] = a[2] < b[2] ? a[2] : b[2];
217
+ }
218
+
219
+ /**
220
+ * @brief 4D component-wise minimum. See point_min_1() for the family docs.
221
+ */
222
+ static inline void
223
+ point_min_4(int16_t *tar, int16_t *a, int16_t *b)
224
+ {
225
+ tar[0] = a[0] < b[0] ? a[0] : b[0];
226
+ tar[1] = a[1] < b[1] ? a[1] : b[1];
227
+ tar[2] = a[2] < b[2] ? a[2] : b[2];
228
+ tar[3] = a[3] < b[3] ? a[3] : b[3];
229
+ }
230
+
231
+ /**
232
+ * @brief Compute component-wise maximum of two points.
233
+ *
234
+ * For each dimension i, sets tar[i] to the larger of a[i] and b[i].
235
+ * Useful for computing bounding box maximum corners or clamping operations.
236
+ *
237
+ * @param[out] tar Output point (maximum per component). May alias a or b.
238
+ * @param[in] a First operand. Array of int16_t.
239
+ * @param[in] b Second operand. Array of int16_t.
240
+ *
241
+ * @note Comparison uses signed int16_t ordering (32767 is maximum value).
242
+ *
243
+ * @see point_min_3
244
+ */
245
+ static inline void
246
+ point_max_1(int16_t *tar, int16_t *a, int16_t *b)
247
+ {
248
+ tar[0] = a[0] > b[0] ? a[0] : b[0];
249
+ }
250
+
251
+ /**
252
+ * @brief 2D component-wise maximum. See point_max_1() for the family docs.
253
+ */
254
+ static inline void
255
+ point_max_2(int16_t *tar, int16_t *a, int16_t *b)
256
+ {
257
+ tar[0] = a[0] > b[0] ? a[0] : b[0];
258
+ tar[1] = a[1] > b[1] ? a[1] : b[1];
259
+ }
260
+
261
+ /**
262
+ * @brief 3D component-wise maximum. See point_max_1() for the family docs.
263
+ */
264
+ static inline void
265
+ point_max_3(int16_t *tar, int16_t *a, int16_t *b)
266
+ {
267
+ tar[0] = a[0] > b[0] ? a[0] : b[0];
268
+ tar[1] = a[1] > b[1] ? a[1] : b[1];
269
+ tar[2] = a[2] > b[2] ? a[2] : b[2];
270
+ }
271
+
272
+ /**
273
+ * @brief 4D component-wise maximum. See point_max_1() for the family docs.
274
+ */
275
+ static inline void
276
+ point_max_4(int16_t *tar, int16_t *a, int16_t *b)
277
+ {
278
+ tar[0] = a[0] > b[0] ? a[0] : b[0];
279
+ tar[1] = a[1] > b[1] ? a[1] : b[1];
280
+ tar[2] = a[2] > b[2] ? a[2] : b[2];
281
+ tar[3] = a[3] > b[3] ? a[3] : b[3];
282
+ }
283
+
284
+ /**
285
+ * @brief Copy a point (component-wise shallow copy).
286
+ *
287
+ * Copies the coordinates of one point into another. The destination must
288
+ * have space for the dimension count of the function used. 1D/2D/4D use
289
+ * exact scalar or multi-byte moves; nothing is ever read or written past
290
+ * the point's own elements.
291
+ *
292
+ * @param[out] tar Destination point. Must have space for the dim count.
293
+ * @param[in] orig Source point. Array of int16_t.
294
+ *
295
+ * @warning Do not use a wider variant than the arrays actually hold: e.g.
296
+ * copying a bare int16_t[3] with point_copy_4() would read/write
297
+ * past the end.
298
+ *
299
+ * @see point_set_3
300
+ */
301
+ static inline void
302
+ point_copy_1(int16_t *tar, int16_t *orig)
303
+ {
304
+ *tar = *orig;
305
+ }
306
+
307
+ /**
308
+ * @brief 2D point copy (exact 4-byte move). See point_copy_1() for docs.
309
+ */
310
+ static inline void
311
+ point_copy_2(int16_t *tar, int16_t *orig)
312
+ {
313
+ *(int32_t *)tar = *(int32_t *)orig;
314
+ }
315
+
316
+ /**
317
+ * @brief 3D point copy. See point_copy_1() for the family docs.
318
+ */
319
+ static inline void
320
+ point_copy_3(int16_t *tar, int16_t *orig)
321
+ {
322
+ tar[0] = orig[0];
323
+ tar[1] = orig[1];
324
+ tar[2] = orig[2];
325
+ }
326
+
327
+ /**
328
+ * @brief 4D point copy (exact 8-byte move). See point_copy_1() for docs.
329
+ */
330
+ static inline void
331
+ point_copy_4(int16_t *tar, int16_t *orig)
332
+ {
333
+ /* Exact 8 bytes (4 x int16): no overrun possible. */
334
+ *(int64_t *)tar = *(int64_t *)orig;
335
+ }
336
+
337
+ /**
338
+ * @brief Compute the volume (product of all components) of a point.
339
+ *
340
+ * Multiplies all components together to get the volume of a box with
341
+ * dimensions specified by the point. Useful for computing bounding box
342
+ * volumes or array sizes for spatial grids.
343
+ *
344
+ * @param[in] p Point with dimensions. Array of int16_t.
345
+ *
346
+ * @return Product of all components: p[0] * p[1] * ... . For 3D a point
347
+ * {200, 200, 200} yields 8,000,000 (fits int32_t), but a 4D
348
+ * product of large sides may overflow int32_t.
349
+ *
350
+ * @note Negative components will produce negative or unexpected results.
351
+ * This function is designed for positive dimensions (lengths).
352
+ *
353
+ * Example (3D volume):
354
+ * @code
355
+ * int16_t size[3] = {10, 20, 30};
356
+ * int32_t volume = point_vol_3(size); // volume = 6000
357
+ * @endcode
358
+ */
359
+ static inline int32_t
360
+ point_vol_1(int16_t *p)
361
+ {
362
+ return (int32_t)p[0];
363
+ }
364
+
365
+ /**
366
+ * @brief 2D area. See point_vol_1() for the family docs.
367
+ */
368
+ static inline int32_t
369
+ point_vol_2(int16_t *p)
370
+ {
371
+ return (int32_t)p[0] * (int32_t)p[1];
372
+ }
373
+
374
+ /**
375
+ * @brief 3D volume. See point_vol_1() for the family docs.
376
+ */
377
+ static inline int32_t
378
+ point_vol_3(int16_t *p)
379
+ {
380
+ return (int32_t)p[0] * (int32_t)p[1] * (int32_t)p[2];
381
+ }
382
+
383
+ /**
384
+ * @brief 4D volume. See point_vol_1() for the family docs.
385
+ */
386
+ static inline int32_t
387
+ point_vol_4(int16_t *p)
388
+ {
389
+ return (int32_t)p[0] * (int32_t)p[1]
390
+ * (int32_t)p[2] * (int32_t)p[3];
391
+ }
392
+
393
+ /**
394
+ * @brief Set all components of a point to the same value.
395
+ *
396
+ * Broadcasts a single value to all dimensions: tar[i] = value for all i.
397
+ * Useful for initializing points to zero, setting uniform bounds, or
398
+ * creating uniform scaling factors.
399
+ *
400
+ * @param[out] tar Output point. Must have space for the dim count.
401
+ * @param[in] value Value to assign to all components.
402
+ *
403
+ * Example (zero initialization):
404
+ * @code
405
+ * int16_t pos[3];
406
+ * point_set_3(pos, 0); // pos = {0, 0, 0}
407
+ * @endcode
408
+ *
409
+ * Example (uniform bounds):
410
+ * @code
411
+ * int16_t min_bounds[3];
412
+ * point_set_3(min_bounds, -100); // {-100, -100, -100}
413
+ * @endcode
414
+ *
415
+ * @see point_copy_3
416
+ */
417
+ static inline void
418
+ point_set_1(int16_t *tar, int16_t value)
419
+ {
420
+ tar[0] = value;
421
+ }
422
+
423
+ /**
424
+ * @brief 2D broadcast set. See point_set_1() for the family docs.
425
+ */
426
+ static inline void
427
+ point_set_2(int16_t *tar, int16_t value)
428
+ {
429
+ tar[0] = value;
430
+ tar[1] = value;
431
+ }
432
+
433
+ /**
434
+ * @brief 3D broadcast set. See point_set_1() for the family docs.
435
+ */
436
+ static inline void
437
+ point_set_3(int16_t *tar, int16_t value)
438
+ {
439
+ tar[0] = value;
440
+ tar[1] = value;
441
+ tar[2] = value;
442
+ }
443
+
444
+ /**
445
+ * @brief 4D broadcast set. See point_set_1() for the family docs.
446
+ */
447
+ static inline void
448
+ point_set_4(int16_t *tar, int16_t value)
449
+ {
450
+ tar[0] = value;
451
+ tar[1] = value;
452
+ tar[2] = value;
453
+ tar[3] = value;
454
+ }
455
+
456
+ /**
457
+ * @brief Print a point to stderr for debugging.
458
+ *
459
+ * Outputs the point in format: "label(p[0], p[1], ..., p[dim-1])\n"
460
+ * to stderr. Useful for debugging spatial algorithms and visualizing
461
+ * coordinate values during development.
462
+ *
463
+ * @param[in] label String label to print before the point (e.g., "pos").
464
+ * @param[in] p Point to print. Array of int16_t.
465
+ *
466
+ * @note Output goes to stderr, not stdout.
467
+ *
468
+ * Example output:
469
+ * @code
470
+ * int16_t pos[3] = {10, -20, 30};
471
+ * point_debug_3("position", pos);
472
+ * // Output to stderr: "position(10, -20, 30)\n"
473
+ * @endcode
474
+ */
475
+ static inline void
476
+ point_debug_1(char *label, int16_t *p)
477
+ {
478
+ fprintf(stderr, "%s(%d)\n", label, p[0]);
479
+ }
480
+
481
+ /**
482
+ * @brief Print a 2D point. See point_debug_1() for the family docs.
483
+ */
484
+ static inline void
485
+ point_debug_2(char *label, int16_t *p)
486
+ {
487
+ fprintf(stderr, "%s(%d, %d)\n", label, p[0], p[1]);
488
+ }
489
+
490
+ /**
491
+ * @brief Print a 3D point. See point_debug_1() for the family docs.
492
+ */
493
+ static inline void
494
+ point_debug_3(char *label, int16_t *p)
495
+ {
496
+ fprintf(stderr, "%s(%d, %d, %d)\n", label, p[0], p[1], p[2]);
497
+ }
498
+
499
+ /**
500
+ * @brief Print a 4D point. See point_debug_1() for the family docs.
501
+ */
502
+ static inline void
503
+ point_debug_4(char *label, int16_t *p)
504
+ {
505
+ fprintf(stderr, "%s(%d, %d, %d, %d)\n",
506
+ label, p[0], p[1], p[2], p[3]);
507
+ }
508
+
509
+ /**
510
+ * @brief Compute a linear index for a point within a bounding box.
511
+ *
512
+ * Converts a multi-dimensional coordinate to a linear array index using
513
+ * row-major ordering. This is useful for mapping spatial coordinates to
514
+ * flat array indices when storing spatial data in contiguous memory.
515
+ *
516
+ * Row-major means the first dimension (p[0]) varies fastest, last
517
+ * dimension (p[dim-1]) varies slowest. This matches C array layout.
518
+ *
519
+ * @param[in] p Point to index. Must be within the box [s, e).
520
+ * Array of int16_t.
521
+ * @param[in] s Box start (minimum corner, inclusive). Array of int16_t.
522
+ * @param[in] e Box end (maximum corner, exclusive). Array of int16_t.
523
+ *
524
+ * @return Linear index in range [0, volume-1] where volume is the product
525
+ * of (e[i] - s[i]) for all dimensions. Returns uint64_t to handle
526
+ * large volumes, but overflow is still possible.
527
+ *
528
+ * @warning Undefined behavior if p is outside the box [s, e). The function
529
+ * does not check bounds. Results may be incorrect or overflow.
530
+ *
531
+ * @note The point p[i] must satisfy: s[i] <= p[i] < e[i] for all dimensions.
532
+ *
533
+ * Example (2D grid):
534
+ * @code
535
+ * int16_t start[2] = {0, 0};
536
+ * int16_t end[2] = {10, 10}; // 10x10 grid
537
+ * int16_t point[2] = {3, 5};
538
+ * uint64_t idx = point_idx_2(point, start, end);
539
+ * // idx = 5 * 10 + 3 = 53
540
+ * @endcode
541
+ *
542
+ * @see point_vol_3
543
+ * @see islet_iter
544
+ */
545
+ static inline uint64_t
546
+ point_idx_1(int16_t *p, int16_t *s, int16_t *e)
547
+ {
548
+ (void)e;
549
+ return (uint64_t)(p[0] - s[0]);
550
+ }
551
+
552
+ /**
553
+ * @brief 2D row-major index. See point_idx_1() for the family docs.
554
+ */
555
+ static inline uint64_t
556
+ point_idx_2(int16_t *p, int16_t *s, int16_t *e)
557
+ {
558
+ return (uint64_t)(p[0] - s[0])
559
+ + (uint64_t)(p[1] - s[1]) * (uint64_t)(e[0] - s[0]);
560
+ }
561
+
562
+ /**
563
+ * @brief 3D row-major index. See point_idx_1() for the family docs.
564
+ */
565
+ static inline uint64_t
566
+ point_idx_3(int16_t *p, int16_t *s, int16_t *e)
567
+ {
568
+ uint64_t w0 = (uint64_t)(e[0] - s[0]);
569
+ uint64_t w1 = (uint64_t)(e[1] - s[1]);
570
+
571
+ return (uint64_t)(p[0] - s[0])
572
+ + (uint64_t)(p[1] - s[1]) * w0
573
+ + (uint64_t)(p[2] - s[2]) * (w0 * w1);
574
+ }
575
+
576
+ /**
577
+ * @brief 4D row-major index. See point_idx_1() for the family docs.
578
+ */
579
+ static inline uint64_t
580
+ point_idx_4(int16_t *p, int16_t *s, int16_t *e)
581
+ {
582
+ uint64_t w0 = (uint64_t)(e[0] - s[0]);
583
+ uint64_t w1 = (uint64_t)(e[1] - s[1]);
584
+ uint64_t w2 = (uint64_t)(e[2] - s[2]);
585
+
586
+ return (uint64_t)(p[0] - s[0])
587
+ + (uint64_t)(p[1] - s[1]) * w0
588
+ + (uint64_t)(p[2] - s[2]) * (w0 * w1)
589
+ + (uint64_t)(p[3] - s[3]) * (w0 * w1 * w2);
590
+ }
591
+
592
+ /* 2D x 32-bit-lane family (morton_set_2_32 / islet_*_2_32 config).
593
+ * Same operations as the int16 families above, on int32_t lanes
594
+ * (-2147483648..2147483647). Arithmetic wraps on overflow; nothing
595
+ * is ever read or written past the point's own 2 elements. */
596
+
597
+ /**
598
+ * @brief 2D x 32-bit vector addition. See point_add_1() for the
599
+ * family docs.
600
+ */
601
+ static inline void
602
+ point_add_2_32(int32_t *tar, int32_t *orig, int32_t *tr)
603
+ {
604
+ tar[0] = orig[0] + tr[0];
605
+ tar[1] = orig[1] + tr[1];
606
+ }
607
+
608
+ /**
609
+ * @brief 2D x 32-bit vector subtraction. See point_sub_1() for the
610
+ * family docs.
611
+ */
612
+ static inline void
613
+ point_sub_2_32(int32_t *tar, int32_t *orig, int32_t *tr)
614
+ {
615
+ tar[0] = orig[0] - tr[0];
616
+ tar[1] = orig[1] - tr[1];
617
+ }
618
+
619
+ /**
620
+ * @brief 2D x 32-bit component-wise minimum. See point_min_1() for
621
+ * the family docs.
622
+ */
623
+ static inline void
624
+ point_min_2_32(int32_t *tar, int32_t *a, int32_t *b)
625
+ {
626
+ tar[0] = a[0] < b[0] ? a[0] : b[0];
627
+ tar[1] = a[1] < b[1] ? a[1] : b[1];
628
+ }
629
+
630
+ /**
631
+ * @brief 2D x 32-bit component-wise maximum. See point_max_1() for
632
+ * the family docs.
633
+ */
634
+ static inline void
635
+ point_max_2_32(int32_t *tar, int32_t *a, int32_t *b)
636
+ {
637
+ tar[0] = a[0] > b[0] ? a[0] : b[0];
638
+ tar[1] = a[1] > b[1] ? a[1] : b[1];
639
+ }
640
+
641
+ /**
642
+ * @brief 2D x 32-bit point copy (exact 8-byte move). See
643
+ * point_copy_1() for the family docs.
644
+ */
645
+ static inline void
646
+ point_copy_2_32(int32_t *tar, int32_t *orig)
647
+ {
648
+ /* Exact 8 bytes (2 x int32): no overrun possible. */
649
+ *(int64_t *)tar = *(int64_t *)orig;
650
+ }
651
+
652
+ /**
653
+ * @brief 2D x 32-bit area. The product of two lanes (each at most
654
+ * 2^32-1 wide) always fits in uint64_t.
655
+ */
656
+ static inline uint64_t
657
+ point_vol_2_32(int32_t *p)
658
+ {
659
+ return (uint64_t)(uint32_t)p[0] * (uint64_t)(uint32_t)p[1];
660
+ }
661
+
662
+ /**
663
+ * @brief 2D x 32-bit broadcast set. See point_set_1() for the
664
+ * family docs.
665
+ */
666
+ static inline void
667
+ point_set_2_32(int32_t *tar, int32_t value)
668
+ {
669
+ tar[0] = value;
670
+ tar[1] = value;
671
+ }
672
+
673
+ /**
674
+ * @brief Print a 2D x 32-bit point. See point_debug_1() for the
675
+ * family docs.
676
+ */
677
+ static inline void
678
+ point_debug_2_32(char *label, int32_t *p)
679
+ {
680
+ fprintf(stderr, "%s(%d, %d)\n", label, p[0], p[1]);
681
+ }
682
+
683
+ /**
684
+ * @brief 2D x 32-bit row-major index. See point_idx_1() for the
685
+ * family docs.
686
+ */
687
+ static inline uint64_t
688
+ point_idx_2_32(int32_t *p, int32_t *s, int32_t *e)
689
+ {
690
+ return (uint64_t)(p[0] - s[0])
691
+ + (uint64_t)(p[1] - s[1]) * (uint64_t)(e[0] - s[0]);
692
+ }
693
+
694
+ /** @} */
695
+
696
+ #endif