==> tests/golden.c <==1/* Golden digests from the Rust (pathtrace-core, R = mesh-ref's Z): four tiles of the default
2 * scene over two passes (pass digests, fold digests, pixels, accumulators, a re-tone), the scalar
3 * functions (sqrt, cis, quantize, tonemap) over 200 000 inputs, and 4000 camera samples. */
4#include "pathtrace/z.h"
5
6#include "pathtrace/default_scene.h"
7
8#include <stdio.h>
9#include <stdlib.h>
10
11static int failures;
12
13static uint64_t fh(uint64_t h, uint64_t w) { return (h ^ w) * 0x100000001b3ull; }
14
15static uint32_t mix(uint32_t x) {
16 x ^= x >> 16;
17 x *= 0x7feb352du;
18 x ^= x >> 15;
19 x *= 0x846ca68bu;
20 return x ^ (x >> 16);
21}
22
23/* The operand generator of the golden program (mesh-ftz's tests have the same). */
24static uint32_t gen(uint32_t m, uint32_t i) {
25 uint32_t h = mix((i * 0x9e3779b9u) ^ (m * 0x85ebca6bu));
26 uint32_t h2 = mix(h ^ 0x27d4eb2fu);
27 if (m == 0) return h;
28 if (m == 1) return (h & 0x80000000u) | ((h2 % 41) << 23) | (h & 0x007fffffu);
29 return (h & 0x80000000u) | ((50 + h2 % 31) << 23) | (h & 0x007fffffu);
30}
31
32static void want(const char *what, uint64_t got, uint64_t want) {
33 if (got != want) {
34 fprintf(stderr, "%s: %#018llx, want %#018llx\n", what, (unsigned long long)got, (unsigned long long)want);
35 failures++;
36 }
37}
38
39static void tiles(const uint32_t *sc) {
40 uint64_t h = 0xcbf29ce484222325ull;
41 const uint32_t ts[4] = {0, 42, 157, 299};
42 pt_v *acc = malloc(PT_TILE_PIX * sizeof *acc), *part = malloc(PT_TILE_PIX * sizeof *part);
43 uint32_t *rgb = malloc(PT_TILE_PIX * sizeof *rgb);
44 for (int i = 0; i < 4; i++) {
45 for (uint32_t p = 0; p < PT_TILE_PIX; p++) acc[p] = (pt_v){0, 0, 0}, rgb[p] = 0;
46 for (uint32_t p = 0; p < 2; p++) {
47 h = fh(h, pt_tile_pass_z(sc, ts[i], p, part));
48 uint64_t da, dr;
49 pt_tile_fold_z(sc, p + 1, p % 2, acc, part, rgb, &da, &dr);
50 h = fh(fh(h, da), dr);
51 }
52 for (uint32_t p = 0; p < PT_TILE_PIX; p++) h = fh(h, rgb[p]);
53 for (uint32_t p = 0; p < PT_TILE_PIX; p++)
54 h = fh(fh(fh(h, pt_to_bits(acc[p].x)), pt_to_bits(acc[p].y)), pt_to_bits(acc[p].z));
55 h = fh(h, pt_tile_retone_z(sc, 2, 1, acc, rgb));
56 }
57 free(acc), free(part), free(rgb);
58 want("tiles", h, 0x0ebdc45fd60c40a7ull);
59}
60
61static void scalars(void) {
62 uint64_t h = 0xcbf29ce484222325ull;
63 for (uint32_t i = 0; i < 200000; i++) {
64 float x = pt_from_bits(gen(i % 3, i));
65 h = fh(h, pt_to_bits(pt_sqrt_z(x)));
66 float c, s;
67 pt_cis_z(mix(i), &c, &s);
68 h = fh(fh(h, pt_to_bits(c)), pt_to_bits(s));
69 h = fh(h, pt_quantize_z(x));
70 h = fh(h, pt_quantize_z(pt_from_bits(mix(i) >> 2)));
71 pt_v v = {x, pt_from_bits(mix(i) >> 1), pt_from_bits(0x3f000000u ^ (i & 0xffff))};
72 h = fh(h, pt_tonemap_z(v, 1 + i % 64, pt_from_bits(0x3f800000u), i % 2));
73 }
74 want("scalars", h, 0x2b90b937379bba2aull);
75}
76
77static void samples(const uint32_t *sc) {
78 pt_layout l = pt_layout_of(sc);
79 uint64_t h = 0xcbf29ce484222325ull;
80 for (uint32_t i = 0; i < 4000; i++) {
81 pt_v v = pt_sample_z(sc, &l, mix(i) % 640, mix(i ^ 0xabcdefu) % 360, i);
82 h = fh(fh(fh(h, pt_to_bits(v.x)), pt_to_bits(v.y)), pt_to_bits(v.z));
83 }
84 want("samples", h, 0x15444c3b8761be83ull);
85}
86
87int main(void) {
88 tiles(pt_default_scene); /* the same digest as the f32 instantiation's: no value here is subnormal */
89 scalars();
90 samples(pt_default_scene);
91 return failures != 0;
92}