Use #include instead of #define - blind - suckless command-line video editing utility
 (HTM) git clone git://git.suckless.org/blind
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c216ac3049102422a41ba2c9476b0dbf4f3e4034
 (DIR) parent e0763df25edbc1ec72ab77d0c22fde41f06e9222
 (HTM) Author: Mattias Andrée <maandree@kth.se>
       Date:   Sun, 16 Jul 2017 00:59:42 +0200
       
       Use #include instead of #define
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M Makefile                            |       1 +
         M src/blind-apply-palette.c           |     102 ++++++++++++++++---------------
         M src/blind-chroma-key.c              |     116 ++++++++++++++++---------------
         M src/blind-cone-gradient.c           |     137 ++++++++++++++++---------------
         M src/blind-coordinate-field.c        |      43 +++++++++++++++++--------------
         M src/blind-cross-product.c           |      52 +++++++++++++++++--------------
         M src/blind-dot-product.c             |      42 +++++++++++++++++--------------
         M src/blind-double-sine-wave.c        |      78 ++++++++++++++++---------------
         M src/blind-dual-key.c                |      90 +++++++++++++++++---------------
         M src/blind-extract-alpha.c           |      60 +++++++++++++++++---------------
         M src/blind-invert-matrix.c           |     118 ++++++++++++++++---------------
         M src/blind-linear-gradient.c         |      99 ++++++++++++++++---------------
         M src/blind-matrix-orthoproject.c     |      98 ++++++++++++++++---------------
         M src/blind-matrix-reflect.c          |      94 ++++++++++++++++---------------
         M src/blind-matrix-rotate.c           |      98 ++++++++++++++++---------------
         M src/blind-matrix-scale.c            |      72 +++++++++++++++++--------------
         M src/blind-matrix-shear.c            |      88 +++++++++++++++++--------------
         M src/blind-matrix-translate.c        |      72 +++++++++++++++++--------------
         M src/blind-matrix-transpose.c        |      70 +++++++++++++++++--------------
         M src/blind-multiply-matrices.c       |     106 ++++++++++++++++---------------
         M src/blind-norm.c                    |      70 ++++++++++++++++---------------
         M src/blind-premultiply.c             |      58 +++++++++++++++++--------------
         M src/blind-quaternion-product.c      |      52 +++++++++++++++++--------------
         M src/blind-radial-gradient.c         |     150 ++++++++++++++++---------------
         M src/blind-round-wave.c              |      74 ++++++++++++++++---------------
         M src/blind-sawtooth-wave.c           |      70 ++++++++++++++++---------------
         M src/blind-set-luma.c                |     166 ++++++++++++++++---------------
         M src/blind-sinc-wave.c               |     130 ++++++++++++++++---------------
         M src/blind-sine-wave.c               |      78 ++++++++++++++++---------------
         M src/blind-single-colour.c           |      55 +++++++++++++++++--------------
         M src/blind-spectrum.c                |     234 ++++++++++++++++---------------
         M src/blind-spiral-gradient.c         |     208 ++++++++++++++++---------------
         M src/blind-square-gradient.c         |     112 ++++++++++++++++---------------
         M src/blind-tee.c                     |       4 ----
         M src/blind-time-blur.c               |      81 +++++++++++++++----------------
         M src/blind-to-text.c                 |       2 --
         M src/blind-to-video.c                |     108 ++++++++++++++++---------------
         M src/blind-triangular-wave.c         |      84 ++++++++++++++++---------------
         M src/blind-unpremultiply.c           |      62 ++++++++++++++++---------------
         M src/blind-vector-projection.c       |      74 ++++++++++++++++---------------
         M src/common.h                        |       4 ++++
         A src/define-functions.h              |      13 +++++++++++++
       
       42 files changed, 1850 insertions(+), 1675 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       @@ -112,6 +112,7 @@ COMMON_OBJ =\
        HDR =\
                arg.h\
                common.h\
       +        define-functions.h\
                stream.h\
                util.h\
                util/to.h\
 (DIR) diff --git a/src/blind-apply-palette.c b/src/blind-apply-palette.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("palette-stream")
       @@ -16,55 +17,8 @@ distance_xyz(double x1, double y1, double z1, double a1, double x2, double y2, d
                return sqrt(x2 + y2 + z2 + a2);
        }
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream, struct stream *palette, char *pal)\
       -        {\
       -                size_t i, j, n, m;\
       -                size_t palsiz = palette->width * palette->height;\
       -                size_t best = 0;\
       -                TYPE x, y, z, a, lx = 0, ly = 0, lz = 0, la = 0;\
       -                TYPE cx, cy, cz, ca;\
       -                double distance, best_distance = 0;\
       -                while (eread_frame(palette, pal)) {\
       -                        m = stream->frame_size;\
       -                        do {\
       -                                n = MIN(stream->ptr, m) / stream->pixel_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        x = ((TYPE *)(stream->buf + i * stream->pixel_size))[0];\
       -                                        y = ((TYPE *)(stream->buf + i * stream->pixel_size))[1];\
       -                                        z = ((TYPE *)(stream->buf + i * stream->pixel_size))[2];\
       -                                        a = ((TYPE *)(stream->buf + i * stream->pixel_size))[3];\
       -                                        if ((!i && m == stream->frame_size) || x != lx || y != ly || z != lz || a != la) {\
       -                                                for (j = 0; j < palsiz; j++) {\
       -                                                        cx = ((TYPE *)(pal + j * stream->pixel_size))[0];\
       -                                                        cy = ((TYPE *)(pal + j * stream->pixel_size))[1];\
       -                                                        cz = ((TYPE *)(pal + j * stream->pixel_size))[2];\
       -                                                        ca = ((TYPE *)(pal + j * stream->pixel_size))[3];\
       -                                                        distance = compare((double)x, (double)y, (double)z, (double)a,\
       -                                                                           (double)cx, (double)cy, (double)cz, (double)ca);\
       -                                                        if (!j || distance < best_distance) {\
       -                                                                best_distance = distance;\
       -                                                                best = j;\
       -                                                        }\
       -                                                }\
       -                                                lx = x, ly = y, lz = z, la = a;\
       -                                        }\
       -                                        memcpy(stream->buf + i * stream->pixel_size,\
       -                                               pal + best * stream->pixel_size,\
       -                                               stream->pixel_size);\
       -                                }\
       -                                m -= n *= stream->pixel_size;\
       -                                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                                memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
       -                        } while (m && eread_stream(stream, SIZE_MAX));\
       -                        if (m)\
       -                                eprintf("%s: incomplete frame\n", stream->file);\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-apply-palette.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -101,3 +55,53 @@ main(int argc, char *argv[])
                free(pal);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream, struct stream *palette, char *pal)
       +{
       +        size_t i, j, n, m;
       +        size_t palsiz = palette->width * palette->height;
       +        size_t best = 0;
       +        TYPE x, y, z, a, lx = 0, ly = 0, lz = 0, la = 0;
       +        TYPE cx, cy, cz, ca;
       +        double distance, best_distance = 0;
       +        while (eread_frame(palette, pal)) {
       +                m = stream->frame_size;
       +                do {
       +                        n = MIN(stream->ptr, m) / stream->pixel_size;
       +                        for (i = 0; i < n; i++) {
       +                                x = ((TYPE *)(stream->buf + i * stream->pixel_size))[0];
       +                                y = ((TYPE *)(stream->buf + i * stream->pixel_size))[1];
       +                                z = ((TYPE *)(stream->buf + i * stream->pixel_size))[2];
       +                                a = ((TYPE *)(stream->buf + i * stream->pixel_size))[3];
       +                                if ((!i && m == stream->frame_size) || x != lx || y != ly || z != lz || a != la) {
       +                                        for (j = 0; j < palsiz; j++) {
       +                                                cx = ((TYPE *)(pal + j * stream->pixel_size))[0];
       +                                                cy = ((TYPE *)(pal + j * stream->pixel_size))[1];
       +                                                cz = ((TYPE *)(pal + j * stream->pixel_size))[2];
       +                                                ca = ((TYPE *)(pal + j * stream->pixel_size))[3];
       +                                                distance = compare((double)x, (double)y, (double)z, (double)a,
       +                                                                   (double)cx, (double)cy, (double)cz, (double)ca);
       +                                                if (!j || distance < best_distance) {
       +                                                        best_distance = distance;
       +                                                        best = j;
       +                                                }
       +                                        }
       +                                        lx = x, ly = y, lz = z, la = a;
       +                                }
       +                                memcpy(stream->buf + i * stream->pixel_size,
       +                                       pal + best * stream->pixel_size,
       +                                       stream->pixel_size);
       +                        }
       +                        m -= n *= stream->pixel_size;
       +                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                        memmove(stream->buf, stream->buf + n, stream->ptr -= n);
       +                } while (m && eread_stream(stream, SIZE_MAX));
       +                if (m)
       +                        eprintf("%s: incomplete frame\n", stream->file);
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-chroma-key.c b/src/blind-chroma-key.c
       @@ -1,64 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("key-stream")
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream, struct stream *key)\
       -        {\
       -                size_t i, n, m = 0;\
       -                TYPE x1, y1, z1, a1, a2, variance2, *keyxyza;\
       -                TYPE x, y, z, d;\
       -                do {\
       -                        if (!m) {\
       -                                m = stream->frame_size;\
       -                                while (key->ptr < key->frame_size)\
       -                                        if (!eread_stream(key, key->frame_size - key->ptr))\
       -                                                return;\
       -                                keyxyza = (TYPE *)(key->buf);\
       -                                x1 = keyxyza[0];\
       -                                y1 = keyxyza[1];\
       -                                z1 = keyxyza[2];\
       -                                a1 = keyxyza[3];\
       -                                x = x1 - keyxyza[4];\
       -                                y = y1 - keyxyza[5];\
       -                                z = z1 - keyxyza[6];\
       -                                a2 = keyxyza[7];\
       -                                variance2 = x * x + y * y + z * z;\
       -                                /* TODO add more formulae: https://en.wikipedia.org/wiki/Color_difference */\
       -                                if (a2 > a1) {\
       -                                        a1 = 1 - a1;\
       -                                        a2 = 1 - a2;\
       -                                }\
       -                                memmove(key->buf, key->buf + key->frame_size,\
       -                                        key->ptr -= key->frame_size);\
       -                        }\
       -                        n = MIN(stream->ptr, m) / stream->pixel_size;\
       -                        for (i = 0; i < n; i++) {\
       -                                x = ((TYPE *)(stream->buf))[4 * i + 0] - x1;\
       -                                y = ((TYPE *)(stream->buf))[4 * i + 1] - y1;\
       -                                z = ((TYPE *)(stream->buf))[4 * i + 2] - z1;\
       -                                d = x * x + y * y + z * z;\
       -                                if (d <= variance2) {\
       -                                        if (a1 == a2)\
       -                                                d = 0;\
       -                                        else\
       -                                                d = sqrt(d / variance2) * (a1 - a2) + a2;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] *= d;\
       -                                }\
       -                        }\
       -                        n *= stream->pixel_size;\
       -                        m -= n;\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-chroma-key.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -89,3 +36,60 @@ main(int argc, char *argv[])
                process(&stream, &key);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream, struct stream *key)
       +{
       +        size_t i, n, m = 0;
       +        TYPE x1, y1, z1, a1, a2, variance2, *keyxyza;
       +        TYPE x, y, z, d;
       +        do {
       +                if (!m) {
       +                        m = stream->frame_size;
       +                        while (key->ptr < key->frame_size)
       +                                if (!eread_stream(key, key->frame_size - key->ptr))
       +                                        return;
       +                        keyxyza = (TYPE *)(key->buf);
       +                        x1 = keyxyza[0];
       +                        y1 = keyxyza[1];
       +                        z1 = keyxyza[2];
       +                        a1 = keyxyza[3];
       +                        x = x1 - keyxyza[4];
       +                        y = y1 - keyxyza[5];
       +                        z = z1 - keyxyza[6];
       +                        a2 = keyxyza[7];
       +                        variance2 = x * x + y * y + z * z;
       +                        /* TODO add more formulae: https://en.wikipedia.org/wiki/Color_difference */
       +                        if (a2 > a1) {
       +                                a1 = 1 - a1;
       +                                a2 = 1 - a2;
       +                        }
       +                        memmove(key->buf, key->buf + key->frame_size,
       +                                key->ptr -= key->frame_size);
       +                }
       +                n = MIN(stream->ptr, m) / stream->pixel_size;
       +                for (i = 0; i < n; i++) {
       +                        x = ((TYPE *)(stream->buf))[4 * i + 0] - x1;
       +                        y = ((TYPE *)(stream->buf))[4 * i + 1] - y1;
       +                        z = ((TYPE *)(stream->buf))[4 * i + 2] - z1;
       +                        d = x * x + y * y + z * z;
       +                        if (d <= variance2) {
       +                                if (a1 == a2)
       +                                        d = 0;
       +                                else
       +                                        d = sqrt(d / variance2) * (a1 - a2) + a2;
       +                                ((TYPE *)(stream->buf))[4 * i + 3] *= d;
       +                        }
       +                }
       +                n *= stream->pixel_size;
       +                m -= n;
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-cone-gradient.c b/src/blind-cone-gradient.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-a | -s] -w width -h height")
       @@ -9,69 +10,8 @@ static size_t width = 0;
        static size_t height = 0;
        static int with_multiplier = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
       -                TYPE *params, x1, y1, x2, y2;\
       -                TYPE x, y, u, v, m = 1;\
       -                size_t ix, iy, ptr = 0;\
       -                for (;;) {\
       -                        while (stream->ptr < stream->frame_size) {\
       -                                if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
       -                                        ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
       -                                        return;\
       -                                }\
       -                        }\
       -                        params = (TYPE *)stream->buf;\
       -                        x1 = (params)[0];\
       -                        y1 = (params)[1];\
       -                        x2 = (params)[4];\
       -                        y2 = (params)[5];\
       -                        if (with_multiplier)\
       -                                m = (params)[9];\
       -                        memmove(stream->buf, stream->buf + stream->frame_size,\
       -                                stream->ptr -= stream->frame_size);\
       -                        \
       -                        x2 -= x1;\
       -                        y2 -= y1;\
       -                        u = atan2(y2, x2);\
       -                        \
       -                        for (iy = 0; iy < height; iy++) {\
       -                                y = (TYPE)iy - y1;\
       -                                for (ix = 0; ix < width; ix++) {\
       -                                        x = (TYPE)ix - x1;\
       -                                        if (!x && !y) {\
       -                                                v = 0.5;\
       -                                        } else {\
       -                                                v = atan2(y, x);\
       -                                                v -= u;\
       -                                                v += 2 * (TYPE)M_PI;\
       -                                                v = mod(v, 2 * (TYPE)M_PI);\
       -                                                v /= 2 * (TYPE)M_PI;\
       -                                                if (anticlockwise)\
       -                                                        v = 1 - v;\
       -                                                v *= m;\
       -                                                if (symmetric) {\
       -                                                        v = mod(2 * v, (TYPE)2);\
       -                                                        if (v > 1)\
       -                                                                v = 2 - v;\
       -                                                }\
       -                                        }\
       -                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = v;\
       -                                        if (++ptr == ELEMENTSOF(buf)) {\
       -                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
       -                                                ptr = 0;\
       -                                        }\
       -                                }\
       -                        }\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-cone-gradient.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -81,13 +21,9 @@ main(int argc, char *argv[])
        
                ARGBEGIN {
                case 'a':
       -                if (symmetric)
       -                        usage();
                        anticlockwise = 1;
                        break;
                case 's':
       -                if (anticlockwise)
       -                        usage();
                        symmetric = 1;
                        break;
                case 'w':
       @@ -100,7 +36,7 @@ main(int argc, char *argv[])
                        usage();
                } ARGEND;
        
       -        if (!width || !height || argc)
       +        if (!width || !height || (symmetric && anticlockwise) || argc)
                        usage();
        
                eopen_stream(&stream, NULL);
       @@ -126,3 +62,68 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t buf[BUFSIZ / sizeof(pixel_t)];
       +        TYPE *params, x1, y1, x2, y2;
       +        TYPE x, y, u, v, m = 1;
       +        size_t ix, iy, ptr = 0;
       +
       +        for (;;) {
       +                while (stream->ptr < stream->frame_size) {
       +                        if (!eread_stream(stream, stream->frame_size - stream->ptr)) {
       +                                ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");
       +                                return;
       +                        }
       +                }
       +                params = (TYPE *)stream->buf;
       +                x1 = (params)[0];
       +                y1 = (params)[1];
       +                x2 = (params)[4];
       +                y2 = (params)[5];
       +                if (with_multiplier)
       +                        m = (params)[9];
       +                memmove(stream->buf, stream->buf + stream->frame_size,
       +                        stream->ptr -= stream->frame_size);
       +
       +                x2 -= x1;
       +                y2 -= y1;
       +                u = atan2(y2, x2);
       +
       +                for (iy = 0; iy < height; iy++) {
       +                        y = (TYPE)iy - y1;
       +                        for (ix = 0; ix < width; ix++) {
       +                                x = (TYPE)ix - x1;
       +                                if (!x && !y) {
       +                                        v = 0.5;
       +                                } else {
       +                                        v = atan2(y, x);
       +                                        v -= u;
       +                                        v += 2 * (TYPE)M_PI;
       +                                        v = mod(v, 2 * (TYPE)M_PI);
       +                                        v /= 2 * (TYPE)M_PI;
       +                                        if (anticlockwise)
       +                                                v = 1 - v;
       +                                        v *= m;
       +                                        if (symmetric) {
       +                                                v = mod(2 * v, (TYPE)2);
       +                                                if (v > 1)
       +                                                        v = 2 - v;
       +                                        }
       +                                }
       +                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = v;
       +                                if (++ptr == ELEMENTSOF(buf)) {
       +                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
       +                                        ptr = 0;
       +                                }
       +                        }
       +                }
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-coordinate-field.c b/src/blind-coordinate-field.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-f frames | -f 'inf'] [-F pixel-format] -w width -h height")
       @@ -6,25 +7,8 @@ USAGE("[-f frames | -f 'inf'] [-F pixel-format] -w width -h height")
        static struct stream stream = { .width = 0, .height = 0, .frames = 1 };
        static int inf = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                TYPE buf[4] = {0, 0, 0, 0};\
       -                size_t x, y;\
       -                \
       -                while (inf || stream.frames--) {\
       -                        for (y = 0; y < stream.height; y++) {\
       -                                buf[1] = (TYPE)y;\
       -                                for (x = 0; x < stream.width; x++) {\
       -                                        buf[0] = (TYPE)x;\
       -                                        if (write(STDOUT_FILENO, buf, sizeof(buf)) < 0)\
       -                                                eprintf("write <stdout>:");\
       -                                }\
       -                        }\
       -                }\
       -        } while (0)
       -
       -static void process_lf(void) {PROCESS(double);}
       -static void process_f(void) {PROCESS(float);}
       +#define FILE "blind-coordinate-field.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -75,3 +59,24 @@ main(int argc, char *argv[])
                process();
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(void)
       +{
       +        TYPE buf[4] = {0, 0, 0, 0};
       +        size_t x, y;
       +        while (inf || stream.frames--) {
       +                for (y = 0; y < stream.height; y++) {
       +                        buf[1] = (TYPE)y;
       +                        for (x = 0; x < stream.width; x++) {
       +                                buf[0] = (TYPE)x;
       +                                if (write(STDOUT_FILENO, buf, sizeof(buf)) < 0)
       +                                        eprintf("write <stdout>:");
       +                        }
       +                }
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-cross-product.c b/src/blind-cross-product.c
       @@ -1,32 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("right-hand-stream")
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\
       -        {\
       -                size_t i;\
       -                TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra, x, y, z, a;\
       -                for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\
       -                        lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;\
       -                        ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;\
       -                        lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;\
       -                        la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;\
       -                        x = *ly * *rz - *lz * *ry;\
       -                        y = *lz * *rx - *lx * *rz;\
       -                        z = *lx * *ry - *ly * *rx;\
       -                        a = *la * *ra;\
       -                        *lx = x;\
       -                        *ly = y;\
       -                        *lz = z;\
       -                        *la = a;\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-cross-product.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -51,3 +30,28 @@ main(int argc, char *argv[])
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *left, struct stream *right, size_t n)
       +{
       +        size_t i;
       +        TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra, x, y, z, a;
       +        for (i = 0; i < n; i += 4 * sizeof(TYPE)) {
       +                lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;
       +                ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;
       +                lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;
       +                la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;
       +                x = *ly * *rz - *lz * *ry;
       +                y = *lz * *rx - *lx * *rz;
       +                z = *lx * *ry - *ly * *rx;
       +                a = *la * *ra;
       +                *lx = x;
       +                *ly = y;
       +                *lz = z;
       +                *la = a;
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-dot-product.c b/src/blind-dot-product.c
       @@ -1,27 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("right-hand-stream")
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\
       -        {\
       -                size_t i, j, s = left->n_chan * sizeof(TYPE);\
       -                TYPE v, *l, *r;\
       -                for (i = 0; i < n; i += s) {\
       -                        l = (TYPE *)(left->buf + i);\
       -                        r = (TYPE *)(right->buf + i);\
       -                        v = 0;\
       -                        for (j = 0; j < left->n_chan; j++)\
       -                                v += l[j] * r[j];\
       -                        for (j = 0; j < left->n_chan; j++)\
       -                                l[j] = v;\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-dot-product.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -46,3 +30,23 @@ main(int argc, char *argv[])
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *left, struct stream *right, size_t n)
       +{
       +        size_t i, j, s = left->n_chan * sizeof(TYPE);
       +        TYPE v, *l, *r;
       +        for (i = 0; i < n; i += s) {
       +                l = (TYPE *)(left->buf + i);
       +                r = (TYPE *)(right->buf + i);
       +                v = 0;
       +                for (j = 0; j < left->n_chan; j++)
       +                        v += l[j] * r[j];
       +                for (j = 0; j < left->n_chan; j++)
       +                        l[j] = v;
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-double-sine-wave.c b/src/blind-double-sine-wave.c
       @@ -1,47 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-e]")
        
        static int equal = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, j, n;\
       -                TYPE v, *p;\
       -                do {\
       -                        if (equal) {\
       -                                n = stream->ptr / stream->pixel_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       -                                        v = posmod(*p, (TYPE)2);\
       -                                        v = v > 1 ? 2 - v : v;\
       -                                        v = 1 - (sin(v * (2 * (TYPE)M_PI)) + 1) / 2;\
       -                                        for (j = 0; j < stream->n_chan; j++)\
       -                                                p[j] = v;\
       -                                }\
       -                                n *= stream->pixel_size;\
       -                        } else {\
       -                                n = stream->ptr / stream->chan_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i;\
       -                                        v = posmod(*p, (TYPE)2);\
       -                                        v = v > 1 ? 2 - v : v;\
       -                                        *p = 1 - (sin(v * (2 * (TYPE)M_PI)) + 1) / 2;\
       -                                }\
       -                                n *= stream->chan_size;\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-double-sine-wave.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -74,3 +40,41 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, j, n;
       +        TYPE v, *p;
       +        do {
       +                if (equal) {
       +                        n = stream->ptr / stream->pixel_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i * stream->n_chan;
       +                                v = posmod(*p, (TYPE)2);
       +                                v = v > 1 ? 2 - v : v;
       +                                v = 1 - (sin(v * (2 * (TYPE)M_PI)) + 1) / 2;
       +                                for (j = 0; j < stream->n_chan; j++)
       +                                        p[j] = v;
       +                        }
       +                        n *= stream->pixel_size;
       +                } else {
       +                        n = stream->ptr / stream->chan_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i;
       +                                v = posmod(*p, (TYPE)2);
       +                                v = v > 1 ? 2 - v : v;
       +                                *p = 1 - (sin(v * (2 * (TYPE)M_PI)) + 1) / 2;
       +                        }
       +                        n *= stream->chan_size;
       +                }
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-dual-key.c b/src/blind-dual-key.c
       @@ -1,52 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-m] X Y Z dual-X dual-Y dual-Z dual-stream")
        
        static double X1, Y1, Z1, X2, Y2, Z2;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                size_t i;\
       -                TYPE x1k = (TYPE)X1, y1k = (TYPE)Y1, z1k = (TYPE)Z1;\
       -                TYPE x2k = (TYPE)X2, y2k = (TYPE)Y2, z2k = (TYPE)Z2;\
       -                TYPE x1, y1, z1, a1, x2, y2, z2, a2;\
       -                TYPE alpha, xalpha, yalpha, zalpha;\
       -                for (i = 0; i < n; i += stream->pixel_size) {\
       -                        x1 = ((TYPE *)(stream->buf + i))[0];\
       -                        y1 = ((TYPE *)(stream->buf + i))[1];\
       -                        z1 = ((TYPE *)(stream->buf + i))[2];\
       -                        a1 = ((TYPE *)(stream->buf + i))[3];\
       -                        x2 = ((TYPE *)(dual->buf + i))[0];\
       -                        y2 = ((TYPE *)(dual->buf + i))[1];\
       -                        z2 = ((TYPE *)(dual->buf + i))[2];\
       -                        a2 = ((TYPE *)(dual->buf + i))[3];\
       -                        if (x1 == x2 && y1 == y2 && z1 == z2) {\
       -                                if (a1 != a2)\
       -                                        ((TYPE *)(stream->buf + i))[3] = (a1 + a2) / 2;\
       -                                continue;\
       -                        }\
       -                        xalpha = x1 == x2 ? (TYPE)0 : (x2 - x1 + x1k - x2k) / (x1k - x2k);\
       -                        yalpha = y1 == y2 ? (TYPE)0 : (y2 - y1 + y1k - y2k) / (y1k - y2k);\
       -                        zalpha = z1 == z2 ? (TYPE)0 : (z2 - z1 + z1k - z2k) / (z1k - z2k);\
       -                        alpha = xalpha > yalpha ? xalpha : yalpha;\
       -                        alpha = alpha  > zalpha ? alpha  : zalpha;\
       -                        if (!alpha) {\
       -                                ((TYPE *)(stream->buf + i))[0] = (TYPE)0;\
       -                                ((TYPE *)(stream->buf + i))[1] = (TYPE)0;\
       -                                ((TYPE *)(stream->buf + i))[2] = (TYPE)0;\
       -                                ((TYPE *)(stream->buf + i))[3] = (TYPE)0;\
       -                        } else {\
       -                                ((TYPE *)(stream->buf + i))[0] = ((x1 - x1k + x2 - x2k) / alpha + x1k + x2k) / 2;\
       -                                ((TYPE *)(stream->buf + i))[1] = ((y1 - y1k + y2 - y2k) / alpha + y1k + y2k) / 2;\
       -                                ((TYPE *)(stream->buf + i))[2] = ((z1 - z1k + z2 - z2k) / alpha + z1k + z2k) / 2;\
       -                                ((TYPE *)(stream->buf + i))[3] = (a1 + a2) / 2 * alpha;\
       -                        }\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream, struct stream *dual, size_t n) {PROCESS(double);}
       -static void process_f (struct stream *stream, struct stream *dual, size_t n) {PROCESS(float);}
       +#define FILE "blind-dual-key.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -79,3 +40,48 @@ main(int argc, char *argv[])
                process_two_streams(&stream, &dual, STDOUT_FILENO, "<stdout>", process);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream, struct stream *dual, size_t n)
       +{
       +        size_t i;
       +        TYPE x1k = (TYPE)X1, y1k = (TYPE)Y1, z1k = (TYPE)Z1;
       +        TYPE x2k = (TYPE)X2, y2k = (TYPE)Y2, z2k = (TYPE)Z2;
       +        TYPE x1, y1, z1, a1, x2, y2, z2, a2;
       +        TYPE alpha, xalpha, yalpha, zalpha;
       +        for (i = 0; i < n; i += stream->pixel_size) {
       +                x1 = ((TYPE *)(stream->buf + i))[0];
       +                y1 = ((TYPE *)(stream->buf + i))[1];
       +                z1 = ((TYPE *)(stream->buf + i))[2];
       +                a1 = ((TYPE *)(stream->buf + i))[3];
       +                x2 = ((TYPE *)(dual->buf + i))[0];
       +                y2 = ((TYPE *)(dual->buf + i))[1];
       +                z2 = ((TYPE *)(dual->buf + i))[2];
       +                a2 = ((TYPE *)(dual->buf + i))[3];
       +                if (x1 == x2 && y1 == y2 && z1 == z2) {
       +                        if (a1 != a2)
       +                                ((TYPE *)(stream->buf + i))[3] = (a1 + a2) / 2;
       +                        continue;
       +                }
       +                xalpha = x1 == x2 ? (TYPE)0 : (x2 - x1 + x1k - x2k) / (x1k - x2k);
       +                yalpha = y1 == y2 ? (TYPE)0 : (y2 - y1 + y1k - y2k) / (y1k - y2k);
       +                zalpha = z1 == z2 ? (TYPE)0 : (z2 - z1 + z1k - z2k) / (z1k - z2k);
       +                alpha = xalpha > yalpha ? xalpha : yalpha;
       +                alpha = alpha  > zalpha ? alpha  : zalpha;
       +                if (!alpha) {
       +                        ((TYPE *)(stream->buf + i))[0] = (TYPE)0;
       +                        ((TYPE *)(stream->buf + i))[1] = (TYPE)0;
       +                        ((TYPE *)(stream->buf + i))[2] = (TYPE)0;
       +                        ((TYPE *)(stream->buf + i))[3] = (TYPE)0;
       +                } else {
       +                        ((TYPE *)(stream->buf + i))[0] = ((x1 - x1k + x2 - x2k) / alpha + x1k + x2k) / 2;
       +                        ((TYPE *)(stream->buf + i))[1] = ((y1 - y1k + y2 - y2k) / alpha + y1k + y2k) / 2;
       +                        ((TYPE *)(stream->buf + i))[2] = ((z1 - z1k + z2 - z2k) / alpha + z1k + z2k) / 2;
       +                        ((TYPE *)(stream->buf + i))[3] = (a1 + a2) / 2 * alpha;
       +                }
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-extract-alpha.c b/src/blind-extract-alpha.c
       @@ -1,36 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("colour-file")
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream, int fd, const char *fname)\
       -        {\
       -                char buf[sizeof(stream->buf)];\
       -                size_t i, j, n;\
       -                TYPE a, *p, *b;\
       -                do {\
       -                        n = stream->ptr / stream->pixel_size;\
       -                        p = (TYPE *)(stream->buf) + stream->n_chan - 1;\
       -                        b = (TYPE *)buf;\
       -                        for (i = 0; i < n; i++, p += stream->n_chan) {\
       -                                a = *p, *p = 1;\
       -                                for (j = stream->n_chan - 1; j--;)\
       -                                        *b++ = a;\
       -                                *b++ = 1;\
       -                        }\
       -                        n *= stream->pixel_size;\
       -                        ewriteall(fd, stream->buf, n, fname);\
       -                        ewriteall(STDOUT_FILENO, buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-extract-alpha.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -59,3 +34,32 @@ main(int argc, char *argv[])
                process(&stream, fd, argv[0]);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream, int fd, const char *fname)
       +{
       +        char buf[sizeof(stream->buf)];
       +        size_t i, j, n;
       +        TYPE a, *p, *b;
       +        do {
       +                n = stream->ptr / stream->pixel_size;
       +                p = (TYPE *)(stream->buf) + stream->n_chan - 1;
       +                b = (TYPE *)buf;
       +                for (i = 0; i < n; i++, p += stream->n_chan) {
       +                        a = *p, *p = 1;
       +                        for (j = stream->n_chan - 1; j--;)
       +                                *b++ = a;
       +                        *b++ = 1;
       +                }
       +                n *= stream->pixel_size;
       +                ewriteall(fd, stream->buf, n, fname);
       +                ewriteall(STDOUT_FILENO, buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-invert-matrix.c b/src/blind-invert-matrix.c
       @@ -1,62 +1,20 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("")
        
        static int equal = 0;
        
       -#define SUB_ROWS()\
       -        do {\
       -                p2 = matrix + r2 * cn;\
       -                t = p2[r1][0];\
       -                for (c = 0; c < cn; c++)\
       -                        p2[c][0] -= p1[c][0] * t;\
       -        } while (0)
       -
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                size_t rn = stream->height, r1, r2, c;\
       -                size_t cn = stream->width > rn ? stream->width : 2 * rn;\
       -                pixel_t *matrix = buf, *p1, *p2;\
       -                TYPE t;\
       -                \
       -                for (r1 = 0; r1 < rn; r1++) {\
       -                        p1 = matrix + r1 * cn;\
       -                         if (!p1[r1][0]) {\
       -                                for (r2 = r1 + 1; r2 < rn; r2++) {\
       -                                        p2 = matrix + r2 * cn;\
       -                                        if (p2[r1][0])\
       -                                                break;\
       -                                }\
       -                                if (r2 >= rn)\
       -                                        eprintf("matrix is not invertable\n");\
       -                                for (c = 0; c < cn; c++)\
       -                                        t = p1[c][0], p1[c][0] = p2[c][0], p2[c][0] = t;\
       -                        }\
       -                        t = 1 / p1[r1][0];\
       -                        for (c = 0; c < cn; c++)\
       -                                p1[c][0] *= t;\
       -                        for (r2 = r1 + 1; r2 < rn; r2++)\
       -                                SUB_ROWS();\
       -                }\
       -                \
       -                for (r1 = rn; r1--;) {\
       -                        p1 = matrix + r1 * cn;\
       -                        for (r2 = r1; r2--;)\
       -                                SUB_ROWS();\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream, void *buf) { PROCESS(double); }
       -static void process_f (struct stream *stream, void *buf) { PROCESS(float); }
       +#define FILE "blind-invert-matrix.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
        {
                struct stream stream;
       -        size_t width, x, y, row_size;
       -        char *buf, *one = alloca(4 * sizeof(double)), *p;
       +        size_t width, x, y, i, row_size;
       +        char *buf, *one, *p;
                void (*process)(struct stream *stream, void *buf);
        
                ARGBEGIN {
       @@ -92,9 +50,8 @@ main(int argc, char *argv[])
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
                }
        
       -        memcpy(one + 1 * stream.chan_size, one, stream.chan_size);
       -        memcpy(one + 2 * stream.chan_size, one, stream.chan_size);
       -        memcpy(one + 3 * stream.chan_size, one, stream.chan_size);
       +        for (i = 1; i < stream.n_chan; i++)
       +                memcpy(one + i * stream.chan_size, one, stream.chan_size);
        
                width = stream.width > stream.height ? stream.width : 2 * stream.height;
                buf = emalloc2(width, stream.col_size);
       @@ -109,19 +66,17 @@ main(int argc, char *argv[])
                                }
                        }
                        if (equal) {
       -                        process(&stream, buf + 1 * stream.chan_size);
       +                        process(&stream, buf);
                                for (y = 0; y < stream.height; y++) {
                                        for (x = 0; x < stream.width; x++) {
                                                p = buf + y * row_size + x * stream.pixel_size;
       -                                        memcpy(p, p + stream.chan_size, stream.chan_size);
       -                                        memcpy(p + 2 * stream.chan_size, p, 2 * stream.chan_size);
       +                                        for (i = 1; i < stream.n_chan; i++)
       +                                                memcpy(p + i * stream.chan_size, p, stream.chan_size);
                                        }
                                }
                        } else {
       -                        process(&stream, buf + 0 * stream.chan_size);
       -                        process(&stream, buf + 1 * stream.chan_size);
       -                        process(&stream, buf + 2 * stream.chan_size);
       -                        process(&stream, buf + 3 * stream.chan_size);
       +                        for (i = 0; i < stream.n_chan; i++)
       +                                process(&stream, buf + i * stream.chan_size);
                        }
                        for (y = 0; y < stream.height; y++)
                                ewriteall(STDOUT_FILENO, buf + y * row_size + stream.col_size, row_size - stream.col_size, "<stdout>");
       @@ -130,3 +85,52 @@ main(int argc, char *argv[])
                free(buf);
                return 0;
        }
       +
       +#else
       +
       +#define SUB_ROWS()\
       +        do {\
       +                p2 = matrix + r2 * cn;\
       +                t = p2[r1][0];\
       +                for (c = 0; c < cn; c++)\
       +                        p2[c][0] -= p1[c][0] * t;\
       +        } while (0)
       +
       +static void
       +PROCESS(struct stream *stream, void *buf)
       +{
       +        typedef TYPE pixel_t[4];
       +        size_t rn = stream->height, r1, r2, c;
       +        size_t cn = stream->width > rn ? stream->width : 2 * rn;
       +        pixel_t *matrix = buf, *p1, *p2;
       +        TYPE t;
       +
       +        for (r1 = 0; r1 < rn; r1++) {
       +                p1 = matrix + r1 * cn;
       +                        if (!p1[r1][0]) {
       +                        for (r2 = r1 + 1; r2 < rn; r2++) {
       +                                p2 = matrix + r2 * cn;
       +                                if (p2[r1][0])
       +                                        break;
       +                        }
       +                        if (r2 >= rn)
       +                                eprintf("matrix is not invertable\n");
       +                        for (c = 0; c < cn; c++)
       +                                t = p1[c][0], p1[c][0] = p2[c][0], p2[c][0] = t;
       +                }
       +                t = 1 / p1[r1][0];
       +                for (c = 0; c < cn; c++)
       +                        p1[c][0] *= t;
       +                for (r2 = r1 + 1; r2 < rn; r2++)
       +                        SUB_ROWS();
       +        }
       +
       +        for (r1 = rn; r1--;) {
       +                p1 = matrix + r1 * cn;
       +                for (r2 = r1; r2--;)
       +                        SUB_ROWS();
       +        }
       +}
       +
       +#undef SUB_ROWS
       +#endif
 (DIR) diff --git a/src/blind-linear-gradient.c b/src/blind-linear-gradient.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-b] -w width -h height")
       @@ -7,53 +8,8 @@ static int bilinear = 0;
        static size_t width = 0;
        static size_t height = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
       -                TYPE *params, x1, y1, x2, y2, norm2;\
       -                TYPE x, y;\
       -                size_t ix, iy, ptr = 0;\
       -                for (;;) {\
       -                        while (stream->ptr < stream->frame_size) {\
       -                                if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
       -                                        ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
       -                                        return;\
       -                                }\
       -                        }\
       -                        params = (TYPE *)stream->buf;\
       -                        x1 = (params)[0];\
       -                        y1 = (params)[1];\
       -                        x2 = (params)[4];\
       -                        y2 = (params)[5];\
       -                        memmove(stream->buf, stream->buf + stream->frame_size,\
       -                                stream->ptr -= stream->frame_size);\
       -                        \
       -                        x2 -= x1;\
       -                        y2 -= y1;\
       -                        norm2 = x2 * x2 + y2 * y2;\
       -                        \
       -                        for (iy = 0; iy < height; iy++) {\
       -                                y = (TYPE)iy - y1;\
       -                                for (ix = 0; ix < width; ix++) {\
       -                                        x = (TYPE)ix - x1;\
       -                                        x = (x * x2 + y * y2) / norm2;\
       -                                        if (bilinear)\
       -                                                x = abs(x);\
       -                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
       -                                        if (++ptr == ELEMENTSOF(buf)) {\
       -                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
       -                                                ptr = 0;\
       -                                        }\
       -                                }\
       -                        }\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-linear-gradient.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -97,3 +53,52 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t buf[BUFSIZ / sizeof(pixel_t)];
       +        TYPE *params, x1, y1, x2, y2, norm2;
       +        TYPE x, y;
       +        size_t ix, iy, ptr = 0;
       +
       +        for (;;) {
       +                while (stream->ptr < stream->frame_size) {
       +                        if (!eread_stream(stream, stream->frame_size - stream->ptr)) {
       +                                ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");
       +                                return;
       +                        }
       +                }
       +                params = (TYPE *)stream->buf;
       +                x1 = (params)[0];
       +                y1 = (params)[1];
       +                x2 = (params)[4];
       +                y2 = (params)[5];
       +                memmove(stream->buf, stream->buf + stream->frame_size,
       +                        stream->ptr -= stream->frame_size);
       +
       +                x2 -= x1;
       +                y2 -= y1;
       +                norm2 = x2 * x2 + y2 * y2;
       +
       +                for (iy = 0; iy < height; iy++) {
       +                        y = (TYPE)iy - y1;
       +                        for (ix = 0; ix < width; ix++) {
       +                                x = (TYPE)ix - x1;
       +                                x = (x * x2 + y * y2) / norm2;
       +                                if (bilinear)
       +                                        x = abs(x);
       +                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;
       +                                if (++ptr == ELEMENTSOF(buf)) {
       +                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
       +                                        ptr = 0;
       +                                }
       +                        }
       +                }
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-matrix-orthoproject.c b/src/blind-matrix-orthoproject.c
       @@ -1,56 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-c]")
        
        static int per_channel = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t matrix[9];\
       -                pixel_t buf[2];\
       -                TYPE x2, y2, norm2;\
       -                size_t i;\
       -                \
       -                for (i = 0; i < stream->n_chan; i++) {\
       -                        matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
       -                        matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
       -                        matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       -                }\
       -                \
       -                while (eread_frame(stream, buf)) {\
       -                        if (per_channel) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        x2 = buf[0][i] * buf[0][i];\
       -                                        y2 = buf[1][i] * buf[1][i];\
       -                                        norm2 = x2 + y2;\
       -                                        matrix[0][i] = x2 / norm2;\
       -                                        matrix[4][i] = y2 / norm2;\
       -                                        matrix[3][i] = matrix[1][i] = buf[0][i] * buf[1][i] / norm2;\
       -                                }\
       -                        } else {\
       -                                buf[0][1] *= buf[0][3];\
       -                                buf[1][1] *= buf[1][3];\
       -                                x2 = buf[0][1] * buf[0][1];\
       -                                y2 = buf[1][1] * buf[1][1];\
       -                                norm2 = x2 + y2;\
       -                                matrix[0][0] = x2 / norm2;\
       -                                matrix[4][0] = y2 / norm2;\
       -                                matrix[3][0] = matrix[1][0] = buf[0][1] * buf[1][1] / norm2;\
       -                                for (i = 1; i < stream->n_chan; i++) {\
       -                                        matrix[0][i] = matrix[0][0];\
       -                                        matrix[1][i] = matrix[1][0];\
       -                                        matrix[3][i] = matrix[3][0];\
       -                                        matrix[4][i] = matrix[4][0];\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream) { PROCESS(double); }
       -static void process_f(struct stream *stream) { PROCESS(float); }
       +#define FILE "blind-matrix-orthoproject.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -89,3 +46,52 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t matrix[9];
       +        pixel_t buf[2];
       +        TYPE x2, y2, norm2;
       +        size_t i;
       +
       +        for (i = 0; i < stream->n_chan; i++) {
       +                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;
       +                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;
       +                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;
       +        }
       +
       +        while (eread_frame(stream, buf)) {
       +                if (per_channel) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                x2 = buf[0][i] * buf[0][i];
       +                                y2 = buf[1][i] * buf[1][i];
       +                                norm2 = x2 + y2;
       +                                matrix[0][i] = x2 / norm2;
       +                                matrix[4][i] = y2 / norm2;
       +                                matrix[3][i] = matrix[1][i] = buf[0][i] * buf[1][i] / norm2;
       +                        }
       +                } else {
       +                        buf[0][1] *= buf[0][3];
       +                        buf[1][1] *= buf[1][3];
       +                        x2 = buf[0][1] * buf[0][1];
       +                        y2 = buf[1][1] * buf[1][1];
       +                        norm2 = x2 + y2;
       +                        matrix[0][0] = x2 / norm2;
       +                        matrix[4][0] = y2 / norm2;
       +                        matrix[3][0] = matrix[1][0] = buf[0][1] * buf[1][1] / norm2;
       +                        for (i = 1; i < stream->n_chan; i++) {
       +                                matrix[0][i] = matrix[0][0];
       +                                matrix[1][i] = matrix[1][0];
       +                                matrix[3][i] = matrix[3][0];
       +                                matrix[4][i] = matrix[4][0];
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-matrix-reflect.c b/src/blind-matrix-reflect.c
       @@ -1,54 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-c]")
        
        static int per_channel = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t matrix[9];\
       -                pixel_t buf[2];\
       -                TYPE x2, y2, norm2;\
       -                size_t i;\
       -                \
       -                for (i = 0; i < stream->n_chan; i++) {\
       -                        matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
       -                        matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
       -                        matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       -                }\
       -                \
       -                while (eread_frame(stream, buf)) {\
       -                        if (per_channel) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        x2 = buf[0][i] * buf[0][i];\
       -                                        y2 = buf[1][i] * buf[1][i];\
       -                                        norm2 = x2 + y2;\
       -                                        matrix[4][i] = -(matrix[0][i] = (x2 - y2) / norm2);\
       -                                        matrix[3][i] = matrix[1][i] = 2 * buf[0][i] * buf[1][i] / norm2;\
       -                                }\
       -                        } else {\
       -                                buf[0][1] *= buf[0][3];\
       -                                buf[1][1] *= buf[1][3];\
       -                                x2 = buf[0][1] * buf[0][1];\
       -                                y2 = buf[1][1] * buf[1][1];\
       -                                norm2 = x2 + y2;\
       -                                matrix[4][0] = -(matrix[0][0] = (x2 - y2) / norm2);\
       -                                matrix[3][0] = matrix[1][0] = 2 * buf[0][1] * buf[1][1] / norm2;\
       -                                for (i = 1; i < stream->n_chan; i++) {\
       -                                        matrix[0][i] = matrix[0][0];\
       -                                        matrix[1][i] = matrix[1][0];\
       -                                        matrix[3][i] = matrix[3][0];\
       -                                        matrix[4][i] = matrix[4][0];\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream) { PROCESS(double); }
       -static void process_f(struct stream *stream) { PROCESS(float); }
       +#define FILE "blind-matrix-reflect.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -87,3 +46,50 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t matrix[9];
       +        pixel_t buf[2];
       +        TYPE x2, y2, norm2;
       +        size_t i;
       +
       +        for (i = 0; i < stream->n_chan; i++) {
       +                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;
       +                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;
       +                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;
       +        }
       +
       +        while (eread_frame(stream, buf)) {
       +                if (per_channel) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                x2 = buf[0][i] * buf[0][i];
       +                                y2 = buf[1][i] * buf[1][i];
       +                                norm2 = x2 + y2;
       +                                matrix[4][i] = -(matrix[0][i] = (x2 - y2) / norm2);
       +                                matrix[3][i] = matrix[1][i] = 2 * buf[0][i] * buf[1][i] / norm2;
       +                        }
       +                } else {
       +                        buf[0][1] *= buf[0][3];
       +                        buf[1][1] *= buf[1][3];
       +                        x2 = buf[0][1] * buf[0][1];
       +                        y2 = buf[1][1] * buf[1][1];
       +                        norm2 = x2 + y2;
       +                        matrix[4][0] = -(matrix[0][0] = (x2 - y2) / norm2);
       +                        matrix[3][0] = matrix[1][0] = 2 * buf[0][1] * buf[1][1] / norm2;
       +                        for (i = 1; i < stream->n_chan; i++) {
       +                                matrix[0][i] = matrix[0][0];
       +                                matrix[1][i] = matrix[1][0];
       +                                matrix[3][i] = matrix[3][0];
       +                                matrix[4][i] = matrix[4][0];
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-matrix-rotate.c b/src/blind-matrix-rotate.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-cd]")
       @@ -6,52 +7,8 @@ USAGE("[-cd]")
        static int per_channel = 0;
        static int in_degrees = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t matrix[9];\
       -                pixel_t buf;\
       -                size_t i;\
       -                \
       -                for (i = 0; i < stream->n_chan; i++) {\
       -                        matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
       -                        matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
       -                        matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       -                }\
       -                \
       -                while (eread_frame(stream, buf)) {\
       -                        if (per_channel && in_degrees) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[4][i] = matrix[0][i] = degcos(buf[i]);\
       -                                        matrix[3][i] = -(matrix[1][i] = degsin(buf[i]));\
       -                                }\
       -                        } else if (per_channel) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[4][i] = matrix[0][i] = cos(buf[i]);\
       -                                        matrix[3][i] = -(matrix[1][i] = sin(buf[i]));\
       -                                }\
       -                        } else {\
       -                                buf[1] *= buf[3];\
       -                                if (in_degrees) {\
       -                                        matrix[4][0] = matrix[0][0] = degcos(buf[1]);\
       -                                        matrix[3][0] = -(matrix[1][0] = degsin(buf[1]));\
       -                                } else {\
       -                                        matrix[4][0] = matrix[0][0] = cos(buf[1]);\
       -                                        matrix[3][0] = -(matrix[1][0] = sin(buf[1]));\
       -                                }\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[0][i] = matrix[0][0];\
       -                                        matrix[1][i] = matrix[1][0];\
       -                                        matrix[3][i] = matrix[3][0];\
       -                                        matrix[4][i] = matrix[4][0];\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream) { PROCESS(double); }
       -static void process_f(struct stream *stream) { PROCESS(float); }
       +#define FILE "blind-matrix-rotate.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -93,3 +50,52 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t matrix[9];
       +        pixel_t buf;
       +        size_t i;
       +
       +        for (i = 0; i < stream->n_chan; i++) {
       +                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;
       +                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;
       +                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;
       +        }
       +
       +        while (eread_frame(stream, buf)) {
       +                if (per_channel && in_degrees) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[4][i] = matrix[0][i] = degcos(buf[i]);
       +                                matrix[3][i] = -(matrix[1][i] = degsin(buf[i]));
       +                        }
       +                } else if (per_channel) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[4][i] = matrix[0][i] = cos(buf[i]);
       +                                matrix[3][i] = -(matrix[1][i] = sin(buf[i]));
       +                        }
       +                } else {
       +                        buf[1] *= buf[3];
       +                        if (in_degrees) {
       +                                matrix[4][0] = matrix[0][0] = degcos(buf[1]);
       +                                matrix[3][0] = -(matrix[1][0] = degsin(buf[1]));
       +                        } else {
       +                                matrix[4][0] = matrix[0][0] = cos(buf[1]);
       +                                matrix[3][0] = -(matrix[1][0] = sin(buf[1]));
       +                        }
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[0][i] = matrix[0][0];
       +                                matrix[1][i] = matrix[1][0];
       +                                matrix[3][i] = matrix[3][0];
       +                                matrix[4][i] = matrix[4][0];
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-matrix-scale.c b/src/blind-matrix-scale.c
       @@ -1,43 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-c]")
        
        static int per_channel = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t matrix[9];\
       -                pixel_t buf[2];\
       -                size_t i;\
       -                \
       -                for (i = 0; i < stream->n_chan; i++) {\
       -                        matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
       -                        matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
       -                        matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       -                }\
       -                \
       -                while (eread_frame(stream, buf)) {\
       -                        if (per_channel) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[0][i] = buf[0][i];\
       -                                        matrix[4][i] = buf[1][i];\
       -                                }\
       -                        } else {\
       -                                buf[0][1] *= buf[0][3];\
       -                                buf[1][1] *= buf[1][3];\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[0][i] = buf[0][1];\
       -                                        matrix[4][i] = buf[1][1];\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream) { PROCESS(double); }
       -static void process_f(struct stream *stream) { PROCESS(float); }
       +#define FILE "blind-matrix-scale.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -76,3 +46,39 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t matrix[9];
       +        pixel_t buf[2];
       +        size_t i;
       +
       +        for (i = 0; i < stream->n_chan; i++) {
       +                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;
       +                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;
       +                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;
       +        }
       +
       +        while (eread_frame(stream, buf)) {
       +                if (per_channel) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[0][i] = buf[0][i];
       +                                matrix[4][i] = buf[1][i];
       +                        }
       +                } else {
       +                        buf[0][1] *= buf[0][3];
       +                        buf[1][1] *= buf[1][3];
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[0][i] = buf[0][1];
       +                                matrix[4][i] = buf[1][1];
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-matrix-shear.c b/src/blind-matrix-shear.c
       @@ -1,52 +1,15 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
       -USAGE("[-a [-d]][c]")
       +USAGE("[-a [-d]] [-c]")
        
        static int by_angle = 0;
        static int per_channel = 0;
        static int in_degrees = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t matrix[9];\
       -                pixel_t buf[2];\
       -                TYPE conv = in_degrees ? (TYPE)(M_PI / 180.) : 1;\
       -                size_t i;\
       -                \
       -                for (i = 0; i < stream->n_chan; i++) {\
       -                        matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
       -                        matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
       -                        matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       -                }\
       -                \
       -                while (eread_frame(stream, buf)) {\
       -                        if (by_angle) {\
       -                                for (i = !per_channel; i < (per_channel ? stream->n_chan : 2); i++) {\
       -                                        buf[0][i] = tan(buf[0][i] * conv);\
       -                                        buf[1][i] = tan(buf[1][i] * conv);\
       -                                }\
       -                        }\
       -                        if (per_channel) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[1][i] = buf[0][i];\
       -                                        matrix[3][i] = buf[1][i];\
       -                                }\
       -                        } else {\
       -                                buf[0][1] *= buf[0][3];\
       -                                buf[1][1] *= buf[1][3];\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[1][i] = buf[0][1];\
       -                                        matrix[3][i] = buf[1][1];\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream) { PROCESS(double); }
       -static void process_f(struct stream *stream) { PROCESS(float); }
       +#define FILE "blind-matrix-shear.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -91,3 +54,46 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t matrix[9];
       +        pixel_t buf[2];
       +        TYPE conv = in_degrees ? (TYPE)(M_PI / 180.) : 1;
       +        size_t i;
       +
       +        for (i = 0; i < stream->n_chan; i++) {
       +                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;
       +                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;
       +                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;
       +        }
       +
       +        while (eread_frame(stream, buf)) {
       +                if (by_angle) {
       +                        for (i = !per_channel; i < (per_channel ? stream->n_chan : 2); i++) {
       +                                buf[0][i] = tan(buf[0][i] * conv);
       +                                buf[1][i] = tan(buf[1][i] * conv);
       +                        }
       +                }
       +                if (per_channel) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[1][i] = buf[0][i];
       +                                matrix[3][i] = buf[1][i];
       +                        }
       +                } else {
       +                        buf[0][1] *= buf[0][3];
       +                        buf[1][1] *= buf[1][3];
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[1][i] = buf[0][1];
       +                                matrix[3][i] = buf[1][1];
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-matrix-translate.c b/src/blind-matrix-translate.c
       @@ -1,43 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-c]")
        
        static int per_channel = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t matrix[9];\
       -                pixel_t buf[2];\
       -                size_t i;\
       -                \
       -                for (i = 0; i < stream->n_chan; i++) {\
       -                        matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
       -                        matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
       -                        matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       -                }\
       -                \
       -                while (eread_frame(stream, buf)) {\
       -                        if (per_channel) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[2][i] = buf[0][i];\
       -                                        matrix[5][i] = buf[1][i];\
       -                                }\
       -                        } else {\
       -                                buf[0][1] *= buf[0][3];\
       -                                buf[1][1] *= buf[1][3];\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[2][i] = buf[0][1];\
       -                                        matrix[5][i] = buf[1][1];\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream) { PROCESS(double); }
       -static void process_f(struct stream *stream) { PROCESS(float); }
       +#define FILE "blind-matrix-translate.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -76,3 +46,39 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t matrix[9];
       +        pixel_t buf[2];
       +        size_t i;
       +
       +        for (i = 0; i < stream->n_chan; i++) {
       +                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;
       +                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;
       +                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;
       +        }
       +
       +        while (eread_frame(stream, buf)) {
       +                if (per_channel) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[2][i] = buf[0][i];
       +                                matrix[5][i] = buf[1][i];
       +                        }
       +                } else {
       +                        buf[0][1] *= buf[0][3];
       +                        buf[1][1] *= buf[1][3];
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[2][i] = buf[0][1];
       +                                matrix[5][i] = buf[1][1];
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-matrix-transpose.c b/src/blind-matrix-transpose.c
       @@ -1,42 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-c]")
        
        static int per_channel = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t matrix[9];\
       -                pixel_t buf;\
       -                size_t i;\
       -                \
       -                for (i = 0; i < stream->n_chan; i++) {\
       -                        matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
       -                        matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
       -                        matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       -                }\
       -                \
       -                while (eread_frame(stream, buf)) {\
       -                        if (per_channel) {\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[3][i] = matrix[1][i] = buf[i];\
       -                                        matrix[4][i] = matrix[0][i] = 1 - buf[i];\
       -                                }\
       -                        } else {\
       -                                buf[1] *= buf[3];\
       -                                for (i = 0; i < stream->n_chan; i++) {\
       -                                        matrix[3][i] = matrix[1][i] = buf[1];\
       -                                        matrix[4][i] = matrix[0][i] = 1 - matrix[3][i];\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream) { PROCESS(double); }
       -static void process_f(struct stream *stream) { PROCESS(float); }
       +#define FILE "blind-matrix-transpose.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -75,3 +46,38 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t matrix[9];
       +        pixel_t buf;
       +        size_t i;
       +
       +        for (i = 0; i < stream->n_chan; i++) {
       +                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;
       +                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;
       +                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;
       +        }
       +
       +        while (eread_frame(stream, buf)) {
       +                if (per_channel) {
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[3][i] = matrix[1][i] = buf[i];
       +                                matrix[4][i] = matrix[0][i] = 1 - buf[i];
       +                        }
       +                } else {
       +                        buf[1] *= buf[3];
       +                        for (i = 0; i < stream->n_chan; i++) {
       +                                matrix[3][i] = matrix[1][i] = buf[1];
       +                                matrix[4][i] = matrix[0][i] = 1 - matrix[3][i];
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-multiply-matrices.c b/src/blind-multiply-matrices.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-en] leftmost-stream ... rightmost-stream")
       @@ -6,56 +7,8 @@ USAGE("[-en] leftmost-stream ... rightmost-stream")
        static int equal = 0;
        static size_t max_frame_size;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t *res, *left, *right, *tmp;\
       -                size_t i, j, w, h, h2, x, y, k, r;\
       -                res = emalloc(max_frame_size);\
       -                left = emalloc(max_frame_size);\
       -                right = emalloc(max_frame_size);\
       -                \
       -                while (eread_frame(streams + (n_streams - 1), res)) {\
       -                        w = streams[n_streams - 1].width;\
       -                        h = streams[n_streams - 1].height;\
       -                        for (i = n_streams - 1; i--;) {\
       -                                tmp = res, res = right, right = tmp;\
       -                                if (!eread_frame(streams + i, left))\
       -                                        goto done;\
       -                                h2 = streams[i].height;\
       -                                memset(res, 0, w * h2 * streams->pixel_size);\
       -                                \
       -                                /* XXX Is there any significant performance to be gained by transposing `right`? */\
       -                                if (equal) {\
       -                                        for (y = r = 0; y < h2; y++) {\
       -                                                for (x = 0; x < w; x++, r++) {\
       -                                                        for (k = 0; k < h; k++) \
       -                                                                res[r][0] += left[y * h + k][0] * right[k * w + x][0];\
       -                                                        for (j = 1; j < streams->n_chan; j++)\
       -                                                                res[r][j] = res[r][0];\
       -                                                }\
       -                                        }\
       -                                } else {\
       -                                        for (y = r = 0; y < h2; y++)\
       -                                                for (x = 0; x < w; x++, r++) \
       -                                                        for (k = 0; k < h; k++)\
       -                                                                for (j = 0; j < streams->n_chan; j++)\
       -                                                                        res[r][j] += left[y * h + k][j] * right[k * w + x][j];\
       -                                }\
       -                                \
       -                                h = h2;\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, res, streams->frame_size, "<stdout>");\
       -                }\
       -                \
       -        done:\
       -                free(res);\
       -                free(left);\
       -                free(right);\
       -        } while (0)
       -
       -static void process_lf(struct stream *streams, size_t n_streams) { PROCESS(double); }
       -static void process_f (struct stream *streams, size_t n_streams) { PROCESS(float); }
       +#define FILE "blind-multiply-matrices.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -137,3 +90,56 @@ main(int argc, char *argv[])
                free(streams);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *streams, size_t n_streams)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t *res, *left, *right, *tmp;
       +        size_t i, j, w, h, h2, x, y, k, r;
       +        res = emalloc(max_frame_size);
       +        left = emalloc(max_frame_size);
       +        right = emalloc(max_frame_size);
       +
       +        while (eread_frame(streams + (n_streams - 1), res)) {
       +                w = streams[n_streams - 1].width;
       +                h = streams[n_streams - 1].height;
       +                for (i = n_streams - 1; i--;) {
       +                        tmp = res, res = right, right = tmp;
       +                        if (!eread_frame(streams + i, left))
       +                                goto done;
       +                        h2 = streams[i].height;
       +                        memset(res, 0, w * h2 * streams->pixel_size);
       +
       +                        /* XXX Is there any significant performance to be gained by transposing `right`? */
       +                        if (equal) {
       +                                for (y = r = 0; y < h2; y++) {
       +                                        for (x = 0; x < w; x++, r++) {
       +                                                for (k = 0; k < h; k++)
       +                                                        res[r][0] += left[y * h + k][0] * right[k * w + x][0];
       +                                                for (j = 1; j < streams->n_chan; j++)
       +                                                        res[r][j] = res[r][0];
       +                                        }
       +                                }
       +                        } else {
       +                                for (y = r = 0; y < h2; y++)
       +                                        for (x = 0; x < w; x++, r++)
       +                                                for (k = 0; k < h; k++)
       +                                                        for (j = 0; j < streams->n_chan; j++)
       +                                                                res[r][j] += left[y * h + k][j] * right[k * w + x][j];
       +                        }
       +
       +                        h = h2;
       +                }
       +                ewriteall(STDOUT_FILENO, res, streams->frame_size, "<stdout>");
       +        }
       +
       +done:
       +        free(res);
       +        free(left);
       +        free(right);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-norm.c b/src/blind-norm.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-axyz]")
       @@ -8,39 +9,8 @@ static int skip_x = 0;
        static int skip_y = 0;
        static int skip_z = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, n;\
       -                TYPE x, y, z, a, norm;\
       -                do {\
       -                        n = stream->ptr / stream->pixel_size;\
       -                        for (i = 0; i < n; i++) {\
       -                                x = ((TYPE *)(stream->buf))[4 * i + 0];\
       -                                y = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                z = ((TYPE *)(stream->buf))[4 * i + 2];\
       -                                a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                norm = sqrt(x * x + y * y + z * z + a * a);\
       -                                if (!skip_x)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = norm;\
       -                                if (!skip_y)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = norm;\
       -                                if (!skip_z)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = norm;\
       -                                if (!skip_a)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = norm;\
       -                        }\
       -                        n *= stream->pixel_size;\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-norm.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -82,3 +52,37 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, n;
       +        TYPE x, y, z, a, norm;\
       +        do {
       +                n = stream->ptr / stream->pixel_size;
       +                for (i = 0; i < n; i++) {
       +                        x = ((TYPE *)(stream->buf))[4 * i + 0];
       +                        y = ((TYPE *)(stream->buf))[4 * i + 1];
       +                        z = ((TYPE *)(stream->buf))[4 * i + 2];
       +                        a = ((TYPE *)(stream->buf))[4 * i + 3];
       +                        norm = sqrt(x * x + y * y + z * z + a * a);
       +                        if (!skip_x)
       +                                ((TYPE *)(stream->buf))[4 * i + 0] = norm;
       +                        if (!skip_y)
       +                                ((TYPE *)(stream->buf))[4 * i + 1] = norm;
       +                        if (!skip_z)
       +                                ((TYPE *)(stream->buf))[4 * i + 2] = norm;
       +                        if (!skip_a)
       +                                ((TYPE *)(stream->buf))[4 * i + 3] = norm;
       +                }
       +                n *= stream->pixel_size;
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-premultiply.c b/src/blind-premultiply.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-xyz]")
       @@ -7,33 +8,8 @@ static int skip_x = 0;
        static int skip_y = 0;
        static int skip_z = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, n;\
       -                TYPE a;\
       -                do {\
       -                        n = stream->ptr / stream->pixel_size;\
       -                        for (i = 0; i < n; i++) {\
       -                                a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                if (!skip_x)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] *= a;\
       -                                if (!skip_y)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] *= a;\
       -                                if (!skip_z)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] *= a;\
       -                        }\
       -                        n *= stream->pixel_size;\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-premultiply.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -72,3 +48,31 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, n;
       +        TYPE a;
       +        do {
       +                n = stream->ptr / stream->pixel_size;
       +                for (i = 0; i < n; i++) {
       +                        a = ((TYPE *)(stream->buf))[4 * i + 3];
       +                        if (!skip_x)
       +                                ((TYPE *)(stream->buf))[4 * i + 0] *= a;
       +                        if (!skip_y)
       +                                ((TYPE *)(stream->buf))[4 * i + 1] *= a;
       +                        if (!skip_z)
       +                                ((TYPE *)(stream->buf))[4 * i + 2] *= a;
       +                }
       +                n *= stream->pixel_size;
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-quaternion-product.c b/src/blind-quaternion-product.c
       @@ -1,32 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("right-hand-stream")
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\
       -        {\
       -                size_t i;\
       -                TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra, x, y, z, a;\
       -                for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\
       -                        lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;\
       -                        ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;\
       -                        lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;\
       -                        la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;\
       -                        x = *lx * *rx - *ly * *ry - *lz * *rz - *la * *ra;\
       -                        y = *lz * *ra - *la * *rz + *lx * *ry + *ly * *rx;\
       -                        z = *la * *ry - *ly * *rz + *lx * *rz + *lz * *rx;\
       -                        a = *ly * *rz - *lz * *rz + *lx * *ra + *la * *rx;\
       -                        *lx = x;\
       -                        *ly = y;\
       -                        *lz = z;\
       -                        *la = a;\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-quaternion-product.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -51,3 +30,28 @@ main(int argc, char *argv[])
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *left, struct stream *right, size_t n)
       +{
       +        size_t i;
       +        TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra, x, y, z, a;
       +        for (i = 0; i < n; i += 4 * sizeof(TYPE)) {
       +                lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;
       +                ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;
       +                lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;
       +                la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;
       +                x = *lx * *rx - *ly * *ry - *lz * *rz - *la * *ra;
       +                y = *lz * *ra - *la * *rz + *lx * *ry + *ly * *rx;
       +                z = *la * *ry - *ly * *rz + *lx * *rz + *lz * *rx;
       +                a = *ly * *rz - *lz * *rz + *lx * *ra + *la * *rx;
       +                *lx = x;
       +                *ly = y;
       +                *lz = z;
       +                *la = a;
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-radial-gradient.c b/src/blind-radial-gradient.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("-w width -h height")
       @@ -7,79 +8,8 @@ static size_t width = 0;
        static size_t height = 0;
        static int with_params;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
       -                TYPE *params, x1, y1, x2, y2, norm, rd = 1, pe = 2, re = 2, e = 0.5;\
       -                TYPE x, y, p, r, rx, ry;\
       -                size_t ix, iy, ptr = 0;\
       -                for (;;) {\
       -                        while (stream->ptr < stream->frame_size) {\
       -                                if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
       -                                        ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
       -                                        return;\
       -                                }\
       -                        }\
       -                        params = (TYPE *)stream->buf;\
       -                        x1 = (params)[0];\
       -                        y1 = (params)[1];\
       -                        x2 = (params)[4];\
       -                        y2 = (params)[5];\
       -                        if (with_params) {\
       -                                pe = (params)[8];\
       -                                re = (params)[9];\
       -                                rd = (params)[10];\
       -                                e = 1 / sqrt(pe * re);\
       -                        }\
       -                        memmove(stream->buf, stream->buf + stream->frame_size,\
       -                                stream->ptr -= stream->frame_size);\
       -                        \
       -                        x2 -= x1;\
       -                        y2 -= y1;\
       -                        norm = sqrt(x2 * x2 + y2 * y2);\
       -                        \
       -                        if (!with_params) {\
       -                                for (iy = 0; iy < height; iy++) {\
       -                                        y = (TYPE)iy - y1;\
       -                                        y *= y;\
       -                                        for (ix = 0; ix < width; ix++) {\
       -                                                x = (TYPE)ix - x1;\
       -                                                x = sqrt(x * x + y) / norm;\
       -                                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
       -                                                if (++ptr == ELEMENTSOF(buf)) {\
       -                                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
       -                                                        ptr = 0;\
       -                                                }\
       -                                        }\
       -                                }\
       -                        } else {\
       -                                for (iy = 0; iy < height; iy++) {\
       -                                        y = (TYPE)iy - y1;\
       -                                        for (ix = 0; ix < width; ix++) {\
       -                                                x = (TYPE)ix - x1;\
       -                                                p = (x * x2 + y * y2) / norm;\
       -                                                rx = x - p * x2 / norm;\
       -                                                ry = y - p * y2 / norm;\
       -                                                r = sqrt(rx * rx + ry * ry) / rd;\
       -                                                p = pow(abs(p / norm), pe);\
       -                                                r = pow(abs(r / norm), re);\
       -                                                x = pow(p + r, e);\
       -                                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
       -                                                if (++ptr == ELEMENTSOF(buf)) {\
       -                                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
       -                                                        ptr = 0;\
       -                                                }\
       -                                        }\
       -                                }\
       -                        }\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-radial-gradient.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -124,3 +54,77 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t buf[BUFSIZ / sizeof(pixel_t)];
       +        TYPE *params, x1, y1, x2, y2, norm, rd = 1, pe = 2, re = 2, e = 0.5;
       +        TYPE x, y, p, r, rx, ry;
       +        size_t ix, iy, ptr = 0;
       +        for (;;) {
       +                while (stream->ptr < stream->frame_size) {
       +                        if (!eread_stream(stream, stream->frame_size - stream->ptr)) {
       +                                ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");
       +                                return;
       +                        }
       +                }
       +                params = (TYPE *)stream->buf;
       +                x1 = (params)[0];
       +                y1 = (params)[1];
       +                x2 = (params)[4];
       +                y2 = (params)[5];
       +                if (with_params) {
       +                        pe = (params)[8];
       +                        re = (params)[9];
       +                        rd = (params)[10];
       +                        e = 1 / sqrt(pe * re);
       +                }
       +                memmove(stream->buf, stream->buf + stream->frame_size,
       +                        stream->ptr -= stream->frame_size);
       +
       +                x2 -= x1;
       +                y2 -= y1;
       +                norm = sqrt(x2 * x2 + y2 * y2);
       +
       +                if (!with_params) {
       +                        for (iy = 0; iy < height; iy++) {
       +                                y = (TYPE)iy - y1;
       +                                y *= y;
       +                                for (ix = 0; ix < width; ix++) {
       +                                        x = (TYPE)ix - x1;
       +                                        x = sqrt(x * x + y) / norm;
       +                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;
       +                                        if (++ptr == ELEMENTSOF(buf)) {
       +                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
       +                                                ptr = 0;
       +                                        }
       +                                }
       +                        }
       +                } else {
       +                        for (iy = 0; iy < height; iy++) {
       +                                y = (TYPE)iy - y1;
       +                                for (ix = 0; ix < width; ix++) {
       +                                        x = (TYPE)ix - x1;
       +                                        p = (x * x2 + y * y2) / norm;
       +                                        rx = x - p * x2 / norm;
       +                                        ry = y - p * y2 / norm;
       +                                        r = sqrt(rx * rx + ry * ry) / rd;
       +                                        p = pow(abs(p / norm), pe);
       +                                        r = pow(abs(r / norm), re);
       +                                        x = pow(p + r, e);
       +                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;
       +                                        if (++ptr == ELEMENTSOF(buf)) {
       +                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
       +                                                ptr = 0;
       +                                        }
       +                                }
       +                        }
       +                }
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-round-wave.c b/src/blind-round-wave.c
       @@ -1,45 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-e]")
        
        static int equal = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, j, n;\
       -                TYPE v, *p;\
       -                do {\
       -                        if (equal) {\
       -                                n = stream->ptr / stream->pixel_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       -                                        v = posmod(*p + 1, (TYPE)4) - 1;\
       -                                        v = v < 1 ? 1 - v * v / 2 : (v - 2) * (v - 2) / 2;\
       -                                        for (j = 0; j < stream->n_chan; j++)\
       -                                                p[j] = v;\
       -                                }\
       -                                n *= stream->pixel_size;\
       -                        } else {\
       -                                n = stream->ptr / stream->chan_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i;\
       -                                        v = posmod(*p + 1, (TYPE)4) - 1;\
       -                                        *p = v < 1 ? 1 - v * v / 2 : (v - 2) * (v - 2) / 2;\
       -                                }\
       -                                n *= stream->chan_size;\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-round-wave.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -72,3 +40,39 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, j, n;
       +        TYPE v, *p;
       +        do {
       +                if (equal) {
       +                        n = stream->ptr / stream->pixel_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i * stream->n_chan;
       +                                v = posmod(*p + 1, (TYPE)4) - 1;
       +                                v = v < 1 ? 1 - v * v / 2 : (v - 2) * (v - 2) / 2;
       +                                for (j = 0; j < stream->n_chan; j++)
       +                                        p[j] = v;
       +                        }
       +                        n *= stream->pixel_size;
       +                } else {
       +                        n = stream->ptr / stream->chan_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i;
       +                                v = posmod(*p + 1, (TYPE)4) - 1;
       +                                *p = v < 1 ? 1 - v * v / 2 : (v - 2) * (v - 2) / 2;
       +                        }
       +                        n *= stream->chan_size;
       +                }
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-sawtooth-wave.c b/src/blind-sawtooth-wave.c
       @@ -1,43 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-e]")
        
        static int equal = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, j, n;\
       -                TYPE v, *p;\
       -                do {\
       -                        if (equal) {\
       -                                n = stream->ptr / stream->pixel_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       -                                        v = posmod(*p, (TYPE)1);\
       -                                        for (j = 0; j < stream->n_chan; j++)\
       -                                                p[j] = v;\
       -                                }\
       -                                n *= stream->pixel_size;\
       -                        } else {\
       -                                n = stream->ptr / stream->chan_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i;\
       -                                        *p = posmod(*p, (TYPE)1);\
       -                                }\
       -                                n *= stream->chan_size;\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-sawtooth-wave.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -70,3 +40,37 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, j, n;
       +        TYPE v, *p;
       +        do {
       +                if (equal) {
       +                        n = stream->ptr / stream->pixel_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i * stream->n_chan;
       +                                v = posmod(*p, (TYPE)1);
       +                                for (j = 0; j < stream->n_chan; j++)
       +                                        p[j] = v;
       +                        }
       +                        n *= stream->pixel_size;
       +                } else {
       +                        n = stream->ptr / stream->chan_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i;
       +                                *p = posmod(*p, (TYPE)1);
       +                        }
       +                        n *= stream->chan_size;
       +                }
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-set-luma.c b/src/blind-set-luma.c
       @@ -1,86 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("luma-stream")
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                size_t i;\
       -                TYPE a, y;\
       -                for (i = 0; i < n; i += colour->pixel_size) {\
       -                        a = ((TYPE *)(luma->buf + i))[1];\
       -                        a *= ((TYPE *)(luma->buf + i))[3];\
       -                        y = ((TYPE *)(colour->buf + i))[1];\
       -                        ((TYPE *)(colour->buf + i))[0] += y * a - y;\
       -                        ((TYPE *)(colour->buf + i))[1]  = y * a;\
       -                        ((TYPE *)(colour->buf + i))[2] += y * a - y;\
       -                        /*
       -                         * Note, this changes the luma only, not the saturation,
       -                         * so the result may look a bit weird. To change both
       -                         * you can use `blind-arithm mul`.
       -                         * 
       -                         * Explaination of algorithm:
       -                         * 
       -                         *   Y is the luma, but (X, Z) is not the chroma,
       -                         *   but in CIELAB, L* is the luma and (a*, *b) is
       -                         *   the chroma. Multiplying
       -                         *   
       -                         *      ⎛0 1   0⎞
       -                         *      ⎜1 −1  0⎟
       -                         *      ⎝0  1 −1⎠
       -                         *   
       -                         *   (X Y Z)' gives a colour model similar to
       -                         *   CIE L*a*b*: a model where each parameter is
       -                         *   a linear transformation of the corresponding
       -                         *   parameter in CIE L*a*b*. The inverse of that
       -                         *   matrix is
       -                         *   
       -                         *      ⎛1 1  0⎞
       -                         *      ⎜1 0  0⎟
       -                         *      ⎝0 0 −1⎠
       -                         *   
       -                         *   and
       -                         *   
       -                         *      ⎛1 1  0⎞⎛a 0 0⎞⎛0 1   0⎞   ⎛1 a−1 0⎞
       -                         *      ⎜1 0  0⎟⎜0 1 0⎟⎜1 −1  0⎟ = ⎜0  a  0⎟.
       -                         *      ⎝0 0 −1⎠⎝0 0 1⎠⎝0  1 −1⎠   ⎝0 a−1 1⎠
       -                         * 
       -                         * Explanation of why changing only the luma looks weird:
       -                         * 
       -                         *   Consider when you are workings with colours,
       -                         *   when you want to change the brightness of a
       -                         *   colour, you multiply all parameters: red, green,
       -                         *   and blue, with the same value (this is however
       -                         *   only an approximation in most cases, since you
       -                         *   are usually usally working with colours that
       -                         *   have the sRGB transfer function applied to their
       -                         *   parameters). This action is the same in all
       -                         *   colour models and colour spaces that are a
       -                         *   linear transformation of the sRGB colour spaces
       -                         *   (sans transfer function); this is simply because
       -                         *   of the properties of linear transformations.
       -                         * 
       -                         *   The reason you change brightness this way can
       -                         *   be explained by how objects reflect colour.
       -                         *   Objects can only reject colours that are present
       -                         *   in the light source. A ideal white object will look
       -                         *   pure red if the light sources is ideal red, and a
       -                         *   a ideal blue object will pure black in the same
       -                         *   light source. An object can also not reflect
       -                         *   colours brighter than the source. When the brightness
       -                         *   of a light source is changed, the intensity of all
       -                         *   colours (by wavelength) it emits is multiplied by
       -                         *   one value. Therefore, when changing the brightness
       -                         *   it looks most natural when all primaries (red, green,
       -                         *   and blue) are multiplied by one value, or all
       -                         *   parameters of the used colour spaces is a linear
       -                         *   transformation of sRGB, such as CIE XYZ.
       -                         */\
       -                }\
       -        } while (0)
       -
       -static void process_xyza (struct stream *colour, struct stream *luma, size_t n) {PROCESS(double);}
       -static void process_xyzaf(struct stream *colour, struct stream *luma, size_t n) {PROCESS(float);}
       +#define FILE "blind-set-luma.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -94,9 +19,9 @@ main(int argc, char *argv[])
                eopen_stream(&luma, argv[0]);
        
                if (!strcmp(colour.pixfmt, "xyza"))
       -                process = process_xyza;
       +                process = process_lf;
                else if (!strcmp(colour.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +                process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt);
        
       @@ -105,3 +30,84 @@ main(int argc, char *argv[])
                process_two_streams(&colour, &luma, STDOUT_FILENO, "<stdout>", process);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *colour, struct stream *luma, size_t n)
       +{\
       +        size_t i;
       +        TYPE a, y;
       +        for (i = 0; i < n; i += colour->pixel_size) {
       +                a = ((TYPE *)(luma->buf + i))[1];
       +                a *= ((TYPE *)(luma->buf + i))[3];
       +                y = ((TYPE *)(colour->buf + i))[1];
       +                ((TYPE *)(colour->buf + i))[0] += y * a - y;
       +                ((TYPE *)(colour->buf + i))[1]  = y * a;
       +                ((TYPE *)(colour->buf + i))[2] += y * a - y;
       +                /*
       +                 * Note, this changes the luma only, not the saturation,
       +                 * so the result may look a bit weird. To change both
       +                 * you can use `blind-arithm mul`.
       +                 * 
       +                 * Explaination of algorithm:
       +                 * 
       +                 *   Y is the luma, but (X, Z) is not the chroma,
       +                 *   but in CIELAB, L* is the luma and (a*, *b) is
       +                 *   the chroma. Multiplying
       +                 *   
       +                 *      ⎛0 1   0⎞
       +                 *      ⎜1 −1  0⎟
       +                 *      ⎝0  1 −1⎠
       +                 *   
       +                 *   (X Y Z)' gives a colour model similar to
       +                 *   CIE L*a*b*: a model where each parameter is
       +                 *   a linear transformation of the corresponding
       +                 *   parameter in CIE L*a*b*. The inverse of that
       +                 *   matrix is
       +                 *   
       +                 *      ⎛1 1  0⎞
       +                 *      ⎜1 0  0⎟
       +                 *      ⎝0 0 −1⎠
       +                 *   
       +                 *   and
       +                 *   
       +                 *      ⎛1 1  0⎞⎛a 0 0⎞⎛0 1   0⎞   ⎛1 a−1 0⎞
       +                 *      ⎜1 0  0⎟⎜0 1 0⎟⎜1 −1  0⎟ = ⎜0  a  0⎟.
       +                 *      ⎝0 0 −1⎠⎝0 0 1⎠⎝0  1 −1⎠   ⎝0 a−1 1⎠
       +                 * 
       +                 * Explanation of why changing only the luma looks weird:
       +                 * 
       +                 *   Consider when you are workings with colours,
       +                 *   when you want to change the brightness of a
       +                 *   colour, you multiply all parameters: red, green,
       +                 *   and blue, with the same value (this is however
       +                 *   only an approximation in most cases, since you
       +                 *   are usually usally working with colours that
       +                 *   have the sRGB transfer function applied to their
       +                 *   parameters). This action is the same in all
       +                 *   colour models and colour spaces that are a
       +                 *   linear transformation of the sRGB colour spaces
       +                 *   (sans transfer function); this is simply because
       +                 *   of the properties of linear transformations.
       +                 * 
       +                 *   The reason you change brightness this way can
       +                 *   be explained by how objects reflect colour.
       +                 *   Objects can only reject colours that are present
       +                 *   in the light source. A ideal white object will look
       +                 *   pure red if the light sources is ideal red, and a
       +                 *   a ideal blue object will pure black in the same
       +                 *   light source. An object can also not reflect
       +                 *   colours brighter than the source. When the brightness
       +                 *   of a light source is changed, the intensity of all
       +                 *   colours (by wavelength) it emits is multiplied by
       +                 *   one value. Therefore, when changing the brightness
       +                 *   it looks most natural when all primaries (red, green,
       +                 *   and blue) are multiplied by one value, or all
       +                 *   parameters of the used colour spaces is a linear
       +                 *   transformation of sRGB, such as CIE XYZ.
       +                 */
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-sinc-wave.c b/src/blind-sinc-wave.c
       @@ -1,73 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-e] [theta0-stream]")
        
        static int equal = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *grad, struct stream *theta0)\
       -        {\
       -                size_t i, n, m = 0;\
       -                TYPE *theta0xyza;\
       -                TYPE x, theta0x = 0;\
       -                TYPE y, theta0y = 0;\
       -                TYPE z, theta0z = 0;\
       -                TYPE a, theta0a = 0;\
       -                do {\
       -                        if (!m) {\
       -                                m = grad->frame_size;\
       -                                if (theta0) {\
       -                                        while (theta0->ptr < theta0->frame_size)\
       -                                                if (!eread_stream(theta0, theta0->frame_size - theta0->ptr))\
       -                                                        return;\
       -                                        theta0xyza = (TYPE *)theta0->buf;\
       -                                        theta0x = (theta0xyza)[0];\
       -                                        theta0y = (theta0xyza)[1];\
       -                                        theta0z = (theta0xyza)[2];\
       -                                        theta0a = (theta0xyza)[3];\
       -                                        memmove(theta0->buf, theta0->buf + theta0->frame_size,\
       -                                                theta0->ptr -= theta0->frame_size);\
       -                                }\
       -                        }\
       -                        n = MIN(grad->ptr, m) / grad->pixel_size;\
       -                        if (equal) {\
       -                                for (i = 0; i < n; i++) {\
       -                                        a = ((TYPE *)(grad->buf))[4 * i + 3];\
       -                                        a = (a ? sin(a + theta0y) / a : sin(a + theta0y)) / 2 + (TYPE)0.5;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 0] = a;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 1] = a;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 2] = a;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 3] = a;\
       -                                }\
       -                        } else {\
       -                                for (i = 0; i < n; i++) {\
       -                                        x = ((TYPE *)(grad->buf))[4 * i + 0];\
       -                                        y = ((TYPE *)(grad->buf))[4 * i + 1];\
       -                                        z = ((TYPE *)(grad->buf))[4 * i + 2];\
       -                                        a = ((TYPE *)(grad->buf))[4 * i + 3];\
       -                                        x = (x ? sin(x + theta0x) / x : sin(x + theta0x)) / 2 + (TYPE)0.5;\
       -                                        y = (y ? sin(y + theta0y) / y : sin(y + theta0y)) / 2 + (TYPE)0.5;\
       -                                        z = (z ? sin(z + theta0z) / z : sin(z + theta0z)) / 2 + (TYPE)0.5;\
       -                                        a = (a ? sin(a + theta0a) / a : sin(a + theta0a)) / 2 + (TYPE)0.5;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 0] = x;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 1] = y;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 2] = z;\
       -                                        ((TYPE *)(grad->buf))[4 * i + 3] = a;\
       -                                }\
       -                        }\
       -                        n *= grad->pixel_size;\
       -                        m -= n;\
       -                        ewriteall(STDOUT_FILENO, grad->buf, n, "<stdout>");\
       -                        memmove(grad->buf, grad->buf + n, grad->ptr -= n);\
       -                } while (eread_stream(grad, SIZE_MAX));\
       -                if (grad->ptr)\
       -                        eprintf("%s: incomplete frame\n", grad->file);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-sinc-wave.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -111,3 +51,67 @@ main(int argc, char *argv[])
                process(&stream, have_theta0 ? &theta0 : NULL);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *grad, struct stream *theta0)
       +{
       +        size_t i, n, m = 0;
       +        TYPE *theta0xyza;
       +        TYPE x, theta0x = 0;
       +        TYPE y, theta0y = 0;
       +        TYPE z, theta0z = 0;
       +        TYPE a, theta0a = 0;
       +        do {
       +                if (!m) {
       +                        m = grad->frame_size;
       +                        if (theta0) {
       +                                while (theta0->ptr < theta0->frame_size)
       +                                        if (!eread_stream(theta0, theta0->frame_size - theta0->ptr))
       +                                                return;
       +                                theta0xyza = (TYPE *)theta0->buf;
       +                                theta0x = (theta0xyza)[0];
       +                                theta0y = (theta0xyza)[1];
       +                                theta0z = (theta0xyza)[2];
       +                                theta0a = (theta0xyza)[3];
       +                                memmove(theta0->buf, theta0->buf + theta0->frame_size,
       +                                        theta0->ptr -= theta0->frame_size);
       +                        }
       +                }
       +                n = MIN(grad->ptr, m) / grad->pixel_size;
       +                if (equal) {
       +                        for (i = 0; i < n; i++) {
       +                                a = ((TYPE *)(grad->buf))[4 * i + 3];
       +                                a = (a ? sin(a + theta0y) / a : sin(a + theta0y)) / 2 + (TYPE)0.5;
       +                                ((TYPE *)(grad->buf))[4 * i + 0] = a;
       +                                ((TYPE *)(grad->buf))[4 * i + 1] = a;
       +                                ((TYPE *)(grad->buf))[4 * i + 2] = a;
       +                                ((TYPE *)(grad->buf))[4 * i + 3] = a;
       +                        }
       +                } else {
       +                        for (i = 0; i < n; i++) {
       +                                x = ((TYPE *)(grad->buf))[4 * i + 0];
       +                                y = ((TYPE *)(grad->buf))[4 * i + 1];
       +                                z = ((TYPE *)(grad->buf))[4 * i + 2];
       +                                a = ((TYPE *)(grad->buf))[4 * i + 3];
       +                                x = (x ? sin(x + theta0x) / x : sin(x + theta0x)) / 2 + (TYPE)0.5;
       +                                y = (y ? sin(y + theta0y) / y : sin(y + theta0y)) / 2 + (TYPE)0.5;
       +                                z = (z ? sin(z + theta0z) / z : sin(z + theta0z)) / 2 + (TYPE)0.5;
       +                                a = (a ? sin(a + theta0a) / a : sin(a + theta0a)) / 2 + (TYPE)0.5;
       +                                ((TYPE *)(grad->buf))[4 * i + 0] = x;
       +                                ((TYPE *)(grad->buf))[4 * i + 1] = y;
       +                                ((TYPE *)(grad->buf))[4 * i + 2] = z;
       +                                ((TYPE *)(grad->buf))[4 * i + 3] = a;
       +                        }
       +                }
       +                n *= grad->pixel_size;
       +                m -= n;
       +                ewriteall(STDOUT_FILENO, grad->buf, n, "<stdout>");
       +                memmove(grad->buf, grad->buf + n, grad->ptr -= n);
       +        } while (eread_stream(grad, SIZE_MAX));
       +        if (grad->ptr)
       +                eprintf("%s: incomplete frame\n", grad->file);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-sine-wave.c b/src/blind-sine-wave.c
       @@ -1,47 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-e]")
        
        static int equal = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, j, n;\
       -                TYPE v, *p;\
       -                do {\
       -                        if (equal) {\
       -                                n = stream->ptr / stream->pixel_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       -                                        v = posmod(*p, (TYPE)2);\
       -                                        v = v > 1 ? 2 - v : v;\
       -                                        v = 1 - (cos(v * (TYPE)M_PI) + 1) / 2;\
       -                                        for (j = 0; j < stream->n_chan; j++)\
       -                                                p[j] = v;\
       -                                }\
       -                                n *= stream->pixel_size;\
       -                        } else {\
       -                                n = stream->ptr / stream->chan_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i;\
       -                                        v = posmod(*p, (TYPE)2);\
       -                                        v = v > 1 ? 2 - v : v;\
       -                                        *p = 1 - (cos(v * (TYPE)M_PI) + 1) / 2;\
       -                                }\
       -                                n *= stream->chan_size;\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-sine-wave.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -74,3 +40,41 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, j, n;
       +        TYPE v, *p;
       +        do {
       +                if (equal) {
       +                        n = stream->ptr / stream->pixel_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i * stream->n_chan;
       +                                v = posmod(*p, (TYPE)2);
       +                                v = v > 1 ? 2 - v : v;
       +                                v = 1 - (cos(v * (TYPE)M_PI) + 1) / 2;
       +                                for (j = 0; j < stream->n_chan; j++)
       +                                        p[j] = v;
       +                        }
       +                        n *= stream->pixel_size;
       +                } else {
       +                        n = stream->ptr / stream->chan_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i;
       +                                v = posmod(*p, (TYPE)2);
       +                                v = v > 1 ? 2 - v : v;
       +                                *p = 1 - (cos(v * (TYPE)M_PI) + 1) / 2;
       +                        }
       +                        n *= stream->chan_size;
       +                }
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-single-colour.c b/src/blind-single-colour.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-f frames | -f 'inf'] [-F pixel-format] -w width -h height (X Y Z | Y) [alpha]")
       @@ -7,29 +8,8 @@ static struct stream stream = { .width = 0, .height = 0, .frames = 1 };
        static double X, Y, Z, alpha = 1;
        static int inf = 0;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t buf[BUFSIZ / 4];\
       -                size_t x, y, n;\
       -                ssize_t r;\
       -                \
       -                for (x = 0; x < ELEMENTSOF(buf); x++) {\
       -                        buf[x][0] = (TYPE)X;\
       -                        buf[x][1] = (TYPE)Y;\
       -                        buf[x][2] = (TYPE)Z;\
       -                        buf[x][3] = (TYPE)alpha;\
       -                }\
       -                while (inf || stream.frames--)\
       -                        for (y = stream.height; y--;)\
       -                                for (x = stream.width * sizeof(*buf); x;)\
       -                                        for (x -= n = MIN(sizeof(buf), x); n; n -= (size_t)r)\
       -                                                if ((r = write(STDOUT_FILENO, buf, n)) < 0)\
       -                                                        eprintf("write <stdout>:");\
       -        } while (0)
       -
       -static void process_xyza(void)  {PROCESS(double);}
       -static void process_xyzaf(void) {PROCESS(float);}
       +#define FILE "blind-single-colour.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -79,9 +59,9 @@ main(int argc, char *argv[])
        
                pixfmt = get_pixel_format(pixfmt, "xyza");
                if (!strcmp(pixfmt, "xyza"))
       -                process = process_xyza;
       +                process = process_lf;
                else if (!strcmp(pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +                process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", pixfmt);
        
       @@ -92,3 +72,28 @@ main(int argc, char *argv[])
                process();
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(void)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t buf[BUFSIZ / 4];
       +        size_t x, y, n;
       +        ssize_t r;
       +        for (x = 0; x < ELEMENTSOF(buf); x++) {
       +                buf[x][0] = (TYPE)X;
       +                buf[x][1] = (TYPE)Y;
       +                buf[x][2] = (TYPE)Z;
       +                buf[x][3] = (TYPE)alpha;
       +        }
       +        while (inf || stream.frames--)
       +                for (y = stream.height; y--;)
       +                        for (x = stream.width * sizeof(*buf); x;)
       +                                for (x -= n = MIN(sizeof(buf), x); n; n -= (size_t)r)
       +                                        if ((r = write(STDOUT_FILENO, buf, n)) < 0)
       +                                                eprintf("write <stdout>:");
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-spectrum.c b/src/blind-spectrum.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-y] [-z depth] spectrum-stream")
       @@ -6,121 +7,8 @@ USAGE("[-y] [-z depth] spectrum-stream")
        static int luma = 0;
        static size_t nz = 1;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream, struct stream *spectrum)\
       -        {\
       -                TYPE *table = emalloc2(nz, spectrum->frame_size);\
       -                size_t i, n, m = 0;\
       -                TYPE x, y, z, a, x1, y1, z1, a1, x2, y2, z2, a2, ix, iy, iz, wx, wy, wz;\
       -                size_t s, t, nx, ny, nxy;\
       -                nx = spectrum->width;\
       -                ny = spectrum->height;\
       -                nxy = nx * ny;\
       -                if (luma)\
       -                        ny = nxy * nz;\
       -                do {\
       -                        if (!m) {\
       -                                m = stream->frame_size;\
       -                                for (i = 0; i < nz; i++) {\
       -                                        if (!eread_frame(spectrum, ((char *)table) + i * spectrum->frame_size)) {\
       -                                                if (!i)\
       -                                                        goto done;\
       -                                                eprintf("%s: incomplete frame set\n", spectrum->file);\
       -                                        }\
       -                                }\
       -                        }\
       -                        n = MIN(stream->ptr, m) / stream->pixel_size;\
       -                        for (i = 0; i < n; i++) {\
       -                                if (luma) {\
       -                                        iy = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                        iy = MIN(MAX(iy, (TYPE)0), (TYPE)1);\
       -                                        iy *= (TYPE)(ny - 1);\
       -                                        s = (size_t)iy;\
       -                                        t = s + 1;\
       -                                        t = t == ny ? ny - 1 : t;\
       -                                        wy = mod(iy, (TYPE)1);\
       -                                        x = table[4 * s + 0] * (1 - wy) + table[4 * t + 0] * wy;\
       -                                        y = table[4 * s + 1] * (1 - wy) + table[4 * t + 1] * wy;\
       -                                        z = table[4 * s + 2] * (1 - wy) + table[4 * t + 2] * wy;\
       -                                        a = table[4 * s + 3] * (1 - wy) + table[4 * t + 3] * wy;\
       -                                } else {\
       -                                        ix = ((TYPE *)(stream->buf))[4 * i + 0];\
       -                                        iy = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                        iz = ((TYPE *)(stream->buf))[4 * i + 2];\
       -                                        ix = MIN(MAX(ix, (TYPE)0), (TYPE)1);\
       -                                        iy = MIN(MAX(iy, (TYPE)0), (TYPE)1);\
       -                                        iz = MIN(MAX(iz, (TYPE)0), (TYPE)1);\
       -                                        ix *= (TYPE)(nx - 1);\
       -                                        iy *= (TYPE)(ny - 1);\
       -                                        iz *= (TYPE)(nz - 1);\
       -                                        wx = mod(ix, (TYPE)1);\
       -                                        wy = mod(iy, (TYPE)1);\
       -                                        wz = mod(iz, (TYPE)1);\
       -                                        s = (size_t)ix;\
       -                                        t = s + 1;\
       -                                        t = t == nx ? nx - 1 : t;\
       -                                        s += (size_t)iy * nx;\
       -                                        t += (size_t)iy * nx;\
       -                                        s += (size_t)iz * nxy;\
       -                                        t += (size_t)iz * nxy;\
       -                                        x = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;\
       -                                        y = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;\
       -                                        z = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;\
       -                                        a = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;\
       -                                        if ((size_t)iy != ny - 1) {\
       -                                                s += nx, t += nx;\
       -                                                x2 = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;\
       -                                                y2 = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;\
       -                                                z2 = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;\
       -                                                a2 = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;\
       -                                                x = x * (1 - wy) + x2 * wy;\
       -                                                y = y * (1 - wy) + y2 * wy;\
       -                                                z = z * (1 - wy) + z2 * wy;\
       -                                                a = a * (1 - wy) + a2 * wy;\
       -                                                s -= nx, t -= nx;\
       -                                        }\
       -                                        if ((size_t)iz != nz - 1) {\
       -                                                s += nxy, t += nxy;\
       -                                                x1 = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;\
       -                                                y1 = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;\
       -                                                z1 = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;\
       -                                                a1 = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;\
       -                                                if ((size_t)iy != ny - 1) {\
       -                                                        s += nx, t += nx;\
       -                                                        x2 = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;\
       -                                                        y2 = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;\
       -                                                        z2 = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;\
       -                                                        a2 = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;\
       -                                                        x1 = x1 * (1 - wy) + x2 * wy;\
       -                                                        y1 = y1 * (1 - wy) + y2 * wy;\
       -                                                        z1 = z1 * (1 - wy) + z2 * wy;\
       -                                                        a1 = a1 * (1 - wy) + a2 * wy;\
       -                                                }\
       -                                                x = x * (1 - wz) + x1 * wz;\
       -                                                y = y * (1 - wz) + y1 * wz;\
       -                                                z = z * (1 - wz) + z1 * wz;\
       -                                                a = a * (1 - wz) + a1 * wz;\
       -                                        }\
       -                                }\
       -                                ((TYPE *)(stream->buf))[4 * i + 0] = x;\
       -                                ((TYPE *)(stream->buf))[4 * i + 1] = y;\
       -                                ((TYPE *)(stream->buf))[4 * i + 2] = z;\
       -                                ((TYPE *)(stream->buf))[4 * i + 3] *= a;\
       -                        }\
       -                        n *= stream->pixel_size;\
       -                        m -= n;\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        done:\
       -                free(table);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-spectrum.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -162,3 +50,119 @@ main(int argc, char *argv[])
                process(&stream, &spectrum);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream, struct stream *spectrum)
       +{
       +        TYPE *table = emalloc2(nz, spectrum->frame_size);
       +        size_t i, n, m = 0;
       +        TYPE x, y, z, a, x1, y1, z1, a1, x2, y2, z2, a2, ix, iy, iz, wx, wy, wz;
       +        size_t s, t, nx, ny, nxy;
       +        nx = spectrum->width;
       +        ny = spectrum->height;
       +        nxy = nx * ny;
       +        if (luma)
       +                ny = nxy * nz;
       +        do {
       +                if (!m) {
       +                        m = stream->frame_size;
       +                        for (i = 0; i < nz; i++) {
       +                                if (!eread_frame(spectrum, ((char *)table) + i * spectrum->frame_size)) {
       +                                        if (!i)
       +                                                goto done;
       +                                        eprintf("%s: incomplete frame set\n", spectrum->file);
       +                                }
       +                        }
       +                }
       +                n = MIN(stream->ptr, m) / stream->pixel_size;
       +                for (i = 0; i < n; i++) {
       +                        if (luma) {
       +                                iy = ((TYPE *)(stream->buf))[4 * i + 1];
       +                                iy = MIN(MAX(iy, (TYPE)0), (TYPE)1);
       +                                iy *= (TYPE)(ny - 1);
       +                                s = (size_t)iy;
       +                                t = s + 1;
       +                                t = t == ny ? ny - 1 : t;
       +                                wy = mod(iy, (TYPE)1);
       +                                x = table[4 * s + 0] * (1 - wy) + table[4 * t + 0] * wy;
       +                                y = table[4 * s + 1] * (1 - wy) + table[4 * t + 1] * wy;
       +                                z = table[4 * s + 2] * (1 - wy) + table[4 * t + 2] * wy;
       +                                a = table[4 * s + 3] * (1 - wy) + table[4 * t + 3] * wy;
       +                        } else {
       +                                ix = ((TYPE *)(stream->buf))[4 * i + 0];
       +                                iy = ((TYPE *)(stream->buf))[4 * i + 1];
       +                                iz = ((TYPE *)(stream->buf))[4 * i + 2];
       +                                ix = MIN(MAX(ix, (TYPE)0), (TYPE)1);
       +                                iy = MIN(MAX(iy, (TYPE)0), (TYPE)1);
       +                                iz = MIN(MAX(iz, (TYPE)0), (TYPE)1);
       +                                ix *= (TYPE)(nx - 1);
       +                                iy *= (TYPE)(ny - 1);
       +                                iz *= (TYPE)(nz - 1);
       +                                wx = mod(ix, (TYPE)1);
       +                                wy = mod(iy, (TYPE)1);
       +                                wz = mod(iz, (TYPE)1);
       +                                s = (size_t)ix;
       +                                t = s + 1;
       +                                t = t == nx ? nx - 1 : t;
       +                                s += (size_t)iy * nx;
       +                                t += (size_t)iy * nx;
       +                                s += (size_t)iz * nxy;
       +                                t += (size_t)iz * nxy;
       +                                x = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;
       +                                y = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;
       +                                z = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;
       +                                a = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;
       +                                if ((size_t)iy != ny - 1) {
       +                                        s += nx, t += nx;
       +                                        x2 = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;
       +                                        y2 = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;
       +                                        z2 = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;
       +                                        a2 = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;
       +                                        x = x * (1 - wy) + x2 * wy;
       +                                        y = y * (1 - wy) + y2 * wy;
       +                                        z = z * (1 - wy) + z2 * wy;
       +                                        a = a * (1 - wy) + a2 * wy;
       +                                        s -= nx, t -= nx;
       +                                }
       +                                if ((size_t)iz != nz - 1) {
       +                                        s += nxy, t += nxy;
       +                                        x1 = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;
       +                                        y1 = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;
       +                                        z1 = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;
       +                                        a1 = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;
       +                                        if ((size_t)iy != ny - 1) {
       +                                                s += nx, t += nx;
       +                                                x2 = table[4 * s + 0] * (1 - wx) + table[4 * t + 0] * wx;
       +                                                y2 = table[4 * s + 1] * (1 - wx) + table[4 * t + 1] * wx;
       +                                                z2 = table[4 * s + 2] * (1 - wx) + table[4 * t + 2] * wx;
       +                                                a2 = table[4 * s + 3] * (1 - wx) + table[4 * t + 3] * wx;
       +                                                x1 = x1 * (1 - wy) + x2 * wy;
       +                                                y1 = y1 * (1 - wy) + y2 * wy;
       +                                                z1 = z1 * (1 - wy) + z2 * wy;
       +                                                a1 = a1 * (1 - wy) + a2 * wy;
       +                                        }
       +                                        x = x * (1 - wz) + x1 * wz;
       +                                        y = y * (1 - wz) + y1 * wz;
       +                                        z = z * (1 - wz) + z1 * wz;
       +                                        a = a * (1 - wz) + a1 * wz;
       +                                }
       +                        }
       +                        ((TYPE *)(stream->buf))[4 * i + 0] = x;
       +                        ((TYPE *)(stream->buf))[4 * i + 1] = y;
       +                        ((TYPE *)(stream->buf))[4 * i + 2] = z;
       +                        ((TYPE *)(stream->buf))[4 * i + 3] *= a;
       +                }
       +                n *= stream->pixel_size;
       +                m -= n;
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +done:
       +        free(table);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-spiral-gradient.c b/src/blind-spiral-gradient.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-s spirals | t] [-al] -w width -h height")
       @@ -12,108 +13,8 @@ static size_t height = 0;
        static int with_params;
        static int with_vector;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
       -                TYPE *params, x1, y1, x2, y2, b, r, u, v;\
       -                TYPE x, y, a = 0, e = 1, p = 1, k = 1, ep = 1;\
       -                TYPE x3 = 1, y3 = 0, rd = 1, P, R, Rx, Ry, Pe = 2, Re = 2, PRe = 0.5;\
       -                size_t ix, iy, ptr = 0;\
       -                for (;;) {\
       -                        while (stream->ptr < stream->frame_size) {\
       -                                if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
       -                                        ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
       -                                        return;\
       -                                }\
       -                        }\
       -                        params = (TYPE *)stream->buf;\
       -                        x1 = (params)[0];\
       -                        y1 = (params)[1];\
       -                        x2 = (params)[4];\
       -                        y2 = (params)[5];\
       -                        if (with_vector) {\
       -                                x3 = (params)[8];\
       -                                y3 = (params)[9];\
       -                                Pe = (params)[12];\
       -                                Re = (params)[13];\
       -                                rd = (params)[14];\
       -                                PRe = 1 / sqrt(Pe * Re);\
       -                                b = sqrt(x3 * x3 + y3 * y3);\
       -                                x3 /= b;\
       -                                y3 /= b;\
       -                        }\
       -                        if (with_params) {\
       -                                a = (params)[with_vector ? 16 : 8];\
       -                                e = (params)[with_vector ? 17 : 9];\
       -                                p = (params)[with_vector ? 18 : 10];\
       -                                k = (params)[with_vector ? 19 : 11];\
       -                                ep = 1 / (e * p);\
       -                        }\
       -                        memmove(stream->buf, stream->buf + stream->frame_size,\
       -                                stream->ptr -= stream->frame_size);\
       -                        \
       -                        x2 -= x1;\
       -                        y2 -= y1;\
       -                        u = atan2(y2, x2);\
       -                        b = sqrt(x2 * x2 + y2 * y2);\
       -                        b *= (TYPE)spirals;\
       -                        if (logarithmic)\
       -                                b = log(b);\
       -                        b /= pow(2 * (TYPE)M_PI, e);\
       -                        \
       -                        for (iy = 0; iy < height; iy++) {\
       -                                y = (TYPE)iy - y1;\
       -                                for (ix = 0; ix < width; ix++) {\
       -                                        x = (TYPE)ix - x1;\
       -                                        if (!x && !y) {\
       -                                                v = 0;\
       -                                        } else {\
       -                                                v = atan2(y, x);\
       -                                                if (anticlockwise)\
       -                                                        v = -v;\
       -                                                v -= u;\
       -                                                v += 4 * (TYPE)M_PI;\
       -                                                v = mod(v, 2 * (TYPE)M_PI);\
       -                                        }\
       -                                        if (!with_vector) {\
       -                                                r = sqrt(x * x + y * y);\
       -                                        } else {\
       -                                                P = x * x3 + y * y3;\
       -                                                Rx = x - P * x3;\
       -                                                Ry = y - P * y3;\
       -                                                R = sqrt(Rx * Rx + Ry * Ry) / rd;\
       -                                                P = pow(abs(P), Pe);\
       -                                                R = pow(abs(R), Re);\
       -                                                r = pow(P + R, PRe);\
       -                                        }\
       -                                        r -= a;\
       -                                        if (!logarithmic) {\
       -                                                r = pow(r / b, ep);\
       -                                                r = (r - v) / (2 * (TYPE)M_PI);\
       -                                        } else if (r) {\
       -                                                r = log(r / k);\
       -                                                r = pow(r / b, ep);\
       -                                                r = (r - v) / (2 * (TYPE)M_PI);\
       -                                        }\
       -                                        if (angle)\
       -                                                r = (TYPE)(int)(r + 1) + v / (2 * (TYPE)M_PI); \
       -                                        else\
       -                                                r = mod(r, 1 / (TYPE)spirals) * (TYPE)spirals + r - mod(r, (TYPE)1);\
       -                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = r;\
       -                                        if (++ptr == ELEMENTSOF(buf)) {\
       -                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
       -                                                ptr = 0;\
       -                                        }\
       -                                }\
       -                        }\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-spiral-gradient.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -173,3 +74,106 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t buf[BUFSIZ / sizeof(pixel_t)];
       +        TYPE *params, x1, y1, x2, y2, b, r, u, v;
       +        TYPE x, y, a = 0, e = 1, p = 1, k = 1, ep = 1;
       +        TYPE x3 = 1, y3 = 0, rd = 1, P, R, Rx, Ry, Pe = 2, Re = 2, PRe = 0.5;
       +        size_t ix, iy, ptr = 0;
       +        for (;;) {
       +                while (stream->ptr < stream->frame_size) {
       +                        if (!eread_stream(stream, stream->frame_size - stream->ptr)) {
       +                                ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");
       +                                return;
       +                        }
       +                }
       +                params = (TYPE *)stream->buf;
       +                x1 = (params)[0];
       +                y1 = (params)[1];
       +                x2 = (params)[4];
       +                y2 = (params)[5];
       +                if (with_vector) {
       +                        x3 = (params)[8];
       +                        y3 = (params)[9];
       +                        Pe = (params)[12];
       +                        Re = (params)[13];
       +                        rd = (params)[14];
       +                        PRe = 1 / sqrt(Pe * Re);
       +                        b = sqrt(x3 * x3 + y3 * y3);
       +                        x3 /= b;
       +                        y3 /= b;
       +                }
       +                if (with_params) {
       +                        a = (params)[with_vector ? 16 : 8];
       +                        e = (params)[with_vector ? 17 : 9];
       +                        p = (params)[with_vector ? 18 : 10];
       +                        k = (params)[with_vector ? 19 : 11];
       +                        ep = 1 / (e * p);
       +                }
       +                memmove(stream->buf, stream->buf + stream->frame_size,
       +                        stream->ptr -= stream->frame_size);
       +
       +                x2 -= x1;
       +                y2 -= y1;
       +                u = atan2(y2, x2);
       +                b = sqrt(x2 * x2 + y2 * y2);
       +                b *= (TYPE)spirals;
       +                if (logarithmic)
       +                        b = log(b);
       +                b /= pow(2 * (TYPE)M_PI, e);
       +
       +                for (iy = 0; iy < height; iy++) {
       +                        y = (TYPE)iy - y1;
       +                        for (ix = 0; ix < width; ix++) {
       +                                x = (TYPE)ix - x1;
       +                                if (!x && !y) {
       +                                        v = 0;
       +                                } else {
       +                                        v = atan2(y, x);
       +                                        if (anticlockwise)
       +                                                v = -v;
       +                                        v -= u;
       +                                        v += 4 * (TYPE)M_PI;
       +                                        v = mod(v, 2 * (TYPE)M_PI);
       +                                }
       +                                if (!with_vector) {
       +                                        r = sqrt(x * x + y * y);
       +                                } else {
       +                                        P = x * x3 + y * y3;
       +                                        Rx = x - P * x3;
       +                                        Ry = y - P * y3;
       +                                        R = sqrt(Rx * Rx + Ry * Ry) / rd;
       +                                        P = pow(abs(P), Pe);
       +                                        R = pow(abs(R), Re);
       +                                        r = pow(P + R, PRe);
       +                                }
       +                                r -= a;
       +                                if (!logarithmic) {
       +                                        r = pow(r / b, ep);
       +                                        r = (r - v) / (2 * (TYPE)M_PI);
       +                                } else if (r) {
       +                                        r = log(r / k);
       +                                        r = pow(r / b, ep);
       +                                        r = (r - v) / (2 * (TYPE)M_PI);
       +                                }
       +                                if (angle)
       +                                        r = (TYPE)(int)(r + 1) + v / (2 * (TYPE)M_PI); 
       +                                else
       +                                        r = mod(r, 1 / (TYPE)spirals) * (TYPE)spirals + r - mod(r, (TYPE)1);
       +                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = r;
       +                                if (++ptr == ELEMENTSOF(buf)) {
       +                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
       +                                        ptr = 0;
       +                                }
       +                        }
       +                }
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-square-gradient.c b/src/blind-square-gradient.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("-w width -h height")
       @@ -7,60 +8,8 @@ static size_t width = 0;
        static size_t height = 0;
        static int with_multiplier;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
       -                TYPE *params, x1, y1, x2, y2, norm, rd = 1; \
       -                TYPE x, y, p, r, rx, ry;\
       -                size_t ix, iy, ptr = 0;\
       -                for (;;) {\
       -                        while (stream->ptr < stream->frame_size) {\
       -                                if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
       -                                        ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
       -                                        return;\
       -                                }\
       -                        }\
       -                        params = (TYPE *)stream->buf;\
       -                        x1 = (params)[0];\
       -                        y1 = (params)[1];\
       -                        x2 = (params)[4];\
       -                        y2 = (params)[5];\
       -                        if (with_multiplier)\
       -                                rd = (params)[9];\
       -                        memmove(stream->buf, stream->buf + stream->frame_size,\
       -                                stream->ptr -= stream->frame_size);\
       -                        \
       -                        x2 -= x1;\
       -                        y2 -= y1;\
       -                        norm = sqrt(x2 * x2 + y2 * y2);\
       -                        x2 /= norm;\
       -                        y2 /= norm;\
       -                        \
       -                        for (iy = 0; iy < height; iy++) {\
       -                                y = (TYPE)iy - y1;\
       -                                for (ix = 0; ix < width; ix++) {\
       -                                        x = (TYPE)ix - x1;\
       -                                        p = x * x2 + y * y2;\
       -                                        rx = x - p * x2;\
       -                                        ry = y - p * y2;\
       -                                        r = sqrt(rx * rx + ry * ry) / rd;\
       -                                        p = abs(p);\
       -                                        x = MAX(p, r) / norm;\
       -                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
       -                                        if (++ptr == ELEMENTSOF(buf)) {\
       -                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
       -                                                ptr = 0;\
       -                                        }\
       -                                }\
       -                        }\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-square-gradient.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -105,3 +54,58 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t buf[BUFSIZ / sizeof(pixel_t)];
       +        TYPE *params, x1, y1, x2, y2, norm, rd = 1; 
       +        TYPE x, y, p, r, rx, ry;
       +        size_t ix, iy, ptr = 0;
       +        for (;;) {
       +                while (stream->ptr < stream->frame_size) {
       +                        if (!eread_stream(stream, stream->frame_size - stream->ptr)) {
       +                                ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");
       +                                return;
       +                        }
       +                }
       +                params = (TYPE *)stream->buf;
       +                x1 = (params)[0];
       +                y1 = (params)[1];
       +                x2 = (params)[4];
       +                y2 = (params)[5];
       +                if (with_multiplier)
       +                        rd = (params)[9];
       +                memmove(stream->buf, stream->buf + stream->frame_size,
       +                        stream->ptr -= stream->frame_size);
       +
       +                x2 -= x1;
       +                y2 -= y1;
       +                norm = sqrt(x2 * x2 + y2 * y2);
       +                x2 /= norm;
       +                y2 /= norm;
       +
       +                for (iy = 0; iy < height; iy++) {
       +                        y = (TYPE)iy - y1;
       +                        for (ix = 0; ix < width; ix++) {
       +                                x = (TYPE)ix - x1;
       +                                p = x * x2 + y * y2;
       +                                rx = x - p * x2;
       +                                ry = y - p * y2;
       +                                r = sqrt(rx * rx + ry * ry) / rd;
       +                                p = abs(p);
       +                                x = MAX(p, r) / norm;
       +                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;
       +                                if (++ptr == ELEMENTSOF(buf)) {
       +                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
       +                                        ptr = 0;
       +                                }
       +                        }
       +                }
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-tee.c b/src/blind-tee.c
       @@ -3,10 +3,6 @@
        
        USAGE("[file ...]")
        
       -#if !defined(PIPE_BUF)
       -# define PIPE_BUF BUFSIZ
       -#endif
       -
        int
        main(int argc, char *argv[])
        {
 (DIR) diff --git a/src/blind-time-blur.c b/src/blind-time-blur.c
       @@ -1,52 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("alpha-stream")
        
        static int first = 1;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                typedef TYPE pixel_t[4];\
       -                pixel_t *restrict clr = (pixel_t *)cbuf;\
       -                pixel_t *restrict alf = (pixel_t *)abuf;\
       -                pixel_t *img = (pixel_t *)output;\
       -                size_t i, n = colour->frame_size / sizeof(pixel_t);\
       -                TYPE a1, a2;\
       -                \
       -                if (first) {\
       -                        memcpy(output, cbuf, colour->frame_size);\
       -                        first = 0;\
       -                        return;\
       -                }\
       -                \
       -                for (i = 0; i < n; i++, clr++, alf++, img++) {\
       -                        a1 = (*img)[3];\
       -                        a2 = (*clr)[3] * (*alf)[1] * (*alf)[3];\
       -                        a1 *= (1 - a2);\
       -                        (*img)[0] = (*img)[0] * a1 + (*clr)[0] * a2;\
       -                        (*img)[1] = (*img)[1] * a1 + (*clr)[1] * a2;\
       -                        (*img)[2] = (*img)[2] * a1 + (*clr)[2] * a2;\
       -                        (*img)[3] = a1 + a2;\
       -                }\
       -                \
       -                (void) colour;\
       -                (void) alpha;\
       -        } while (0)
       -
       -static void
       -process_lf(char *output, char *restrict cbuf, char *restrict abuf,
       -           struct stream *colour, struct stream *alpha)
       -{
       -        PROCESS(double);
       -}
       -
       -static void
       -process_f(char *output, char *restrict cbuf, char *restrict abuf,
       -          struct stream *colour, struct stream *alpha)
       -{
       -        PROCESS(float);
       -}
       +#define FILE "blind-time-blur.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -79,3 +40,39 @@ main(int argc, char *argv[])
                process_each_frame_two_streams(&colour, &alpha, STDOUT_FILENO, "<stdout>", process);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(char *output, char *restrict cbuf, char *restrict abuf,
       +        struct stream *colour, struct stream *alpha)
       +{
       +        typedef TYPE pixel_t[4];
       +        pixel_t *restrict clr = (pixel_t *)cbuf;
       +        pixel_t *restrict alf = (pixel_t *)abuf;
       +        pixel_t *img = (pixel_t *)output;
       +        size_t i, n = colour->frame_size / sizeof(pixel_t);
       +        TYPE a1, a2;
       +
       +        if (first) {
       +                memcpy(output, cbuf, colour->frame_size);
       +                first = 0;
       +                return;
       +        }
       +
       +        for (i = 0; i < n; i++, clr++, alf++, img++) {
       +                a1 = (*img)[3];
       +                a2 = (*clr)[3] * (*alf)[1] * (*alf)[3];
       +                a1 *= (1 - a2);
       +                (*img)[0] = (*img)[0] * a1 + (*clr)[0] * a2;
       +                (*img)[1] = (*img)[1] * a1 + (*clr)[1] * a2;
       +                (*img)[2] = (*img)[2] * a1 + (*clr)[2] * a2;
       +                (*img)[3] = a1 + a2;
       +        }
       +
       +        (void) colour;
       +        (void) alpha;
       +
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-to-text.c b/src/blind-to-text.c
       @@ -1,8 +1,6 @@
        /* See LICENSE file for copyright and license details. */
        #include "common.h"
        
       -#include <string.h>
       -
        USAGE("")
        
        #define PROCESS(TYPE, CAST, FMT)\
 (DIR) diff --git a/src/blind-to-video.c b/src/blind-to-video.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-d] frame-rate ffmpeg-arguments ...")
       @@ -6,55 +7,8 @@ USAGE("[-d] frame-rate ffmpeg-arguments ...")
        static int draft = 0;
        static int fd;
        
       -#define PROCESS(TYPE)\
       -        do {\
       -                char *buf = stream->buf;\
       -                TYPE *pixel, r, g, b;\
       -                uint16_t *pixels, *end;\
       -                uint16_t pixbuf[BUFSIZ / sizeof(uint16_t)];\
       -                long int a, y, u, v;\
       -                size_t ptr;\
       -                pixels = pixbuf;\
       -                end = pixbuf + ELEMENTSOF(pixbuf);\
       -                if (draft) {\
       -                        for (ptr = 0; ptr < n; ptr += 4 * sizeof(TYPE)) {\
       -                                pixel = (TYPE *)(buf + ptr);\
       -                                ciexyz_to_scaled_yuv(pixel[0], pixel[1], pixel[2], &r, &g, &b);\
       -                                y = (long int)r +  16L * 256L;\
       -                                u = (long int)g + 128L * 256L;\
       -                                v = (long int)b + 128L * 256L;\
       -                                *pixels++ = 0xFFFFU;\
       -                                *pixels++ = htole((uint16_t)CLIP(0, y, 0xFFFFL));\
       -                                *pixels++ = htole((uint16_t)CLIP(0, u, 0xFFFFL));\
       -                                *pixels++ = htole((uint16_t)CLIP(0, v, 0xFFFFL));\
       -                                if (pixels == end)\
       -                                        ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), "<subprocess>");\
       -                        }\
       -                } else {\
       -                        for (ptr = 0; ptr < n; ptr += 4 * sizeof(TYPE)) {\
       -                                pixel = (TYPE *)(buf + ptr);\
       -                                a = (long int)(pixel[3] * 0xFFFFL);\
       -                                ciexyz_to_srgb(pixel[0], pixel[1], pixel[2], &r, &g, &b);\
       -                                r = srgb_encode(r);\
       -                                g = srgb_encode(g);\
       -                                b = srgb_encode(b);\
       -                                srgb_to_yuv(r, g, b, pixel + 0, pixel + 1, pixel + 2);\
       -                                y = (long int)(pixel[0] * 0xFFFFL) +  16L * 256L;\
       -                                u = (long int)(pixel[1] * 0xFFFFL) + 128L * 256L;\
       -                                v = (long int)(pixel[2] * 0xFFFFL) + 128L * 256L;\
       -                                *pixels++ = htole((uint16_t)CLIP(0, a, 0xFFFFL));\
       -                                *pixels++ = htole((uint16_t)CLIP(0, y, 0xFFFFL));\
       -                                *pixels++ = htole((uint16_t)CLIP(0, u, 0xFFFFL));\
       -                                *pixels++ = htole((uint16_t)CLIP(0, v, 0xFFFFL));\
       -                                if (pixels == end)\
       -                                        ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), "<subprocess>");\
       -                        }\
       -                }\
       -                ewriteall(fd, pixbuf, (size_t)(pixels - pixbuf) * sizeof(*pixels), "<subprocess>");\
       -        } while (0)
       -
       -static void process_xyza (struct stream *stream, size_t n) {PROCESS(double);}
       -static void process_xyzaf(struct stream *stream, size_t n) {PROCESS(float);}
       +#define FILE "blind-to-video.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -94,9 +48,9 @@ main(int argc, char *argv[])
                sprintf(geometry, "%zux%zu", stream.width, stream.height);
        
                if (!strcmp(stream.pixfmt, "xyza"))
       -                process = process_xyza;
       +                process = process_lf;
                else if (!strcmp(stream.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +                process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
        
       @@ -121,3 +75,55 @@ main(int argc, char *argv[])
                ewaitpid(pid, &status, 0);
                return !!status;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream, size_t n)
       +{
       +        char *buf = stream->buf;
       +        TYPE *pixel, r, g, b;
       +        uint16_t *pixels, *end;
       +        uint16_t pixbuf[BUFSIZ / sizeof(uint16_t)];
       +        long int a, y, u, v;
       +        size_t ptr;
       +        pixels = pixbuf;
       +        end = pixbuf + ELEMENTSOF(pixbuf);
       +        if (draft) {
       +                for (ptr = 0; ptr < n; ptr += 4 * sizeof(TYPE)) {
       +                        pixel = (TYPE *)(buf + ptr);
       +                        ciexyz_to_scaled_yuv(pixel[0], pixel[1], pixel[2], &r, &g, &b);
       +                        y = (long int)r +  16L * 256L;
       +                        u = (long int)g + 128L * 256L;
       +                        v = (long int)b + 128L * 256L;
       +                        *pixels++ = 0xFFFFU;
       +                        *pixels++ = htole((uint16_t)CLIP(0, y, 0xFFFFL));
       +                        *pixels++ = htole((uint16_t)CLIP(0, u, 0xFFFFL));
       +                        *pixels++ = htole((uint16_t)CLIP(0, v, 0xFFFFL));
       +                        if (pixels == end)
       +                                ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), "<subprocess>");
       +                }
       +        } else {
       +                for (ptr = 0; ptr < n; ptr += 4 * sizeof(TYPE)) {
       +                        pixel = (TYPE *)(buf + ptr);
       +                        a = (long int)(pixel[3] * 0xFFFFL);
       +                        ciexyz_to_srgb(pixel[0], pixel[1], pixel[2], &r, &g, &b);
       +                        r = srgb_encode(r);
       +                        g = srgb_encode(g);
       +                        b = srgb_encode(b);
       +                        srgb_to_yuv(r, g, b, pixel + 0, pixel + 1, pixel + 2);
       +                        y = (long int)(pixel[0] * 0xFFFFL) +  16L * 256L;
       +                        u = (long int)(pixel[1] * 0xFFFFL) + 128L * 256L;
       +                        v = (long int)(pixel[2] * 0xFFFFL) + 128L * 256L;
       +                        *pixels++ = htole((uint16_t)CLIP(0, a, 0xFFFFL));
       +                        *pixels++ = htole((uint16_t)CLIP(0, y, 0xFFFFL));
       +                        *pixels++ = htole((uint16_t)CLIP(0, u, 0xFFFFL));
       +                        *pixels++ = htole((uint16_t)CLIP(0, v, 0xFFFFL));
       +                        if (pixels == end)
       +                                ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), "<subprocess>");
       +                }
       +        }
       +        ewriteall(fd, pixbuf, (size_t)(pixels - pixbuf) * sizeof(*pixels), "<subprocess>");
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-triangular-wave.c b/src/blind-triangular-wave.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-es]")
       @@ -6,46 +7,8 @@ USAGE("[-es]")
        static int equal = 0;
        static int spiral = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, j, n;\
       -                TYPE v, *p;\
       -                do {\
       -                        if (equal) {\
       -                                n = stream->ptr / stream->pixel_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       -                                        v = posmod(*p, (TYPE)2);\
       -                                        v = v > 1 ? 2 - v : v;\
       -                                        if (spiral)\
       -                                                v = (v > (TYPE)0.5 ? 1 - v : v) * 2;\
       -                                        for (j = 0; j < stream->n_chan; j++)\
       -                                                p[j] = v;\
       -                                }\
       -                                n *= stream->pixel_size;\
       -                        } else {\
       -                                n = stream->ptr / stream->chan_size;\
       -                                for (i = 0; i < n; i++) {\
       -                                        p = (TYPE *)(stream->buf) + i;\
       -                                        v = posmod(*p, (TYPE)2);\
       -                                        v = v > 1 ? 2 - v : v;\
       -                                        if (spiral)\
       -                                                v = (v > (TYPE)0.5 ? 1 - v : v) * 2;\
       -                                        *p = v;\
       -                                }\
       -                                n *= stream->chan_size;\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-triangular-wave.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -81,3 +44,44 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, j, n;
       +        TYPE v, *p;
       +        do {
       +                if (equal) {
       +                        n = stream->ptr / stream->pixel_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i * stream->n_chan;
       +                                v = posmod(*p, (TYPE)2);
       +                                v = v > 1 ? 2 - v : v;
       +                                if (spiral)
       +                                        v = (v > (TYPE)0.5 ? 1 - v : v) * 2;
       +                                for (j = 0; j < stream->n_chan; j++)
       +                                        p[j] = v;
       +                        }
       +                        n *= stream->pixel_size;
       +                } else {
       +                        n = stream->ptr / stream->chan_size;
       +                        for (i = 0; i < n; i++) {
       +                                p = (TYPE *)(stream->buf) + i;
       +                                v = posmod(*p, (TYPE)2);
       +                                v = v > 1 ? 2 - v : v;
       +                                if (spiral)
       +                                        v = (v > (TYPE)0.5 ? 1 - v : v) * 2;
       +                                *p = v;
       +                        }
       +                        n *= stream->chan_size;
       +                }
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-unpremultiply.c b/src/blind-unpremultiply.c
       @@ -1,4 +1,5 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-xyz]")
       @@ -7,35 +8,8 @@ static int skip_x = 0;
        static int skip_y = 0;
        static int skip_z = 0;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *stream)\
       -        {\
       -                size_t i, n;\
       -                TYPE a;\
       -                do {\
       -                        n = stream->ptr / stream->pixel_size;\
       -                        for (i = 0; i < n; i++) {\
       -                                a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                if (!a)\
       -                                        continue;\
       -                                if (!skip_x)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] /= a;\
       -                                if (!skip_y)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] /= a;\
       -                                if (!skip_z)\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] /= a;\
       -                        }\
       -                        n *= stream->pixel_size;\
       -                        ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
       -                        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);\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-unpremultiply.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -74,3 +48,33 @@ main(int argc, char *argv[])
                process(&stream);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream)
       +{
       +        size_t i, n;
       +        TYPE a;
       +        do {
       +                n = stream->ptr / stream->pixel_size;
       +                for (i = 0; i < n; i++) {
       +                        a = ((TYPE *)(stream->buf))[4 * i + 3];
       +                        if (!a)
       +                                continue;
       +                        if (!skip_x)
       +                                ((TYPE *)(stream->buf))[4 * i + 0] /= a;
       +                        if (!skip_y)
       +                                ((TYPE *)(stream->buf))[4 * i + 1] /= a;
       +                        if (!skip_z)
       +                                ((TYPE *)(stream->buf))[4 * i + 2] /= a;
       +                }
       +                n *= stream->pixel_size;
       +                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
       +                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);
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-vector-projection.c b/src/blind-vector-projection.c
       @@ -1,45 +1,13 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("[-r | -s] plane-stream")
        
        static int level = 1;
        
       -#define PROCESS(TYPE, SUFFIX)\
       -        static void\
       -        process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\
       -        {\
       -                size_t i;\
       -                TYPE *lx, *ly, *lz, *la, rx, ry, rz, ra, x, y, z, a, norm;\
       -                for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\
       -                        lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i))[0];\
       -                        ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i))[1];\
       -                        lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i))[2];\
       -                        la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i))[3];\
       -                        norm = rx * rx + ry * ry + rz * rz + ra * ra;\
       -                        norm = sqrt(norm);\
       -                        x = y = z = a = *lx * rx + *ly * ry + *lz * rz + *la * ra;\
       -                        if (level) {\
       -                                x *= rx;\
       -                                y *= ry;\
       -                                z *= rz;\
       -                                a *= rz;\
       -                                if (level > 1) {\
       -                                        x = *lx - x;\
       -                                        y = *ly - y;\
       -                                        z = *lz - z;\
       -                                        a = *la - a;\
       -                                }\
       -                        }\
       -                        *lx = x;\
       -                        *ly = y;\
       -                        *lz = z;\
       -                        *la = a;\
       -                }\
       -        }
       -
       -PROCESS(double, lf)
       -PROCESS(float, f)
       +#define FILE "blind-vector-projection.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -80,3 +48,39 @@ main(int argc, char *argv[])
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *left, struct stream *right, size_t n)
       +{
       +        size_t i;
       +        TYPE *lx, *ly, *lz, *la, rx, ry, rz, ra, x, y, z, a, norm;
       +        for (i = 0; i < n; i += 4 * sizeof(TYPE)) {
       +                lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i))[0];
       +                ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i))[1];
       +                lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i))[2];
       +                la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i))[3];
       +                norm = rx * rx + ry * ry + rz * rz + ra * ra;
       +                norm = sqrt(norm);
       +                x = y = z = a = *lx * rx + *ly * ry + *lz * rz + *la * ra;
       +                if (level) {
       +                        x *= rx;
       +                        y *= ry;
       +                        z *= rz;
       +                        a *= rz;
       +                        if (level > 1) {
       +                                x = *lx - x;
       +                                y = *ly - y;
       +                                z = *lz - z;
       +                                a = *la - a;
       +                        }
       +                }
       +                *lx = x;
       +                *ly = y;
       +                *lz = z;
       +                *la = a;
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/common.h b/src/common.h
       @@ -64,3 +64,7 @@
        #ifndef CMSG_LEN
        # define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
        #endif
       +
       +#if !defined(PIPE_BUF)
       +# define PIPE_BUF BUFSIZ
       +#endif
 (DIR) diff --git a/src/define-functions.h b/src/define-functions.h
       @@ -0,0 +1,13 @@
       +/* See LICENSE file for copyright and license details. */
       +
       +#define PROCESS process_lf
       +#define TYPE double
       +#include FILE
       +#undef PROCESS
       +#undef TYPE
       +
       +#define PROCESS process_f
       +#define TYPE float
       +#include FILE
       +#undef PROCESS
       +#undef TYPE