aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-from-portable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/blind-from-portable.c')
-rw-r--r--src/blind-from-portable.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/blind-from-portable.c b/src/blind-from-portable.c
new file mode 100644
index 0000000..ccb902d
--- /dev/null
+++ b/src/blind-from-portable.c
@@ -0,0 +1,117 @@
+/* See LICENSE file for copyright and license details. */
+#include "stream.h"
+#include "util.h"
+
+#include <alloca.h>
+#include <math.h>
+#include <string.h>
+
+USAGE("[-s]")
+
+#define USING_BINARY32 0
+#define USING_BINARY64 0
+
+#define CONV(ITYPE, SITYPE, OTYPE, EXPONENT, HA2EXPONENT, FRACTION, SUFFIX)\
+ do {\
+ static int cache_i = 0;\
+ static ITYPE cache_in[] = {0, 0, 0, 0};\
+ static OTYPE cache_out[] = {0, 0, 0, 0};\
+ ITYPE exponent, fraction, signb;\
+ SITYPE sexponent;\
+ OTYPE ret, dexponent;\
+ if (portable == cache_in[cache_i]) {\
+ ret = cache_out[cache_i++];\
+ cache_i &= 3;\
+ return ret;\
+ }\
+ signb = portable >> (EXPONENT + FRACTION);\
+ exponent = (portable >> FRACTION) ^ (signb << EXPONENT);\
+ fraction = portable & (((ITYPE)1 << FRACTION) - 1);\
+ if (!exponent) {\
+ if (!fraction) {\
+ ret = (OTYPE)0.0;\
+ } else {\
+ sexponent = 1 - HA2EXPONENT - FRACTION;\
+ dexponent = (OTYPE)sexponent;\
+ ret = (ITYPE)fraction;\
+ ret *= pow##SUFFIX((OTYPE)2.0, dexponent);\
+ }\
+ } else if (exponent + 1 == (ITYPE)1 << EXPONENT) {\
+ ret = (OTYPE)(fraction ? NAN : INFINITY);\
+ } else {\
+ fraction |= (ITYPE)1 << FRACTION;\
+ sexponent = (SITYPE)exponent;\
+ sexponent -= HA2EXPONENT + FRACTION;\
+ dexponent = (OTYPE)sexponent;\
+ ret = (ITYPE)fraction;\
+ ret *= pow##SUFFIX((OTYPE)2.0, dexponent);\
+ }\
+ ret = signb ? -ret : ret;\
+ cache_out[cache_i++] = ret;\
+ cache_i &= 3;\
+ return ret;\
+ } while (0)
+
+#define PROCESS(ITYPE, OTYPE, BITS)\
+ do {\
+ size_t i, n;\
+ ITYPE *ibuf = (ITYPE *)(stream->buf);\
+ OTYPE *obuf = sizeof(ITYPE) == sizeof(OTYPE) ? (OTYPE *)(stream->buf)\
+ : alloca(sizeof(stream->buf) / sizeof(ITYPE) * sizeof(OTYPE));\
+ strict *= !USING_BINARY##BITS;\
+ if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\
+ eprintf("-s is required on this machine\n");\
+ do {\
+ n = stream->ptr / sizeof(ITYPE);\
+ if (strict) {\
+ for (i = 0; i < n; i++)\
+ obuf[i] = conv_##OTYPE(le##BITS##toh(ibuf[i]));\
+ } else {\
+ for (i = 0; i < n; i++)\
+ obuf[i] = *(OTYPE *)&(ITYPE){le##BITS##toh(ibuf[i])};\
+ }\
+ ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE), "<stdout>");\
+ n *= sizeof(ITYPE);\
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
+ } while (eread_stream(stream, SIZE_MAX));\
+ if (stream->ptr)\
+ eprintf("%s: incomplete frame\n", stream->file);\
+ } while (0)
+
+static double conv_double(uint64_t portable) {CONV(uint64_t, int64_t, double, 11, 1023, 52,);}
+static float conv_float (uint32_t portable) {CONV(uint32_t, int32_t, float, 8, 127, 23, f);}
+
+static void process_xyza (struct stream *stream, int strict) {PROCESS(uint64_t, double, 64);}
+static void process_xyzaf(struct stream *stream, int strict) {PROCESS(uint32_t, float, 32);}
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ int strict = 0;
+ void (*process)(struct stream *stream, int strict);
+
+ ARGBEGIN {
+ case 's':
+ strict = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+ if (argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_xyza;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_xyzaf;
+ else
+ eprintf("pixel format %s is not supported\n", stream.pixfmt);
+
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream, strict);
+ return 0;
+}