Subversion Repositories shark

Rev

Rev 55 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
72 giacomo 1
/* $Id: mmath.h,v 1.2 2003-03-13 12:20:29 giacomo Exp $ */
55 pj 2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  5.0
6
 *
7
 * Copyright (C) 1999-2002 Brian Paul   All Rights Reserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included
17
 * in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
 
27
 
28
/*
29
 * Faster arithmetic functions.  If the FAST_MATH preprocessor symbol is
30
 * defined on the command line (-DFAST_MATH) then we'll use some (hopefully)
31
 * faster functions for sqrt(), etc.
32
 */
33
 
34
 
35
#ifndef MMATH_H
36
#define MMATH_H
37
 
38
 
39
#include "glheader.h"
40
#include "imports.h"
41
/* Do not reference mtypes.h from this file.
42
 */
43
 
44
/*
45
 * Set the x86 FPU control word to guarentee only 32 bits of presision
46
 * are stored in registers.  Allowing the FPU to store more introduces
47
 * differences between situations where numbers are pulled out of memory
48
 * vs. situations where the compiler is able to optimize register usage.
49
 *
50
 * In the worst case, we force the compiler to use a memory access to
51
 * truncate the float, by specifying the 'volatile' keyword.
52
 */
53
#if defined(__GNUC__) && defined(__i386__)
54
 
55
/* Hardware default: All exceptions masked, extended double precision,
56
 * round to nearest.  IEEE compliant.
57
 */
58
#define DEFAULT_X86_FPU         0x037f
59
 
60
/* All exceptions masked, single precision, round to nearest.
61
 */
62
#define FAST_X86_FPU            0x003f
63
 
64
/* Set it up how we want it.  The fldcw instruction will cause any
65
 * pending FP exceptions to be raised prior to entering the block, and
66
 * we clear any pending exceptions before exiting the block.  Hence, asm
67
 * code has free reign over the FPU while in the fast math block.
68
 */
69
#if defined(NO_FAST_MATH)
70
#define START_FAST_MATH(x)                                              \
71
do {                                                                    \
72
   static GLuint mask = DEFAULT_X86_FPU;                                \
73
   __asm__ ( "fnstcw %0" : "=m" (*&(x)) );                              \
74
   __asm__ ( "fldcw %0" : : "m" (mask) );                               \
75
} while (0)
76
#else
77
#define START_FAST_MATH(x)                                              \
78
do {                                                                    \
79
   static GLuint mask = FAST_X86_FPU;                                   \
80
   __asm__ ( "fnstcw %0" : "=m" (*&(x)) );                              \
81
   __asm__ ( "fldcw %0" : : "m" (mask) );                               \
82
} while (0)
83
#endif
84
 
85
/* Put it back how the application had it, and clear any exceptions that
86
 * may have occurred in the FAST_MATH block.
87
 */
88
#define END_FAST_MATH(x)                                                \
89
do {                                                                    \
90
   __asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) );                     \
91
} while (0)
92
 
93
#define HAVE_FAST_MATH
94
 
95
#elif defined(__WATCOMC__) && !defined(NO_FAST_MATH)
96
 
97
/* This is the watcom specific inline assembly version of setcw and getcw */
98
 
99
void START_FAST_MATH2(unsigned short *x);
100
#pragma aux START_FAST_MATH2 =          \
101
    "fstcw   word ptr [esi]"            \
102
    "or      word ptr [esi], 0x3f"      \
103
    "fldcw   word ptr [esi]"            \
104
    parm [esi]                          \
105
    modify exact [];
106
 
107
void END_FAST_MATH2(unsigned short *x);
108
#pragma aux END_FAST_MATH2 =            \
109
    "fldcw   word ptr [esi]"            \
110
    parm [esi]                          \
111
    modify exact [];
112
 
113
#define START_FAST_MATH(x)  START_FAST_MATH2(& x)
114
#define END_FAST_MATH(x)  END_FAST_MATH2(& x)
115
 
116
/*
117
__inline START_FAST_MATH(unsigned short x)
118
    {
119
    _asm {
120
        fstcw   ax
121
        mov     x , ax
122
        or      ax, 0x3f
123
        fldcw   ax
124
        }
125
    }
126
 
127
__inline END_FAST_MATH(unsigned short x)
128
    {
129
    _asm {
130
        fldcw   x
131
        }
132
    }
133
*/
134
#define HAVE_FAST_MATH
135
 
136
#else
137
#define START_FAST_MATH(x) x = 0
138
#define END_FAST_MATH(x)   (void)(x)
139
 
140
/* The mac float really is a float, with the same precision as a
141
 * single precision 387 float.
142
 */
143
#if defined(macintosh) || defined(__powerpc__)
144
#define HAVE_FAST_MATH
145
#endif
146
 
147
#endif
148
 
149
 
150
 
151
/*
152
 * Square root
153
 */
154
 
155
extern float gl_sqrt(float x);
156
 
157
#ifdef FAST_MATH
158
#if defined(__WATCOMC__) && defined(USE_X86_ASM)
159
#  define GL_SQRT(X)  asm_sqrt(X)
160
#else
161
#  define GL_SQRT(X)  gl_sqrt(X)
162
#endif
163
#else
164
#  define GL_SQRT(X)  sqrt(X)
165
#endif
166
 
167
 
168
/*
169
 * Normalize a 3-element vector to unit length.
170
 */
171
#define NORMALIZE_3FV( V )                      \
172
do {                                            \
173
   GLfloat len = (GLfloat) LEN_SQUARED_3FV(V);  \
174
   if (len) {                                   \
175
      len = (GLfloat) (1.0 / GL_SQRT(len));     \
176
      (V)[0] = (GLfloat) ((V)[0] * len);        \
177
      (V)[1] = (GLfloat) ((V)[1] * len);        \
178
      (V)[2] = (GLfloat) ((V)[2] * len);        \
179
   }                                            \
180
} while(0)
181
 
182
#define LEN_3FV( V ) (GL_SQRT((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2]))
183
#define LEN_2FV( V ) (GL_SQRT((V)[0]*(V)[0]+(V)[1]*(V)[1]))
184
 
185
#define LEN_SQUARED_3FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2])
186
#define LEN_SQUARED_2FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1])
187
 
188
 
189
/*
190
 * Single precision ceiling, floor, and absolute value functions
191
 */
192
#if defined(__sparc__) /* XXX this probably isn't the ideal test */
193
#define CEILF(x)   ceil(x)
194
#define FLOORF(x)  floor(x)
195
#define FABSF(x)   fabs(x)
196
#elif defined(__WIN32__)
197
#define CEILF(x)   ((GLfloat)ceil(x))
198
#define FLOORF(x)  ((GLfloat)floor(x))
199
#define FABSF(x)   ((GLfloat)fabs(x))
200
#else
201
#define CEILF(x)   ceilf(x)
202
#define FLOORF(x)  floorf(x)
203
#define FABSF(x)   ((GLfloat)fabs(x))
204
#endif
205
 
206
 
207
#if defined(__i386__) || defined(__sparc__) || defined(__s390x__) || \
208
    defined(__powerpc__) || \
209
    ( defined(__alpha__) && ( defined(__IEEE_FLOAT) || !defined(VMS) ) )
210
#define USE_IEEE
211
#endif
212
 
213
 
214
 
215
#define GET_FLOAT_BITS(x) ((fi_type *) &(x))->i
216
 
217
/*
218
 * Float -> Int conversions (rounding, floor, ceiling)
219
 */
220
 
221
#if defined(USE_SPARC_ASM) && defined(__GNUC__) && defined(__sparc__)
222
 
223
static INLINE int iround(float f)
224
{
225
       int r;
226
       __asm__ ("fstoi %1, %0" : "=f" (r) : "f" (f));
227
       return r;
228
}
229
 
230
#define IROUND(x)  iround(x)
231
 
232
#elif defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
233
 
234
 
235
static INLINE int iround(float f)
236
{
237
   int r;
238
   __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
239
   return r;
240
}
241
 
242
#define IROUND(x)  iround(x)
243
 
244
/*
245
 * IEEE floor for computers that round to nearest or even.
246
 * 'f' must be between -4194304 and 4194303.
247
 * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1",
248
 * but uses some IEEE specific tricks for better speed.
249
 * Contributed by Josh Vanderhoof
250
 */
251
static INLINE int ifloor(float f)
252
{
253
   int ai, bi;
254
   double af, bf;
255
   af = (3 << 22) + 0.5 + (double)f;
256
   bf = (3 << 22) + 0.5 - (double)f;
257
   /* GCC generates an extra fstp/fld without this. */
258
   __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
259
   __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
260
   return (ai - bi) >> 1;
261
}
262
 
263
#define IFLOOR(x)  ifloor(x)
264
 
265
/*
266
 * IEEE ceil for computers that round to nearest or even.
267
 * 'f' must be between -4194304 and 4194303.
268
 * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1",
269
 * but uses some IEEE specific tricks for better speed.
270
 * Contributed by Josh Vanderhoof
271
 */
272
static INLINE int iceil(float f)
273
{
274
   int ai, bi;
275
   double af, bf;
276
   af = (3 << 22) + 0.5 + (double)f;
277
   bf = (3 << 22) + 0.5 - (double)f;
278
   /* GCC generates an extra fstp/fld without this. */
279
   __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
280
   __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
281
   return (ai - bi + 1) >> 1;
282
}
283
 
284
#define ICEIL(x)  iceil(x)
285
 
286
 
287
#elif defined(USE_X86_ASM) && defined(__MSC__) && defined(__WIN32__)
288
 
289
 
290
static INLINE int iround(float f)
291
{
292
   int r;
293
   _asm {
294
         fld f
295
         fistp r
296
        }
297
   return r;
298
}
299
 
300
#define IROUND(x)  iround(x)
301
 
302
 
303
#elif defined(USE_X86_ASM) && defined(__WATCOMC__)
304
 
305
 
306
long iround(float f);
307
#pragma aux iround =                        \
308
        "push   eax"                        \
309
        "fistp  dword ptr [esp]"            \
310
        "pop    eax"                        \
311
        parm [8087]                         \
312
        value [eax]                         \
313
        modify exact [eax];
314
 
315
#define IROUND(x)  iround(x)
316
 
317
float asm_sqrt (float x);
318
#pragma aux asm_sqrt =                      \
319
        "fsqrt"                             \
320
        parm [8087]                         \
321
        value [8087]                        \
322
        modify exact [];
323
 
324
 
325
#endif /* assembly/optimized IROUND, IROUND_POS, IFLOOR, ICEIL macros */
326
 
327
 
328
/* default IROUND macro */
329
#ifndef IROUND
330
#define IROUND(f)  ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
331
#endif
332
 
333
 
334
/* default IROUND_POS macro */
335
#ifndef IROUND_POS
336
#ifdef DEBUG
72 giacomo 337
#define IROUND_POS(f) (IROUND(f))
55 pj 338
#else
339
#define IROUND_POS(f) (IROUND(f))
340
#endif
341
#endif /* IROUND_POS */
342
 
343
 
344
/* default IFLOOR macro */
345
#ifndef IFLOOR
346
static INLINE int ifloor(float f)
347
{
348
#ifdef USE_IEEE
349
   int ai, bi;
350
   double af, bf;
351
   union { int i; float f; } u;
352
 
353
   af = (3 << 22) + 0.5 + (double)f;
354
   bf = (3 << 22) + 0.5 - (double)f;
355
   u.f = af; ai = u.i;
356
   u.f = bf; bi = u.i;
357
   return (ai - bi) >> 1;
358
#else
359
   int i = IROUND(f);
360
   return (i > f) ? i - 1 : i;
361
#endif
362
}
363
#define IFLOOR(x)  ifloor(x)
364
#endif /* IFLOOR */
365
 
366
 
367
/* default ICEIL macro */
368
#ifndef ICEIL
369
static INLINE int iceil(float f)
370
{
371
#ifdef USE_IEEE
372
   int ai, bi;
373
   double af, bf;
374
   union { int i; float f; } u;
375
   af = (3 << 22) + 0.5 + (double)f;
376
   bf = (3 << 22) + 0.5 - (double)f;
377
   u.f = af; ai = u.i;
378
   u.f = bf; bi = u.i;
379
   return (ai - bi + 1) >> 1;
380
#else
381
   int i = IROUND(f);
382
   return (i < f) ? i + 1 : i;
383
#endif
384
}
385
#define ICEIL(x)  iceil(x)
386
#endif /* ICEIL */
387
 
388
 
389
 
390
/*
391
 * Convert unclamped or clamped ([0,1]) floats to ubytes for color
392
 * conversion only.  These functions round to the nearest int.
393
 */
394
#define IEEE_ONE 0x3f800000
395
#define IEEE_0996 0x3f7f0000    /* 0.996 or something??? used in macro
396
                                   below only */
397
 
398
#if defined(USE_IEEE) && !defined(DEBUG)
399
 
400
/*
401
 * This function/macro is sensitive to precision.  Test carefully
402
 * if you change it.
403
 */
404
#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f)                                 \
405
        do {                                                            \
406
           union { GLfloat r; GLuint i; } __tmp;                        \
407
           __tmp.r = (f);                                               \
408
           ub = ((__tmp.i >= IEEE_0996)                                 \
409
               ? ((GLint)__tmp.i < 0) ? (GLubyte)0 : (GLubyte)255       \
410
               : (__tmp.r = __tmp.r*(255.0F/256.0F) + 32768.0F,         \
411
                  (GLubyte)__tmp.i));                                   \
412
        } while (0)
413
 
414
#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
415
        UNCLAMPED_FLOAT_TO_UBYTE(ub, f)
416
 
417
#define COPY_FLOAT( dst, src )                                  \
418
        ((fi_type *) &(dst))->i = ((fi_type *) &(src))->i
419
 
420
#else /* USE_IEEE */
421
 
422
#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \
423
        ub = ((GLubyte) IROUND(CLAMP((f), 0.0F, 1.0F) * 255.0F))
424
 
425
#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
426
        ub = ((GLubyte) IROUND((f) * 255.0F))
427
 
428
#define COPY_FLOAT( dst, src )          (dst) = (src)
429
 
430
#endif /* USE_IEEE */
431
 
432
 
433
 
434
/*
435
 * Integer / float conversion for colors, normals, etc.
436
 */
437
 
438
/* Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */
439
extern float _mesa_ubyte_to_float_color_tab[256];
440
#define UBYTE_TO_FLOAT(u) _mesa_ubyte_to_float_color_tab[(unsigned int)(u)]
441
 
442
/* Convert GLfloat in [0.0,1.0] to GLubyte in [0,255] */
443
#define FLOAT_TO_UBYTE(X)       ((GLubyte) (GLint) ((X) * 255.0F))
444
 
445
 
446
/* Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0] */
447
#define BYTE_TO_FLOAT(B)        ((2.0F * (B) + 1.0F) * (1.0F/255.0F))
448
 
449
/* Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127] */
450
#define FLOAT_TO_BYTE(X)        ( (((GLint) (255.0F * (X))) - 1) / 2 )
451
 
452
 
453
/* Convert GLushort in [0,65536] to GLfloat in [0.0,1.0] */
454
#define USHORT_TO_FLOAT(S)      ((GLfloat) (S) * (1.0F / 65535.0F))
455
 
456
/* Convert GLfloat in [0.0,1.0] to GLushort in [0,65536] */
457
#define FLOAT_TO_USHORT(X)      ((GLushort) (GLint) ((X) * 65535.0F))
458
 
459
 
460
/* Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
461
#define SHORT_TO_FLOAT(S)       ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
462
 
463
/* Convert GLfloat in [0.0,1.0] to GLshort in [-32768,32767] */
464
#define FLOAT_TO_SHORT(X)       ( (((GLint) (65535.0F * (X))) - 1) / 2 )
465
 
466
 
467
/* Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */
468
#define UINT_TO_FLOAT(U)        ((GLfloat) (U) * (1.0F / 4294967295.0F))
469
 
470
/* Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */
471
#define FLOAT_TO_UINT(X)        ((GLuint) ((X) * 4294967295.0))
472
 
473
 
474
/* Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */
475
#define INT_TO_FLOAT(I)         ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0F))
476
 
477
/* Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */
478
/* causes overflow:
479
#define FLOAT_TO_INT(X)         ( (((GLint) (4294967294.0F * (X))) - 1) / 2 )
480
*/
481
/* a close approximation: */
482
#define FLOAT_TO_INT(X)         ( (GLint) (2147483647.0 * (X)) )
483
 
484
 
485
#define BYTE_TO_UBYTE(b)   ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b)))
486
#define SHORT_TO_UBYTE(s)  ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7)))
487
#define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8))
488
#define INT_TO_UBYTE(i)    ((GLubyte) ((i) < 0 ? 0 : (GLubyte) ((i) >> 23)))
489
#define UINT_TO_UBYTE(i)   ((GLubyte) ((i) >> 24))
490
 
491
 
492
#define BYTE_TO_USHORT(b)  ((b) < 0 ? 0 : ((GLushort) (((b) * 65535) / 255)))
493
#define UBYTE_TO_USHORT(b) (((GLushort) (b) << 8) | (GLushort) (b))
494
#define SHORT_TO_USHORT(s) ((s) < 0 ? 0 : ((GLushort) (((s) * 65535 / 32767))))
495
#define INT_TO_USHORT(i)   ((i) < 0 ? 0 : ((GLushort) ((i) >> 15)))
496
#define UINT_TO_USHORT(i)  ((i) < 0 ? 0 : ((GLushort) ((i) >> 16)))
497
#define UNCLAMPED_FLOAT_TO_USHORT(us, f)  \
498
        us = ( (GLushort) IROUND( CLAMP((f), 0.0, 1.0) * 65535.0F) )
499
#define CLAMPED_FLOAT_TO_USHORT(us, f)  \
500
        us = ( (GLushort) IROUND( (f) * 65535.0F) )
501
 
502
 
503
 
504
/*
505
 * Linear interpolation
506
 * NOTE:  OUT argument is evaluated twice!
507
 * NOTE:  Be wary of using *coord++ as an argument to any of these macros!
508
 */
509
#define LINTERP(T, OUT, IN)     ((OUT) + (T) * ((IN) - (OUT)))
510
 
511
/* Can do better with integer math:
512
 */
513
#define INTERP_UB( t, dstub, outub, inub )      \
514
do {                                            \
515
   GLfloat inf = UBYTE_TO_FLOAT( inub );        \
516
   GLfloat outf = UBYTE_TO_FLOAT( outub );      \
517
   GLfloat dstf = LINTERP( t, outf, inf );      \
518
   UNCLAMPED_FLOAT_TO_UBYTE( dstub, dstf );     \
519
} while (0)
520
 
521
#define INTERP_CHAN( t, dstc, outc, inc )       \
522
do {                                            \
523
   GLfloat inf = CHAN_TO_FLOAT( inc );          \
524
   GLfloat outf = CHAN_TO_FLOAT( outc );        \
525
   GLfloat dstf = LINTERP( t, outf, inf );      \
526
   UNCLAMPED_FLOAT_TO_CHAN( dstc, dstf );       \
527
} while (0)
528
 
529
#define INTERP_UI( t, dstui, outui, inui )      \
530
   dstui = (GLuint) (GLint) LINTERP( (t), (GLfloat) (outui), (GLfloat) (inui) )
531
 
532
#define INTERP_F( t, dstf, outf, inf )          \
533
   dstf = LINTERP( t, outf, inf )
534
 
535
#define INTERP_4F( t, dst, out, in )            \
536
do {                                            \
537
   dst[0] = LINTERP( (t), (out)[0], (in)[0] );  \
538
   dst[1] = LINTERP( (t), (out)[1], (in)[1] );  \
539
   dst[2] = LINTERP( (t), (out)[2], (in)[2] );  \
540
   dst[3] = LINTERP( (t), (out)[3], (in)[3] );  \
541
} while (0)
542
 
543
#define INTERP_3F( t, dst, out, in )            \
544
do {                                            \
545
   dst[0] = LINTERP( (t), (out)[0], (in)[0] );  \
546
   dst[1] = LINTERP( (t), (out)[1], (in)[1] );  \
547
   dst[2] = LINTERP( (t), (out)[2], (in)[2] );  \
548
} while (0)
549
 
550
#define INTERP_4CHAN( t, dst, out, in )                 \
551
do {                                                    \
552
   INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] );     \
553
   INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] );     \
554
   INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] );     \
555
   INTERP_CHAN( (t), (dst)[3], (out)[3], (in)[3] );     \
556
} while (0)
557
 
558
#define INTERP_3CHAN( t, dst, out, in )                 \
559
do {                                                    \
560
   INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] );     \
561
   INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] );     \
562
   INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] );     \
563
} while (0)
564
 
565
#define INTERP_SZ( t, vec, to, out, in, sz )                            \
566
do {                                                                    \
567
   switch (sz) {                                                        \
568
   case 4: vec[to][3] = LINTERP( (t), (vec)[out][3], (vec)[in][3] );    \
569
   case 3: vec[to][2] = LINTERP( (t), (vec)[out][2], (vec)[in][2] );    \
570
   case 2: vec[to][1] = LINTERP( (t), (vec)[out][1], (vec)[in][1] );    \
571
   case 1: vec[to][0] = LINTERP( (t), (vec)[out][0], (vec)[in][0] );    \
572
   }                                                                    \
573
} while(0)
574
 
575
 
576
/*
577
 * Fixed point arithmetic macros
578
 */
579
#ifdef FIXED_14
580
#define FIXED_ONE       0x00004000
581
#define FIXED_HALF      0x00002000
582
#define FIXED_FRAC_MASK 0x00003FFF
583
#define FIXED_SCALE     16384.0f
584
#define FIXED_SHIFT     14
585
#else
586
#define FIXED_ONE       0x00000800
587
#define FIXED_HALF      0x00000400
588
#define FIXED_FRAC_MASK 0x000007FF
589
#define FIXED_SCALE     2048.0f
590
#define FIXED_SHIFT     11
591
#endif
592
#define FIXED_INT_MASK  (~FIXED_FRAC_MASK)
593
#define FIXED_EPSILON   1
594
#define FloatToFixed(X) (IROUND((X) * FIXED_SCALE))
595
#define IntToFixed(I)   ((I) << FIXED_SHIFT)
596
#define FixedToInt(X)   ((X) >> FIXED_SHIFT)
597
#define FixedToUns(X)   (((unsigned int)(X)) >> FIXED_SHIFT)
598
#define FixedCeil(X)    (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
599
#define FixedFloor(X)   ((X) & FIXED_INT_MASK)
600
#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE))
601
#define PosFloatToFixed(X)      FloatToFixed(X)
602
#define SignedFloatToFixed(X)   FloatToFixed(X)
603
 
604
/* Returns TRUE for x == Inf or x == NaN. */
605
#ifdef USE_IEEE
606
static INLINE int IS_INF_OR_NAN( float x )
607
{
608
   union {float f; int i;} tmp;
609
   tmp.f = x;
610
   return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
611
}
612
#elif defined(isfinite)
613
#define IS_INF_OR_NAN(x)        (!isfinite(x))
614
#elif defined(finite)
615
#define IS_INF_OR_NAN(x)        (!finite(x))
616
#elif __VMS
617
#define IS_INF_OR_NAN(x)        (!finite(x))
618
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
619
#define IS_INF_OR_NAN(x)        (!isfinite(x))
620
#else
621
#define IS_INF_OR_NAN(x)        (!finite(x))
622
#endif 
623
 
624
 
625
/*
626
 * Return log_base_2(x).
627
 */
628
#ifdef USE_IEEE
629
 
630
#if 0
631
/* This is pretty fast, but not accurate enough (only 2 fractional bits).
632
 * Based on code from http://www.stereopsis.com/log2.html
633
 */
634
static INLINE GLfloat LOG2(GLfloat x)
635
{
636
   const GLfloat y = x * x * x * x;
637
   const GLuint ix = *((GLuint *) &y);
638
   const GLuint exp = (ix >> 23) & 0xFF;
639
   const GLint log2 = ((GLint) exp) - 127;
640
   return (GLfloat) log2 * (1.0 / 4.0);  /* 4, because of x^4 above */
641
}
642
#endif
643
 
644
/* Pretty fast, and accurate.
645
 * Based on code from http://www.flipcode.com/totd/
646
 */
647
static INLINE GLfloat LOG2(GLfloat val)
648
{
649
   GLint *exp_ptr = (GLint *) &val;
650
   GLint x = *exp_ptr;
651
   const GLint log_2 = ((x >> 23) & 255) - 128;
652
   x &= ~(255 << 23);
653
   x += 127 << 23;
654
   *exp_ptr = x;
655
   val = ((-1.0f/3) * val + 2) * val - 2.0f/3;
656
   return val + log_2;
657
}
658
 
659
#else /* USE_IEEE */
660
 
661
/* Slow, portable solution.
662
 * NOTE: log_base_2(x) = log(x) / log(2)
663
 * NOTE: 1.442695 = 1/log(2).
664
 */
665
#define LOG2(x)  ((GLfloat) (log(x) * 1.442695F))
666
 
667
#endif /* USE_IEEE */
668
 
669
 
670
extern void
671
_mesa_init_math(void);
672
 
673
 
674
extern GLuint
675
_mesa_bitcount(GLuint n);
676
 
677
 
678
#endif