about summary refs log tree commit diff
path: root/lib/util/floatcode.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util/floatcode.h')
-rw-r--r--lib/util/floatcode.h185
1 files changed, 185 insertions, 0 deletions
diff --git a/lib/util/floatcode.h b/lib/util/floatcode.h
new file mode 100644
index 00000000..23c57e9b
--- /dev/null
+++ b/lib/util/floatcode.h
@@ -0,0 +1,185 @@
+#ifndef FLOATCODE_H_INCLUDED
+#define FLOATCODE_H_INCLUDED
+
+#include "pm_config.h"  /* BYTE_ORDER */
+
+unsigned int const pm_byteOrder = BYTE_ORDER;
+
+
+typedef struct {
+/*----------------------------------------------------------------------------
+   This is a big-endian representation of a 32 bit floating point number.
+   I.e. bytes[0] contains the sign bit, etc.
+
+   On a big-endian machines, this is bit for bit identical to 'float'.
+   On a little-endian machine, it isn't.
+
+   This is an important data type because decent file formats use
+   big-endian -- they don't care if some CPU happens to use some other
+   code for its own work.
+-----------------------------------------------------------------------------*/
+    unsigned char bytes[4];
+} pm_bigendFloat;
+
+
+static __inline__ float
+pm_floatFromBigendFloat(pm_bigendFloat const arg) {
+
+    float retval;
+
+    switch (pm_byteOrder) {
+    case BIG_ENDIAN: {
+        union {
+            pm_bigendFloat bigend;
+            float native;
+        } converter;
+        
+        converter.bigend = arg;
+        
+        retval = converter.native;
+    }; break;
+    case LITTLE_ENDIAN: {
+        union {
+            unsigned char bytes[4];
+            float native;
+        } converter;
+
+        converter.bytes[0] = arg.bytes[3];
+        converter.bytes[1] = arg.bytes[2];
+        converter.bytes[2] = arg.bytes[1];
+        converter.bytes[3] = arg.bytes[0];
+
+        retval = converter.native;
+    } break;
+    }
+    return retval;
+}
+
+
+
+static __inline__ pm_bigendFloat
+pm_bigendFloatFromFloat(float const arg) {
+
+    pm_bigendFloat retval;
+
+    switch (pm_byteOrder) {
+    case BIG_ENDIAN: {
+        union {
+            pm_bigendFloat bigend;
+            float native;
+        } converter;
+        
+        converter.native = arg;
+
+        retval = converter.bigend;
+    } break;
+    case LITTLE_ENDIAN: {
+        union {
+            unsigned char bytes[4];
+            float native;
+        } converter;
+
+        converter.native = arg;
+
+        retval.bytes[0] = converter.bytes[3];
+        retval.bytes[1] = converter.bytes[2];
+        retval.bytes[2] = converter.bytes[1];
+        retval.bytes[3] = converter.bytes[0];
+    } break;
+    }
+    return retval;
+}
+
+typedef struct {
+/*----------------------------------------------------------------------------
+   This is a big-endian representation of a 64 bit floating point number.
+   I.e. bytes[0] contains the sign bit, etc.
+
+   On a big-endian machines, this is bit for bit identical to 'float'.
+   On a little-endian machine, it isn't.
+
+   This is an important data type because decent file formats use
+   big-endian -- they don't care if some CPU happens to use some other
+   code for its own work.
+-----------------------------------------------------------------------------*/
+    unsigned char bytes[8];
+} pm_bigendDouble;
+
+
+static __inline__ double
+pm_doubleFromBigendDouble(pm_bigendDouble const arg) {
+
+    double retval;
+
+    switch (pm_byteOrder) {
+    case BIG_ENDIAN: {
+        union {
+            pm_bigendDouble bigend;
+            double native;
+        } converter;
+        
+        converter.bigend = arg;
+        
+        retval = converter.native;
+    }; break;
+    case LITTLE_ENDIAN: {
+        union {
+            unsigned char bytes[4];
+            double native;
+        } converter;
+
+        converter.bytes[0] = arg.bytes[7];
+        converter.bytes[1] = arg.bytes[6];
+        converter.bytes[2] = arg.bytes[5];
+        converter.bytes[3] = arg.bytes[4];
+        converter.bytes[4] = arg.bytes[3];
+        converter.bytes[5] = arg.bytes[2];
+        converter.bytes[6] = arg.bytes[1];
+        converter.bytes[7] = arg.bytes[0];
+
+        retval = converter.native;
+    } break;
+    }
+    return retval;
+}
+
+
+
+static __inline__ pm_bigendDouble
+pm_bigendDoubleFromDouble(double const arg) {
+
+    pm_bigendDouble retval;
+
+    switch (pm_byteOrder) {
+    case BIG_ENDIAN: {
+        union {
+            pm_bigendDouble bigend;
+            double native;
+        } converter;
+        
+        converter.native = arg;
+
+        retval = converter.bigend;
+    } break;
+    case LITTLE_ENDIAN: {
+        union {
+            unsigned char bytes[4];
+            double native;
+        } converter;
+
+        converter.native = arg;
+
+        retval.bytes[0] = converter.bytes[7];
+        retval.bytes[1] = converter.bytes[6];
+        retval.bytes[2] = converter.bytes[5];
+        retval.bytes[3] = converter.bytes[4];
+        retval.bytes[4] = converter.bytes[3];
+        retval.bytes[5] = converter.bytes[2];
+        retval.bytes[6] = converter.bytes[1];
+        retval.bytes[7] = converter.bytes[0];
+    } break;
+    }
+    return retval;
+}
+
+#endif