aboutsummaryrefslogtreecommitdiffstats
path: root/libglitter_per_channel_desaturate_double.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libglitter_per_channel_desaturate_double.c311
1 files changed, 310 insertions, 1 deletions
diff --git a/libglitter_per_channel_desaturate_double.c b/libglitter_per_channel_desaturate_double.c
index 1f2fcdc..a9bafb9 100644
--- a/libglitter_per_channel_desaturate_double.c
+++ b/libglitter_per_channel_desaturate_double.c
@@ -53,10 +53,319 @@ libglitter_per_channel_desaturate_double(double **rasters, size_t nrasters, size
#else
+#define TOLERANCE 0.0001
+#define TOL 4
+
+#define RY 0.212673370378408277403536885686
+#define GY 0.715151730491031756287156895269
+#define BY 0.072174899130559869164791564344
+
+
+static int
+eq(double a, double b)
+{
+ double r = a - b;
+ return (r < 0 ? -r : r) < TOLERANCE;
+}
+
int
main(void)
{
- return 0; /* TODO add test */
+ double zeroes[2 * 6 * 3];
+ double raster1[2 * 6 * 3];
+ double raster2[2 * 6 * 3];
+ double raster3[2 * 6 * 3];
+ double *rasters[3], saturations[3], primary_ys[3];
+ size_t i;
+
+#define POS(Y, X) ((Y) * 6 * 3 + (X) * 3)
+#define ASSERT2(A, B) do { ASSERT(A); ASSERT(B); } while (0)
+#define ASSERT3(A, B, C) do { ASSERT(A); ASSERT(B); ASSERT(C); } while (0)
+
+ memset(zeroes, 0, sizeof(zeroes));
+
+ for (i = 0; i <= 2; i++) {
+ double v = (double)i / 2;
+
+ memset(raster1, 0, sizeof(raster1));
+ memset(raster2, 0, sizeof(raster2));
+ memset(raster3, 0, sizeof(raster3));
+ raster1[POS(0, 0)] = v, raster2[POS(0, 0)] = v;
+ raster1[POS(0, 1)] = v, raster2[POS(0, 1)] = v;
+ raster1[POS(0, 2)] = v, raster2[POS(0, 2)] = v;
+ raster1[POS(0, 3)] = v, raster2[POS(0, 3)] = v;
+ raster1[POS(1, 0)] = v, raster2[POS(1, 0)] = v;
+ raster1[POS(1, 1)] = v, raster2[POS(1, 1)] = v;
+ raster1[POS(1, 2)] = v, raster2[POS(1, 2)] = v;
+ raster1[POS(1, 3)] = v, raster2[POS(1, 3)] = v;
+ rasters[0] = raster1;
+ rasters[1] = raster2;
+ rasters[2] = raster3;
+ saturations[0] = 0.5;
+ saturations[1] = 0.25;
+ primary_ys[0] = 0.75;
+ primary_ys[1] = 0.25;
+ libglitter_per_channel_desaturate_double(rasters, 2, 6, 3, 4, 2, saturations, primary_ys);
+ ASSERT2(raster1[POS(0, 0)] == v, raster2[POS(0, 0)] == v);
+ ASSERT2(raster1[POS(0, 1)] == v, raster2[POS(0, 1)] == v);
+ ASSERT2(raster1[POS(0, 2)] == v, raster2[POS(0, 2)] == v);
+ ASSERT2(raster1[POS(0, 3)] == v, raster2[POS(0, 3)] == v);
+ ASSERT2(raster1[POS(1, 0)] == v, raster2[POS(1, 0)] == v);
+ ASSERT2(raster1[POS(1, 1)] == v, raster2[POS(1, 1)] == v);
+ ASSERT2(raster1[POS(1, 2)] == v, raster2[POS(1, 2)] == v);
+ ASSERT2(raster1[POS(1, 3)] == v, raster2[POS(1, 3)] == v);
+ raster1[POS(0, 0)] = 0, raster2[POS(0, 0)] = 0;
+ raster1[POS(0, 1)] = 0, raster2[POS(0, 1)] = 0;
+ raster1[POS(0, 2)] = 0, raster2[POS(0, 2)] = 0;
+ raster1[POS(0, 3)] = 0, raster2[POS(0, 3)] = 0;
+ raster1[POS(1, 0)] = 0, raster2[POS(1, 0)] = 0;
+ raster1[POS(1, 1)] = 0, raster2[POS(1, 1)] = 0;
+ raster1[POS(1, 2)] = 0, raster2[POS(1, 2)] = 0;
+ raster1[POS(1, 3)] = 0, raster2[POS(1, 3)] = 0;
+ ASSERT(!memcmp(raster1, zeroes, sizeof(raster1)));
+ ASSERT(!memcmp(raster2, zeroes, sizeof(raster2)));
+ ASSERT(!memcmp(raster3, zeroes, sizeof(raster3)));
+
+ memset(raster1, 0, sizeof(raster1));
+ memset(raster2, 0, sizeof(raster2));
+ memset(raster3, 0, sizeof(raster3));
+ raster1[POS(0, 0)] = v, raster2[POS(0, 0)] = v, raster3[POS(0, 0)] = v;
+ raster1[POS(0, 1)] = v, raster2[POS(0, 1)] = v, raster3[POS(0, 1)] = v;
+ raster1[POS(0, 2)] = v, raster2[POS(0, 2)] = v, raster3[POS(0, 2)] = v;
+ raster1[POS(0, 3)] = v, raster2[POS(0, 3)] = v, raster3[POS(0, 3)] = v;
+ raster1[POS(1, 0)] = v, raster2[POS(1, 0)] = v, raster3[POS(1, 0)] = v;
+ raster1[POS(1, 1)] = v, raster2[POS(1, 1)] = v, raster3[POS(1, 1)] = v;
+ raster1[POS(1, 2)] = v, raster2[POS(1, 2)] = v, raster3[POS(1, 2)] = v;
+ raster1[POS(1, 3)] = v, raster2[POS(1, 3)] = v, raster3[POS(1, 3)] = v;
+ rasters[0] = raster1;
+ rasters[1] = raster2;
+ rasters[2] = raster3;
+ saturations[0] = 0.5;
+ saturations[1] = 0.25;
+ saturations[2] = 0.125;
+ primary_ys[0] = 0.375;
+ primary_ys[1] = 0.50;
+ primary_ys[2] = 0.125;
+ libglitter_per_channel_desaturate_double(rasters, 3, 6, 3, 4, 2, saturations, primary_ys);
+ ASSERT3(raster1[POS(0, 0)] == v, raster2[POS(0, 0)] == v, raster3[POS(0, 0)] == v);
+ ASSERT3(raster1[POS(0, 1)] == v, raster2[POS(0, 1)] == v, raster3[POS(0, 1)] == v);
+ ASSERT3(raster1[POS(0, 2)] == v, raster2[POS(0, 2)] == v, raster3[POS(0, 2)] == v);
+ ASSERT3(raster1[POS(0, 3)] == v, raster2[POS(0, 3)] == v, raster3[POS(0, 3)] == v);
+ ASSERT3(raster1[POS(1, 0)] == v, raster2[POS(1, 0)] == v, raster3[POS(1, 0)] == v);
+ ASSERT3(raster1[POS(1, 1)] == v, raster2[POS(1, 1)] == v, raster3[POS(1, 1)] == v);
+ ASSERT3(raster1[POS(1, 2)] == v, raster2[POS(1, 2)] == v, raster3[POS(1, 2)] == v);
+ ASSERT3(raster1[POS(1, 3)] == v, raster2[POS(1, 3)] == v, raster3[POS(1, 3)] == v);
+ raster1[POS(0, 0)] = 0, raster2[POS(0, 0)] = 0, raster3[POS(0, 0)] = 0;
+ raster1[POS(0, 1)] = 0, raster2[POS(0, 1)] = 0, raster3[POS(0, 1)] = 0;
+ raster1[POS(0, 2)] = 0, raster2[POS(0, 2)] = 0, raster3[POS(0, 2)] = 0;
+ raster1[POS(0, 3)] = 0, raster2[POS(0, 3)] = 0, raster3[POS(0, 3)] = 0;
+ raster1[POS(1, 0)] = 0, raster2[POS(1, 0)] = 0, raster3[POS(1, 0)] = 0;
+ raster1[POS(1, 1)] = 0, raster2[POS(1, 1)] = 0, raster3[POS(1, 1)] = 0;
+ raster1[POS(1, 2)] = 0, raster2[POS(1, 2)] = 0, raster3[POS(1, 2)] = 0;
+ raster1[POS(1, 3)] = 0, raster2[POS(1, 3)] = 0, raster3[POS(1, 3)] = 0;
+ ASSERT(!memcmp(raster1, zeroes, sizeof(raster1)));
+ ASSERT(!memcmp(raster2, zeroes, sizeof(raster2)));
+ ASSERT(!memcmp(raster3, zeroes, sizeof(raster3)));
+
+ memset(raster1, 0, sizeof(raster1));
+ memset(raster2, 0, sizeof(raster2));
+ memset(raster3, 0, sizeof(raster3));
+ raster1[POS(0, 0)] = v, raster2[POS(0, 0)] = v, raster3[POS(0, 0)] = v;
+ raster1[POS(0, 1)] = v, raster2[POS(0, 1)] = v, raster3[POS(0, 1)] = v;
+ raster1[POS(0, 2)] = v, raster2[POS(0, 2)] = v, raster3[POS(0, 2)] = v;
+ raster1[POS(0, 3)] = v, raster2[POS(0, 3)] = v, raster3[POS(0, 3)] = v;
+ raster1[POS(1, 0)] = v, raster2[POS(1, 0)] = v, raster3[POS(1, 0)] = v;
+ raster1[POS(1, 1)] = v, raster2[POS(1, 1)] = v, raster3[POS(1, 1)] = v;
+ raster1[POS(1, 2)] = v, raster2[POS(1, 2)] = v, raster3[POS(1, 2)] = v;
+ raster1[POS(1, 3)] = v, raster2[POS(1, 3)] = v, raster3[POS(1, 3)] = v;
+ rasters[0] = raster1;
+ rasters[1] = raster2;
+ rasters[2] = raster3;
+ saturations[0] = 0.5;
+ saturations[1] = 0.25;
+ saturations[2] = 0.125;
+ primary_ys[0] = 0.375;
+ primary_ys[1] = 0.5;
+ primary_ys[2] = 0.125;
+ libglitter_per_channel_desaturate_double(rasters, 3, 6, 3, 4, 2, saturations, NULL);
+ ASSERT3(eq(raster1[POS(0, 0)], v), eq(raster2[POS(0, 0)], v), eq(raster3[POS(0, 0)], v));
+ ASSERT3(eq(raster1[POS(0, 1)], v), eq(raster2[POS(0, 1)], v), eq(raster3[POS(0, 1)], v));
+ ASSERT3(eq(raster1[POS(0, 2)], v), eq(raster2[POS(0, 2)], v), eq(raster3[POS(0, 2)], v));
+ ASSERT3(eq(raster1[POS(0, 3)], v), eq(raster2[POS(0, 3)], v), eq(raster3[POS(0, 3)], v));
+ ASSERT3(eq(raster1[POS(1, 0)], v), eq(raster2[POS(1, 0)], v), eq(raster3[POS(1, 0)], v));
+ ASSERT3(eq(raster1[POS(1, 1)], v), eq(raster2[POS(1, 1)], v), eq(raster3[POS(1, 1)], v));
+ ASSERT3(eq(raster1[POS(1, 2)], v), eq(raster2[POS(1, 2)], v), eq(raster3[POS(1, 2)], v));
+ ASSERT3(eq(raster1[POS(1, 3)], v), eq(raster2[POS(1, 3)], v), eq(raster3[POS(1, 3)], v));
+ raster1[POS(0, 0)] = 0, raster2[POS(0, 0)] = 0, raster3[POS(0, 0)] = 0;
+ raster1[POS(0, 1)] = 0, raster2[POS(0, 1)] = 0, raster3[POS(0, 1)] = 0;
+ raster1[POS(0, 2)] = 0, raster2[POS(0, 2)] = 0, raster3[POS(0, 2)] = 0;
+ raster1[POS(0, 3)] = 0, raster2[POS(0, 3)] = 0, raster3[POS(0, 3)] = 0;
+ raster1[POS(1, 0)] = 0, raster2[POS(1, 0)] = 0, raster3[POS(1, 0)] = 0;
+ raster1[POS(1, 1)] = 0, raster2[POS(1, 1)] = 0, raster3[POS(1, 1)] = 0;
+ raster1[POS(1, 2)] = 0, raster2[POS(1, 2)] = 0, raster3[POS(1, 2)] = 0;
+ raster1[POS(1, 3)] = 0, raster2[POS(1, 3)] = 0, raster3[POS(1, 3)] = 0;
+ ASSERT(!memcmp(raster1, zeroes, sizeof(raster1)));
+ ASSERT(!memcmp(raster2, zeroes, sizeof(raster2)));
+ ASSERT(!memcmp(raster3, zeroes, sizeof(raster3)));
+ }
+
+ memset(raster1, 0, sizeof(raster1));
+ memset(raster2, 0, sizeof(raster2));
+ memset(raster3, 0, sizeof(raster3));
+ raster1[POS(0, 0)] = 4, raster2[POS(0, 0)] = 8;
+ raster1[POS(0, 1)] = 16, raster2[POS(0, 1)] = 2;
+ raster1[POS(0, 2)] = 1, raster2[POS(0, 2)] = 8;
+ raster1[POS(0, 3)] = 32, raster2[POS(0, 3)] = 4;
+ raster1[POS(1, 0)] = 8, raster2[POS(1, 0)] = 8;
+ raster1[POS(1, 1)] = -4, raster2[POS(1, 1)] = 2;
+ raster1[POS(1, 2)] = 16, raster2[POS(1, 2)] = -16;
+ raster1[POS(1, 3)] = 8, raster2[POS(1, 3)] = 2;
+ rasters[0] = raster1;
+ rasters[1] = raster2;
+ rasters[2] = raster3;
+ saturations[0] = 0.5;
+ saturations[1] = 0.25;
+ primary_ys[0] = 0.75;
+ primary_ys[1] = 0.25;
+ libglitter_per_channel_desaturate_double(rasters, 2, 6, 3, 4, 2, saturations, primary_ys);
+#define G(x, y) ((x) * 0.75 + (y) * 0.25)
+#define X(x, y) (((x) - G(x, y)) * 0.5 + G(x, y))
+#define Y(x, y) (((y) - G(x, y)) * 0.25 + G(x, y))
+ ASSERT2(raster1[POS(0, 0)] == X(4, 8), raster2[POS(0, 0)] == Y(4, 8));
+ ASSERT2(raster1[POS(0, 1)] == X(16, 2), raster2[POS(0, 1)] == Y(16, 2));
+ ASSERT2(raster1[POS(0, 2)] == X(1, 8), raster2[POS(0, 2)] == Y(1, 8));
+ ASSERT2(raster1[POS(0, 3)] == X(32, 4), raster2[POS(0, 3)] == Y(32, 4));
+ ASSERT2(raster1[POS(1, 0)] == X(8, 8), raster2[POS(1, 0)] == Y(8, 8));
+ ASSERT2(raster1[POS(1, 1)] == X(-4, 2), raster2[POS(1, 1)] == Y(-4, 2));
+ ASSERT2(raster1[POS(1, 2)] == X(16, -16), raster2[POS(1, 2)] == Y(16, -16));
+ ASSERT2(raster1[POS(1, 3)] == X(8, 2), raster2[POS(1, 3)] == Y(8, 2));
+#undef G
+#undef X
+#undef Y
+ raster1[POS(0, 0)] = 0, raster2[POS(0, 0)] = 0;
+ raster1[POS(0, 1)] = 0, raster2[POS(0, 1)] = 0;
+ raster1[POS(0, 2)] = 0, raster2[POS(0, 2)] = 0;
+ raster1[POS(0, 3)] = 0, raster2[POS(0, 3)] = 0;
+ raster1[POS(1, 0)] = 0, raster2[POS(1, 0)] = 0;
+ raster1[POS(1, 1)] = 0, raster2[POS(1, 1)] = 0;
+ raster1[POS(1, 2)] = 0, raster2[POS(1, 2)] = 0;
+ raster1[POS(1, 3)] = 0, raster2[POS(1, 3)] = 0;
+ ASSERT(!memcmp(raster1, zeroes, sizeof(raster1)));
+ ASSERT(!memcmp(raster2, zeroes, sizeof(raster2)));
+ ASSERT(!memcmp(raster3, zeroes, sizeof(raster3)));
+
+ memset(raster1, 0, sizeof(raster1));
+ memset(raster2, 0, sizeof(raster2));
+ memset(raster3, 0, sizeof(raster3));
+ raster1[POS(0, 0)] = 4, raster2[POS(0, 0)] = 8, raster3[POS(0, 0)] = 4;
+ raster1[POS(0, 1)] = 16, raster2[POS(0, 1)] = 2, raster3[POS(0, 1)] = 16;
+ raster1[POS(0, 2)] = 1, raster2[POS(0, 2)] = 8, raster3[POS(0, 2)] = 2;
+ raster1[POS(0, 3)] = 32, raster2[POS(0, 3)] = 4, raster3[POS(0, 3)] = 8;
+ raster1[POS(1, 0)] = 8, raster2[POS(1, 0)] = 8, raster3[POS(1, 0)] = 8;
+ raster1[POS(1, 1)] = -4, raster2[POS(1, 1)] = 2, raster3[POS(1, 1)] = 16;
+ raster1[POS(1, 2)] = 16, raster2[POS(1, 2)] = -16, raster3[POS(1, 2)] = -16;
+ raster1[POS(1, 3)] = 8, raster2[POS(1, 3)] = 2, raster3[POS(1, 3)] = 4;
+ rasters[0] = raster1;
+ rasters[1] = raster2;
+ rasters[2] = raster3;
+ saturations[0] = 0.5;
+ saturations[1] = 0.25;
+ saturations[2] = 0.125;
+ primary_ys[0] = 0.375;
+ primary_ys[1] = 0.5;
+ primary_ys[2] = 0.125;
+ libglitter_per_channel_desaturate_double(rasters, 3, 6, 3, 4, 2, saturations, primary_ys);
+#define G(x, y, z) ((x) * 0.375 + (y) * 0.5 + (z) * 0.125)
+#define X(x, y, z) (((x) - G(x, y, z)) * 0.5 + G(x, y, z))
+#define Y(x, y, z) (((y) - G(x, y, z)) * 0.25 + G(x, y, z))
+#define Z(x, y, z) (((z) - G(x, y, z)) * 0.125 + G(x, y, z))
+ ASSERT3(raster1[POS(0, 0)] == X(4, 8, 4), raster2[POS(0, 0)] == Y(4, 8, 4), raster3[POS(0, 0)] == Z(4, 8, 4));
+ ASSERT3(raster1[POS(0, 1)] == X(16, 2, 16), raster2[POS(0, 1)] == Y(16, 2, 16), raster3[POS(0, 1)] == Z(16, 2, 16));
+ ASSERT3(raster1[POS(0, 2)] == X(1, 8, 2), raster2[POS(0, 2)] == Y(1, 8, 2), raster3[POS(0, 2)] == Z(1, 8, 2));
+ ASSERT3(raster1[POS(0, 3)] == X(32, 4, 8), raster2[POS(0, 3)] == Y(32, 4, 8), raster3[POS(0, 3)] == Z(32, 4, 8));
+ ASSERT3(raster1[POS(1, 0)] == X(8, 8, 8), raster2[POS(1, 0)] == Y(8, 8, 8), raster3[POS(1, 0)] == Z(8, 8, 8));
+ ASSERT3(raster1[POS(1, 1)] == X(-4, 2, 16), raster2[POS(1, 1)] == Y(-4, 2, 16), raster3[POS(1, 1)] == Z(-4, 2, 16));
+ ASSERT3(raster1[POS(1, 2)] == X(16, -16, -16), raster2[POS(1, 2)] == Y(16, -16, -16), raster3[POS(1, 2)] == Z(16, -16, -16));
+ ASSERT3(raster1[POS(1, 3)] == X(8, 2, 4), raster2[POS(1, 3)] == Y(8, 2, 4), raster3[POS(1, 3)] == Z(8, 2, 4));
+#undef G
+#undef X
+#undef Y
+#undef Z
+ raster1[POS(0, 0)] = 0, raster2[POS(0, 0)] = 0, raster3[POS(0, 0)] = 0;
+ raster1[POS(0, 1)] = 0, raster2[POS(0, 1)] = 0, raster3[POS(0, 1)] = 0;
+ raster1[POS(0, 2)] = 0, raster2[POS(0, 2)] = 0, raster3[POS(0, 2)] = 0;
+ raster1[POS(0, 3)] = 0, raster2[POS(0, 3)] = 0, raster3[POS(0, 3)] = 0;
+ raster1[POS(1, 0)] = 0, raster2[POS(1, 0)] = 0, raster3[POS(1, 0)] = 0;
+ raster1[POS(1, 1)] = 0, raster2[POS(1, 1)] = 0, raster3[POS(1, 1)] = 0;
+ raster1[POS(1, 2)] = 0, raster2[POS(1, 2)] = 0, raster3[POS(1, 2)] = 0;
+ raster1[POS(1, 3)] = 0, raster2[POS(1, 3)] = 0, raster3[POS(1, 3)] = 0;
+ ASSERT(!memcmp(raster1, zeroes, sizeof(raster1)));
+ ASSERT(!memcmp(raster2, zeroes, sizeof(raster2)));
+ ASSERT(!memcmp(raster3, zeroes, sizeof(raster3)));
+
+ memset(raster1, 0, sizeof(raster1));
+ memset(raster2, 0, sizeof(raster2));
+ memset(raster3, 0, sizeof(raster3));
+ raster1[POS(0, 0)] = 4, raster2[POS(0, 0)] = 8, raster3[POS(0, 0)] = 4;
+ raster1[POS(0, 1)] = 16, raster2[POS(0, 1)] = 2, raster3[POS(0, 1)] = 16;
+ raster1[POS(0, 2)] = 1, raster2[POS(0, 2)] = 8, raster3[POS(0, 2)] = 2;
+ raster1[POS(0, 3)] = 32, raster2[POS(0, 3)] = 4, raster3[POS(0, 3)] = 8;
+ raster1[POS(1, 0)] = 8, raster2[POS(1, 0)] = 8, raster3[POS(1, 0)] = 8;
+ raster1[POS(1, 1)] = -4, raster2[POS(1, 1)] = 2, raster3[POS(1, 1)] = 16;
+ raster1[POS(1, 2)] = 16, raster2[POS(1, 2)] = -16, raster3[POS(1, 2)] = -16;
+ raster1[POS(1, 3)] = 8, raster2[POS(1, 3)] = 2, raster3[POS(1, 3)] = 4;
+ rasters[0] = raster1;
+ rasters[1] = raster2;
+ rasters[2] = raster3;
+ saturations[0] = 0.5;
+ saturations[1] = 0.25;
+ saturations[2] = 0.125;
+ libglitter_per_channel_desaturate_double(rasters, 3, 6, 3, 4, 2, saturations, NULL);
+#define G(x, y, z) ((x) * RY + (y) * GY + (z) * BY)
+#define X(x, y, z) (((x) - G(x, y, z)) * 0.5 + G(x, y, z))
+#define Y(x, y, z) (((y) - G(x, y, z)) * 0.25 + G(x, y, z))
+#define Z(x, y, z) (((z) - G(x, y, z)) * 0.125 + G(x, y, z))
+ ASSERT(eq(raster1[POS(0, 0)], X(4, 8, 4)));
+ ASSERT(eq(raster1[POS(0, 1)], X(16, 2, 16)));
+ ASSERT(eq(raster1[POS(0, 2)], X(1, 8, 2)));
+ ASSERT(eq(raster1[POS(0, 3)], X(32, 4, 8)));
+ ASSERT(eq(raster1[POS(1, 0)], X(8, 8, 8)));
+ ASSERT(eq(raster1[POS(1, 1)], X(-4, 2, 16)));
+ ASSERT(eq(raster1[POS(1, 2)], X(16, -16, -16)));
+ ASSERT(eq(raster1[POS(1, 3)], X(8, 2, 4)));
+ ASSERT(eq(raster2[POS(0, 0)], Y(4, 8, 4)));
+ ASSERT(eq(raster2[POS(0, 1)], Y(16, 2, 16)));
+ ASSERT(eq(raster2[POS(0, 2)], Y(1, 8, 2)));
+ ASSERT(eq(raster2[POS(0, 3)], Y(32, 4, 8)));
+ ASSERT(eq(raster2[POS(1, 0)], Y(8, 8, 8)));
+ ASSERT(eq(raster2[POS(1, 1)], Y(-4, 2, 16)));
+ ASSERT(eq(raster2[POS(1, 2)], Y(16, -16, -16)));
+ ASSERT(eq(raster2[POS(1, 3)], Y(8, 2, 4)));
+ ASSERT(eq(raster3[POS(0, 0)], Z(4, 8, 4)));
+ ASSERT(eq(raster3[POS(0, 1)], Z(16, 2, 16)));
+ ASSERT(eq(raster3[POS(0, 2)], Z(1, 8, 2)));
+ ASSERT(eq(raster3[POS(0, 3)], Z(32, 4, 8)));
+ ASSERT(eq(raster3[POS(1, 0)], Z(8, 8, 8)));
+ ASSERT(eq(raster3[POS(1, 1)], Z(-4, 2, 16)));
+ ASSERT(eq(raster3[POS(1, 2)], Z(16, -16, -16)));
+ ASSERT(eq(raster3[POS(1, 3)], Z(8, 2, 4)));
+#undef G
+#undef X
+#undef Y
+#undef Z
+ raster1[POS(0, 0)] = 0, raster2[POS(0, 0)] = 0, raster3[POS(0, 0)] = 0;
+ raster1[POS(0, 1)] = 0, raster2[POS(0, 1)] = 0, raster3[POS(0, 1)] = 0;
+ raster1[POS(0, 2)] = 0, raster2[POS(0, 2)] = 0, raster3[POS(0, 2)] = 0;
+ raster1[POS(0, 3)] = 0, raster2[POS(0, 3)] = 0, raster3[POS(0, 3)] = 0;
+ raster1[POS(1, 0)] = 0, raster2[POS(1, 0)] = 0, raster3[POS(1, 0)] = 0;
+ raster1[POS(1, 1)] = 0, raster2[POS(1, 1)] = 0, raster3[POS(1, 1)] = 0;
+ raster1[POS(1, 2)] = 0, raster2[POS(1, 2)] = 0, raster3[POS(1, 2)] = 0;
+ raster1[POS(1, 3)] = 0, raster2[POS(1, 3)] = 0, raster3[POS(1, 3)] = 0;
+ ASSERT(!memcmp(raster1, zeroes, sizeof(raster1)));
+ ASSERT(!memcmp(raster2, zeroes, sizeof(raster2)));
+ ASSERT(!memcmp(raster3, zeroes, sizeof(raster3)));
+
+ return 0;
}