File size: 5,855 Bytes
9425aed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "sov_test_stubs.h"
#include "sov_rtx.h"

/* Host stubs */
int  sov_cuda_memcpy_h2d(void* dst, const void* src, size_t sz) { memcpy(dst,src,sz); return 0; }
int  sov_cuda_init(void) { return 0; }
int  sov_cuda_load_ptx(const char* p, unsigned int s, void** m) { (void)p;(void)s;(void)m; return 0; }
int  sov_cuda_flash_attention(int a,int b,float*c,float*d,float*e,float*f,int*g,int*h,int i,int j)
     { (void)a;(void)b;(void)c;(void)d;(void)e;(void)f;(void)g;(void)h;(void)i;(void)j; return 0; }
void* sov_cuda_malloc(size_t s) { (void)s; return 0; }
int  sov_scheduler_init(sov_scheduler_t* s) { (void)s; return 0; }
int  sov_scheduler_step(sov_scheduler_t* s, void* b, void* k) { (void)s;(void)b;(void)k; return 0; }
int  sov_kv_init(void* k, int a, int b, int c, int d, int e) { (void)k;(void)a;(void)b;(void)c;(void)d;(void)e; return 0; }
int  sov_kv_allocate_blocks(void* k, int a, int b, int* t) { (void)k;(void)a;(void)b;(void)t; return 0; }
int  sov_kv_append_tokens(void* k, int* t, float* kp, float* v, int l, int p)
     { (void)k;(void)t;(void)kp;(void)v;(void)l;(void)p; return 0; }
int  sov_gguf_load(const char* p, void** c) { (void)p;(void)c; return 0; }
const void* sov_gguf_get_tensor(void* c, const char* n) { (void)c;(void)n; return 0; }
int  sov_bft_vote(sov_bft_state_t* b, uint8_t v) { (void)b;(void)v; return 0; }
int  sov_bft_check_quorum(const sov_bft_state_t* b) { (void)b; return 0; }
int  sov_worm_checkpoint(void* k) { (void)k; return 0; }
int  sov_worm_restore(void* k) { (void)k; return 0; }
int  sov_set_power_state(sov_power_state_t s) { (void)s; return 0; }
sov_power_state_t sov_get_power_state(void) { return SOV_POWER_ACTIVE; }
int  sov_speculative_draft(void* b, int d, void* k) { (void)b;(void)d;(void)k; return 0; }
int  sov_speculative_verify(void* d, void* t, int l) { (void)d;(void)t;(void)l; return 0; }
float sov_janet_get(int s) { (void)s; return 0.0f; }
void  sov_janet_set(int s, float v) { (void)s;(void)v; }

#include "../src/sampler.c"

/* f16 encode helper */
static uint16_t f32_to_f16(float v) {
    uint32_t bits;
    memcpy(&bits, &v, 4);
    uint16_t sign = (bits >> 16) & 0x8000;
    int exp  = ((bits >> 23) & 0xff) - 127 + 15;
    uint32_t mant = bits & 0x7fffff;
    if (exp <= 0)  return sign;
    if (exp >= 31) return sign | 0x7c00;
    return (uint16_t)(sign | ((uint16_t)exp << 10) | (mant >> 13));
}

static int test_greedy(void) {
    float logits[8] = {0.1f,0.5f,0.9f,0.2f,0.3f,0.8f,0.4f,0.6f};
    SOV_ASSERT(sov_sample_greedy(logits, 8) == 2);
    SOV_PASS("greedy");
    return 0;
}

static int test_greedy_f16(void) {
    uint16_t logits[4] = { f32_to_f16(0.1f), f32_to_f16(5.0f),
                           f32_to_f16(1.0f), f32_to_f16(2.0f) };
    SOV_ASSERT(sov_sample_greedy_f16(logits, 4) == 1);
    SOV_PASS("greedy_f16");
    return 0;
}

static int test_sample_token_greedy(void) {
    float logits[4] = {0.0f,5.0f,1.0f,2.0f};
    SOV_ASSERT(sov_sample_token(logits, 4, 0.0f, 1.0f, 0, 0) == 1);
    SOV_PASS("sample_token_greedy");
    return 0;
}

static int test_flat_distribution(void) {
    static float logits[256];
    uint64_t rng = UINT64_C(0xdeadbeefcafe1234);
    int i, tok;
    for (i = 0; i < 256; i++) logits[i] = 0.0f;
    tok = sov_sample_token(logits, 256, 1.0f, 1.0f, 0, &rng);
    SOV_ASSERT(tok >= 0 && tok < 256);
    SOV_PASS("flat_distribution");
    return 0;
}

/* top_k=128 uses heapsort path; spike at 100 must always win */
static int test_topk_heapsort_path(void) {
    static float logits[256];
    uint64_t rng = UINT64_C(0x1234567890abcdef);
    int i, tok;
    for (i = 0; i < 256; i++) logits[i] = -100.0f;
    logits[100] = 10.0f;
    for (i = 0; i < 50; i++) {
        tok = sov_sample_token(logits, 256, 1.0f, 1.0f, 128, &rng);
        SOV_ASSERT(tok == 100);
    }
    SOV_PASS("topk_heapsort_path");
    return 0;
}

/* flat 128-tok dist, top_k=0, top_p=0.75 → tokens 0..95 only,

 * and tokens 64..95 must appear (old 64-cap would never reach them) */
static int test_topk_zero_above_64_reachable(void) {
    static float logits[128];
    uint64_t rng = UINT64_C(0xabcdef1234567890);
    int i, tok, saw_upper = 0;
    for (i = 0; i < 128; i++) logits[i] = 0.0f;
    for (i = 0; i < 4096; i++) {
        tok = sov_sample_token(logits, 128, 1.0f, 0.75f, 0, &rng);
        SOV_ASSERT(tok >= 0 && tok < 96);
        if (tok >= 64) saw_upper = 1;
    }
    SOV_ASSERT(saw_upper);
    SOV_PASS("topk_zero_above_64_reachable");
    return 0;
}

static int test_vocab_ceiling(void) {
    float one = 1.0f;
    SOV_ASSERT(SOV_SAMPLER_MAX_VOCAB == 131072);
    SOV_ASSERT(sov_sample_greedy(&one, 131073) == -1);
    SOV_PASS("vocab_ceiling");
    return 0;
}

static int test_bad_args(void) {
    float logits[4] = {1,2,3,4};
    uint64_t rng = 1, zero = 0;
    SOV_ASSERT(sov_sample_greedy(NULL, 4)              == -1);
    SOV_ASSERT(sov_sample_greedy(logits, 0)             == -1);
    SOV_ASSERT(sov_sample_token(NULL, 4,1,1,0,&rng)     == -1);
    SOV_ASSERT(sov_sample_token(logits,4,1,1,-1,&rng)   == -1);
    SOV_ASSERT(sov_sample_token(logits,4,-1,1,0,&rng)   == -1);
    SOV_ASSERT(sov_sample_token(logits,4,1,1,0,NULL)    == -1);
    SOV_ASSERT(sov_sample_token(logits,4,1,1,0,&zero)   == -1);
    SOV_PASS("bad_args");
    return 0;
}

int main(void) {
    int fail = 0;
    fail |= test_greedy();
    fail |= test_greedy_f16();
    fail |= test_sample_token_greedy();
    fail |= test_flat_distribution();
    fail |= test_topk_heapsort_path();
    fail |= test_topk_zero_above_64_reachable();
    fail |= test_vocab_ceiling();
    fail |= test_bad_args();
    if (!fail) printf("ALL PASS\n");
    return fail;
}