skip to content
==> 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}