00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00037
00038 #ifndef OPENIMAGEIO_FMATH_H
00039 #define OPENIMAGEIO_FMATH_H
00040
00041 #include <cmath>
00042 #include <limits>
00043 #include <typeinfo>
00044 #include <algorithm>
00045
00046 #if defined(_MSC_VER)
00047 typedef __int8 int8_t;
00048 typedef __int16 int16_t;
00049 typedef __int32 int32_t;
00050 typedef __int64 int64_t;
00051 typedef unsigned __int8 uint8_t;
00052 typedef unsigned __int16 uint16_t;
00053 # ifndef _UINT64_T
00054 typedef unsigned __int32 uint32_t;
00055 typedef unsigned __int64 uint64_t;
00056 # define _UINT32_T
00057 # define _UINT64_T
00058 # endif
00059 #else
00060 # include <stdint.h>
00061 #endif
00062
00063
00064 #ifdef OPENIMAGEIO_NAMESPACE
00065 namespace OPENIMAGEIO_NAMESPACE {
00066 #endif
00067
00068
00069
00070 #ifndef M_PI
00073 # define M_PI 3.1415926535897932
00074 #endif
00075
00076 #ifndef M_PI_2
00079 # define M_PI_2 1.5707963267948966
00080 #endif
00081
00082 #ifndef M_TWO_PI
00085 # define M_TWO_PI (M_PI * 2.0)
00086 #endif
00087
00088 #ifndef M_SQRT2
00091 # define M_SQRT2 1.414135623730950
00092 #endif
00093
00094 #ifndef M_SQRT1_2
00097 # define M_SQRT1_2 0.7071067811865475
00098 #endif
00099
00100 #ifndef M_LN2
00103 # define M_LN2 0.6931471805599453
00104 #endif
00105
00106 #ifndef M_LN10
00109 # define M_LN10 2.3025850929940457
00110 #endif
00111
00112
00113
00114
00115 #if (defined(_WIN32) || defined(__i386__) || defined(__x86_64__))
00116 # define USE_INTEL_MATH_SHORTCUTS 1
00117 # ifndef __LITTLE_ENDIAN__
00118 # define __LITTLE_ENDIAN__ 1
00119 # undef __BIG_ENDIAN__
00120 # endif
00121 #endif
00122
00123
00124
00127 #define HUGE_FLOAT ((float)1.0e38)
00128
00131 inline bool huge (float f) { return (f >= HUGE_FLOAT/2); }
00132
00135 #define UNINITIALIZED_FLOAT (- std::numeric_limits<float>::max())
00136
00137
00138
00139
00142 inline bool
00143 ispow2 (int x)
00144 {
00145
00146
00147
00148 return (x & (x-1)) == 0 && (x >= 0);
00149 }
00150
00151
00152
00155 inline bool
00156 ispow2 (unsigned int x)
00157 {
00158
00159
00160
00161 return (x & (x-1)) == 0;
00162 }
00163
00164
00165
00168 inline int
00169 pow2roundup (int x)
00170 {
00171
00172 if (x < 0)
00173 return 0;
00174
00175
00176 --x;
00177
00178 x |= x >> 1;
00179 x |= x >> 2;
00180 x |= x >> 4;
00181 x |= x >> 8;
00182 x |= x >> 16;
00183
00184 return x+1;
00185 }
00186
00187
00188
00191 inline int
00192 pow2rounddown (int x)
00193 {
00194
00195 x |= x >> 1;
00196 x |= x >> 2;
00197 x |= x >> 4;
00198 x |= x >> 8;
00199 x |= x >> 16;
00200
00201
00202 return x & ~(x >> 1);
00203 }
00204
00205
00206
00209 inline bool littleendian (void)
00210 {
00211 #ifdef __BIG_ENDIAN__
00212 return false;
00213 #endif
00214 #ifdef __LITTLE_ENDIAN__
00215 return true;
00216 #endif
00217
00218 int i = 1;
00219 return *((char *) &i);
00220 }
00221
00222
00223
00226 inline bool bigendian (void)
00227 {
00228 return ! littleendian();
00229 }
00230
00231
00232
00236 template<class T>
00237 inline void
00238 swap_endian (T *f, int len=1)
00239 {
00240 for (char *c = (char *) f; len--; c += sizeof(T)) {
00241 if (sizeof(T) == 2) {
00242 std::swap (c[0], c[1]);
00243 } else if (sizeof(T) == 4) {
00244 std::swap (c[0], c[3]);
00245 std::swap (c[1], c[2]);
00246 } else if (sizeof(T) == 8) {
00247 std::swap (c[0], c[7]);
00248 std::swap (c[1], c[6]);
00249 std::swap (c[2], c[5]);
00250 std::swap (c[3], c[4]);
00251 }
00252 }
00253 }
00254
00255
00256
00259 template <class T=float>
00260 class EightBitConverter {
00261 public:
00262 EightBitConverter () { init(); }
00263 T operator() (unsigned char c) const { return val[c]; }
00264 private:
00265 T val[256];
00266 void init () {
00267 float scale = 1.0f / 255.0f;
00268 if (std::numeric_limits<T>::is_integer)
00269 scale *= (float)std::numeric_limits<T>::max();
00270 for (int i = 0; i < 256; ++i)
00271 val[i] = (T)(i * scale);
00272 }
00273 };
00274
00275
00276
00279 template <class T>
00280 inline T
00281 clamp (T a, T l, T h)
00282 {
00283 return (a < l)? l : ((a > h)? h : a);
00284 }
00285
00286
00287
00290 inline uint32_t
00291 clamped_mult32 (uint32_t a, uint32_t b)
00292 {
00293 const uint32_t Err = std::numeric_limits<uint32_t>::max();
00294 uint64_t r = (uint64_t)a * (uint64_t)b;
00295 return r < Err ? (uint32_t)r : Err;
00296 }
00297
00298
00299
00302 inline uint64_t
00303 clamped_mult64 (uint64_t a, uint64_t b)
00304 {
00305 uint64_t ab = a*b;
00306 if (b && ab/b != a)
00307 return std::numeric_limits<uint64_t>::max();
00308 else
00309 return ab;
00310 }
00311
00312
00313
00314
00315 template<typename T, typename U> struct is_same { static const bool value = false; };
00316 template<typename T> struct is_same<T,T> { static const bool value = true; };
00317
00318
00319
00326
00327
00328
00329 template<typename S, typename D>
00330 void convert_type (const S *src, D *dst, size_t n, D _zero=0, D _one=1,
00331 D _min=std::numeric_limits<D>::min(),
00332 D _max=std::numeric_limits<D>::max())
00333 {
00334 if (is_same<S,D>::value) {
00335
00336 memcpy (dst, src, n*sizeof(D));
00337 return;
00338 }
00339 typedef double F;
00340 F scale = std::numeric_limits<S>::is_integer ?
00341 ((F)1.0)/std::numeric_limits<S>::max() : (F)1.0;
00342 if (std::numeric_limits<D>::is_integer) {
00343
00344 F min = (F)_min;
00345 F max = (F)_max;
00346 scale *= _max;
00347
00348 for ( ; n >= 16; n -= 16) {
00349 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00350 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00351 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00352 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00353 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00354 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00355 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00356 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00357 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00358 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00359 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00360 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00361 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00362 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00363 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00364 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00365 }
00366 while (n--)
00367 *dst++ = (D)(clamp ((F)(*src++) * scale, min, max));
00368 } else {
00369
00370
00371
00372 for ( ; n >= 16; n -= 16) {
00373 *dst++ = (D)((*src++) * scale);
00374 *dst++ = (D)((*src++) * scale);
00375 *dst++ = (D)((*src++) * scale);
00376 *dst++ = (D)((*src++) * scale);
00377 *dst++ = (D)((*src++) * scale);
00378 *dst++ = (D)((*src++) * scale);
00379 *dst++ = (D)((*src++) * scale);
00380 *dst++ = (D)((*src++) * scale);
00381 *dst++ = (D)((*src++) * scale);
00382 *dst++ = (D)((*src++) * scale);
00383 *dst++ = (D)((*src++) * scale);
00384 *dst++ = (D)((*src++) * scale);
00385 *dst++ = (D)((*src++) * scale);
00386 *dst++ = (D)((*src++) * scale);
00387 *dst++ = (D)((*src++) * scale);
00388 *dst++ = (D)((*src++) * scale);
00389 }
00390 while (n--)
00391 *dst++ = (D)((*src++) * scale);
00392 }
00393 }
00394
00395
00396
00402 template<typename S, typename D>
00403 D convert_type (const S &src)
00404 {
00405 if (is_same<S,D>::value) {
00406
00407 return (D)src;
00408 }
00409 typedef double F;
00410 F scale = std::numeric_limits<S>::is_integer ?
00411 ((F)1.0)/std::numeric_limits<S>::max() : (F)1.0;
00412 if (std::numeric_limits<D>::is_integer) {
00413
00414 typedef double F;
00415 F min = (F) std::numeric_limits<D>::min();
00416 F max = (F) std::numeric_limits<D>::max();
00417 scale *= max;
00418 return (D)(clamp ((F)src * scale, min, max));
00419 } else {
00420
00421
00422 return (D)((F)src * scale);
00423 }
00424 }
00425
00426
00427
00431 template<typename I, typename E>
00432 struct DataProxy {
00433 DataProxy (I &data) : m_data(data) { }
00434 E operator= (E newval) { m_data = convert_type<E,I>(newval); return newval; }
00435 operator E () const { return convert_type<I,E>(m_data); }
00436 private:
00437 I &m_data;
00438 };
00439
00440
00441
00445 template<typename I, typename E>
00446 struct ConstDataProxy {
00447 ConstDataProxy (const I &data) : m_data(data) { }
00448 operator E () const { return convert_type<E,I>(*m_data); }
00449 private:
00450 const I &m_data;
00451 };
00452
00453
00454
00458 template<typename I, typename E>
00459 struct DataArrayProxy {
00460 DataArrayProxy (I *data=NULL) : m_data(data) { }
00461 E operator* () const { return convert_type<I,E>(*m_data); }
00462 E operator[] (int i) const { return convert_type<I,E>(m_data[i]); }
00463 DataProxy<I,E> operator[] (int i) { return DataProxy<I,E> (m_data[i]); }
00464 void set (I *data) { m_data = data; }
00465 I * get () const { return m_data; }
00466 private:
00467 I *m_data;
00468 };
00469
00470
00471
00475 template<typename I, typename E>
00476 struct ConstDataArrayProxy {
00477 ConstDataArrayProxy (const I *data=NULL) : m_data(data) { }
00478 E operator* () const { return convert_type<I,E>(*m_data); }
00479 E operator[] (int i) const { return convert_type<I,E>(m_data[i]); }
00480 void set (const I *data) { m_data = data; }
00481 const I * get () const { return m_data; }
00482 private:
00483 const I *m_data;
00484 };
00485
00486
00487
00488
00492 template <class T, class Q>
00493 inline T
00494 bilerp (T v0, T v1, T v2, T v3, Q s, Q t)
00495 {
00496
00497 Q s1 = (Q)1 - s;
00498 return (T) ((1-t)*(v0*s1 + v1*s) + t*(v2*s1 + v3*s));
00499 }
00500
00501
00502
00507 template <class T, class Q>
00508 inline void
00509 bilerp (const T *v0, const T *v1,
00510 const T *v2, const T *v3,
00511 Q s, Q t, int n, T *result)
00512 {
00513 Q s1 = (Q)1 - s;
00514 Q t1 = (Q)1 - t;
00515 for (int i = 0; i < n; ++i)
00516 result[i] = (T) (t1*(v0[i]*s1 + v1[i]*s) + t*(v2[i]*s1 + v3[i]*s));
00517 }
00518
00519
00520
00521
00527 template <class T, class Q>
00528 inline void
00529 bilerp_mad (const T *v0, const T *v1,
00530 const T *v2, const T *v3,
00531 Q s, Q t, Q scale, int n, T *result)
00532 {
00533 Q s1 = (Q)1 - s;
00534 Q t1 = (Q)1 - t;
00535 for (int i = 0; i < n; ++i)
00536 result[i] += (T) (scale * (t1*(v0[i]*s1 + v1[i]*s) +
00537 t*(v2[i]*s1 + v3[i]*s)));
00538 }
00539
00540
00541
00545 inline int
00546 RoundToInt (double val)
00547 {
00548 #ifdef USE_INTEL_MATH_SHORTCUTS
00549 union { int i; double d; } myunion;
00550 myunion.d = val;
00551 const double doublemagic = double (6755399441055744.0);
00552
00553 myunion.d += doublemagic;
00554 return myunion.i;
00555 #else
00556 return round (val);
00557 #endif
00558 }
00559
00560
00561 inline int
00562 RoundToInt (float val)
00563 {
00564 #ifdef USE_INTEL_MATH_SHORTCUTS
00565 return RoundToInt (double(val));
00566 #else
00567 return roundf (val);
00568 #endif
00569 }
00570
00571
00575 inline int
00576 FloorToInt (double val)
00577 {
00578 #ifdef USE_INTEL_MATH_SHORTCUTS
00579 const double doublemagicdelta = (1.5e-8);
00580
00581 const double doublemagicroundeps = (0.5f-doublemagicdelta);
00582
00583 return RoundToInt (val - doublemagicroundeps);
00584 #else
00585 return (int) floor (val);
00586 #endif
00587 }
00588
00589
00590 inline int
00591 FloorToInt (float val)
00592 {
00593 #ifdef USE_INTEL_MATH_SHORTCUTS
00594 return FloorToInt (double(val));
00595 #else
00596 return (int) floorf (val);
00597 #endif
00598 }
00599
00600
00604 inline int
00605 CeilToInt (double val)
00606 {
00607 #ifdef USE_INTEL_MATH_SHORTCUTS
00608 const double doublemagicdelta = (1.5e-8);
00609
00610 const double doublemagicroundeps = (0.5f-doublemagicdelta);
00611
00612 return RoundToInt (val + doublemagicroundeps);
00613 #else
00614 return (int) ceil (val);
00615 #endif
00616 }
00617
00618 inline int
00619 CeilToInt (float val)
00620 {
00621 #ifdef USE_INTEL_MATH_SHORTCUTS
00622 return CeilToInt (double(val));
00623 #else
00624 return (int) ceilf (val);
00625 #endif
00626 }
00627
00631 inline int
00632 FloatToInt (double val)
00633 {
00634 #ifdef USE_INTEL_MATH_SHORTCUTS
00635 return (val<0) ? CeilToInt(val) : FloorToInt(val);
00636 #else
00637 return (int) val;
00638 #endif
00639 }
00640
00641
00642 inline int
00643 FloatToInt (float val)
00644 {
00645 #ifdef USE_INTEL_MATH_SHORTCUTS
00646 return FloatToInt (double(val));
00647 #else
00648 return (int) val;
00649 #endif
00650 }
00651
00652
00653
00654
00659 inline float
00660 floorfrac (float x, int *xint)
00661 {
00662
00663
00664 #if 1
00665 int i = (int) x - (x < 0.0f ? 1 : 0);
00666 #else
00667
00668 int i = FloorToInt (x);
00669 #endif
00670 *xint = i;
00671 return x - i;
00672 }
00673
00674
00675
00678 inline float radians (float deg) { return deg * (float)(M_PI / 180.0); }
00679
00682 inline float degrees (float rad) { return rad * (float)(180.0 / M_PI); }
00683
00684
00685
00686 #ifdef _WIN32
00687
00688 #define hypotf _hypotf
00689 #define copysign(x,y) _copysign(x,y)
00690 #define copysignf(x,y) copysign(x,y)
00691 #define isnan(x) _isnan(x)
00692 #define isfinite(x) _finite(x)
00693 #define usleep(a) Sleep((a)/1000)
00694
00695 inline double
00696 round (float val) {
00697 return floor (val + 0.5);
00698 }
00699
00700 template<class T>
00701 inline int isinf (T x) {
00702 return (isfinite(x)||isnan(x)) ? 0 : copysign(1.0f, x);
00703 }
00704
00705 inline float
00706 log2f (float val) {
00707 return logf (val)/M_LN2;
00708 }
00709 #endif
00710
00711
00712
00718 inline void
00719 float_to_rational (float f, unsigned int &num, unsigned int &den)
00720 {
00721 if (f <= 0) {
00722 num = 0;
00723 den = 1;
00724 } else if ((int)(1.0/f) == (1.0/f)) {
00725 num = 1;
00726 den = (int)f;
00727 } else {
00728 num = (int)f;
00729 den = 1;
00730 while (fabsf(f-num) > 0.00001 && den < 1000000) {
00731 den *= 10;
00732 f *= 10;
00733 num = (int)f;
00734 }
00735 }
00736 }
00737
00738
00739
00745 inline void
00746 float_to_rational (float f, int &num, int &den)
00747 {
00748 unsigned int n, d;
00749 float_to_rational (fabsf(f), n, d);
00750 num = (f >= 0) ? (int)n : -(int)n;
00751 den = (int) d;
00752 }
00753
00754
00755
00756 #ifdef OPENIMAGEIO_NAMESPACE
00757 };
00758 using namespace OPENIMAGEIO_NAMESPACE;
00759 #endif
00760
00761 #endif // OPENIMAGEIO_FMATH_H