skip to content
==> src/cubic.c <==
1/* programs/train's and infer's CPU reference (mesh-ref lib.rs `cubic`, `warp_sum`, `step_sums`,
2 * `apply`, `loss`, `sin_pi`, `grid`, `samples`). */
3#include "mesh/ref/cubic.h"
4
5#include "mesh/abi/view_train.h"
6#include "mesh/ftz.h"
7#include "mesh/ref/block.h"
8
9float mesh_cubic(const float p[4], float x) {
10    float x2 = mesh_ftz_mul(x, x), x3 = mesh_ftz_mul(x2, x);
11    return mesh_ftz_add(mesh_ftz_add(mesh_ftz_add(p[0], mesh_ftz_mul(p[1], x)), mesh_ftz_mul(p[2], x2)),
12                        mesh_ftz_mul(p[3], x3));
13}
14
15float mesh_cubic_warp_sum(const float v[32]) {
16    float w[32];
17    for (int l = 0; l < 32; l++) w[l] = v[l];
18    mesh_block_warp_reduce_f32(w, mesh_block_add_f32);
19    return w[0];
20}
21
22void mesh_cubic_step_sums(const float p[4], const float *xs, const float *ys, uint32_t off, float out[5]) {
23    float lanes[5][32];
24    for (uint32_t l = 0; l < 32; l++) {
25        size_t i = (8 * l + off) % 256;
26        float x = xs[i], y = ys[i];
27        float e = mesh_ftz_sub(mesh_cubic(p, x), y);
28        float g = mesh_ftz_mul(2.0f, e);
29        float x2 = mesh_ftz_mul(x, x);
30        lanes[0][l] = mesh_ftz_mul(e, e);
31        lanes[1][l] = g;
32        lanes[2][l] = mesh_ftz_mul(g, x);
33        lanes[3][l] = mesh_ftz_mul(g, x2);
34        lanes[4][l] = mesh_ftz_mul(g, mesh_ftz_mul(x2, x));
35    }
36    for (int k = 0; k < 5; k++) out[k] = mesh_cubic_warp_sum(lanes[k]);
37}
38
39void mesh_cubic_apply(float p[4], const float s[5], float lr, float inv) {
40    for (int k = 0; k < 4; k++) p[k] = mesh_ftz_sub(p[k], mesh_ftz_mul(mesh_ftz_mul(lr, s[k + 1]), inv));
41}
42
43float mesh_cubic_loss(const float s[5], float inv) { return mesh_ftz_mul(s[0], inv); }
44
45float mesh_cubic_sin_pi(float x) {
46    double t = mesh_ftz_to_f64(x);
47    if (t > 0.5)
48        t = 1.0 - t;
49    else if (t < -0.5)
50        t = -1.0 - t;
51    double a = 3.141592653589793 * t;
52    double a2 = a * a;
53    double s = 1.0;
54    for (uint32_t k = 11; k >= 1; k--) s = 1.0 - a2 / (double)((2 * k) * (2 * k + 1)) * s;
55    return mesh_ftz_from_f64(a * s);
56}
57
58void mesh_cubic_grid(uint32_t n, float *out) {
59    float d = mesh_ftz_from_u32(n - 1);
60    for (uint32_t i = 0; i < n; i++) out[i] = mesh_ftz_add(-1.0f, mesh_ftz_div(mesh_ftz_mul(2.0f, mesh_ftz_from_u32(i)), d));
61}
62
63void mesh_cubic_samples(float *xs, float *ys) {
64    mesh_cubic_grid(MESH_TRAIN_SAMPLES, xs);
65    for (uint32_t i = 0; i < MESH_TRAIN_SAMPLES; i++) ys[i] = mesh_cubic_sin_pi(xs[i]);
66}