Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSENDIAN_H__
00020 #define __CS_CSENDIAN_H__
00021
00029 #include <math.h>
00030 #include "cstypes.h"
00031 #include "csgeom/math.h"
00032 #include "csutil/bitops.h"
00033 #if defined(CS_HAVE_BYTESWAP_H)
00034 #include <byteswap.h>
00035 #endif
00036
00037 #define csQroundSure(x) (int ((x) + ((x < 0) ? -0.5 : +0.5)))
00038
00042 struct csSwapBytes
00043 {
00044 public:
00046
00047 static CS_FORCEINLINE uint16 Swap (uint16 s)
00048 {
00049 #if defined(CS_COMPILER_MSVC) && (_MSC_VER >= 1300)
00050 return _byteswap_ushort (s);
00051 #elif defined(CS_HAVE_BYTESWAP_H)
00052 return bswap_16 (s);
00053 #else
00054 return (s >> 8) | (s << 8);
00055 #endif
00056 }
00057 static CS_FORCEINLINE int16 Swap (int16 s)
00058 { return (int16)Swap ((uint16)s); }
00059 static CS_FORCEINLINE uint32 Swap (uint32 l)
00060 {
00061 #if defined(CS_COMPILER_MSVC) && (_MSC_VER >= 1300)
00062 return _byteswap_ulong (l);
00063 #elif defined(CS_HAVE_BYTESWAP_H)
00064 return bswap_32 (l);
00065 #else
00066 return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24);
00067 #endif
00068 }
00069 static CS_FORCEINLINE int32 Swap (int32 l)
00070 { return (int32)Swap ((uint32)l); }
00071 static CS_FORCEINLINE uint64 Swap (uint64 l)
00072 {
00073 #if defined(CS_COMPILER_MSVC) && (_MSC_VER >= 1300)
00074 return _byteswap_uint64 (l);
00075 #elif defined(CS_HAVE_BYTESWAP_H) && !defined(__STRICT_ANSI__)
00076 return bswap_64 (l);
00077 #else
00078 union
00079 {
00080 uint64 ui64;
00081 uint32 ui32[2];
00082 } u1, u2;
00083 u1.ui64 = l;
00084 u2.ui32[0] = Swap (u1.ui32[1]);
00085 u2.ui32[1] = Swap (u1.ui32[0]);
00086 return u2.ui64;
00087 #endif
00088 }
00089 static CS_FORCEINLINE int64 Swap (int64 l)
00090 { return (int64)Swap ((uint64)l); }
00091
00092 static CS_FORCEINLINE uint16 UInt16 (uint16 x) { return Swap (x); }
00093 static CS_FORCEINLINE int16 Int16 (int16 x) { return Swap (x); }
00094 static CS_FORCEINLINE uint32 UInt32 (uint32 x) { return Swap (x); }
00095 static CS_FORCEINLINE int32 Int32 (int32 x) { return Swap (x); }
00096 static CS_FORCEINLINE uint64 UInt64 (uint64 x) { return Swap (x); }
00097 static CS_FORCEINLINE int64 Int64 (int64 x) { return Swap (x); }
00099 };
00100
00101 #ifdef CS_BIG_ENDIAN
00102 struct csBigEndian
00103 #else
00109 struct csLittleEndian
00110 #endif
00111 {
00113
00114 static CS_FORCEINLINE uint16 Convert (uint16 x) { return x; }
00115 static CS_FORCEINLINE int16 Convert (int16 x) { return x; }
00116 static CS_FORCEINLINE uint32 Convert (uint32 x) { return x; }
00117 static CS_FORCEINLINE int32 Convert (int32 x) { return x; }
00118 static CS_FORCEINLINE uint64 Convert (uint64 x) { return x; }
00119 static CS_FORCEINLINE int64 Convert (int64 x) { return x; }
00120
00121 static CS_FORCEINLINE uint16 UInt16 (uint16 x) { return Convert (x); }
00122 static CS_FORCEINLINE int16 Int16 (int16 x) { return Convert (x); }
00123 static CS_FORCEINLINE uint32 UInt32 (uint32 x) { return Convert (x); }
00124 static CS_FORCEINLINE int32 Int32 (int32 x) { return Convert (x); }
00125 static CS_FORCEINLINE uint64 UInt64 (uint64 x) { return Convert (x); }
00126 static CS_FORCEINLINE int64 Int64 (int64 x) { return Convert (x); }
00128 };
00129
00130 #ifdef CS_LITTLE_ENDIAN
00131
00136 struct csBigEndian
00137 #else
00138 struct csLittleEndian
00139 #endif
00140 {
00141 public:
00143
00144 static CS_FORCEINLINE uint16 Convert (uint16 s)
00145 { return csSwapBytes::Swap (s); }
00146 static CS_FORCEINLINE int16 Convert (int16 s)
00147 { return csSwapBytes::Swap (s); }
00148 static CS_FORCEINLINE uint32 Convert (uint32 l)
00149 { return csSwapBytes::Swap (l); }
00150 static CS_FORCEINLINE int32 Convert (int32 l)
00151 { return csSwapBytes::Swap (l); }
00152 static CS_FORCEINLINE uint64 Convert (uint64 l)
00153 { return csSwapBytes::Swap (l); }
00154 static CS_FORCEINLINE int64 Convert (int64 l)
00155 { return csSwapBytes::Swap (l); }
00156
00157 static CS_FORCEINLINE uint16 UInt16 (uint16 x) { return Convert (x); }
00158 static CS_FORCEINLINE int16 Int16 (int16 x) { return Convert (x); }
00159 static CS_FORCEINLINE uint32 UInt32 (uint32 x) { return Convert (x); }
00160 static CS_FORCEINLINE int32 Int32 (int32 x) { return Convert (x); }
00161 static CS_FORCEINLINE uint64 UInt64 (uint64 x) { return Convert (x); }
00162 static CS_FORCEINLINE int64 Int64 (int64 x) { return Convert (x); }
00164 };
00165
00169 struct csIEEEfloat
00170 {
00171
00172
00173 #ifdef CS_IEEE_DOUBLE_FORMAT
00174
00175
00176 static CS_FORCEINLINE uint32 FromNative (float f)
00177 {
00178 union
00179 {
00180 float f;
00181 uint32 ui32;
00182 } u;
00183 u.f = f;
00184 return u.ui32;
00185 }
00186 static CS_FORCEINLINE uint64 FromNative (double f)
00187 {
00188 union
00189 {
00190 double f;
00191 uint64 ui64;
00192 } u;
00193 u.f = f;
00194 return u.ui64;
00195 }
00197
00199
00200 static CS_FORCEINLINE float ToNative (uint32 f)
00201 {
00202 union
00203 {
00204 float f;
00205 uint32 ui32;
00206 } u;
00207 u.ui32 = f;
00208 return u.f;
00209 }
00210 static CS_FORCEINLINE double ToNative (uint64 f)
00211 {
00212 union
00213 {
00214 double f;
00215 uint64 ui64;
00216 } u;
00217 u.ui64 = f;
00218 return u.f;
00219 }
00221 #else
00222 #error Do not know how to convert to IEEE floats
00223 #endif
00224
00226 static CS_FORCEINLINE float ToNative (uint16 half)
00227 {
00228 union
00229 {
00230 uint32 u;
00231 float f;
00232 } u2f;
00233
00234 uint32 sign = (half & 0x8000) << 16;
00235 int32 exponent = (half & 0x7C00) >> 10;
00236 uint32 mantissa = (half & 0x03ff) << 13;
00237
00238
00239 if (exponent == 0x1F)
00240 {
00241 u2f.u = sign | mantissa;
00242
00243 if (mantissa != 0)
00244 {
00245
00246 u2f.u |= 0x7FC00000;
00247 }
00248 else
00249 {
00250
00251 u2f.u |= 0x7f800000;
00252 }
00253
00254 return u2f.f;
00255 }
00256
00257
00258 if(exponent == 0)
00259 {
00260 unsigned long index;
00261 CS::Utility::BitOps::ScanBitReverse (mantissa, index);
00262
00263 exponent -= (index - 9);
00264 mantissa <<= (index - 8);
00265 mantissa &= 0x007FFFFF;
00266 }
00267
00268
00269 exponent += 112;
00270 exponent <<= 23;
00271
00272
00273 u2f.u = sign | exponent | mantissa;
00274
00275 return u2f.f;
00276 }
00277
00282 static CS_FORCEINLINE uint16 FromNativeRTZ (float f)
00283 {
00284 union
00285 {
00286 float f;
00287 unsigned int u;
00288 } f2u;
00289
00290 f2u.f = f;
00291 unsigned short sign = 0x8000 & (f2u.u >> 16);
00292
00293
00294 f2u.u &= 0x7FFFFFFF;
00295
00296
00297 if(CS::IsNaN (f2u.f))
00298 {
00299
00300 f2u.u >>= 13;
00301 f2u.u &= 0x7fff;
00302 f2u.u |= 0x0200;
00303 return sign | f2u.u;
00304 }
00305
00306
00307 if(f2u.u >= 0x47800000)
00308 {
00309
00310 if(f2u.u == 0x7F800000)
00311 return sign | 0x7C00;
00312
00313 return sign | 0x7BFF;
00314 }
00315
00316
00317 if(f2u.u < 0x38800000)
00318 return sign;
00319
00320
00321 f2u.u &= 0xFFFFE000U;
00322 f2u.u -= 0x38000000U;
00323 return sign | (f2u.u >> 13);
00324 }
00325 };
00326
00335 struct csGetFromAddress
00336 {
00338
00339 static CS_FORCEINLINE uint16 UInt16 (const void *buff)
00340 {
00341 #ifdef CS_STRICT_ALIGNMENT
00342 uint16 s; memcpy (&s, buff, sizeof (s));
00343 return s;
00344 #else
00345 return *(uint16 *)buff;
00346 #endif
00347 }
00348 static CS_FORCEINLINE int16 Int16 (const void *buff)
00349 { return (int16)UInt16 (buff); }
00350 static CS_FORCEINLINE uint32 UInt32 (const void *buff)
00351 {
00352 #ifdef CS_STRICT_ALIGNMENT
00353 uint32 s; memcpy (&s, buff, sizeof (s));
00354 return s;
00355 #else
00356 return *(uint32 *)buff;
00357 #endif
00358 }
00359 static CS_FORCEINLINE int32 Int32 (const void *buff)
00360 { return (int32)UInt32 (buff); }
00361 static CS_FORCEINLINE uint64 UInt64 (const void *buff)
00362 {
00363 #ifdef CS_STRICT_ALIGNMENT
00364 uint64 s; memcpy (&s, buff, sizeof (s));
00365 return s;
00366 #else
00367 return *(uint64 *)buff;
00368 #endif
00369 }
00370 static CS_FORCEINLINE int64 Int64 (const void *buff)
00371 { return (int64)UInt64 (buff); }
00373 };
00374
00383 struct csSetToAddress
00384 {
00386
00387 static CS_FORCEINLINE void UInt16 (void *buff, uint16 s)
00388 {
00389 #ifdef CS_STRICT_ALIGNMENT
00390 memcpy (buff, &s, sizeof (s));
00391 #else
00392 *((uint16 *)buff) = s;
00393 #endif
00394 }
00395 static CS_FORCEINLINE void Int16 (void *buff, int16 s)
00396 { UInt16 (buff, (uint16)s); }
00397 static CS_FORCEINLINE void UInt32 (void *buff, uint32 s)
00398 {
00399 #ifdef CS_STRICT_ALIGNMENT
00400 memcpy (buff, &s, sizeof (s));
00401 #else
00402 *((uint32 *)buff) = s;
00403 #endif
00404 }
00405 static CS_FORCEINLINE void Int32 (void *buff, int32 s)
00406 { UInt32 (buff, (uint32)s); }
00407 static CS_FORCEINLINE void UInt64 (void *buff, uint64 s)
00408 {
00409 #ifdef CS_STRICT_ALIGNMENT
00410 memcpy (buff, &s, sizeof (s));
00411 #else
00412 *((uint64 *)buff) = s;
00413 #endif
00414 }
00415 static CS_FORCEINLINE void Int64 (void *buff, int64 s)
00416 { UInt64 (buff, (uint64)s); }
00418 };
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00442 CS_DEPRECATED_METHOD_MSG("Use csIEEEfloat methods instead")
00443 static inline int32 csFloatToLong (float f)
00444 {
00445 int exp;
00446 int32 mant = csQroundSure (frexp (f, &exp) * 0x1000000);
00447 int32 sign = mant & 0x80000000;
00448 if (mant < 0) mant = -mant;
00449 if (exp > 63) exp = 63; else if (exp < -64) exp = -64;
00450 return sign | ((exp & 0x7f) << 24) | (mant & 0xffffff);
00451 }
00452
00458 CS_DEPRECATED_METHOD_MSG("Use csIEEEfloat methods instead")
00459 static inline float csLongToFloat (int32 l)
00460 {
00461 int exp = (l >> 24) & 0x7f;
00462 if (exp & 0x40) exp = exp | ~0x7f;
00463 float mant = float (l & 0x00ffffff) / 0x1000000;
00464 if (l & 0x80000000) mant = -mant;
00465 return (float) ldexp (mant, exp);
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00481 CS_DEPRECATED_METHOD_MSG("Use csIEEEfloat methods instead")
00482 static inline int64 csDoubleToLongLong (double d)
00483 {
00484 int exp;
00485 int64 mant = (int64) (frexp (d, &exp) * ((int64)1 << 48));
00486 int64 sign = mant & ((int64)1 << 59);
00487 if (mant < 0) mant = -mant;
00488 if (exp > 32767) exp = 32767; else if (exp < -32768) exp = -32768;
00489 int64 const mask = ((uint64)0xffff << 32) | (uint64)0xffffffff;
00490 return sign | ((int64 (exp) & 0x7fff) << 48) | (mant & mask);
00491 }
00492
00498 CS_DEPRECATED_METHOD_MSG("Use csIEEEfloat methods instead")
00499 static inline double csLongLongToDouble (int64 i)
00500 {
00501 int exp = (i >> 48) & 0x7fff;
00502 if (exp & 0x4000) exp = exp | ~0x7fff;
00503 int64 const mask = ((uint64)0xffff << 32) | (uint64)0xffffffff;
00504 double mant = double (i & mask) / ((int64)1 << 48);
00505 if (i & ((int64)1 << 59)) mant = -mant;
00506 return ldexp (mant, exp);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00522 CS_DEPRECATED_METHOD_MSG("Use csIEEEfloat methods instead")
00523 static inline short csFloatToShort (float f)
00524 {
00525 int exp;
00526 long mant = csQroundSure (frexp (f, &exp) * 0x1000);
00527 long sign = mant & 0x8000;
00528 if (mant < 0) mant = -mant;
00529 if (exp > 7) mant = 0x7ff, exp = 7; else if (exp < -8) mant = 0, exp = -8;
00530 return short(sign | ((exp & 0xf) << 11) | (mant & 0x7ff));
00531 }
00532
00538 CS_DEPRECATED_METHOD_MSG("Use csIEEEfloat methods instead")
00539 static inline float csShortToFloat (short s)
00540 {
00541 int exp = (s >> 11) & 0xf;
00542 if (exp & 0x8) exp = exp | ~0xf;
00543 float mant = float ((s & 0x07ff) | 0x0800) / 0x1000;
00544 if (s & 0x8000) mant = -mant;
00545 return (float) ldexp (mant, exp);
00546 }
00547
00555 #endif // __CS_CSENDIAN_H__