home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / halffloat.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  1.8 KB  |  80 lines

  1. #include "stdafx.h"
  2. #include <vd2/system/halffloat.h>
  3.  
  4. uint16 VDConvertFloatToHalf(const void *f) {
  5.     uint32 v = *(const uint32 *)f;
  6.  
  7.     uint32 sign = (v >> 16) & 0x8000;
  8.     sint32 exmant = v & 0x7fffffff;
  9.  
  10.     if (exmant > 0x7f800000) {
  11.         // convert NaNs directly
  12.         exmant = (exmant & 0x00400000) + 0x47a00000;
  13.     } else if (exmant > 0x47800000) {
  14.         // clamp large numbers to infinity
  15.         exmant = 0x47800000;
  16.     } else if (exmant < 0x33800000) {
  17.         // clamp very tiny numbers to zero
  18.         exmant = 0x38000000;
  19.     } else if (exmant < 0x38800000) {
  20.         // normalized finite converting to denormal
  21.         uint32 ex = exmant & 0x7f800000;
  22.         uint32 mant = (exmant & 0x007fffff) | 0x800000;
  23.         uint32 sticky = 0;
  24.  
  25.         while(ex < 0x38800000) {
  26.             ex += 0x00800000;
  27.             sticky |= mant;
  28.             mant >>= 1;
  29.         }
  30.  
  31.         // round to nearest even
  32.         sticky |= mant >> 13;
  33.  
  34.         // round up with sticky bits
  35.         mant += (sticky & 1);
  36.  
  37.         // round up with round bit
  38.         mant += 0x0fff;
  39.  
  40.         exmant = ex + mant - 0x800000;
  41.     } else {
  42.         // round normal numbers using round to nearest even
  43.         exmant |= (exmant & 0x00002000) >> 13;
  44.         exmant += 0x00000fff;
  45.     }
  46.  
  47.     // shift and rebias exponent
  48.     exmant -= 0x38000000;
  49.     exmant >>= 13;
  50.  
  51.     return (uint16)(sign + exmant);
  52. }
  53.  
  54. void VDConvertHalfToFloat(uint16 h, void *dst) {
  55.     uint32 sign = ((uint32)h << 16) & 0x80000000;
  56.     uint32 exmant = (uint32)h & 0x7fff;
  57.     uint32 v = 0;
  58.  
  59.     if (exmant >= 0x7c00) {
  60.         // infinity or NaN
  61.         v = (exmant << 13) + 0x70000000;
  62.     } else if (exmant >= 0x0400) {
  63.         // normalized finite
  64.         v = (exmant << 13) + 0x38000000;
  65.     } else if (exmant) {
  66.         // denormal
  67.         uint32 ex32 = 0x38000000;
  68.         uint32 mant32 = (exmant & 0x3ff) << 13;
  69.  
  70.         while(!(mant32 & 0x800000)) {
  71.             mant32 <<= 1;
  72.             ex32 -= 0x800000;
  73.         }
  74.  
  75.         v = ex32 + mant32;
  76.     }
  77.  
  78.     *(uint32 *)dst = v + sign;
  79. }
  80.