1/**
2 * \file macros.h
3 * A collection of useful macros.
4 */
5
6/*
7 * Mesa 3-D graphics library
8 * Version:  6.5.2
9 *
10 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30
31#ifndef MACROS_H
32#define MACROS_H
33
34#include "imports.h"
35
36
37/**
38 * \name Integer / float conversion for colors, normals, etc.
39 */
40/*@{*/
41
42/** Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */
43extern GLfloat _mesa_ubyte_to_float_color_tab[256];
44#define UBYTE_TO_FLOAT(u) _mesa_ubyte_to_float_color_tab[(unsigned int)(u)]
45
46/** Convert GLfloat in [0.0,1.0] to GLubyte in [0,255] */
47#define FLOAT_TO_UBYTE(X)   ((GLubyte) (GLint) ((X) * 255.0F))
48
49
50/** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0] */
51#define BYTE_TO_FLOAT(B)    ((2.0F * (B) + 1.0F) * (1.0F/255.0F))
52
53/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127] */
54#define FLOAT_TO_BYTE(X)    ( (((GLint) (255.0F * (X))) - 1) / 2 )
55
56
57/** Convert GLbyte to GLfloat while preserving zero */
58#define BYTE_TO_FLOATZ(B)   ((B) == 0 ? 0.0F : BYTE_TO_FLOAT(B))
59
60
61/** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0], texture/fb data */
62#define BYTE_TO_FLOAT_TEX(B)    ((B) == -128 ? -1.0F : (B) * (1.0F/127.0F))
63
64/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127], texture/fb data */
65#define FLOAT_TO_BYTE_TEX(X)    CLAMP( (GLint) (127.0F * (X)), -128, 127 )
66
67/** Convert GLushort in [0,65535] to GLfloat in [0.0,1.0] */
68#define USHORT_TO_FLOAT(S)  ((GLfloat) (S) * (1.0F / 65535.0F))
69
70/** Convert GLfloat in [0.0,1.0] to GLushort in [0, 65535] */
71#define FLOAT_TO_USHORT(X)   ((GLuint) ((X) * 65535.0F))
72
73
74/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
75#define SHORT_TO_FLOAT(S)   ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
76
77/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767] */
78#define FLOAT_TO_SHORT(X)   ( (((GLint) (65535.0F * (X))) - 1) / 2 )
79
80/** Convert GLshort to GLfloat while preserving zero */
81#define SHORT_TO_FLOATZ(S)   ((S) == 0 ? 0.0F : SHORT_TO_FLOAT(S))
82
83
84/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0], texture/fb data */
85#define SHORT_TO_FLOAT_TEX(S)    ((S) == -32768 ? -1.0F : (S) * (1.0F/32767.0F))
86
87/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767], texture/fb data */
88#define FLOAT_TO_SHORT_TEX(X)    ( (GLint) (32767.0F * (X)) )
89
90
91/** Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */
92#define UINT_TO_FLOAT(U)    ((GLfloat) ((U) * (1.0F / 4294967295.0)))
93
94/** Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */
95#define FLOAT_TO_UINT(X)    ((GLuint) ((X) * 4294967295.0))
96
97
98/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */
99#define INT_TO_FLOAT(I)     ((GLfloat) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0)))
100
101/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */
102/* causes overflow:
103#define FLOAT_TO_INT(X)     ( (((GLint) (4294967294.0 * (X))) - 1) / 2 )
104*/
105/* a close approximation: */
106#define FLOAT_TO_INT(X)     ( (GLint) (2147483647.0 * (X)) )
107
108/** Convert GLfloat in [-1.0,1.0] to GLint64 in [-(1<<63),(1 << 63) -1] */
109#define FLOAT_TO_INT64(X)     ( (GLint64) (9223372036854775807.0 * (double)(X)) )
110
111
112/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0], texture/fb data */
113#define INT_TO_FLOAT_TEX(I)    ((I) == -2147483648 ? -1.0F : (I) * (1.0F/2147483647.0))
114
115/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647], texture/fb data */
116#define FLOAT_TO_INT_TEX(X)    ( (GLint) (2147483647.0 * (X)) )
117
118
119#define BYTE_TO_UBYTE(b)   ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b)))
120#define SHORT_TO_UBYTE(s)  ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7)))
121#define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8))
122#define INT_TO_UBYTE(i)    ((GLubyte) ((i) < 0 ? 0 : (GLubyte) ((i) >> 23)))
123#define UINT_TO_UBYTE(i)   ((GLubyte) ((i) >> 24))
124
125
126#define BYTE_TO_USHORT(b)  ((b) < 0 ? 0 : ((GLushort) (((b) * 65535) / 255)))
127#define UBYTE_TO_USHORT(b) (((GLushort) (b) << 8) | (GLushort) (b))
128#define SHORT_TO_USHORT(s) ((s) < 0 ? 0 : ((GLushort) (((s) * 65535 / 32767))))
129#define INT_TO_USHORT(i)   ((i) < 0 ? 0 : ((GLushort) ((i) >> 15)))
130#define UINT_TO_USHORT(i)  ((i) < 0 ? 0 : ((GLushort) ((i) >> 16)))
131#define UNCLAMPED_FLOAT_TO_USHORT(us, f)  \
132        us = ( (GLushort) F_TO_I( CLAMP((f), 0.0F, 1.0F) * 65535.0F) )
133#define CLAMPED_FLOAT_TO_USHORT(us, f)  \
134        us = ( (GLushort) F_TO_I( (f) * 65535.0F) )
135
136#define UNCLAMPED_FLOAT_TO_SHORT(s, f)  \
137        s = ( (GLshort) F_TO_I( CLAMP((f), -1.0F, 1.0F) * 32767.0F) )
138
139/***
140 *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255]
141 *** CLAMPED_FLOAT_TO_UBYTE: map float known to be in [0,1] to ubyte in [0,255]
142 ***/
143#if defined(USE_IEEE) && !defined(DEBUG)
144#define IEEE_0996 0x3f7f0000	/* 0.996 or so */
145/* This function/macro is sensitive to precision.  Test very carefully
146 * if you change it!
147 */
148#define UNCLAMPED_FLOAT_TO_UBYTE(UB, F)					\
149        do {								\
150           fi_type __tmp;						\
151           __tmp.f = (F);						\
152           if (__tmp.i < 0)						\
153              UB = (GLubyte) 0;						\
154           else if (__tmp.i >= IEEE_0996)				\
155              UB = (GLubyte) 255;					\
156           else {							\
157              __tmp.f = __tmp.f * (255.0F/256.0F) + 32768.0F;		\
158              UB = (GLubyte) __tmp.i;					\
159           }								\
160        } while (0)
161#define CLAMPED_FLOAT_TO_UBYTE(UB, F)					\
162        do {								\
163           fi_type __tmp;						\
164           __tmp.f = (F) * (255.0F/256.0F) + 32768.0F;			\
165           UB = (GLubyte) __tmp.i;					\
166        } while (0)
167#else
168#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \
169	ub = ((GLubyte) F_TO_I(CLAMP((f), 0.0F, 1.0F) * 255.0F))
170#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
171	ub = ((GLubyte) F_TO_I((f) * 255.0F))
172#endif
173
174static inline GLfloat INT_AS_FLT(GLint i)
175{
176   fi_type tmp;
177   tmp.i = i;
178   return tmp.f;
179}
180
181static inline GLfloat UINT_AS_FLT(GLuint u)
182{
183   fi_type tmp;
184   tmp.u = u;
185   return tmp.f;
186}
187
188/*@}*/
189
190
191/** Stepping a GLfloat pointer by a byte stride */
192#define STRIDE_F(p, i)  (p = (GLfloat *)((GLubyte *)p + i))
193/** Stepping a GLuint pointer by a byte stride */
194#define STRIDE_UI(p, i)  (p = (GLuint *)((GLubyte *)p + i))
195/** Stepping a GLubyte[4] pointer by a byte stride */
196#define STRIDE_4UB(p, i)  (p = (GLubyte (*)[4])((GLubyte *)p + i))
197/** Stepping a GLfloat[4] pointer by a byte stride */
198#define STRIDE_4F(p, i)  (p = (GLfloat (*)[4])((GLubyte *)p + i))
199/** Stepping a \p t pointer by a byte stride */
200#define STRIDE_T(p, t, i)  (p = (t)((GLubyte *)p + i))
201
202
203/**********************************************************************/
204/** \name 4-element vector operations */
205/*@{*/
206
207/** Zero */
208#define ZERO_4V( DST )  (DST)[0] = (DST)[1] = (DST)[2] = (DST)[3] = 0
209
210/** Test for equality */
211#define TEST_EQ_4V(a,b)  ((a)[0] == (b)[0] &&   \
212              (a)[1] == (b)[1] &&   \
213              (a)[2] == (b)[2] &&   \
214              (a)[3] == (b)[3])
215
216/** Test for equality (unsigned bytes) */
217static inline GLboolean
218TEST_EQ_4UBV(const GLubyte a[4], const GLubyte b[4])
219{
220#if defined(__i386__)
221   return *((const GLuint *) a) == *((const GLuint *) b);
222#else
223   return TEST_EQ_4V(a, b);
224#endif
225}
226
227
228/** Copy a 4-element vector */
229#define COPY_4V( DST, SRC )         \
230do {                                \
231   (DST)[0] = (SRC)[0];             \
232   (DST)[1] = (SRC)[1];             \
233   (DST)[2] = (SRC)[2];             \
234   (DST)[3] = (SRC)[3];             \
235} while (0)
236
237/** Copy a 4-element unsigned byte vector */
238static inline void
239COPY_4UBV(GLubyte dst[4], const GLubyte src[4])
240{
241#if defined(__i386__)
242   *((GLuint *) dst) = *((GLuint *) src);
243#else
244   /* The GLuint cast might fail if DST or SRC are not dword-aligned (RISC) */
245   COPY_4V(dst, src);
246#endif
247}
248
249/** Copy a 4-element float vector */
250static inline void
251COPY_4FV(GLfloat dst[4], const GLfloat src[4])
252{
253   /* memcpy seems to be most efficient */
254   memcpy(dst, src, sizeof(GLfloat) * 4);
255}
256
257/** Copy \p SZ elements into a 4-element vector */
258#define COPY_SZ_4V(DST, SZ, SRC)  \
259do {                              \
260   switch (SZ) {                  \
261   case 4: (DST)[3] = (SRC)[3];   \
262   case 3: (DST)[2] = (SRC)[2];   \
263   case 2: (DST)[1] = (SRC)[1];   \
264   case 1: (DST)[0] = (SRC)[0];   \
265   }                              \
266} while(0)
267
268/** Copy \p SZ elements into a homegeneous (4-element) vector, giving
269 * default values to the remaining */
270#define COPY_CLEAN_4V(DST, SZ, SRC)  \
271do {                                 \
272      ASSIGN_4V( DST, 0, 0, 0, 1 );  \
273      COPY_SZ_4V( DST, SZ, SRC );    \
274} while (0)
275
276/** Subtraction */
277#define SUB_4V( DST, SRCA, SRCB )           \
278do {                                        \
279      (DST)[0] = (SRCA)[0] - (SRCB)[0];     \
280      (DST)[1] = (SRCA)[1] - (SRCB)[1];     \
281      (DST)[2] = (SRCA)[2] - (SRCB)[2];     \
282      (DST)[3] = (SRCA)[3] - (SRCB)[3];     \
283} while (0)
284
285/** Addition */
286#define ADD_4V( DST, SRCA, SRCB )           \
287do {                                        \
288      (DST)[0] = (SRCA)[0] + (SRCB)[0];     \
289      (DST)[1] = (SRCA)[1] + (SRCB)[1];     \
290      (DST)[2] = (SRCA)[2] + (SRCB)[2];     \
291      (DST)[3] = (SRCA)[3] + (SRCB)[3];     \
292} while (0)
293
294/** Element-wise multiplication */
295#define SCALE_4V( DST, SRCA, SRCB )         \
296do {                                        \
297      (DST)[0] = (SRCA)[0] * (SRCB)[0];     \
298      (DST)[1] = (SRCA)[1] * (SRCB)[1];     \
299      (DST)[2] = (SRCA)[2] * (SRCB)[2];     \
300      (DST)[3] = (SRCA)[3] * (SRCB)[3];     \
301} while (0)
302
303/** In-place addition */
304#define ACC_4V( DST, SRC )          \
305do {                                \
306      (DST)[0] += (SRC)[0];         \
307      (DST)[1] += (SRC)[1];         \
308      (DST)[2] += (SRC)[2];         \
309      (DST)[3] += (SRC)[3];         \
310} while (0)
311
312/** Element-wise multiplication and addition */
313#define ACC_SCALE_4V( DST, SRCA, SRCB )     \
314do {                                        \
315      (DST)[0] += (SRCA)[0] * (SRCB)[0];    \
316      (DST)[1] += (SRCA)[1] * (SRCB)[1];    \
317      (DST)[2] += (SRCA)[2] * (SRCB)[2];    \
318      (DST)[3] += (SRCA)[3] * (SRCB)[3];    \
319} while (0)
320
321/** In-place scalar multiplication and addition */
322#define ACC_SCALE_SCALAR_4V( DST, S, SRCB ) \
323do {                                        \
324      (DST)[0] += S * (SRCB)[0];            \
325      (DST)[1] += S * (SRCB)[1];            \
326      (DST)[2] += S * (SRCB)[2];            \
327      (DST)[3] += S * (SRCB)[3];            \
328} while (0)
329
330/** Scalar multiplication */
331#define SCALE_SCALAR_4V( DST, S, SRCB ) \
332do {                                    \
333      (DST)[0] = S * (SRCB)[0];         \
334      (DST)[1] = S * (SRCB)[1];         \
335      (DST)[2] = S * (SRCB)[2];         \
336      (DST)[3] = S * (SRCB)[3];         \
337} while (0)
338
339/** In-place scalar multiplication */
340#define SELF_SCALE_SCALAR_4V( DST, S ) \
341do {                                   \
342      (DST)[0] *= S;                   \
343      (DST)[1] *= S;                   \
344      (DST)[2] *= S;                   \
345      (DST)[3] *= S;                   \
346} while (0)
347
348/** Assignment */
349#define ASSIGN_4V( V, V0, V1, V2, V3 )  \
350do {                                    \
351    V[0] = V0;                          \
352    V[1] = V1;                          \
353    V[2] = V2;                          \
354    V[3] = V3;                          \
355} while(0)
356
357/*@}*/
358
359
360/**********************************************************************/
361/** \name 3-element vector operations*/
362/*@{*/
363
364/** Zero */
365#define ZERO_3V( DST )  (DST)[0] = (DST)[1] = (DST)[2] = 0
366
367/** Test for equality */
368#define TEST_EQ_3V(a,b)  \
369   ((a)[0] == (b)[0] &&  \
370    (a)[1] == (b)[1] &&  \
371    (a)[2] == (b)[2])
372
373/** Copy a 3-element vector */
374#define COPY_3V( DST, SRC )         \
375do {                                \
376   (DST)[0] = (SRC)[0];             \
377   (DST)[1] = (SRC)[1];             \
378   (DST)[2] = (SRC)[2];             \
379} while (0)
380
381/** Copy a 3-element vector with cast */
382#define COPY_3V_CAST( DST, SRC, CAST )  \
383do {                                    \
384   (DST)[0] = (CAST)(SRC)[0];           \
385   (DST)[1] = (CAST)(SRC)[1];           \
386   (DST)[2] = (CAST)(SRC)[2];           \
387} while (0)
388
389/** Copy a 3-element float vector */
390#define COPY_3FV( DST, SRC )        \
391do {                                \
392   const GLfloat *_tmp = (SRC);     \
393   (DST)[0] = _tmp[0];              \
394   (DST)[1] = _tmp[1];              \
395   (DST)[2] = _tmp[2];              \
396} while (0)
397
398/** Subtraction */
399#define SUB_3V( DST, SRCA, SRCB )        \
400do {                                     \
401      (DST)[0] = (SRCA)[0] - (SRCB)[0];  \
402      (DST)[1] = (SRCA)[1] - (SRCB)[1];  \
403      (DST)[2] = (SRCA)[2] - (SRCB)[2];  \
404} while (0)
405
406/** Addition */
407#define ADD_3V( DST, SRCA, SRCB )       \
408do {                                    \
409      (DST)[0] = (SRCA)[0] + (SRCB)[0]; \
410      (DST)[1] = (SRCA)[1] + (SRCB)[1]; \
411      (DST)[2] = (SRCA)[2] + (SRCB)[2]; \
412} while (0)
413
414/** In-place scalar multiplication */
415#define SCALE_3V( DST, SRCA, SRCB )     \
416do {                                    \
417      (DST)[0] = (SRCA)[0] * (SRCB)[0]; \
418      (DST)[1] = (SRCA)[1] * (SRCB)[1]; \
419      (DST)[2] = (SRCA)[2] * (SRCB)[2]; \
420} while (0)
421
422/** In-place element-wise multiplication */
423#define SELF_SCALE_3V( DST, SRC )   \
424do {                                \
425      (DST)[0] *= (SRC)[0];         \
426      (DST)[1] *= (SRC)[1];         \
427      (DST)[2] *= (SRC)[2];         \
428} while (0)
429
430/** In-place addition */
431#define ACC_3V( DST, SRC )          \
432do {                                \
433      (DST)[0] += (SRC)[0];         \
434      (DST)[1] += (SRC)[1];         \
435      (DST)[2] += (SRC)[2];         \
436} while (0)
437
438/** Element-wise multiplication and addition */
439#define ACC_SCALE_3V( DST, SRCA, SRCB )     \
440do {                                        \
441      (DST)[0] += (SRCA)[0] * (SRCB)[0];    \
442      (DST)[1] += (SRCA)[1] * (SRCB)[1];    \
443      (DST)[2] += (SRCA)[2] * (SRCB)[2];    \
444} while (0)
445
446/** Scalar multiplication */
447#define SCALE_SCALAR_3V( DST, S, SRCB ) \
448do {                                    \
449      (DST)[0] = S * (SRCB)[0];         \
450      (DST)[1] = S * (SRCB)[1];         \
451      (DST)[2] = S * (SRCB)[2];         \
452} while (0)
453
454/** In-place scalar multiplication and addition */
455#define ACC_SCALE_SCALAR_3V( DST, S, SRCB ) \
456do {                                        \
457      (DST)[0] += S * (SRCB)[0];            \
458      (DST)[1] += S * (SRCB)[1];            \
459      (DST)[2] += S * (SRCB)[2];            \
460} while (0)
461
462/** In-place scalar multiplication */
463#define SELF_SCALE_SCALAR_3V( DST, S ) \
464do {                                   \
465      (DST)[0] *= S;                   \
466      (DST)[1] *= S;                   \
467      (DST)[2] *= S;                   \
468} while (0)
469
470/** In-place scalar addition */
471#define ACC_SCALAR_3V( DST, S )     \
472do {                                \
473      (DST)[0] += S;                \
474      (DST)[1] += S;                \
475      (DST)[2] += S;                \
476} while (0)
477
478/** Assignment */
479#define ASSIGN_3V( V, V0, V1, V2 )  \
480do {                                \
481    V[0] = V0;                      \
482    V[1] = V1;                      \
483    V[2] = V2;                      \
484} while(0)
485
486/*@}*/
487
488
489/**********************************************************************/
490/** \name 2-element vector operations*/
491/*@{*/
492
493/** Zero */
494#define ZERO_2V( DST )  (DST)[0] = (DST)[1] = 0
495
496/** Copy a 2-element vector */
497#define COPY_2V( DST, SRC )         \
498do {                        \
499   (DST)[0] = (SRC)[0];             \
500   (DST)[1] = (SRC)[1];             \
501} while (0)
502
503/** Copy a 2-element vector with cast */
504#define COPY_2V_CAST( DST, SRC, CAST )      \
505do {                        \
506   (DST)[0] = (CAST)(SRC)[0];           \
507   (DST)[1] = (CAST)(SRC)[1];           \
508} while (0)
509
510/** Copy a 2-element float vector */
511#define COPY_2FV( DST, SRC )            \
512do {                        \
513   const GLfloat *_tmp = (SRC);         \
514   (DST)[0] = _tmp[0];              \
515   (DST)[1] = _tmp[1];              \
516} while (0)
517
518/** Subtraction */
519#define SUB_2V( DST, SRCA, SRCB )       \
520do {                        \
521      (DST)[0] = (SRCA)[0] - (SRCB)[0];     \
522      (DST)[1] = (SRCA)[1] - (SRCB)[1];     \
523} while (0)
524
525/** Addition */
526#define ADD_2V( DST, SRCA, SRCB )       \
527do {                        \
528      (DST)[0] = (SRCA)[0] + (SRCB)[0];     \
529      (DST)[1] = (SRCA)[1] + (SRCB)[1];     \
530} while (0)
531
532/** In-place scalar multiplication */
533#define SCALE_2V( DST, SRCA, SRCB )     \
534do {                        \
535      (DST)[0] = (SRCA)[0] * (SRCB)[0];     \
536      (DST)[1] = (SRCA)[1] * (SRCB)[1];     \
537} while (0)
538
539/** In-place addition */
540#define ACC_2V( DST, SRC )          \
541do {                        \
542      (DST)[0] += (SRC)[0];         \
543      (DST)[1] += (SRC)[1];         \
544} while (0)
545
546/** Element-wise multiplication and addition */
547#define ACC_SCALE_2V( DST, SRCA, SRCB )     \
548do {                        \
549      (DST)[0] += (SRCA)[0] * (SRCB)[0];    \
550      (DST)[1] += (SRCA)[1] * (SRCB)[1];    \
551} while (0)
552
553/** Scalar multiplication */
554#define SCALE_SCALAR_2V( DST, S, SRCB )     \
555do {                        \
556      (DST)[0] = S * (SRCB)[0];         \
557      (DST)[1] = S * (SRCB)[1];         \
558} while (0)
559
560/** In-place scalar multiplication and addition */
561#define ACC_SCALE_SCALAR_2V( DST, S, SRCB ) \
562do {                        \
563      (DST)[0] += S * (SRCB)[0];        \
564      (DST)[1] += S * (SRCB)[1];        \
565} while (0)
566
567/** In-place scalar multiplication */
568#define SELF_SCALE_SCALAR_2V( DST, S )      \
569do {                        \
570      (DST)[0] *= S;                \
571      (DST)[1] *= S;                \
572} while (0)
573
574/** In-place scalar addition */
575#define ACC_SCALAR_2V( DST, S )         \
576do {                        \
577      (DST)[0] += S;                \
578      (DST)[1] += S;                \
579} while (0)
580
581/** Assign scalers to short vectors */
582#define ASSIGN_2V( V, V0, V1 )	\
583do {				\
584    V[0] = V0;			\
585    V[1] = V1;			\
586} while(0)
587
588/*@}*/
589
590/** Copy \p sz elements into a homegeneous (4-element) vector, giving
591 * default values to the remaining components.
592 * The default values are chosen based on \p type.
593 */
594static inline void
595COPY_CLEAN_4V_TYPE_AS_FLOAT(GLfloat dst[4], int sz, const GLfloat src[4],
596                            GLenum type)
597{
598   switch (type) {
599   case GL_FLOAT:
600      ASSIGN_4V(dst, 0, 0, 0, 1);
601      break;
602   case GL_INT:
603      ASSIGN_4V(dst, INT_AS_FLT(0), INT_AS_FLT(0),
604                     INT_AS_FLT(0), INT_AS_FLT(1));
605      break;
606   case GL_UNSIGNED_INT:
607      ASSIGN_4V(dst, UINT_AS_FLT(0), UINT_AS_FLT(0),
608                     UINT_AS_FLT(0), UINT_AS_FLT(1));
609      break;
610   default:
611      ASSERT(0);
612   }
613   COPY_SZ_4V(dst, sz, src);
614}
615
616/** \name Linear interpolation functions */
617/*@{*/
618
619static inline GLfloat
620LINTERP(GLfloat t, GLfloat out, GLfloat in)
621{
622   return out + t * (in - out);
623}
624
625static inline void
626INTERP_3F(GLfloat t, GLfloat dst[3], const GLfloat out[3], const GLfloat in[3])
627{
628   dst[0] = LINTERP( t, out[0], in[0] );
629   dst[1] = LINTERP( t, out[1], in[1] );
630   dst[2] = LINTERP( t, out[2], in[2] );
631}
632
633static inline void
634INTERP_4F(GLfloat t, GLfloat dst[4], const GLfloat out[4], const GLfloat in[4])
635{
636   dst[0] = LINTERP( t, out[0], in[0] );
637   dst[1] = LINTERP( t, out[1], in[1] );
638   dst[2] = LINTERP( t, out[2], in[2] );
639   dst[3] = LINTERP( t, out[3], in[3] );
640}
641
642/*@}*/
643
644
645
646/** Clamp X to [MIN,MAX] */
647#define CLAMP( X, MIN, MAX )  ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
648
649/** Minimum of two values: */
650#define MIN2( A, B )   ( (A)<(B) ? (A) : (B) )
651
652/** Maximum of two values: */
653#define MAX2( A, B )   ( (A)>(B) ? (A) : (B) )
654
655/** Minimum and maximum of three values: */
656#define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C))
657#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C))
658
659
660
661/** Cross product of two 3-element vectors */
662static inline void
663CROSS3(GLfloat n[3], const GLfloat u[3], const GLfloat v[3])
664{
665   n[0] = u[1] * v[2] - u[2] * v[1];
666   n[1] = u[2] * v[0] - u[0] * v[2];
667   n[2] = u[0] * v[1] - u[1] * v[0];
668}
669
670
671/** Dot product of two 2-element vectors */
672static inline GLfloat
673DOT2(const GLfloat a[2], const GLfloat b[2])
674{
675   return a[0] * b[0] + a[1] * b[1];
676}
677
678static inline GLfloat
679DOT3(const GLfloat a[3], const GLfloat b[3])
680{
681   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
682}
683
684static inline GLfloat
685DOT4(const GLfloat a[4], const GLfloat b[4])
686{
687   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
688}
689
690
691static inline GLfloat
692LEN_SQUARED_3FV(const GLfloat v[3])
693{
694   return DOT3(v, v);
695}
696
697static inline GLfloat
698LEN_SQUARED_2FV(const GLfloat v[2])
699{
700   return DOT2(v, v);
701}
702
703
704static inline GLfloat
705LEN_3FV(const GLfloat v[3])
706{
707   return SQRTF(LEN_SQUARED_3FV(v));
708}
709
710static inline GLfloat
711LEN_2FV(const GLfloat v[2])
712{
713   return SQRTF(LEN_SQUARED_2FV(v));
714}
715
716
717/* Normalize a 3-element vector to unit length. */
718static inline void
719NORMALIZE_3FV(GLfloat v[3])
720{
721   GLfloat len = (GLfloat) LEN_SQUARED_3FV(v);
722   if (len) {
723      len = INV_SQRTF(len);
724      v[0] *= len;
725      v[1] *= len;
726      v[2] *= len;
727   }
728}
729
730
731/** Compute ceiling of integer quotient of A divided by B. */
732#define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
733
734
735/** casts to silence warnings with some compilers */
736#define ENUM_TO_INT(E)     ((GLint)(E))
737#define ENUM_TO_FLOAT(E)   ((GLfloat)(GLint)(E))
738#define ENUM_TO_DOUBLE(E)  ((GLdouble)(GLint)(E))
739#define ENUM_TO_BOOLEAN(E) ((E) ? GL_TRUE : GL_FALSE)
740
741
742#endif
743