summaryrefslogtreecommitdiffstats
path: root/thirdparty/meshoptimizer/quantization.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/meshoptimizer/quantization.cpp')
-rw-r--r--thirdparty/meshoptimizer/quantization.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/thirdparty/meshoptimizer/quantization.cpp b/thirdparty/meshoptimizer/quantization.cpp
new file mode 100644
index 0000000000..09a314d602
--- /dev/null
+++ b/thirdparty/meshoptimizer/quantization.cpp
@@ -0,0 +1,70 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+
+unsigned short meshopt_quantizeHalf(float v)
+{
+ union { float f; unsigned int ui; } u = {v};
+ unsigned int ui = u.ui;
+
+ int s = (ui >> 16) & 0x8000;
+ int em = ui & 0x7fffffff;
+
+ // bias exponent and round to nearest; 112 is relative exponent bias (127-15)
+ int h = (em - (112 << 23) + (1 << 12)) >> 13;
+
+ // underflow: flush to zero; 113 encodes exponent -14
+ h = (em < (113 << 23)) ? 0 : h;
+
+ // overflow: infinity; 143 encodes exponent 16
+ h = (em >= (143 << 23)) ? 0x7c00 : h;
+
+ // NaN; note that we convert all types of NaN to qNaN
+ h = (em > (255 << 23)) ? 0x7e00 : h;
+
+ return (unsigned short)(s | h);
+}
+
+float meshopt_quantizeFloat(float v, int N)
+{
+ assert(N >= 0 && N <= 23);
+
+ union { float f; unsigned int ui; } u = {v};
+ unsigned int ui = u.ui;
+
+ const int mask = (1 << (23 - N)) - 1;
+ const int round = (1 << (23 - N)) >> 1;
+
+ int e = ui & 0x7f800000;
+ unsigned int rui = (ui + round) & ~mask;
+
+ // round all numbers except inf/nan; this is important to make sure nan doesn't overflow into -0
+ ui = e == 0x7f800000 ? ui : rui;
+
+ // flush denormals to zero
+ ui = e == 0 ? 0 : ui;
+
+ u.ui = ui;
+ return u.f;
+}
+
+float meshopt_dequantizeHalf(unsigned short h)
+{
+ unsigned int s = unsigned(h & 0x8000) << 16;
+ int em = h & 0x7fff;
+
+ // bias exponent and pad mantissa with 0; 112 is relative exponent bias (127-15)
+ int r = (em + (112 << 10)) << 13;
+
+ // denormal: flush to zero
+ r = (em < (1 << 10)) ? 0 : r;
+
+ // infinity/NaN; note that we preserve NaN payload as a byproduct of unifying inf/nan cases
+ // 112 is an exponent bias fixup; since we already applied it once, applying it twice converts 31 to 255
+ r += (em >= (31 << 10)) ? (112 << 23) : 0;
+
+ union { float f; unsigned int ui; } u;
+ u.ui = s | r;
+ return u.f;
+}