BRL-CAD
vmath.h
Go to the documentation of this file.
1 /* V M A T H . H
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2024 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup vmath */
21 /** @{ */
22 /** @file vmath.h
23  *
24  * @brief fundamental vector, matrix, quaternion math macros
25  *
26  * VMATH defines commonly needed macros for 2D/3D/4D math involving:
27  *
28  * points (point2d_t, point_t, and hpoint_t),
29  * vectors (vect2d_t, vect_t, and hvect_t),
30  * quaternions (quat_t),
31  * planes (plane_t), and
32  * 4x4 matrices (mat_t).
33  *
34  * By default, all floating point numbers are stored in arrays using
35  * the 'fastf_t' type definition. It should be manually typedef'd to
36  * the "fastest" 64-bit floating point type available on the current
37  * hardware with at least 64 bits of precision. On 16 and 32 bit
38  * machines, this is typically "double", but on 64 bit machines, it
39  * could be "float".
40  *
41  * Matrix array elements have the following positions in the matrix:
42  * @code
43  * | 0 1 2 3 | | 0 |
44  * [ 0 1 2 3 ] | 4 5 6 7 | | 1 |
45  * | 8 9 10 11 | | 2 |
46  * | 12 13 14 15 | | 3 |
47  *
48  * preVector (vect_t) Matrix (mat_t) postVector (vect_t)
49  * @endcode
50  *
51  * Note that while many people in the computer graphics field use
52  * post-multiplication with row vectors (i.e., vector * matrix *
53  * matrix ...) VMATH uses the more traditional representation of
54  * column vectors (i.e., ... matrix * matrix * vector). (The matrices
55  * in these two representations are the transposes of each
56  * other). Therefore, when transforming a vector by a matrix,
57  * pre-multiplication is used, i.e.:
58  *
59  * view_vec = model2view_mat * model_vec
60  *
61  * Furthermore, additional transformations are multiplied on the left,
62  * i.e.:
63  *
64  * @code
65  * vec' = T1 * vec
66  * vec'' = T2 * T1 * vec = T2 * vec'
67  * @endcode
68  *
69  * The most notable implication of this is the location of the "delta"
70  * (translation) values in the matrix, i.e.:
71  *
72  * @code
73  * x' (R0 R1 R2 Dx) x
74  * y' = (R4 R5 R6 Dy) * y
75  * z' (R8 R9 R10 Dz) z
76  * w' (0 0 0 1/s) w
77  * @endcode
78  *
79  * Note -
80  *@n vect_t objects are 3-tuples
81  *@n hvect_t objects are 4-tuples
82  *
83  * Most of these macros require that the result be in separate
84  * storage, distinct from the input parameters, except where noted.
85  *
86  * IMPLEMENTER NOTES
87  *
88  * When writing macros like this, it is very important that any
89  * variables declared within a macro code blocks start with an
90  * underscore in order to (hopefully) minimize any name conflicts with
91  * user-provided parameters, such as _f in the following example:
92  *
93  * @code
94  * #define ABC() do { double _f; do stuff; } while (0)
95  * @endcode
96  *
97  * All of the macros that introduce a scope like the preceding
98  * example are written as do { } while (0) loops in order to require
99  * callers provide a trailing semicolon (e.g., ABC();). This helps
100  * preserve source code formatting.
101  */
102 
103 #ifndef VMATH_H
104 #define VMATH_H
105 
106 #include "common.h"
107 
108 /* needed for additional math defines on Windows when including math.h */
109 #define _USE_MATH_DEFINES 1
110 
111 /* for sqrt(), sin(), cos(), rint(), M_PI, INFINITY (HUGE_VAL), and more */
112 #include <math.h>
113 
114 /* for floating point tolerances and other math constants */
115 #include <float.h>
116 
117 
118 #ifdef __cplusplus
119 extern "C" {
120 #endif
121 
122 
123 #ifndef M_
124 # define M_ XXX /**< all with 36-digits of precision */
125 #endif
126 
127 #ifndef M_1_2PI
128 # define M_1_2PI 0.159154943091895335768883763372514362 /**< 1/(2*pi) */
129 #endif
130 #ifndef M_1_PI
131 # define M_1_PI 0.318309886183790671537767526745028724 /**< 1/pi */
132 #endif
133 #ifndef M_2_PI
134 # define M_2_PI 0.636619772367581343075535053490057448 /**< 2/pi */
135 #endif
136 #ifndef M_2_SQRTPI
137 # define M_2_SQRTPI 1.12837916709551257389615890312154517 /**< 2/sqrt(pi) */
138 #endif
139 #ifndef M_E
140 # define M_E 2.71828182845904523536028747135266250 /**< e */
141 #endif
142 #ifndef M_EULER
143 # define M_EULER 0.577215664901532860606512090082402431 /**< Euler's constant */
144 #endif
145 #ifndef M_LOG2E
146 # define M_LOG2E 1.44269504088896340735992468100189214 /**< log_2(e) */
147 #endif
148 #ifndef M_LOG10E
149 # define M_LOG10E 0.434294481903251827651128918916605082 /**< log_10(e) */
150 #endif
151 #ifndef M_LN2
152 # define M_LN2 0.693147180559945309417232121458176568 /**< log_e(2) */
153 #endif
154 #ifndef M_LN10
155 # define M_LN10 2.30258509299404568401799145468436421 /**< log_e(10) */
156 #endif
157 #ifndef M_LNPI
158 # define M_LNPI 1.14472988584940017414342735135305871 /** log_e(pi) */
159 #endif
160 #ifndef M_PI
161 # define M_PI 3.14159265358979323846264338327950288 /**< pi */
162 #endif
163 #ifndef M_2PI
164 # define M_2PI 6.28318530717958647692528676655900576 /**< 2*pi */
165 #endif
166 #ifndef M_PI_2
167 # define M_PI_2 1.57079632679489661923132169163975144 /**< pi/2 */
168 #endif
169 #ifndef M_PI_3
170 # define M_PI_3 1.04719755119659774615421446109316763 /**< pi/3 */
171 #endif
172 #ifndef M_PI_4
173 # define M_PI_4 0.785398163397448309615660845819875721 /**< pi/4 */
174 #endif
175 #ifndef M_SQRT1_2
176 # define M_SQRT1_2 0.707106781186547524400844362104849039 /**< sqrt(1/2) */
177 #endif
178 #ifndef M_SQRT2
179 # define M_SQRT2 1.41421356237309504880168872420969808 /**< sqrt(2) */
180 #endif
181 #ifndef M_SQRT3
182 # define M_SQRT3 1.73205080756887729352744634150587237 /**< sqrt(3) */
183 #endif
184 #ifndef M_SQRTPI
185 # define M_SQRTPI 1.77245385090551602729816748334114518 /**< sqrt(pi) */
186 #endif
187 
188 #ifndef DEG2RAD
189 # define DEG2RAD 0.0174532925199432957692369076848861271 /**< pi/180 */
190 #endif
191 #ifndef RAD2DEG
192 # define RAD2DEG 57.2957795130823208767981548141051703 /**< 180/pi */
193 #endif
194 
195 
196 /**
197  * Definitions about limits of floating point representation
198  * Eventually, should be tied to type of hardware (IEEE, IBM, Cray)
199  * used to implement the fastf_t type.
200  *
201  * MAX_FASTF - Very close to the largest value that can be held by a
202  * fastf_t without overflow. Typically specified as an integer power
203  * of ten, to make the value easy to spot when printed. TODO: macro
204  * function syntax instead of constant (DEPRECATED)
205  *
206  * SQRT_MAX_FASTF - sqrt(MAX_FASTF), or slightly smaller. Any number
207  * larger than this, if squared, can be expected to * produce an
208  * overflow. TODO: macro function syntax instead of constant
209  * (DEPRECATED)
210  *
211  * SMALL_FASTF - Very close to the smallest value that can be
212  * represented while still being greater than zero. Any number
213  * smaller than this (and non-negative) can be considered to be
214  * zero; dividing by such a number can be expected to produce a
215  * divide-by-zero error. All divisors should be checked against
216  * this value before actual division is performed. TODO: macro
217  * function syntax instead of constant (DEPRECATED)
218  *
219  * SQRT_SMALL_FASTF - sqrt(SMALL_FASTF), or slightly larger. The
220  * value of this is quite a lot larger than that of SMALL_FASTF. Any
221  * number smaller than this, when squared, can be expected to produce
222  * a zero result. TODO: macro function syntax instead of constant
223  * (DEPRECATED)
224  *
225  */
226 #if defined(vax)
227 /* DEC VAX "D" format, the most restrictive */
228 # define MAX_FASTF 1.0e37 /* Very close to the largest number */
229 # define SQRT_MAX_FASTF 1.0e18 /* This squared just avoids overflow */
230 # define SMALL_FASTF 1.0e-37 /* Anything smaller is zero */
231 # define SQRT_SMALL_FASTF 1.0e-18 /* This squared gives zero */
232 #else
233 /* IBM format, being the next most restrictive format */
234 # define MAX_FASTF 1.0e73 /* Very close to the largest number */
235 # define SQRT_MAX_FASTF 1.0e36 /* This squared just avoids overflow */
236 # define SMALL_FASTF 1.0e-77 /* Anything smaller is zero */
237 # if defined(aux)
238 # define SQRT_SMALL_FASTF 1.0e-40 /* _doprnt error in libc */
239 # else
240 # define SQRT_SMALL_FASTF 1.0e-39 /* This squared gives zero */
241 # endif
242 #endif
243 
244 /** DEPRECATED, do not use */
245 #define SMALL SQRT_SMALL_FASTF
246 
247 /**
248  * It is necessary to have a representation of 1.0/0.0 or log(0),
249  * i.e., "infinity" that fits within the dynamic range of the machine
250  * being used. This constant places an upper bound on the size object
251  * which can be represented in the model. With IEEE 754 floating
252  * point, this may print as 'inf' and is represented with all 1 bits
253  * in the biased-exponent field and all 0 bits in the fraction with
254  * the sign indicating positive (0) or negative (1) infinity.
255  * However, we do not assume or rely on IEEE 754 floating point.
256  */
257 #ifndef INFINITY
258 # if defined(DBL_MAX)
259 # define INFINITY ((fastf_t)DBL_MAX)
260 # elif defined(HUGE_VAL)
261 # define INFINITY ((fastf_t)HUGE_VAL)
262 # elif defined(MAXDOUBLE)
263 # define INFINITY ((fastf_t)MAXDOUBLE)
264 # elif defined(HUGE)
265 # define INFINITY ((fastf_t)HUGE)
266 /* fall back to a single-precision limit */
267 # elif defined(FLT_MAX)
268 # define INFINITY ((fastf_t)FLT_MAX)
269 # elif defined(HUGE_VALF)
270 # define INFINITY ((fastf_t)HUGE_VALF)
271 # elif defined(MAXFLOAT)
272 # define INFINITY ((fastf_t)MAXFLOAT)
273 # else
274  /* all else fails, just pick something big slightly under the
275  * 32-bit single-precision floating point limit for IEEE 754.
276  */
277 # define INFINITY ((fastf_t)1.0e38)
278 # endif
279 #endif
280 
281 
282 /* minimum computation tolerances */
283 #ifdef vax
284 # define VDIVIDE_TOL (1.0e-10)
285 # define VUNITIZE_TOL (1.0e-7)
286 #else
287 # ifdef DBL_EPSILON
288 # define VDIVIDE_TOL (DBL_EPSILON)
289 # else
290 # define VDIVIDE_TOL (1.0e-20)
291 # endif
292 # ifdef FLT_EPSILON
293 # define VUNITIZE_TOL (FLT_EPSILON)
294 # else
295 # define VUNITIZE_TOL (1.0e-15)
296 # endif
297 #endif
298 
299 
300 /** @brief number of fastf_t's per vect2d_t */
301 #define ELEMENTS_PER_VECT2D 2
302 
303 /** @brief number of fastf_t's per point2d_t */
304 #define ELEMENTS_PER_POINT2D 2
305 
306 /** @brief number of fastf_t's per vect_t */
307 #define ELEMENTS_PER_VECT 3
308 
309 /** @brief number of fastf_t's per point_t */
310 #define ELEMENTS_PER_POINT 3
311 
312 /** @brief number of fastf_t's per hvect_t (homogeneous vector) */
313 #define ELEMENTS_PER_HVECT 4
314 
315 /** @brief number of fastf_t's per hpt_t (homogeneous point) */
316 #define ELEMENTS_PER_HPOINT 4
317 
318 /** @brief number of fastf_t's per plane_t */
319 #define ELEMENTS_PER_PLANE 4
320 
321 /** @brief number of fastf_t's per mat_t */
322 #define ELEMENTS_PER_MAT (ELEMENTS_PER_PLANE*ELEMENTS_PER_PLANE)
323 
324 
325 /*
326  * Fundamental types
327  */
328 
329 /** @brief fastest 64-bit (or larger) floating point type */
330 typedef double fastf_t;
331 
332 /** @brief 2-tuple vector */
334 
335 /** @brief pointer to a 2-tuple vector */
336 typedef fastf_t *vect2dp_t;
337 
338 /** @brief 2-tuple point */
340 
341 /** @brief pointer to a 2-tuple point */
342 typedef fastf_t *point2dp_t;
343 
344 /** @brief 3-tuple vector */
346 
347 /** @brief pointer to a 3-tuple vector */
348 typedef fastf_t *vectp_t;
349 
350 /** @brief 3-tuple point */
352 
353 /** @brief pointer to a 3-tuple point */
354 typedef fastf_t *pointp_t;
355 
356 /** @brief 4-tuple vector */
358 
359 /** @brief 4-element quaternion */
360 typedef hvect_t quat_t;
361 
362 /** @brief 4-tuple point */
364 
365 /** @brief 4x4 matrix */
367 
368 /** @brief pointer to a 4x4 matrix */
369 typedef fastf_t *matp_t;
370 
371 /**
372  * @brief Definition of a plane equation
373  *
374  * A plane is defined by a unit-length outward pointing normal vector
375  * (N), and the perpendicular (shortest) distance from the origin to
376  * the plane (in element N[W]).
377  *
378  * The plane consists of all points P=(x, y, z) such that
379  *@n VDOT(P, N) - N[W] == 0
380  *@n that is,
381  *@n N[X]*x + N[Y]*y + N[Z]*z - N[W] == 0
382  *
383  * The inside of the halfspace bounded by the plane
384  * consists of all points P such that
385  *@n VDOT(P, N) - N[W] <= 0
386  *
387  * A ray with direction D is classified w.r.t. the plane by
388  *
389  *@n VDOT(D, N) < 0 ray enters halfspace defined by plane
390  *@n VDOT(D, N) == 0 ray is parallel to plane
391  *@n VDOT(D, N) > 0 ray exits halfspace defined by plane
392  */
394 
395 /** Vector component names for homogeneous (4-tuple) vectors */
396 typedef enum vmath_vector_component_ {
397  X = 0,
398  Y = 1,
399  Z = 2,
400  W = 3,
401  H = W
403 
404 /**
405  * Locations of deltas (MD*) and scaling values (MS*) in a 4x4
406  * Homogeneous Transform matrix
407  */
408 typedef enum vmath_matrix_component_ {
409  MSX = 0,
410  MDX = 3,
411  MSY = 5,
412  MDY = 7,
413  MSZ = 10,
414  MDZ = 11,
415  MSA = 15
417 
418 /**
419  * Evaluates truthfully whether a number is not within valid range of
420  * INFINITY to -INFINITY exclusive (open set).
421  */
422 #define INVALID(n) (!((n) > -INFINITY && (n) < INFINITY))
423 
424 /**
425  * Evaluates truthfully whether any components of a vector are not
426  * within a valid range.
427  */
428 #define VINVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]) || INVALID((v)[Z]))
429 
430 /**
431  * Evaluates truthfully whether any components of a 2D vector are not
432  * within a valid range.
433  */
434 #define V2INVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]))
435 
436 /**
437  * Evaluates truthfully whether any components of a 4D vector are not
438  * within a valid range.
439  */
440 #define HINVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]) || INVALID((v)[Z]) || INVALID((v)[W]))
441 
442 /**
443  * Return truthfully whether a value is within a specified epsilon
444  * distance from zero.
445  */
446 #ifdef KEITH_WANTS_THIS
447 /* this is a proposed change to equality/zero testing. prior behavior
448  * evaluated as an open set. this would change the behavior to that
449  * of a closed set so that you can perform exact comparisons against
450  * the tolerance and get a match. examples that fail with the current
451  * macro: tol=0.1; 1.1 == 1.0 or tol=0; 1==1
452  *
453  * these need to be tested carefully to make sure we pass ALL
454  * regression and integration tests, which will require some
455  * concerted effort to coordinate prior to a release. first step is
456  * to evaluate impact on performance and behavior of our tests.
457  */
458 # define NEAR_ZERO(val, epsilon) (!(((val) < -epsilon) || ((val) > epsilon)))
459 # define NEAR_ZERO(val, epsilon) (!(((val) < -epsilon)) && !(((val) > epsilon)))
460 #else
461 # define NEAR_ZERO(val, epsilon) (((val) > -epsilon) && ((val) < epsilon))
462 #endif
463 
464 /**
465  * Return truthfully whether all elements of a given vector are within
466  * a specified epsilon distance from zero.
467  */
468 #define VNEAR_ZERO(v, tol) \
469  (NEAR_ZERO(v[X], tol) \
470  && NEAR_ZERO(v[Y], tol) \
471  && NEAR_ZERO(v[Z], tol))
472 
473 /**
474  * Test for all elements of `v' being smaller than `tol'.
475  * Version for degree 2 vectors.
476  */
477 #define V2NEAR_ZERO(v, tol) (NEAR_ZERO(v[X], tol) && NEAR_ZERO(v[Y], tol))
478 
479 /**
480  * Test for all elements of `v' being smaller than `tol'.
481  * Version for degree 2 vectors.
482  */
483 #define HNEAR_ZERO(v, tol) \
484  (NEAR_ZERO(v[X], tol) \
485  && NEAR_ZERO(v[Y], tol) \
486  && NEAR_ZERO(v[Z], tol) \
487  && NEAR_ZERO(h[W], tol))
488 
489 
490 /**
491  * Return truthfully whether a value is within a minimum
492  * representation tolerance from zero.
493  */
494 #define ZERO(_a) NEAR_ZERO((_a), SMALL_FASTF)
495 
496 /**
497  * Return truthfully whether a vector is within a minimum
498  * representation tolerance from zero.
499  */
500 #define VZERO(_a) VNEAR_ZERO((_a), SMALL_FASTF)
501 
502 /**
503  * Return truthfully whether a 2d vector is within a minimum
504  * representation tolerance from zero.
505  */
506 #define V2ZERO(_a) V2NEAR_ZERO((_a), SMALL_FASTF)
507 
508 /**
509  * Return truthfully whether a homogenized 4-element vector is within
510  * a minimum representation tolerance from zero.
511  */
512 #define HZERO(_a) HNEAR_ZERO((_a), SMALL_FASTF)
513 
514 
515 /**
516  * Return truthfully whether two values are within a specified epsilon
517  * distance from each other.
518  */
519 #define NEAR_EQUAL(_a, _b, _tol) NEAR_ZERO((_a) - (_b), (_tol))
520 
521 /**
522  * Return truthfully whether two 3D vectors are approximately equal,
523  * within a specified absolute tolerance.
524  */
525 #define VNEAR_EQUAL(_a, _b, _tol) \
526  (NEAR_EQUAL((_a)[X], (_b)[X], (_tol)) \
527  && NEAR_EQUAL((_a)[Y], (_b)[Y], (_tol)) \
528  && NEAR_EQUAL((_a)[Z], (_b)[Z], (_tol)))
529 
530 /**
531  * Return truthfully whether two 2D vectors are approximately equal,
532  * within a specified absolute tolerance.
533  */
534 #define V2NEAR_EQUAL(a, b, tol) \
535  (NEAR_EQUAL((a)[X], (b)[X], tol) \
536  && NEAR_EQUAL((a)[Y], (b)[Y], tol))
537 
538 /**
539  * Return truthfully whether two 4D vectors are approximately equal,
540  * within a specified absolute tolerance.
541  */
542 #define HNEAR_EQUAL(_a, _b, _tol) \
543  (NEAR_EQUAL((_a)[X], (_b)[X], (_tol)) \
544  && NEAR_EQUAL((_a)[Y], (_b)[Y], (_tol)) \
545  && NEAR_EQUAL((_a)[Z], (_b)[Z], (_tol)) \
546  && NEAR_EQUAL((_a)[W], (_b)[W], (_tol)))
547 
548 /**
549  * Return truthfully whether two values are within a minimum
550  * representation tolerance from each other.
551  */
552 #define EQUAL(_a, _b) NEAR_EQUAL((_a), (_b), SMALL_FASTF)
553 
554 
555 /**
556  * Return truthfully whether two vectors are equal within a minimum
557  * representation tolerance.
558  */
559 #define VEQUAL(_a, _b) VNEAR_EQUAL((_a), (_b), SMALL_FASTF)
560 
561 /**
562  * @brief Return truthfully whether two 2D vectors are equal within
563  * a minimum representation tolerance.
564  */
565 #define V2EQUAL(_a, _b) V2NEAR_EQUAL((_a), (_b), SMALL_FASTF)
566 
567 /**
568  * @brief Return truthfully whether two higher degree vectors are
569  * equal within a minimum representation tolerance.
570  */
571 #define HEQUAL(_a, _b) HNEAR_EQUAL((_a), (_b), SMALL_FASTF)
572 
573 
574 /** @brief Compute distance from a point to a plane. */
575 #define DIST_PNT_PLANE(_pt, _pl) (VDOT(_pt, _pl) - (_pl)[W])
576 
577 /** @brief Compute distance between two points. */
578 #define DIST_PNT_PNT_SQ(_a, _b) \
579  ((_a)[X]-(_b)[X])*((_a)[X]-(_b)[X]) + \
580  ((_a)[Y]-(_b)[Y])*((_a)[Y]-(_b)[Y]) + \
581  ((_a)[Z]-(_b)[Z])*((_a)[Z]-(_b)[Z])
582 #define DIST_PNT_PNT(_a, _b) sqrt(DIST_PNT_PNT_SQ(_a, _b))
583 
584 /** @brief Compute distance between two 2D points. */
585 #define DIST_PNT2_PNT2_SQ(_a, _b) \
586  ((_a)[X]-(_b)[X])*((_a)[X]-(_b)[X]) + \
587  ((_a)[Y]-(_b)[Y])*((_a)[Y]-(_b)[Y])
588 #define DIST_PNT2_PNT2(_a, _b) sqrt(DIST_PNT2_PNT2_SQ(_a, _b))
589 
590 /** @brief set translation values of 4x4 matrix with x, y, z values. */
591 #define MAT_DELTAS(_m, _x, _y, _z) do { \
592  (_m)[MDX] = (_x); \
593  (_m)[MDY] = (_y); \
594  (_m)[MDZ] = (_z); \
595  } while (0)
596 
597 /** @brief set translation values of 4x4 matrix from a vector. */
598 #define MAT_DELTAS_VEC(_m, _v) \
599  MAT_DELTAS(_m, (_v)[X], (_v)[Y], (_v)[Z])
600 
601 /**
602  * @brief set translation values of 4x4 matrix from a reversed
603  * vector.
604  */
605 #define MAT_DELTAS_VEC_NEG(_m, _v) \
606  MAT_DELTAS(_m, -(_v)[X], -(_v)[Y], -(_v)[Z])
607 
608 /** @brief get translation values of 4x4 matrix to a vector. */
609 #define MAT_DELTAS_GET(_v, _m) do { \
610  (_v)[X] = (_m)[MDX]; \
611  (_v)[Y] = (_m)[MDY]; \
612  (_v)[Z] = (_m)[MDZ]; \
613  } while (0)
614 
615 /**
616  * @brief get translation values of 4x4 matrix to a vector,
617  * reversed.
618  */
619 #define MAT_DELTAS_GET_NEG(_v, _m) do { \
620  (_v)[X] = -(_m)[MDX]; \
621  (_v)[Y] = -(_m)[MDY]; \
622  (_v)[Z] = -(_m)[MDZ]; \
623  } while (0)
624 
625 /**
626  * @brief increment translation elements in a 4x4 matrix with x, y, z
627  * values.
628  */
629 #define MAT_DELTAS_ADD(_m, _x, _y, _z) do { \
630  (_m)[MDX] += (_x); \
631  (_m)[MDY] += (_y); \
632  (_m)[MDZ] += (_z); \
633  } while (0)
634 
635 /**
636  * @brief increment translation elements in a 4x4 matrix from a
637  * vector.
638  */
639 #define MAT_DELTAS_ADD_VEC(_m, _v) do { \
640  (_m)[MDX] += (_v)[X]; \
641  (_m)[MDY] += (_v)[Y]; \
642  (_m)[MDZ] += (_v)[Z]; \
643  } while (0)
644 
645 /**
646  * @brief decrement translation elements in a 4x4 matrix with x, y, z
647  * values.
648  */
649 #define MAT_DELTAS_SUB(_m, _x, _y, _z) do { \
650  (_m)[MDX] -= (_x); \
651  (_m)[MDY] -= (_y); \
652  (_m)[MDZ] -= (_z); \
653  } while (0)
654 
655 /**
656  * @brief decrement translation elements in a 4x4 matrix from a
657  * vector.
658  */
659 #define MAT_DELTAS_SUB_VEC(_m, _v) do { \
660  (_m)[MDX] -= (_v)[X]; \
661  (_m)[MDY] -= (_v)[Y]; \
662  (_m)[MDZ] -= (_v)[Z]; \
663  } while (0)
664 
665 /**
666  * @brief decrement translation elements in a 4x4 matrix with x, y, z
667  * values.
668  */
669 #define MAT_DELTAS_MUL(_m, _x, _y, _z) do { \
670  (_m)[MDX] *= (_x); \
671  (_m)[MDY] *= (_y); \
672  (_m)[MDZ] *= (_z); \
673  } while (0)
674 
675 /**
676  * @brief decrement translation elements in a 4x4 matrix from a
677  * vector.
678  */
679 #define MAT_DELTAS_MUL_VEC(_m, _v) do { \
680  (_m)[MDX] *= (_v)[X]; \
681  (_m)[MDY] *= (_v)[Y]; \
682  (_m)[MDZ] *= (_v)[Z]; \
683  } while (0)
684 
685 /** @brief set scale of 4x4 matrix from xyz. */
686 #define MAT_SCALE(_m, _x, _y, _z) do { \
687  (_m)[MSX] = _x; \
688  (_m)[MSY] = _y; \
689  (_m)[MSZ] = _z; \
690  } while (0)
691 
692 /** @brief set scale of 4x4 matrix from vector. */
693 #define MAT_SCALE_VEC(_m, _v) do { \
694  (_m)[MSX] = (_v)[X]; \
695  (_m)[MSY] = (_v)[Y]; \
696  (_m)[MSZ] = (_v)[Z]; \
697  } while (0)
698 
699 /** @brief set uniform scale of 4x4 matrix from scalar. */
700 #define MAT_SCALE_ALL(_m, _s) (_m)[MSA] = (_s)
701 
702 /** @brief add to scaling elements in a 4x4 matrix from xyz. */
703 #define MAT_SCALE_ADD(_m, _x, _y, _z) do { \
704  (_m)[MSX] += _x; \
705  (_m)[MSY] += _y; \
706  (_m)[MSZ] += _z; \
707  } while (0)
708 
709 /** @brief add to scaling elements in a 4x4 matrix from vector. */
710 #define MAT_SCALE_ADD_VEC(_m, _v) do { \
711  (_m)[MSX] += (_v)[X]; \
712  (_m)[MSY] += (_v)[Y]; \
713  (_m)[MSZ] += (_v)[Z]; \
714  } while (0)
715 
716 /** @brief subtract from scaling elements in a 4x4 matrix from xyz. */
717 #define MAT_SCALE_SUB(_m, _x, _y, _z) do { \
718  (_m)[MSX] -= _x; \
719  (_m)[MSY] -= _y; \
720  (_m)[MSZ] -= _z; \
721  } while (0)
722 
723 /**
724  * @brief subtract from scaling elements in a 4x4 matrix from
725  * vector.
726  */
727 #define MAT_SCALE_SUB_VEC(_m, _v) do { \
728  (_m)[MSX] -= (_v)[X]; \
729  (_m)[MSY] -= (_v)[Y]; \
730  (_m)[MSZ] -= (_v)[Z]; \
731  } while (0)
732 
733 /** @brief multiply scaling elements in a 4x4 matrix from xyz. */
734 #define MAT_SCALE_MUL(_m, _x, _y, _z) do { \
735  (_m)[MSX] *= _x; \
736  (_m)[MSY] *= _y; \
737  (_m)[MSZ] *= _z; \
738  } while (0)
739 
740 /** @brief multiply scaling elements in a 4x4 matrix from vector. */
741 #define MAT_SCALE_MUL_VEC(_m, _v) do { \
742  (_m)[MSX] *= (_v)[X]; \
743  (_m)[MSY] *= (_v)[Y]; \
744  (_m)[MSZ] *= (_v)[Z]; \
745  } while (0)
746 
747 
748 /**
749  * In following are macro versions of librt/mat.c functions for when
750  * speed really matters.
751  */
752 
753 
754 /** @brief Zero a matrix. */
755 #define MAT_ZERO(m) do { \
756  (m)[0] = (m)[1] = (m)[2] = (m)[3] = \
757  (m)[4] = (m)[5] = (m)[6] = (m)[7] = \
758  (m)[8] = (m)[9] = (m)[10] = (m)[11] = \
759  (m)[12] = (m)[13] = (m)[14] = (m)[15] = 0.0; \
760  } while (0)
761 
762 /** @brief Set matrix to identity. */
763 #define MAT_IDN(m) do { \
764  (m)[1] = (m)[2] = (m)[3] = (m)[4] = \
765  (m)[6] = (m)[7] = (m)[8] = (m)[9] = \
766  (m)[11] = (m)[12] = (m)[13] = (m)[14] = 0.0; \
767  (m)[0] = (m)[5] = (m)[10] = (m)[15] = 1.0; \
768  } while (0)
769 
770 /**
771  * @brief set t to the transpose of matrix m
772  *
773  * NOTE: This implementation will not transpose in-place or
774  * overlapping matrices (e.g., MAT_TRANSPOSE(m, m) will be wrong).
775  */
776 #define MAT_TRANSPOSE(t, m) do { \
777  (t)[0] = (m)[0]; \
778  (t)[4] = (m)[1]; \
779  (t)[8] = (m)[2]; \
780  (t)[12] = (m)[3]; \
781  (t)[1] = (m)[4]; \
782  (t)[5] = (m)[5]; \
783  (t)[9] = (m)[6]; \
784  (t)[13] = (m)[7]; \
785  (t)[2] = (m)[8]; \
786  (t)[6] = (m)[9]; \
787  (t)[10] = (m)[10]; \
788  (t)[14] = (m)[11]; \
789  (t)[3] = (m)[12]; \
790  (t)[7] = (m)[13]; \
791  (t)[11] = (m)[14]; \
792  (t)[15] = (m)[15]; \
793  } while (0)
794 
795 /** @brief Copy a matrix `m' into `c'. */
796 #define MAT_COPY(c, m) do { \
797  (c)[0] = (m)[0]; \
798  (c)[1] = (m)[1]; \
799  (c)[2] = (m)[2]; \
800  (c)[3] = (m)[3]; \
801  (c)[4] = (m)[4]; \
802  (c)[5] = (m)[5]; \
803  (c)[6] = (m)[6]; \
804  (c)[7] = (m)[7]; \
805  (c)[8] = (m)[8]; \
806  (c)[9] = (m)[9]; \
807  (c)[10] = (m)[10]; \
808  (c)[11] = (m)[11]; \
809  (c)[12] = (m)[12]; \
810  (c)[13] = (m)[13]; \
811  (c)[14] = (m)[14]; \
812  (c)[15] = (m)[15]; \
813  } while (0)
814 
815 /** @brief Set 3D vector at `o' to have coordinates `a', `b', and `c'. */
816 #define VSET(o, a, b, c) do { \
817  (o)[X] = (a); \
818  (o)[Y] = (b); \
819  (o)[Z] = (c); \
820  } while (0)
821 
822 /** @brief Set 2D vector at `o' to have coordinates `a' and `b'. */
823 #define V2SET(o, a, b) do { \
824  (o)[X] = (a); \
825  (o)[Y] = (b); \
826  } while (0)
827 
828 /** @brief Set 4D vector at `o' to homogeneous coordinates `a', `b', `c', and `d'. */
829 #define HSET(o, a, b, c, d) do { \
830  (o)[X] = (a); \
831  (o)[Y] = (b); \
832  (o)[Z] = (c); \
833  (o)[W] = (d); \
834  } while (0)
835 
836 
837 /** @brief Set all elements of 3D vector to same scalar value. */
838 #define VSETALL(v, s) do { \
839  (v)[X] = (v)[Y] = (v)[Z] = (s); \
840  } while (0)
841 
842 /** @brief Set 2D vector elements to same scalar value. */
843 #define V2SETALL(v, s) do { \
844  (v)[X] = (v)[Y] = (s); \
845  } while (0)
846 
847 /** @brief Set 4D vector elements to same scalar value. */
848 #define HSETALL(v, s) do { \
849  (v)[X] = (v)[Y] = (v)[Z] = (v)[W] = (s); \
850  } while (0)
851 
852 
853 /** @brief Set all elements of N-vector to same scalar value. */
854 #define VSETALLN(v, s, n) do { \
855  size_t _j; \
856  for (_j=0; _j < (size_t)(n); _j++) v[_j]=(s); \
857  } while (0)
858 
859 
860 /** @brief Transfer 3D vector at `v' to vector at `o'. */
861 #define VMOVE(o, v) do { \
862  (o)[X] = (v)[X]; \
863  (o)[Y] = (v)[Y]; \
864  (o)[Z] = (v)[Z]; \
865  } while (0)
866 
867 /** @brief Move a 2D vector at `v' to vector at `o'. */
868 #define V2MOVE(o, v) do { \
869  (o)[X] = (v)[X]; \
870  (o)[Y] = (v)[Y]; \
871  } while (0)
872 
873 /** @brief Move a homogeneous 4-tuple at `v' to `o'. */
874 #define HMOVE(o, v) do { \
875  (o)[X] = (v)[X]; \
876  (o)[Y] = (v)[Y]; \
877  (o)[Z] = (v)[Z]; \
878  (o)[W] = (v)[W]; \
879  } while (0)
880 
881 /** @brief Transfer vector of length `n' at `v' to vector at `o'. */
882 #define VMOVEN(o, v, n) do { \
883  size_t _vmove; \
884  for (_vmove = 0; _vmove < (size_t)(n); _vmove++) { \
885  (o)[_vmove] = (v)[_vmove]; \
886  } \
887  } while (0)
888 
889 
890 /**
891  * @brief Reverse the direction of 3D vector `v' and store it in `o'.
892  *
893  * NOTE: Reversing in place works (i.e., VREVERSE(v, v))
894  */
895 #define VREVERSE(o, v) do { \
896  (o)[X] = -(v)[X]; \
897  (o)[Y] = -(v)[Y]; \
898  (o)[Z] = -(v)[Z]; \
899  } while (0)
900 
901 /**
902  * @brief Reverse the direction of 2D vector `v' and store it in `o'.
903  *
904  * NOTE: Reversing in place works (i.e., V2REVERSE(v, v))
905  */
906 #define V2REVERSE(o, v) do { \
907  (o)[X] = -(v)[X]; \
908  (o)[Y] = -(v)[Y]; \
909  } while (0)
910 
911 /**
912  * @brief Same as VREVERSE, but for a 4-tuple. Also useful on plane_t
913  * objects.
914  *
915  * NOTE: Reversing in place works (i.e., HREVERSE(v, v))
916  */
917 #define HREVERSE(o, v) do { \
918  (o)[X] = -(v)[X]; \
919  (o)[Y] = -(v)[Y]; \
920  (o)[Z] = -(v)[Z]; \
921  (o)[W] = -(v)[W]; \
922  } while (0)
923 
924 /** @brief Add 3D vectors at `a' and `b', store result at `o'. */
925 #define VADD2(o, a, b) do { \
926  (o)[X] = (a)[X] + (b)[X]; \
927  (o)[Y] = (a)[Y] + (b)[Y]; \
928  (o)[Z] = (a)[Z] + (b)[Z]; \
929  } while (0)
930 
931 /** @brief Add 2D vectors at `a' and `b', store result at `o'. */
932 #define V2ADD2(o, a, b) do { \
933  (o)[X] = (a)[X] + (b)[X]; \
934  (o)[Y] = (a)[Y] + (b)[Y]; \
935  } while (0)
936 
937 /** @brief Add 4D vectors at `a' and `b', store result at `o'. */
938 #define HADD2(o, a, b) do { \
939  (o)[X] = (a)[X] + (b)[X]; \
940  (o)[Y] = (a)[Y] + (b)[Y]; \
941  (o)[Z] = (a)[Z] + (b)[Z]; \
942  (o)[W] = (a)[W] + (b)[W]; \
943  } while (0)
944 
945 /**
946  * @brief Add vectors of length `n' at `a' and `b', store result at
947  * `o'.
948  */
949 #define VADD2N(o, a, b, n) do { \
950  size_t _vadd2; \
951  for (_vadd2 = 0; _vadd2 < (size_t)(n); _vadd2++) { \
952  (o)[_vadd2] = (a)[_vadd2] + (b)[_vadd2]; \
953  } \
954  } while (0)
955 
956 
957 /**
958  * @brief Subtract 3D vector at `b' from vector at `a', store result at
959  * `o'.
960  */
961 #define VSUB2(o, a, b) do { \
962  (o)[X] = (a)[X] - (b)[X]; \
963  (o)[Y] = (a)[Y] - (b)[Y]; \
964  (o)[Z] = (a)[Z] - (b)[Z]; \
965  } while (0)
966 
967 /**
968  * @brief Subtract 2D vector at `b' from vector at `a', store result at
969  * `o'.
970  */
971 #define V2SUB2(o, a, b) do { \
972  (o)[X] = (a)[X] - (b)[X]; \
973  (o)[Y] = (a)[Y] - (b)[Y]; \
974  } while (0)
975 
976 /**
977  * @brief Subtract 4D vector at `b' from vector at `a', store result at
978  * `o'.
979  */
980 #define HSUB2(o, a, b) do { \
981  (o)[X] = (a)[X] - (b)[X]; \
982  (o)[Y] = (a)[Y] - (b)[Y]; \
983  (o)[Z] = (a)[Z] - (b)[Z]; \
984  (o)[W] = (a)[W] - (b)[W]; \
985  } while (0)
986 
987 /**
988  * @brief Subtract `n' length vector at `b' from `n' length vector at
989  * `a', store result at `o'.
990  */
991 #define VSUB2N(o, a, b, n) do { \
992  size_t _vsub2; \
993  for (_vsub2 = 0; _vsub2 < (size_t)(n); _vsub2++) { \
994  (o)[_vsub2] = (a)[_vsub2] - (b)[_vsub2]; \
995  } \
996  } while (0)
997 
998 
999 /** @brief 3D Vectors: O = A - B - C */
1000 #define VSUB3(o, a, b, c) do { \
1001  (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1002  (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1003  (o)[Z] = (a)[Z] - (b)[Z] - (c)[Z]; \
1004  } while (0)
1005 
1006 /** @brief 2D Vectors: O = A - B - C */
1007 #define V2SUB3(o, a, b, c) do { \
1008  (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1009  (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1010  } while (0)
1012 /** @brief 4D Vectors: O = A - B - C */
1013 #define HSUB3(o, a, b, c) do { \
1014  (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1015  (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1016  (o)[Z] = (a)[Z] - (b)[Z] - (c)[Z]; \
1017  (o)[W] = (a)[W] - (b)[W] - (c)[W]; \
1018  } while (0)
1019 
1020 /** @brief Vectors: O = A - B - C for vectors of length `n'. */
1021 #define VSUB3N(o, a, b, c, n) do { \
1022  size_t _vsub3; \
1023  for (_vsub3 = 0; _vsub3 < (size_t)(n); _vsub3++) { \
1024  (o)[_vsub3] = (a)[_vsub3] - (b)[_vsub3] - (c)[_vsub3]; \
1025  } \
1026  } while (0)
1027 
1028 
1029 /** @brief Add 3 3D vectors at `a', `b', and `c', store result at `o'. */
1030 #define VADD3(o, a, b, c) do { \
1031  (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1032  (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1033  (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z]; \
1034  } while (0)
1035 
1036 /** @brief Add 3 2D vectors at `a', `b', and `c', store result at `o'. */
1037 #define V2ADD3(o, a, b, c) do { \
1038  (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1039  (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1040  } while (0)
1042 /** @brief Add 3 4D vectors at `a', `b', and `c', store result at `o'. */
1043 #define HADD3(o, a, b, c) do { \
1044  (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1045  (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1046  (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z]; \
1047  (o)[W] = (a)[W] + (b)[W] + (c)[W]; \
1048  } while (0)
1049 
1050 /**
1051  * @brief Add 3 vectors of length `n' at `a', `b', and `c', store
1052  * result at `o'.
1053  */
1054 #define VADD3N(o, a, b, c, n) do { \
1055  size_t _vadd3; \
1056  for (_vadd3 = 0; _vadd3 < (size_t)(n); _vadd3++) { \
1057  (o)[_vadd3] = (a)[_vadd3] + (b)[_vadd3] + (c)[_vadd3]; \
1058  } \
1059  } while (0)
1060 
1061 
1062 /**
1063  * @brief Add 4 vectors at `a', `b', `c', and `d', store result at
1064  * `o'.
1065  */
1066 #define VADD4(o, a, b, c, d) do { \
1067  (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1068  (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1069  (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z] + (d)[Z]; \
1070  } while (0)
1071 
1072 /**
1073  * @brief Add 4 2D vectors at `a', `b', `c', and `d', store result at
1074  * `o'.
1075  */
1076 #define V2ADD4(o, a, b, c, d) do { \
1077  (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1078  (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1079  } while (0)
1081 /**
1082  * @brief Add 4 4D vectors at `a', `b', `c', and `d', store result at
1083  * `o'.
1084  */
1085 #define HADD4(o, a, b, c, d) do { \
1086  (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1087  (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1088  (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z] + (d)[Z]; \
1089  (o)[W] = (a)[W] + (b)[W] + (c)[W] + (d)[W]; \
1090  } while (0)
1091 
1092 /**
1093  * @brief Add 4 `n' length vectors at `a', `b', `c', and `d', store
1094  * result at `o'.
1095  */
1096 #define VADD4N(o, a, b, c, d, n) do { \
1097  size_t _vadd4; \
1098  for (_vadd4 = 0; _vadd4 < (size_t)(n); _vadd4++) { \
1099  (o)[_vadd4] = (a)[_vadd4] + (b)[_vadd4] + (c)[_vadd4] + (d)[_vadd4]; \
1100  } \
1101  } while (0)
1102 
1103 
1104 /** @brief Scale 3D vector at `v' by scalar `s', store result at `o'. */
1105 #define VSCALE(o, v, s) do { \
1106  (o)[X] = (v)[X] * (s); \
1107  (o)[Y] = (v)[Y] * (s); \
1108  (o)[Z] = (v)[Z] * (s); \
1109  } while (0)
1110 
1111 /** @brief Scale 2D vector at `v' by scalar `s', store result at `o'. */
1112 #define V2SCALE(o, v, s) do { \
1113  (o)[X] = (v)[X] * (s); \
1114  (o)[Y] = (v)[Y] * (s); \
1115  } while (0)
1117 /** @brief Scale 4D vector at `v' by scalar `s', store result at `o'. */
1118 #define HSCALE(o, v, s) do { \
1119  (o)[X] = (v)[X] * (s); \
1120  (o)[Y] = (v)[Y] * (s); \
1121  (o)[Z] = (v)[Z] * (s); \
1122  (o)[W] = (v)[W] * (s); \
1123  } while (0)
1124 
1125 /**
1126  * @brief Scale vector of length `n' at `v' by scalar `s', store
1127  * result at `o'
1128  */
1129 #define VSCALEN(o, v, s, n) do { \
1130  size_t _vscale; \
1131  for (_vscale = 0; _vscale < (size_t)(n); _vscale++) { \
1132  (o)[_vscale] = (v)[_vscale] * (s); \
1133  } \
1134  } while (0)
1135 
1136 /** @brief Normalize vector `v' to be a unit vector. */
1137 #define VUNITIZE(v) do { \
1138  double _f = MAGSQ(v); \
1139  if (! NEAR_EQUAL(_f, 1.0, VUNITIZE_TOL)) { \
1140  _f = sqrt(_f); \
1141  if (_f < VDIVIDE_TOL) { \
1142  VSETALL((v), 0.0); \
1143  } else { \
1144  _f = 1.0/_f; \
1145  (v)[X] *= _f; (v)[Y] *= _f; (v)[Z] *= _f; \
1146  } \
1147  } \
1148  } while (0)
1149 
1150 /** @brief Normalize 2D vector `v' to be a unit vector. */
1151 #define V2UNITIZE(v) do { \
1152  double _f = MAG2SQ(v); \
1153  if (! NEAR_EQUAL(_f, 1.0, VUNITIZE_TOL)) { \
1154  _f = sqrt(_f); \
1155  if (_f < VDIVIDE_TOL) { \
1156  V2SETALL((v), 0.0); \
1157  } else { \
1158  _f = 1.0/_f; \
1159  (v)[X] *= _f; (v)[Y] *= _f; \
1160  } \
1161  } \
1162  } while (0)
1163 
1164 /**
1165  * @brief Find the sum of two points, and scale the result. Often
1166  * used to find the midpoint.
1167  */
1168 #define VADD2SCALE(o, a, b, s) do { \
1169  (o)[X] = ((a)[X] + (b)[X]) * (s); \
1170  (o)[Y] = ((a)[Y] + (b)[Y]) * (s); \
1171  (o)[Z] = ((a)[Z] + (b)[Z]) * (s); \
1172  } while (0)
1173 
1174 /**
1175  * @brief Find the sum of two vectors of length `n', and scale the
1176  * result by `s'. Often used to find the midpoint.
1177  */
1178 #define VADD2SCALEN(o, a, b, s, n) do { \
1179  size_t _vadd2scale; \
1180  for (_vadd2scale = 0; \
1181  _vadd2scale < (size_t)(n); \
1182  _vadd2scale++) { \
1183  (o)[_vadd2scale] = ((a)[_vadd2scale] + (b)[_vadd2scale]) * (s); \
1184  } \
1185  } while (0)
1186 
1187 /**
1188  * @brief Find the difference between two points, and scale result.
1189  * Often used to compute bounding sphere radius given rpp points.
1190  */
1191 #define VSUB2SCALE(o, a, b, s) do { \
1192  (o)[X] = ((a)[X] - (b)[X]) * (s); \
1193  (o)[Y] = ((a)[Y] - (b)[Y]) * (s); \
1194  (o)[Z] = ((a)[Z] - (b)[Z]) * (s); \
1195  } while (0)
1196 
1197 /**
1198  * @brief Find the difference between two vectors of length `n', and
1199  * scale result by `s'.
1200  */
1201 #define VSUB2SCALEN(o, a, b, s, n) do { \
1202  size_t _vsub2scale; \
1203  for (_vsub2scale = 0; \
1204  _vsub2scale < (size_t)(n); \
1205  _vsub2scale++) { \
1206  (o)[_vsub2scale] = ((a)[_vsub2scale] - (b)[_vsub2scale]) * (s); \
1207  } \
1208  } while (0)
1209 
1210 
1211 /**
1212  * @brief Combine together three vectors, all scaled by scalars.
1213  *
1214  * DEPRECATED: API inconsistent, use combo of other macros.
1215  */
1216 #define VCOMB3(o, a, b, c, d, e, f) do { \
1217  (o)[X] = (a) * (b)[X] + (c) * (d)[X] + (e) * (f)[X]; \
1218  (o)[Y] = (a) * (b)[Y] + (c) * (d)[Y] + (e) * (f)[Y]; \
1219  (o)[Z] = (a) * (b)[Z] + (c) * (d)[Z] + (e) * (f)[Z]; \
1220  } while (0)
1221 
1222 /**
1223  * @brief Combine together three vectors of length `n', all scaled by
1224  * scalars.
1225  *
1226  * DEPRECATED: API inconsistent, use combo of other macros.
1227  */
1228 #define VCOMB3N(o, a, b, c, d, e, f, n) do { \
1229  size_t _vcomb3; \
1230  for (_vcomb3 = 0; \
1231  _vcomb3 < (size_t)(n); \
1232  _vcomb3++) { \
1233  (o)[_vcomb3] = (a) * (b)[_vcomb3] + (c) * (d)[_vcomb3] + (e) * (f)[_vcomb3]; \
1234  } \
1235  } while (0)
1236 
1237 /**
1238  * @brief Combine together 2 vectors, both scaled by scalars.
1239  */
1240 #define VCOMB2(o, sa, va, sb, vb) do { \
1241  (o)[X] = (sa) * (va)[X] + (sb) * (vb)[X]; \
1242  (o)[Y] = (sa) * (va)[Y] + (sb) * (vb)[Y]; \
1243  (o)[Z] = (sa) * (va)[Z] + (sb) * (vb)[Z]; \
1244  } while (0)
1245 
1246 /**
1247  * @brief Combine together 2 vectors of length `n', both scaled by
1248  * scalars.
1249  */
1250 #define VCOMB2N(o, sa, a, sb, b, n) do { \
1251  size_t _vcomb2; \
1252  for (_vcomb2 = 0; \
1253  _vcomb2 < (size_t)(n); \
1254  _vcomb2++) { \
1255  (o)[_vcomb2] = (sa) * (va)[_vcomb2] + (sb) * (vb)[_vcomb2]; \
1256  } \
1257  } while (0)
1258 
1259 /**
1260  * DEPRECATED.
1261  */
1262 #define VJOIN4(a, b, c, d, e, f, g, h, i, j) do { \
1263  (a)[X] = (b)[X] + (c)*(d)[X] + (e)*(f)[X] + (g)*(h)[X] + (i)*(j)[X]; \
1264  (a)[Y] = (b)[Y] + (c)*(d)[Y] + (e)*(f)[Y] + (g)*(h)[Y] + (i)*(j)[Y]; \
1265  (a)[Z] = (b)[Z] + (c)*(d)[Z] + (e)*(f)[Z] + (g)*(h)[Z] + (i)*(j)[Z]; \
1266  } while (0)
1267 
1268 /**
1269  * Join three scaled vectors to a base `a', storing the result in `o'.
1270  */
1271 #define VJOIN3(o, a, sb, b, sc, c, sd, d) do { \
1272  (o)[X] = (a)[X] + (sb)*(b)[X] + (sc)*(c)[X] + (sd)*(d)[X]; \
1273  (o)[Y] = (a)[Y] + (sb)*(b)[Y] + (sc)*(c)[Y] + (sd)*(d)[Y]; \
1274  (o)[Z] = (a)[Z] + (sb)*(b)[Z] + (sc)*(c)[Z] + (sd)*(d)[Z]; \
1275  } while (0)
1276 
1277 
1278 /**
1279  * @brief Compose 3D vector at `o' of:
1280  * Vector at `a' plus
1281  * scalar `sb' times vector at `b' plus
1282  * scalar `sc' times vector at `c'
1283  */
1284 #define VJOIN2(o, a, sb, b, sc, c) do { \
1285  (o)[X] = (a)[X] + (sb) * (b)[X] + (sc) * (c)[X]; \
1286  (o)[Y] = (a)[Y] + (sb) * (b)[Y] + (sc) * (c)[Y]; \
1287  (o)[Z] = (a)[Z] + (sb) * (b)[Z] + (sc) * (c)[Z]; \
1288  } while (0)
1289 
1290 /**
1291  * @brief Compose 2D vector at `o' of:
1292  * Vector at `a' plus
1293  * scalar `sb' times vector at `b' plus
1294  * scalar `sc' times vector at `c'
1295  */
1296 #define V2JOIN2(o, a, sb, b, sc, c) do { \
1297  (o)[X] = (a)[X] + (sb) * (b)[X] + (sc) * (c)[X]; \
1298  (o)[Y] = (a)[Y] + (sb) * (b)[Y] + (sc) * (c)[Y]; \
1299  } while (0)
1301 /**
1302  * @brief Compose 4D vector at `o' of:
1303  * Vector at `a' plus
1304  * scalar `sb' times vector at `b' plus
1305  * scalar `sc' times vector at `c'
1306  */
1307 #define HJOIN2(o, a, sb, b, sc, c) do { \
1308  (o)[X] = (a)[X] + (sb) * (b)[X] + (sc) * (c)[X]; \
1309  (o)[Y] = (a)[Y] + (sb) * (b)[Y] + (sc) * (c)[Y]; \
1310  (o)[Z] = (a)[Z] + (sb) * (b)[Z] + (sc) * (c)[Z]; \
1311  (o)[W] = (a)[W] + (sb) * (b)[W] + (sc) * (c)[W]; \
1312  } while (0)
1313 
1314 #define VJOIN2N(o, a, sb, b, sc, c, n) do { \
1315  size_t _vjoin2; \
1316  for (_vjoin2 = 0; \
1317  _vjoin2 < (size_t)(n); \
1318  _vjoin2++) { \
1319  (o)[_vjoin2] = (a)[_vjoin2] + (sb) * (b)[_vjoin2] + (sc) * (c)[_vjoin2]; \
1320  } \
1321  } while (0)
1322 
1323 
1324 /**
1325  * Compose 3D vector at `o' of:
1326  * vector at `a' plus
1327  * scalar `sb' times vector at `b'
1328  *
1329  * This is basically a shorthand for VSCALE();VADD2();.
1330  */
1331 #define VJOIN1(o, a, sb, b) do { \
1332  (o)[X] = (a)[X] + (sb) * (b)[X]; \
1333  (o)[Y] = (a)[Y] + (sb) * (b)[Y]; \
1334  (o)[Z] = (a)[Z] + (sb) * (b)[Z]; \
1335  } while (0)
1336 
1337 /**
1338  * Compose 2D vector at `o' of:
1339  * vector at `a' plus
1340  * scalar `sb' times vector at `b'
1341  *
1342  * This is basically a shorthand for V2SCALE();V2ADD2();.
1343  */
1344 #define V2JOIN1(o, a, sb, b) do { \
1345  (o)[X] = (a)[X] + (sb) * (b)[X]; \
1346  (o)[Y] = (a)[Y] + (sb) * (b)[Y]; \
1347  } while (0)
1349 /**
1350  * Compose 4D vector at `o' of:
1351  * vector at `a' plus
1352  * scalar `sb' times vector at `b'
1353  *
1354  * This is basically a shorthand for HSCALE();HADD2();.
1355  */
1356 #define HJOIN1(o, a, sb, b) do { \
1357  (o)[X] = (a)[X] + (sb) * (b)[X]; \
1358  (o)[Y] = (a)[Y] + (sb) * (b)[Y]; \
1359  (o)[Z] = (a)[Z] + (sb) * (b)[Z]; \
1360  (o)[W] = (a)[W] + (sb) * (b)[W]; \
1361  } while (0)
1362 
1363 /**
1364  * Compose `n'-D vector at `o' of:
1365  * vector at `a' plus
1366  * scalar `sb' times vector at `b'
1367  *
1368  * This is basically a shorthand for VSCALEN();VADD2N();.
1369  */
1370 #define VJOIN1N(o, a, sb, b, n) do { \
1371  size_t _vjoin1; \
1372  for (_vjoin1 = 0; \
1373  _vjoin1 < (size_t)(n); \
1374  _vjoin1++) { \
1375  (o)[_vjoin1] = (a)[_vjoin1] + (sb) * (b)[_vjoin1]; \
1376  } \
1377  } while (0)
1378 
1379 
1380 /**
1381  * @brief Blend into vector `o'
1382  * scalar `sa' times vector at `a' plus
1383  * scalar `sb' times vector at `b'
1384  */
1385 #define VBLEND2(o, sa, a, sb, b) do { \
1386  (o)[X] = (sa) * (a)[X] + (sb) * (b)[X]; \
1387  (o)[Y] = (sa) * (a)[Y] + (sb) * (b)[Y]; \
1388  (o)[Z] = (sa) * (a)[Z] + (sb) * (b)[Z]; \
1389  } while (0)
1390 
1391 /**
1392  * @brief Blend into vector `o'
1393  * scalar `sa' times vector at `a' plus
1394  * scalar `sb' times vector at `b'
1395  */
1396 #define VBLEND2N(o, sa, a, sb, b, n) do { \
1397  size_t _vblend2; \
1398  for (_vblend2 = 0; \
1399  _vblend2 < (size_t)(n); \
1400  _vblend2++) { \
1401  (b)[_vblend2] = (sa) * (a)[_vblend2] + (sb) * (b)[_vblend2]; \
1402  } \
1403  } while (0)
1404 
1405 
1406 /**
1407  * @brief Project vector `a' onto `b'
1408  * vector `c' is the component of `a' parallel to `b'
1409  * " `d' " " " " " orthogonal " "
1410  *
1411  * FIXME: consistency, the result should come first
1412  */
1413 #define VPROJECT(a, b, c, d) do { \
1414  VSCALE(c, b, VDOT(a, b) / VDOT(b, b)); \
1415  VSUB2(d, a, c); \
1416  } while (0)
1417 
1418 /** @brief Return scalar magnitude squared of vector at `v' */
1419 #define MAGSQ(v) ((v)[X]*(v)[X] + (v)[Y]*(v)[Y] + (v)[Z]*(v)[Z])
1420 #define MAG2SQ(v) ((v)[X]*(v)[X] + (v)[Y]*(v)[Y])
1421 
1422 
1423 /**
1424  * @brief Return scalar magnitude of the 3D vector `a'. This is
1425  * otherwise known as the Euclidean norm of the provided vector..
1426  */
1427 #define MAGNITUDE(v) sqrt(MAGSQ(v))
1428 
1429 /**
1430  * @brief Return scalar magnitude of the 2D vector at `a'. This is
1431  * otherwise known as the Euclidean norm of the provided vector..
1432  */
1433 #define MAGNITUDE2(v) sqrt(MAG2SQ(v))
1434 
1435 /**
1436  * @brief Store cross product of 3D vectors at `a' and `b' in vector at `o'.
1437  *
1438  * NOTE: The "right hand rule" applies. If closing your right hand
1439  * goes from `a' to `b', then your thumb points in the direction of
1440  * the cross product.
1441  *
1442  * If the angle from `a' to `b' goes clockwise, then the result vector
1443  * points "into" the plane (inward normal). Example: a=(0, 1, 0),
1444  * b=(1, 0, 0), then aXb=(0, 0, -1).
1445  *
1446  * If the angle from `a' to `b' goes counter-clockwise, then the
1447  * result vector points "out" of the plane. This outward pointing
1448  * normal is the BRL-CAD convention.
1449  */
1450 #define VCROSS(o, a, b) do { \
1451  (o)[X] = (a)[Y] * (b)[Z] - (a)[Z] * (b)[Y]; \
1452  (o)[Y] = (a)[Z] * (b)[X] - (a)[X] * (b)[Z]; \
1453  (o)[Z] = (a)[X] * (b)[Y] - (a)[Y] * (b)[X]; \
1454  } while (0)
1456 /**
1457  * Return the analog of a cross product for 2D vectors `a' and `b'
1458  * as a scalar value. If a = (ax, ay) and b = (bx, by), then the analog
1459  * of a x b is det(a*b) = ax*by - ay*bx
1460  */
1461 #define V2CROSS(a, b) ((a)[X] * (b)[Y] - (a)[Y] * (b)[X])
1462 
1463 /**
1464  * TODO: implement me
1465  */
1466 #define HCROSS(a, b, c)
1467 
1468 
1469 /** @brief Compute dot product of vectors at `a' and `b'. */
1470 #define VDOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z])
1471 
1472 #define V2DOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y])
1473 
1474 #define HDOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z] + (a)[W]*(b)[W])
1475 
1477 /**
1478  * @brief Linearly interpolate between two 3D vectors `a' and `b' by
1479  * interpolant `t', expected in the range [0,1], with result in `o'.
1480  *
1481  * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1482  * mathematically equivalent to "o = a + (b-a)*t". The latter might
1483  * result in fewer math operations but cannot guarantee o==v1 when
1484  * t==1 due to floating-point arithmetic error.
1485  */
1486 #define VLERP(o, a, b, t) do { \
1487  (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1488  (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1489  (o)[Z] = (a)[Z] * (1 - (t)) + (b)[Z] * (t); \
1490  } while (0)
1491 
1492 /**
1493  * @brief Linearly interpolate between two 2D vectors `a' and `b' by
1494  * interpolant `t', expected in the range [0,1], with result in `o'.
1495  *
1496  * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1497  * mathematically equivalent to "o = a + (b-a)*t". The latter might
1498  * result in fewer math operations but cannot guarantee o==v1 when
1499  * t==1 due to floating-point arithmetic error.
1500  */
1501 #define V2LERP(o, a, b, t) do { \
1502  (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1503  (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1504  } while (0)
1505 
1506 /**
1507  * @brief Linearly interpolate between two 4D vectors `a' and `b' by
1508  * interpolant `t', expected in the range [0,1], with result in `o'.
1509  *
1510  * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1511  * mathematically equivalent to "o = a + (b-a)*t". The latter might
1512  * result in fewer math operations but cannot guarantee o==v1 when
1513  * t==1 due to floating-point arithmetic error.
1514  */
1515 #define HLERP(o, a, b, t) do { \
1516  (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1517  (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1518  (o)[Z] = (a)[Z] * (1 - (t)) + (b)[Z] * (t); \
1519  (o)[W] = (a)[W] * (1 - (t)) + (b)[W] * (t); \
1520  } while (0)
1522 
1523 /**
1524  * @brief Subtract two points to make a vector, dot with another
1525  * vector. Returns the dot product scalar value.
1526  */
1527 #define VSUB2DOT(_pt2, _pt, _vec) (\
1528  ((_pt2)[X] - (_pt)[X]) * (_vec)[X] + \
1529  ((_pt2)[Y] - (_pt)[Y]) * (_vec)[Y] + \
1530  ((_pt2)[Z] - (_pt)[Z]) * (_vec)[Z])
1531 
1532 /**
1533  * @brief Turn a vector into comma-separated list of elements, for
1534  * variable argument subroutines (e.g. printf()).
1535  */
1536 #define V2ARGS(a) (a)[X], (a)[Y]
1537 #define V3ARGS(a) (a)[X], (a)[Y], (a)[Z]
1538 #define V4ARGS(a) (a)[X], (a)[Y], (a)[Z], (a)[W]
1539 
1540 /**
1541  * Clamp values within tolerance of an integer to that value.
1542  *
1543  * For example, INTCLAMP(10.0000123123) evaluates to 10.0
1544  *
1545  * NOTE: should use VDIVIDE_TOL here, but cannot yet. we use
1546  * VUINITIZE_TOL until floats are replaced universally with fastf_t's
1547  * since their epsilon is considerably less than that of a double.
1548  */
1549 #define INTCLAMP(_a) (NEAR_EQUAL((_a), rint(_a), VUNITIZE_TOL) ? rint(_a) : (_a))
1550 
1551 /** Clamp a 3D vector's elements to nearby integer values. */
1552 #define VINTCLAMP(_v) do { \
1553  (_v)[X] = INTCLAMP((_v)[X]); \
1554  (_v)[Y] = INTCLAMP((_v)[Y]); \
1555  (_v)[Z] = INTCLAMP((_v)[Z]); \
1556  } while (0)
1557 
1558 /** Clamp a 2D vector's elements to nearby integer values. */
1559 #define V2INTCLAMP(_v) do { \
1560  (_v)[X] = INTCLAMP((_v)[X]); \
1561  (_v)[Y] = INTCLAMP((_v)[Y]); \
1562  } while (0)
1563 
1564 /** Clamp a 4D vector's elements to nearby integer values. */
1565 #define HINTCLAMP(_v) do { \
1566  VINTCLAMP(_v); \
1567  (_v)[W] = INTCLAMP((_v)[W]); \
1568  } while (0)
1569 
1570 
1571 /** @brief integer clamped versions of the previous arg macros. */
1572 #define V2INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y])
1573 /** @brief integer clamped versions of the previous arg macros. */
1574 #define V3INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z])
1575 /** @brief integer clamped versions of the previous arg macros. */
1576 #define V4INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z]), INTCLAMP((a)[W])
1577 
1578 /** @brief Print vector name and components on stderr. */
1579 #define V2PRINT(a, b) \
1580  fprintf(stderr, "%s (%.6f, %.6g)\n", a, V2ARGS(b));
1581 #define VPRINT(a, b) \
1582  fprintf(stderr, "%s (%.6f, %.6f, %.6f)\n", a, V3ARGS(b));
1583 #define HPRINT(a, b) \
1584  fprintf(stderr, "%s (%.6f, %.6f, %.6f, %.6f)\n", a, V4ARGS(b));
1586 /**
1587  * @brief Included below are integer clamped versions of the previous
1588  * print macros.
1589  */
1590 
1591 #define V2INTCLAMPPRINT(a, b) \
1592  fprintf(stderr, "%s (%g, %g)\n", a, V2INTCLAMPARGS(b));
1593 #define VINTCLAMPPRINT(a, b) \
1594  fprintf(stderr, "%s (%g, %g, %g)\n", a, V3INTCLAMPARGS(b));
1595 #define HINTCLAMPPRINT(a, b) \
1596  fprintf(stderr, "%s (%g, %g, %g, %g)\n", a, V4INTCLAMPARGS(b));
1598 
1599 /** @brief Vector element multiplication. Really: diagonal matrix X vect. */
1600 #define VELMUL(o, a, b) do { \
1601  (o)[X] = (a)[X] * (b)[X]; \
1602  (o)[Y] = (a)[Y] * (b)[Y]; \
1603  (o)[Z] = (a)[Z] * (b)[Z]; \
1604  } while (0)
1605 
1606 #define VELMUL3(o, a, b, c) do { \
1607  (o)[X] = (a)[X] * (b)[X] * (c)[X]; \
1608  (o)[Y] = (a)[Y] * (b)[Y] * (c)[Y]; \
1609  (o)[Z] = (a)[Z] * (b)[Z] * (c)[Z]; \
1610  } while (0)
1611 
1612 /** @brief Similar to VELMUL. */
1613 #define VELDIV(o, a, b) do { \
1614  (o)[X] = (a)[X] / (b)[X]; \
1615  (o)[Y] = (a)[Y] / (b)[Y]; \
1616  (o)[Z] = (a)[Z] / (b)[Z]; \
1617  } while (0)
1618 
1619 /**
1620  * @brief Given a direction vector, compute the inverses of each element.
1621  * When division by zero would have occurred, mark inverse as INFINITY.
1622  */
1623 #define VINVDIR(_inv, _dir) do { \
1624  if ((_dir)[X] < -SQRT_SMALL_FASTF || (_dir)[X] > SQRT_SMALL_FASTF) { \
1625  (_inv)[X]=1.0/(_dir)[X]; \
1626  } else { \
1627  (_dir)[X] = 0.0; \
1628  (_inv)[X] = INFINITY; \
1629  } \
1630  if ((_dir)[Y] < -SQRT_SMALL_FASTF || (_dir)[Y] > SQRT_SMALL_FASTF) { \
1631  (_inv)[Y]=1.0/(_dir)[Y]; \
1632  } else { \
1633  (_dir)[Y] = 0.0; \
1634  (_inv)[Y] = INFINITY; \
1635  } \
1636  if ((_dir)[Z] < -SQRT_SMALL_FASTF || (_dir)[Z] > SQRT_SMALL_FASTF) { \
1637  (_inv)[Z]=1.0/(_dir)[Z]; \
1638  } else { \
1639  (_dir)[Z] = 0.0; \
1640  (_inv)[Z] = INFINITY; \
1641  } \
1642  } while (0)
1643 
1644 /**
1645  * @brief Apply the 3x3 part of a mat_t to a 3-tuple. This rotates a
1646  * vector without scaling it (changing its length).
1647  */
1648 #define MAT3X3VEC(o, mat, vec) do { \
1649  (o)[X] = (mat)[X]*(vec)[X]+(mat)[Y]*(vec)[Y] + (mat)[ 2]*(vec)[Z]; \
1650  (o)[Y] = (mat)[4]*(vec)[X]+(mat)[5]*(vec)[Y] + (mat)[ 6]*(vec)[Z]; \
1651  (o)[Z] = (mat)[8]*(vec)[X]+(mat)[9]*(vec)[Y] + (mat)[10]*(vec)[Z]; \
1652  } while (0)
1653 
1654 /** @brief Multiply a 3-tuple by the 3x3 part of a mat_t. */
1655 #define VEC3X3MAT(o, i, m) do { \
1656  (o)[X] = (i)[X]*(m)[X] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]; \
1657  (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]; \
1658  (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]; \
1659  } while (0)
1660 
1661 /** @brief Apply the 3x3 part of a mat_t to a 2-tuple (Z part=0). */
1662 #define MAT3X2VEC(o, mat, vec) do { \
1663  (o)[X] = (mat)[0]*(vec)[X] + (mat)[Y]*(vec)[Y]; \
1664  (o)[Y] = (mat)[4]*(vec)[X] + (mat)[5]*(vec)[Y]; \
1665  (o)[Z] = (mat)[8]*(vec)[X] + (mat)[9]*(vec)[Y]; \
1666  } while (0)
1667 
1668 /** @brief Multiply a 2-tuple (Z=0) by the 3x3 part of a mat_t. */
1669 #define VEC2X3MAT(o, i, m) do { \
1670  (o)[X] = (i)[X]*(m)[0] + (i)[Y]*(m)[4]; \
1671  (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5]; \
1672  (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6]; \
1673  } while (0)
1674 
1675 /**
1676  * @brief Apply a 4x4 matrix to a 3-tuple which is an absolute Point
1677  * in space. Output and input points should be separate arrays.
1678  */
1679 #define MAT4X3PNT(o, m, i) do { \
1680  double _f; \
1681  _f = 1.0/((m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]); \
1682  (o)[X]=((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[3]) * _f; \
1683  (o)[Y]=((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[7]) * _f; \
1684  (o)[Z]=((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11])* _f; \
1685  } while (0)
1686 
1687 /**
1688  * @brief Multiply an Absolute 3-Point by a full 4x4 matrix. Output
1689  * and input points should be separate arrays.
1690  */
1691 #define PNT3X4MAT(o, i, m) do { \
1692  double _f; \
1693  _f = 1.0/((i)[X]*(m)[3] + (i)[Y]*(m)[7] + (i)[Z]*(m)[11] + (m)[15]); \
1694  (o)[X]=((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8] + (m)[12]) * _f; \
1695  (o)[Y]=((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9] + (m)[13]) * _f; \
1696  (o)[Z]=((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10] + (m)[14])* _f; \
1697  } while (0)
1698 
1699 /**
1700  * @brief Multiply an Absolute hvect_t 4-Point by a full 4x4 matrix.
1701  * Output and input points should be separate arrays.
1702  */
1703 #define MAT4X4PNT(o, m, i) do { \
1704  (o)[X]=(m)[ 0]*(i)[X] + (m)[ 1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[ 3]*(i)[W]; \
1705  (o)[Y]=(m)[ 4]*(i)[X] + (m)[ 5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[ 7]*(i)[W]; \
1706  (o)[Z]=(m)[ 8]*(i)[X] + (m)[ 9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11]*(i)[W]; \
1707  (o)[W]=(m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]*(i)[W]; \
1708  } while (0)
1710 /**
1711  * @brief Apply a 4x4 matrix to a 3-tuple which is a relative Vector
1712  * in space. This macro can scale the length of the vector if [15] !=
1713  * 1.0. Output and input vectors should be separate arrays.
1714  */
1715 #define MAT4X3VEC(o, m, i) do { \
1716  double _f; \
1717  _f = 1.0/((m)[15]); \
1718  (o)[X] = ((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z]) * _f; \
1719  (o)[Y] = ((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z]) * _f; \
1720  (o)[Z] = ((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z]) * _f; \
1721  } while (0)
1722 
1723 #define MAT4XSCALOR(o, m, i) do { \
1724  (o) = (i) / (m)[15]; \
1725  } while (0)
1726 
1727 /**
1728  * @brief Multiply a Relative 3-Vector by most of a 4x4 matrix.
1729  * Output and input vectors should be separate arrays.
1730  */
1731 #define VEC3X4MAT(o, i, m) do { \
1732  double _f; \
1733  _f = 1.0/((m)[15]); \
1734  (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]) * _f; \
1735  (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]) * _f; \
1736  (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]) * _f; \
1737  } while (0)
1738 
1739 /** @brief Multiply a Relative 2-Vector by most of a 4x4 matrix. */
1740 #define VEC2X4MAT(o, i, m) do { \
1741  double _f; \
1742  _f = 1.0/((m)[15]); \
1743  (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4]) * _f; \
1744  (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5]) * _f; \
1745  (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6]) * _f; \
1746  } while (0)
1747 
1748 /**
1749  * @brief Included below are macros to update min and max X, Y, Z
1750  * values to contain a point
1751  */
1752 
1753 #define V_MIN(r, s) if ((r) > (s)) r = (s)
1754 
1755 #define V_MAX(r, s) if ((r) < (s)) r = (s)
1756 
1757 #ifdef VMIN
1758 # undef VMIN
1759 #endif
1760 #define VMIN(r, s) do { \
1761  V_MIN((r)[X], (s)[X]); V_MIN((r)[Y], (s)[Y]); V_MIN((r)[Z], (s)[Z]); \
1762  } while (0)
1763 
1764 #ifdef VMAX
1765 # undef VMAX
1766 #endif
1767 #define VMAX(r, s) do { \
1768  V_MAX((r)[X], (s)[X]); V_MAX((r)[Y], (s)[Y]); V_MAX((r)[Z], (s)[Z]); \
1769  } while (0)
1770 
1771 #ifdef VMINMAX
1772 # undef VMINMAX
1773 #endif
1774 #define VMINMAX(min, max, pt) do { \
1775  VMIN((min), (pt)); VMAX((max), (pt)); \
1776  } while (0)
1777 
1778 /**
1779  * @brief Included below are macros to update min and max X, Y
1780  * values to contain a point
1781  */
1782 
1783 #define V2MIN(r, s) do { \
1784  V_MIN((r)[X], (s)[X]); V_MIN((r)[Y], (s)[Y]); \
1785  } while (0)
1786 
1787 #define V2MAX(r, s) do { \
1788  V_MAX((r)[X], (s)[X]); V_MAX((r)[Y], (s)[Y]); \
1789  } while (0)
1790 
1791 #define V2MINMAX(min, max, pt) do { \
1792  V2MIN((min), (pt)); V2MAX((max), (pt)); \
1793  } while (0)
1794 
1795 /**
1796  * clamp a value to a low/high number.
1797  */
1798 #define CLAMP(_v, _l, _h) V_MAX((_v), (_l)); else V_MIN((_v), (_h))
1799 
1800 
1801 /**
1802  * @brief Divide out homogeneous parameter from hvect_t, creating
1803  * vect_t.
1804  */
1805 #define HDIVIDE(o, v) do { \
1806  (o)[X] = (v)[X] / (v)[W]; \
1807  (o)[Y] = (v)[Y] / (v)[W]; \
1808  (o)[Z] = (v)[Z] / (v)[W]; \
1809  } while (0)
1810 
1811 /**
1812  * @brief Quaternion math definitions.
1813  *
1814  * Note that the [W] component will be put in the last (i.e., third)
1815  * place rather than the first [X] (i.e., [0]) place, so that the X,
1816  * Y, and Z elements will be compatible with vectors. Only
1817  * QUAT_FROM_VROT macros depend on component locations, however.
1818  */
1819 
1820 /**
1821  * @brief Create Quaternion from Vector and Rotation about vector.
1822  *
1823  * To produce a quaternion representing a rotation by PI radians about
1824  * X-axis:
1825  *
1826  * VSET(axis, 1, 0, 0);
1827  * QUAT_FROM_VROT(quat, M_PI, axis);
1828  * or
1829  * QUAT_FROM_ROT(quat, M_PI, 1.0, 0.0, 0.0, 0.0);
1830  *
1831  * Alternatively, in degrees:
1832  * QUAT_FROM_ROT_DEG(quat, 180.0, 1.0, 0.0, 0.0, 0.0);
1833  */
1834 #define QUAT_FROM_ROT(q, r, x, y, z) do { \
1835  fastf_t _rot = (r) * 0.5; \
1836  QSET(q, x, y, z, cos(_rot)); \
1837  VUNITIZE(q); \
1838  _rot = sin(_rot); /* _rot is really just a temp variable now */ \
1839  VSCALE(q, q, _rot); \
1840  } while (0)
1841 
1842 #define QUAT_FROM_VROT(q, r, v) do { \
1843  fastf_t _rot = (r) * 0.5; \
1844  VMOVE(q, v); \
1845  VUNITIZE(q); \
1846  (q)[W] = cos(_rot); \
1847  _rot = sin(_rot); /* _rot is really just a temp variable now */ \
1848  VSCALE(q, q, _rot); \
1849  } while (0)
1850 
1851 #define QUAT_FROM_VROT_DEG(q, r, v) \
1852  QUAT_FROM_VROT(q, ((r)*DEG2RAD), v)
1853 
1854 #define QUAT_FROM_ROT_DEG(q, r, x, y, z) \
1855  QUAT_FROM_ROT(q, ((r)*DEG2RAD), x, y, z)
1856 
1858 /**
1859  * @brief Set quaternion at `a' to have coordinates `b', `c', `d', and
1860  * `e'.
1861  */
1862 #define QSET(a, b, c, d, e) do { \
1863  (a)[X] = (b); \
1864  (a)[Y] = (c); \
1865  (a)[Z] = (d); \
1866  (a)[W] = (e); \
1867  } while (0)
1869 /** @brief Transfer quaternion at `b' to quaternion at `a'. */
1870 #define QMOVE(a, b) do { \
1871  (a)[X] = (b)[X]; \
1872  (a)[Y] = (b)[Y]; \
1873  (a)[Z] = (b)[Z]; \
1874  (a)[W] = (b)[W]; \
1875  } while (0)
1877 /** @brief Add quaternions at `b' and `c', store result at `a'. */
1878 #define QADD2(a, b, c) do { \
1879  (a)[X] = (b)[X] + (c)[X]; \
1880  (a)[Y] = (b)[Y] + (c)[Y]; \
1881  (a)[Z] = (b)[Z] + (c)[Z]; \
1882  (a)[W] = (b)[W] + (c)[W]; \
1883  } while (0)
1885 /**
1886  * @brief Subtract quaternion at `c' from quaternion at `b', store
1887  * result at `a'.
1888  */
1889 #define QSUB2(a, b, c) do { \
1890  (a)[X] = (b)[X] - (c)[X]; \
1891  (a)[Y] = (b)[Y] - (c)[Y]; \
1892  (a)[Z] = (b)[Z] - (c)[Z]; \
1893  (a)[W] = (b)[W] - (c)[W]; \
1894  } while (0)
1896 /**
1897  * @brief Scale quaternion at `b' by scalar `c', store result at
1898  * `a'.
1899  */
1900 #define QSCALE(a, b, c) do { \
1901  (a)[X] = (b)[X] * (c); \
1902  (a)[Y] = (b)[Y] * (c); \
1903  (a)[Z] = (b)[Z] * (c); \
1904  (a)[W] = (b)[W] * (c); \
1905  } while (0)
1907 /** @brief Normalize quaternion 'a' to be a unit quaternion. */
1908 #define QUNITIZE(a) do { \
1909  double _f; \
1910  _f = QMAGNITUDE(a); \
1911  if (_f < VDIVIDE_TOL) _f = 0.0; else _f = 1.0/_f; \
1912  (a)[X] *= _f; (a)[Y] *= _f; (a)[Z] *= _f; (a)[W] *= _f; \
1913  } while (0)
1915 /** @brief Return scalar magnitude squared of quaternion at `a'. */
1916 #define QMAGSQ(a) \
1917  ((a)[X]*(a)[X] + (a)[Y]*(a)[Y] \
1918  + (a)[Z]*(a)[Z] + (a)[W]*(a)[W])
1919 
1920 /** @brief Return scalar magnitude of quaternion at `a'. */
1921 #define QMAGNITUDE(a) sqrt(QMAGSQ(a))
1923 /** @brief Compute dot product of quaternions at `a' and `b'. */
1924 #define QDOT(a, b) \
1925  ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] \
1926  + (a)[Z]*(b)[Z] + (a)[W]*(b)[W])
1928 /**
1929  * @brief Compute quaternion product a = b * c
1930  *
1931  * a[W] = b[W]*c[W] - VDOT(b, c);
1932  * VCROSS(temp, b, c);
1933  * VJOIN2(a, temp, b[W], c, c[W], b);
1934  */
1935 #define QMUL(a, b, c) do { \
1936  (a)[W] = (b)[W]*(c)[W] - (b)[X]*(c)[X] - (b)[Y]*(c)[Y] - (b)[Z]*(c)[Z]; \
1937  (a)[X] = (b)[W]*(c)[X] + (b)[X]*(c)[W] + (b)[Y]*(c)[Z] - (b)[Z]*(c)[Y]; \
1938  (a)[Y] = (b)[W]*(c)[Y] + (b)[Y]*(c)[W] + (b)[Z]*(c)[X] - (b)[X]*(c)[Z]; \
1939  (a)[Z] = (b)[W]*(c)[Z] + (b)[Z]*(c)[W] + (b)[X]*(c)[Y] - (b)[Y]*(c)[X]; \
1940  } while (0)
1942 /** @brief Conjugate quaternion */
1943 #define QCONJUGATE(a, b) do { \
1944  (a)[X] = -(b)[X]; \
1945  (a)[Y] = -(b)[Y]; \
1946  (a)[Z] = -(b)[Z]; \
1947  (a)[W] = (b)[W]; \
1948  } while (0)
1950 /** @brief Multiplicative inverse quaternion */
1951 #define QINVERSE(a, b) do { \
1952  double _f = QMAGSQ(b); \
1953  if (_f < VDIVIDE_TOL) _f = 0.0; else _f = 1.0/_f; \
1954  (a)[X] = -(b)[X] * _f; \
1955  (a)[Y] = -(b)[Y] * _f; \
1956  (a)[Z] = -(b)[Z] * _f; \
1957  (a)[W] = (b)[W] * _f; \
1958  } while (0)
1959 
1960 /**
1961  * @brief Blend into quaternion `a'
1962  *
1963  * scalar `b' times quaternion at `c' plus
1964  * scalar `d' times quaternion at `e'
1965  */
1966 #define QBLEND2(a, b, c, d, e) do { \
1967  (a)[X] = (b) * (c)[X] + (d) * (e)[X]; \
1968  (a)[Y] = (b) * (c)[Y] + (d) * (e)[Y]; \
1969  (a)[Z] = (b) * (c)[Z] + (d) * (e)[Z]; \
1970  (a)[W] = (b) * (c)[W] + (d) * (e)[W]; \
1971  } while (0)
1973 /**
1974  * Macros for dealing with 3-D "extents", aka bounding boxes, that are
1975  * represented as axis-aligned right parallelepipeds (RPPs). This is
1976  * stored as two points: a min point, and a max point. RPP 1 is
1977  * defined by lo1, hi1, RPP 2 by lo2, hi2.
1978  */
1979 
1980 /**
1981  * Compare two bounding boxes and return true if they are disjoint.
1982  */
1983 #define V3RPP_DISJOINT(_l1, _h1, _l2, _h2) \
1984  ((_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
1985  (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z])
1986 
1987 /**
1988  * Compare two bounding boxes and return true if they are disjoint
1989  * by at least distance tolerance.
1990  */
1991 #define V3RPP_DISJOINT_TOL(_l1, _h1, _l2, _h2, _t) \
1992  ((_l1)[X] > (_h2)[X] + (_t) || \
1993  (_l1)[Y] > (_h2)[Y] + (_t) || \
1994  (_l1)[Z] > (_h2)[Z] + (_t) || \
1995  (_l2)[X] > (_h1)[X] + (_t) || \
1996  (_l2)[Y] > (_h1)[Y] + (_t) || \
1997  (_l2)[Z] > (_h1)[Z] + (_t))
1998 
1999 /** Compare two bounding boxes and return true If they overlap. */
2000 #define V3RPP_OVERLAP(_l1, _h1, _l2, _h2) \
2001  (! ((_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
2002  (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z]))
2003 
2004 /**
2005  * @brief If two extents overlap within distance tolerance, return
2006  * true.
2007  */
2008 #define V3RPP_OVERLAP_TOL(_l1, _h1, _l2, _h2, _t) \
2009  (! ((_l1)[X] > (_h2)[X] + (_t) || \
2010  (_l1)[Y] > (_h2)[Y] + (_t) || \
2011  (_l1)[Z] > (_h2)[Z] + (_t) || \
2012  (_l2)[X] > (_h1)[X] + (_t) || \
2013  (_l2)[Y] > (_h1)[Y] + (_t) || \
2014  (_l2)[Z] > (_h1)[Z] + (_t)))
2015 
2016 /**
2017  * @brief Is the point within or on the boundary of the RPP?
2018  *
2019  * FIXME: should not be using >= <=, '=' case is unreliable
2020  */
2021 #define V3PNT_IN_RPP(_pt, _lo, _hi) (\
2022  (_pt)[X] >= (_lo)[X] && (_pt)[X] <= (_hi)[X] && \
2023  (_pt)[Y] >= (_lo)[Y] && (_pt)[Y] <= (_hi)[Y] && \
2024  (_pt)[Z] >= (_lo)[Z] && (_pt)[Z] <= (_hi)[Z])
2025 
2026 /**
2027  * @brief Within the distance tolerance, is the point within the RPP?
2028  *
2029  * FIXME: should not be using >= <=, '=' case is unreliable
2030  */
2031 #define V3PNT_IN_RPP_TOL(_pt, _lo, _hi, _t) (\
2032  (_pt)[X] >= (_lo)[X]-(_t) && (_pt)[X] <= (_hi)[X]+(_t) && \
2033  (_pt)[Y] >= (_lo)[Y]-(_t) && (_pt)[Y] <= (_hi)[Y]+(_t) && \
2034  (_pt)[Z] >= (_lo)[Z]-(_t) && (_pt)[Z] <= (_hi)[Z]+(_t))
2035 
2036 /**
2037  * @brief Is the point outside the RPP by at least the distance tolerance?
2038  * This will not return true if the point is on the RPP.
2039  */
2040 #define V3PNT_OUT_RPP_TOL(_pt, _lo, _hi, _t) (\
2041  (_pt)[X] < (_lo)[X]-(_t) || (_pt)[X] > (_hi)[X]+(_t) || \
2042  (_pt)[Y] < (_lo)[Y]-(_t) || (_pt)[Y] > (_hi)[Y]+(_t) || \
2043  (_pt)[Z] < (_lo)[Z]-(_t) || (_pt)[Z] > (_hi)[Z]+(_t))
2044 
2045 /**
2046  * @brief Determine if one bounding box is within another. Also
2047  * returns true if the boxes are the same.
2048  *
2049  * FIXME: should not be using >= <=, '=' case is unreliable
2050  */
2051 #define V3RPP1_IN_RPP2(_lo1, _hi1, _lo2, _hi2) (\
2052  (_lo1)[X] >= (_lo2)[X] && (_hi1)[X] <= (_hi2)[X] && \
2053  (_lo1)[Y] >= (_lo2)[Y] && (_hi1)[Y] <= (_hi2)[Y] && \
2054  (_lo1)[Z] >= (_lo2)[Z] && (_hi1)[Z] <= (_hi2)[Z])
2055 
2056 
2057 /** Swap two 3D vectors */
2058 #define VSWAP(_a, _b) do { \
2059  fastf_t _t; \
2060  _t = (_a)[X]; \
2061  (_a)[X] = (_b)[X]; \
2062  (_b)[X] = _t; \
2063  _t = (_a)[Y]; \
2064  (_a)[Y] = (_b)[Y]; \
2065  (_b)[Y] = _t; \
2066  _t = (_a)[Z]; \
2067  (_a)[Z] = (_b)[Z]; \
2068  (_b)[Z] = _t; \
2069  } while (0)
2070 
2071 /** Swap two 2D vectors */
2072 #define V2SWAP(_a, _b) do { \
2073  fastf_t _t; \
2074  _t = (_a)[X]; \
2075  (_a)[X] = (_b)[X]; \
2076  (_b)[X] = _t; \
2077  _t = (_a)[Y]; \
2078  (_a)[Y] = (_b)[Y]; \
2079  (_b)[Y] = _t; \
2080  } while (0)
2082 /** Swap two 4D vectors */
2083 #define HSWAP(_a, _b) do { \
2084  fastf_t _t; \
2085  _t = (_a)[X]; \
2086  (_a)[X] = (_b)[X]; \
2087  (_b)[X] = _t; \
2088  _t = (_a)[Y]; \
2089  (_a)[Y] = (_b)[Y]; \
2090  (_b)[Y] = _t; \
2091  _t = (_a)[Z]; \
2092  (_a)[Z] = (_b)[Z]; \
2093  (_b)[Z] = _t; \
2094  _t = (_a)[W]; \
2095  (_a)[W] = (_b)[W]; \
2096  (_b)[W] = _t; \
2097  } while (0)
2098 
2099 /** Swap two 4x4 matrices */
2100 #define MAT_SWAP(_a, _b) do { \
2101  mat_t _t; \
2102  MAT_COPY(_t, (_a)); \
2103  MAT_COPY((_a), (_b)); \
2104  MAT_COPY((_b), _t); \
2105  } while (0)
2106 
2107 /*** Macros suitable for declaration statement initialization. ***/
2108 
2109 /**
2110  * 3D vector macro suitable for declaration statement initialization.
2111  * this sets all vector elements to the specified value similar to
2112  * VSETALL() but as an initializer array declaration instead of as a
2113  * statement.
2114  */
2115 #define VINITALL(_v) {(_v), (_v), (_v)}
2116 
2117 /**
2118  * 2D vector macro suitable for declaration statement initialization.
2119  * this sets all vector elements to the specified value similar to
2120  * VSETALLN(hvect_t,val,2) but as an initializer array declaration
2121  * instead of as a statement.
2122  */
2123 #define V2INITALL(_v) {(_v), (_v), (_v)}
2125 /**
2126  * 4D homogeneous vector macro suitable for declaration statement
2127  * initialization. this sets all vector elements to the specified
2128  * value similar to VSETALLN(hvect_t,val,4) but as an initializer
2129  * array declaration instead of as a statement.
2130  */
2131 #define HINITALL(_v) {(_v), (_v), (_v), (_v)}
2133 /**
2134  * 3D vector macro suitable for declaration statement initialization.
2135  * this sets all vector elements to zero similar to calling
2136  * VSETALL(0.0) but as an initializer array declaration instead of as
2137  * a statement.
2138  */
2139 #define VINIT_ZERO {0.0, 0.0, 0.0}
2141 /**
2142  * 2D vector macro suitable for declaration statement initialization.
2143  * this sets all vector elements to zero similar to calling
2144  * V2SETALL(0.0) but as an initializer array declaration instead of as
2145  * a statement.
2146  */
2147 #define V2INIT_ZERO {0.0, 0.0}
2149 /**
2150  * 4D homogeneous vector macro suitable for declaration statement
2151  * initialization. this sets all vector elements to zero similar to
2152  * calling VSETALLN(hvect_t,0.0,4) but as an initializer array
2153  * declaration instead of as a statement.
2154  */
2155 #define HINIT_ZERO {0.0, 0.0, 0.0, 0.0}
2157 /**
2158  * matrix macro suitable for declaration statement initialization.
2159  * this sets up an identity matrix similar to calling MAT_IDN but as
2160  * an initializer array declaration instead of as a statement.
2161  */
2162 #define MAT_INIT_IDN {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0}
2163 
2164 /**
2165  * matrix macro suitable for declaration statement initialization.
2166  * this sets up a zero matrix similar to calling MAT_ZERO but as an
2167  * initializer array declaration instead of as a statement.
2168  */
2169 #define MAT_INIT_ZERO {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}
2170 
2172 #ifdef __cplusplus
2173 } /* end extern "C" */
2174 #endif
2175 
2176 #endif /* VMATH_H */
2177 
2178 /** @} */
2179 /*
2180  * Local Variables:
2181  * mode: C
2182  * tab-width: 8
2183  * indent-tabs-mode: t
2184  * c-file-style: "stroustrup"
2185  * End:
2186  * ex: shiftwidth=4 tabstop=8
2187  */
Header file for the BRL-CAD common definitions.
fastf_t * pointp_t
pointer to a 3-tuple point
Definition: vmath.h:358
fastf_t vect_t[ELEMENTS_PER_VECT]
3-tuple vector
Definition: vmath.h:349
fastf_t * point2dp_t
pointer to a 2-tuple point
Definition: vmath.h:346
double fastf_t
fastest 64-bit (or larger) floating point type
Definition: vmath.h:334
#define ELEMENTS_PER_POINT
number of fastf_t's per point_t
Definition: vmath.h:314
fastf_t mat_t[ELEMENTS_PER_MAT]
4x4 matrix
Definition: vmath.h:370
fastf_t hvect_t[ELEMENTS_PER_HVECT]
4-tuple vector
Definition: vmath.h:361
enum vmath_matrix_component_ vmath_matrix_component
#define ELEMENTS_PER_PLANE
number of fastf_t's per plane_t
Definition: vmath.h:323
fastf_t point2d_t[ELEMENTS_PER_POINT2D]
2-tuple point
Definition: vmath.h:343
#define ELEMENTS_PER_HVECT
number of fastf_t's per hvect_t (homogeneous vector)
Definition: vmath.h:317
fastf_t * vect2dp_t
pointer to a 2-tuple vector
Definition: vmath.h:340
#define ELEMENTS_PER_POINT2D
number of fastf_t's per point2d_t
Definition: vmath.h:308
#define ELEMENTS_PER_VECT2D
number of fastf_t's per vect2d_t
Definition: vmath.h:305
fastf_t hpoint_t[ELEMENTS_PER_HPOINT]
4-tuple point
Definition: vmath.h:367
fastf_t plane_t[ELEMENTS_PER_PLANE]
Definition of a plane equation.
Definition: vmath.h:397
vmath_vector_component_
Definition: vmath.h:400
fastf_t * matp_t
pointer to a 4x4 matrix
Definition: vmath.h:373
#define ELEMENTS_PER_HPOINT
number of fastf_t's per hpt_t (homogeneous point)
Definition: vmath.h:320
fastf_t point_t[ELEMENTS_PER_POINT]
3-tuple point
Definition: vmath.h:355
#define ELEMENTS_PER_VECT
number of fastf_t's per vect_t
Definition: vmath.h:311
hvect_t quat_t
4-element quaternion
Definition: vmath.h:364
fastf_t * vectp_t
pointer to a 3-tuple vector
Definition: vmath.h:352
#define ELEMENTS_PER_MAT
number of fastf_t's per mat_t
Definition: vmath.h:326
fastf_t vect2d_t[ELEMENTS_PER_VECT2D]
2-tuple vector
Definition: vmath.h:337
enum vmath_vector_component_ vmath_vector_component
vmath_matrix_component_
Definition: vmath.h:412
@ H
Definition: vmath.h:405
@ Y
Definition: vmath.h:402
@ X
Definition: vmath.h:401
@ Z
Definition: vmath.h:403
@ W
Definition: vmath.h:404
@ MSA
Definition: vmath.h:419
@ MDZ
Definition: vmath.h:418
@ MSX
Definition: vmath.h:413
@ MDX
Definition: vmath.h:414
@ MDY
Definition: vmath.h:416
@ MSZ
Definition: vmath.h:417
@ MSY
Definition: vmath.h:415