GCC Code Coverage Report


Directory: brotensor/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 93.4% 328 / 0 / 351
Functions: 100.0% 28 / 0 / 28
Branches: 36.1% 338 / 0 / 936

src/api/native_tensor_extra.cpp
Line Branch Exec Source
1 // native_tensor_extra.cpp — the brotensor ops that never had a JS binding:
2 // the elementwise / reduction / index half, the INT32 upload + download pair
3 // the index-taking ops need, and the group's registration entry point (which
4 // chains native_tensor_extra_nn.cpp and native_tensor_extra_conv.cpp).
5 //
6 // Everything here is a free function on `bro.tensor`; js/tensor_extra.js is
7 // the wrapper half that validates arguments and reads the error slot back.
8 // Every body checks each operand against the dims it is handed before the op
9 // runs (the ops trust their caller's dims; from JS that trust is an
10 // out-of-bounds read or write) — see native_tensor_extra_util.h.
11
12 #include "native_tensor_extra_decl.h"
13 #include "native_tensor_extra_util.h"
14 #include "api_internal.h"
15 #include "native_register.h"
16
17 #include <cmath>
18 #include <cstring>
19 #include <string>
20 #include <vector>
21
22 using namespace brotensor::api;
23 using namespace brotensor::api::extra;
24
25 namespace brotensor::api::extra {
26
27 68 bool hostInt32(const char* label, const char* name, const brotensor::Tensor* t, int64_t n,
28 std::vector<int32_t>& out) {
29
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
68 if (!needElems(label, name, t, n)) return false;
30 66 out.clear();
31
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (t->empty()) return true;
32 66 const brotensor::Tensor host = t->to(brotensor::Device::CPU);
33
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 const auto count = static_cast<size_t>(host.size());
34
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 out.resize(count);
35
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 22 times.
66 if (host.dtype == brotensor::Dtype::INT32) {
36
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 std::memcpy(out.data(), host.host_raw(), count * sizeof(int32_t));
37 44 return true;
38 }
39
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (host.dtype == brotensor::Dtype::FP32) {
40
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 const float* f = host.host_f32();
41
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 20 times.
66 for (size_t i = 0; i < count; ++i) {
42 46 const float v = f[i];
43
4/6
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 44 times.
46 if (!(v == std::floor(v)) || v < -2147483648.0f || v >= 2147483648.0f) {
44
8/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
2 setError(std::string(label) + ": " + name + "[" + std::to_string(i) +
45 "] is not a whole number that fits INT32");
46 2 return false;
47 }
48 44 out[i] = static_cast<int32_t>(v);
49 44 }
50 20 return true;
51 }
52 ✗ setError(std::string(label) + ": " + name + " is " + dtypeToString(host.dtype) + ", expected int32 (or whole-number fp32)");
53 ✗ return false;
54 68 }
55
56 48 const brotensor::Tensor& int32Operand(const brotensor::Tensor& t, const std::vector<int32_t>& vals,
57 brotensor::Tensor& scratch) {
58
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 14 times.
48 if (t.dtype == brotensor::Dtype::INT32) return t;
59 28 scratch = brotensor::Tensor::from_raw_bytes_on(t.device, vals.data(), t.rows, t.cols,
60 14 brotensor::Dtype::INT32, vals.size() * sizeof(int32_t));
61 14 return scratch;
62 48 }
63
64 50 bool needIndicesIn(const char* label, const char* name, const std::vector<int32_t>& vals, int64_t n,
65 int64_t lo, int64_t hi) {
66
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 36 times.
156 for (int64_t i = 0; i < n && i < static_cast<int64_t>(vals.size()); ++i) {
67 120 const int64_t v = vals[static_cast<size_t>(i)];
68
4/4
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 106 times.
120 if (v < lo || v >= hi) {
69
10/20
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 14 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 14 times.
✗ Branch 19 not taken.
28 setError(std::string(label) + ": " + name + "[" + std::to_string(i) + "] = " + std::to_string(v) +
70
6/12
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
14 " is outside [" + std::to_string(lo) + ", " + std::to_string(hi) + ")");
71 14 return false;
72 }
73 106 }
74 36 return true;
75 50 }
76
77 } // namespace brotensor::api::extra
78
79 namespace {
80
81 thread_local std::vector<int32_t> tl_download_i32;
82
83 12 void emptyBuffer(bronze_native_buffer* out) {
84 12 out->data = nullptr;
85 12 out->length = 0;
86 12 out->release = nullptr;
87 12 out->ctx = nullptr;
88 12 }
89
90 // The FP32-only elementwise pair shape: x FP32, dY the same size.
91 14 bool fp32Pair(const char* label, void* x, const char* xn, void* dY) {
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!need(label, {x, dY})) return false;
93
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
28 return needDtype(label, xn, toTensor(x), brotensor::Dtype::FP32) &&
94
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 needDtype(label, "dY", toTensor(dY), brotensor::Dtype::FP32) &&
95 14 needSameSize(label, "dY", toTensor(dY), toTensor(x));
96 14 }
97
98 } // namespace
99
100 extern "C" {
101
102 // ---- INT32 upload / download -----------------------------------------------
103
104 50 void bro_tensor_uploadInt32(void* self, const int32_t* data, uint32_t data_len) {
105 50 auto* t = toTensor(self);
106
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 if (!t || !data) {
107 ✗ setError("uploadInt32: not a GpuTensor / Int32Array");
108 ✗ return;
109 }
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (data_len > static_cast<uint32_t>(INT_MAX)) {
111 ✗ setError("uploadInt32: too many elements");
112 ✗ return;
113 }
114 50 int r = t->rows, c = t->cols;
115
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (static_cast<int64_t>(r) * c != static_cast<int64_t>(data_len)) {
116 ✗ r = static_cast<int>(data_len);
117 ✗ c = 1;
118 ✗ }
119 BROTENSOR_API_TRY
120 // The typed-array view is only valid for this call: copy it into the
121 // tensor before anything else runs.
122
3/6
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
50 *t = brotensor::Tensor::from_raw_bytes_on(brotensor::default_device(), data, r, c,
123 brotensor::Dtype::INT32,
124 50 static_cast<size_t>(data_len) * sizeof(int32_t));
125
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
50 BROTENSOR_API_CATCH("uploadInt32")
126 50 }
127
128 12 void bro_tensor_downloadInt32(void* self, bronze_native_buffer* out) {
129
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (!out) return;
130 12 emptyBuffer(out);
131 12 auto* t = toTensor(self);
132
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (!t) {
133 ✗ setError("downloadInt32: not a GpuTensor");
134 ✗ return;
135 }
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (t->empty()) return;
137
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (t->dtype != brotensor::Dtype::INT32) {
138
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 setError(std::string("downloadInt32: tensor is ") + dtypeToString(t->dtype) + ", expected int32");
139 2 return;
140 }
141 BROTENSOR_API_TRY
142
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 const brotensor::Tensor host = t->to(brotensor::Device::CPU);
143
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 tl_download_i32.resize(static_cast<size_t>(host.size()));
144
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 std::memcpy(tl_download_i32.data(), host.host_raw(), tl_download_i32.size() * sizeof(int32_t));
145 10 out->data = tl_download_i32.data();
146 10 out->length = static_cast<uint32_t>(tl_download_i32.size());
147
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
10 BROTENSOR_API_CATCH("downloadInt32")
148 12 }
149
150 // ---- bias adds + axpby -----------------------------------------------------
151
152 6 void bro_tensor_addChannelBiasInplace(void* y, void* bias, int32_t C, int32_t L) {
153 6 constexpr const char* lb = "addChannelBiasInplace";
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!need(lb, {y, bias})) return;
155 6 auto* Y = toTensor(y);
156 6 auto* B = toTensor(bias);
157
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (!needFloat(lb, "y", Y) || !needSameDtype(lb, "bias", B, Y)) return;
158 6 const int64_t n = prod({C, L});
159
1/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6 if (n < 0) { setError(std::string(lb) + ": negative C or L"); return; }
160
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (n != Y->size()) {
161
8/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
2 setError(std::string(lb) + ": y holds " + std::to_string(Y->size()) + " elements, C*L is " + std::to_string(n));
162 2 return;
163 }
164
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!needElems(lb, "bias", B, C)) return;
165 BROTENSOR_API_TRY
166
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 brotensor::add_channel_bias_inplace(*Y, *B, C, L);
167
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH(lb)
168 6 }
169
170 4 void bro_tensor_addRowBiasInplace(void* y, void* bias) {
171 4 constexpr const char* lb = "addRowBiasInplace";
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!need(lb, {y, bias})) return;
173 4 auto* Y = toTensor(y);
174 4 auto* B = toTensor(bias);
175
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!needFloat(lb, "Y", Y) || !needSameDtype(lb, "bias", B, Y)) return;
176
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (B->size() != Y->cols) {
177
7/14
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
6 setError(std::string(lb) + ": bias holds " + std::to_string(B->size()) + " elements, Y has " +
178
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 std::to_string(Y->cols) + " columns");
179 2 return;
180 }
181 BROTENSOR_API_TRY
182
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 brotensor::add_row_bias_inplace(*Y, *B);
183
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH(lb)
184 4 }
185
186 4 void bro_tensor_axpbyInplace(void* y, void* x, double a, double b) {
187 4 constexpr const char* lb = "axpbyInplace";
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!need(lb, {y, x})) return;
189 4 auto* Y = toTensor(y);
190 4 auto* X = toTensor(x);
191
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
4 if (!needFloat(lb, "y", Y) || !needSameDtype(lb, "x", X, Y) || !needSameSize(lb, "x", X, Y)) return;
192 BROTENSOR_API_TRY
193
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 brotensor::axpby_inplace(*Y, *X, static_cast<float>(a), static_cast<float>(b));
194
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH(lb)
195 4 }
196
197 // ---- sin / cos / rsqrt (FP32 elementwise) ----------------------------------
198
199 2 void bro_tensor_sinForward(void* x, void* y) {
200
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!need("sinForward", {x, y}) || !needDtype("sinForward", "x", toTensor(x), brotensor::Dtype::FP32)) return;
201 BROTENSOR_API_TRY
202
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 brotensor::sin_forward(*toTensor(x), *toTensor(y));
203
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("sinForward")
204 2 }
205
206 4 void bro_tensor_sinBackward(void* x, void* dY, void* dX) {
207
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (!need("sinBackward", {dX}) || !fp32Pair("sinBackward", x, "x", dY)) return;
208 BROTENSOR_API_TRY
209
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 brotensor::sin_backward(*toTensor(x), *toTensor(dY), *toTensor(dX));
210
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("sinBackward")
211 4 }
212
213 4 void bro_tensor_cosForward(void* x, void* y) {
214
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (!need("cosForward", {x, y}) || !needDtype("cosForward", "x", toTensor(x), brotensor::Dtype::FP32)) return;
215 BROTENSOR_API_TRY
216
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 brotensor::cos_forward(*toTensor(x), *toTensor(y));
217
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("cosForward")
218 4 }
219
220 2 void bro_tensor_cosBackward(void* x, void* dY, void* dX) {
221
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!need("cosBackward", {dX}) || !fp32Pair("cosBackward", x, "x", dY)) return;
222 BROTENSOR_API_TRY
223
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 brotensor::cos_backward(*toTensor(x), *toTensor(dY), *toTensor(dX));
224
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("cosBackward")
225 2 }
226
227 2 void bro_tensor_rsqrtForward(void* x, void* y) {
228
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!need("rsqrtForward", {x, y}) || !needDtype("rsqrtForward", "x", toTensor(x), brotensor::Dtype::FP32)) return;
229 BROTENSOR_API_TRY
230
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 brotensor::rsqrt_forward(*toTensor(x), *toTensor(y));
231
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("rsqrtForward")
232 2 }
233
234 4 void bro_tensor_rsqrtBackward(void* y, void* dY, void* dX) {
235
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (!need("rsqrtBackward", {dX}) || !fp32Pair("rsqrtBackward", y, "y", dY)) return;
236 BROTENSOR_API_TRY
237
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 brotensor::rsqrt_backward(*toTensor(y), *toTensor(dY), *toTensor(dX));
238
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("rsqrtBackward")
239 4 }
240
241 // ---- pixel norm --------------------------------------------------------------
242
243 2 void bro_tensor_pixelNormForward(void* X, double eps, void* Y) {
244
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!need("pixelNormForward", {X, Y}) ||
245 2 !needDtype("pixelNormForward", "X", toTensor(X), brotensor::Dtype::FP32)) return;
246 BROTENSOR_API_TRY
247
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 brotensor::pixel_norm_forward(*toTensor(X), static_cast<float>(eps), *toTensor(Y));
248
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("pixelNormForward")
249 2 }
250
251 4 void bro_tensor_pixelNormBackward(void* X, void* dY, double eps, void* dX) {
252
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (!need("pixelNormBackward", {dX}) || !fp32Pair("pixelNormBackward", X, "X", dY)) return;
253 BROTENSOR_API_TRY
254
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 brotensor::pixel_norm_backward(*toTensor(X), *toTensor(dY), static_cast<float>(eps), *toTensor(dX));
255
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("pixelNormBackward")
256 4 }
257
258 // ---- thresholds + row counts -------------------------------------------------
259
260 4 void bro_tensor_thresholdU8(void* X, double t, void* Y) {
261
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (!need("thresholdU8", {X, Y}) || !needFloat("thresholdU8", "X", toTensor(X))) return;
262 BROTENSOR_API_TRY
263
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 brotensor::threshold_u8(*toTensor(X), static_cast<float>(t), *toTensor(Y));
264
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("thresholdU8")
265 4 }
266
267 2 void bro_tensor_rowsCountAbove(void* X, double tLo, double tHi, void* counts) {
268
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!need("rowsCountAbove", {X, counts}) || !needFloat("rowsCountAbove", "X", toTensor(X))) return;
269 BROTENSOR_API_TRY
270
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 brotensor::rows_count_above(*toTensor(X), static_cast<float>(tLo), static_cast<float>(tHi),
271
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 *toTensor(counts));
272
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH("rowsCountAbove")
273 2 }
274
275 // ---- softmax ---------------------------------------------------------------
276
277 4 void bro_tensor_softmaxRowsForward(void* X, void* Y, int32_t rows, int32_t cols) {
278 4 constexpr const char* lb = "softmaxRowsForward";
279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!need(lb, {X, Y})) return;
280 4 auto* x = toTensor(X);
281
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (!needFloat(lb, "X", x) || !needElems(lb, "X", x, prod({rows, cols}))) return;
282 BROTENSOR_API_TRY
283
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 brotensor::softmax_rows_forward(*x, *toTensor(Y), rows, cols);
284
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH(lb)
285 4 }
286
287 8 double bro_tensor_softmaxXent(void* logits, void* target, void* probs, void* dLogits, uint64_t mask_bits) {
288 8 constexpr const char* lb = "softmaxXent";
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!need(lb, {logits, target, probs, dLogits})) return 0.0;
290 8 auto* L = toTensor(logits);
291 8 auto* T = toTensor(target);
292
4/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 6 times.
8 if (!needDtype(lb, "logits", L, brotensor::Dtype::FP32) || !needDtype(lb, "target", T, brotensor::Dtype::FP32) ||
293 8 !needSameSize(lb, "target", T, L)) return 0.0;
294 6 auto* M = tensorFromValue(mask_bits);
295
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (!optF32Elems(lb, "mask", M, L->size())) return 0.0;
296 BROTENSOR_API_TRY
297
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
8 return brotensor::softmax_xent(*L, *T, *toTensor(probs), *toTensor(dLogits),
298
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 M ? static_cast<const float*>(M->data) : nullptr);
299 ✗ BROTENSOR_API_CATCH(lb)
300 ✗ return 0.0;
301 8 }
302
303 // ---- strided copy + row scatter ----------------------------------------------
304
305 6 void bro_tensor_copyD2DStrided(void* src, int32_t srcOff, int32_t srcPitch, void* dst, int32_t dstOff,
306 int32_t dstPitch, int32_t width, int32_t height) {
307 6 constexpr const char* lb = "copyD2DStrided";
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!need(lb, {src, dst})) return;
309 6 auto* S = toTensor(src);
310 6 auto* D = toTensor(dst);
311
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!needSameDtype(lb, "dst", D, S)) return;
312
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
6 if (width < 0 || height < 0 || srcOff < 0 || dstOff < 0) {
313 ✗ setError(std::string(lb) + ": offsets, width and height must be non-negative");
314 ✗ return;
315 }
316
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (srcPitch < width || dstPitch < width) {
317 ✗ setError(std::string(lb) + ": pitch must be >= width");
318 ✗ return;
319 }
320
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (width == 0 || height == 0) return;
321 6 const int64_t srcNeed = static_cast<int64_t>(srcOff) + static_cast<int64_t>(height - 1) * srcPitch + width;
322 6 const int64_t dstNeed = static_cast<int64_t>(dstOff) + static_cast<int64_t>(height - 1) * dstPitch + width;
323
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
6 if (!needElems(lb, "src", S, srcNeed) || !needElems(lb, "dst", D, dstNeed)) return;
324 BROTENSOR_API_TRY
325
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 brotensor::copy_d2d_strided(*S, srcOff, srcPitch, *D, dstOff, dstPitch, width, height);
326
0/12
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 BROTENSOR_API_CATCH(lb)
327 6 }
328
329 8 void bro_tensor_scatterRows(void* Y, void* Idx, void* X) {
330 8 constexpr const char* lb = "scatterRows";
331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!need(lb, {Y, Idx, X})) return;
332 8 auto* y = toTensor(Y);
333 8 auto* x = toTensor(X);
334
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (!needFloat(lb, "Y", y) || !needSameDtype(lb, "X", x, y)) return;
335
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if (x->empty()) { setError(std::string(lb) + ": X must be allocated (it is updated in place)"); return; }
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (x->cols != y->cols) {
337 ✗ setError(std::string(lb) + ": X has " + std::to_string(x->cols) + " columns, Y has " + std::to_string(y->cols));
338 ✗ return;
339 }
340 8 auto* I = toTensor(Idx);
341
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
8 if (I->rows != y->rows || I->cols != 1) {
342
5/10
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
2 setError(std::string(lb) + ": Idx must be (" + std::to_string(y->rows) + ", 1), one row index per Y row");
343 2 return;
344 }
345 BROTENSOR_API_TRY
346 6 std::vector<int32_t> idx;
347
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (!hostInt32(lb, "Idx", I, y->rows, idx)) return;
348
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 if (!needIndicesIn(lb, "Idx", idx, y->rows, 0, x->rows)) return;
349 4 brotensor::Tensor scratch;
350
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 brotensor::scatter_rows(*y, int32Operand(*I, idx, scratch), *x);
351
2/15
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
6 BROTENSOR_API_CATCH(lb)
352 8 }
353
354 // ---- segment softmax statistics ------------------------------------------------
355
356 4 void bro_tensor_segmentSoftmaxStats(void* logits, void* segOffsets, void* out) {
357 4 constexpr const char* lb = "segmentSoftmaxStats";
358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!need(lb, {logits, segOffsets, out})) return;
359 4 auto* L = toTensor(logits);
360 4 auto* O = toTensor(segOffsets);
361
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!needFloat(lb, "logits", L)) return;
362
2/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 if (O->cols != 1 || O->rows < 1) { setError(std::string(lb) + ": segOffsets must be (S+1, 1)"); return; }
363 BROTENSOR_API_TRY
364 4 std::vector<int32_t> off;
365
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (!hostInt32(lb, "segOffsets", O, O->rows, off)) return;
366
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 const int64_t K = L->size();
367
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 for (size_t s = 0; s < off.size(); ++s) {
368
5/6
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
10 const bool bad = off[s] < 0 || off[s] > K || (s > 0 && off[s] < off[s - 1]);
369
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (bad) {
370
6/12
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
4 setError(std::string(lb) + ": segOffsets must be non-decreasing within [0, " + std::to_string(K) +
371
5/10
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
2 "]; entry " + std::to_string(s) + " is " + std::to_string(off[s]));
372 2 return;
373 }
374 8 }
375 2 brotensor::Tensor scratch;
376
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 brotensor::segment_softmax_stats(*L, int32Operand(*O, off, scratch), *toTensor(out));
377
2/15
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
4 BROTENSOR_API_CATCH(lb)
378 4 }
379
380 // ---- masked-diffusion token selection ------------------------------------------
381
382 6 void bro_tensor_maskedDiffusionScores(void* logits, void* tokens, int32_t T, int32_t C, int32_t V,
383 int32_t maskId, double guidanceScale, double layerPenalty,
384 double positionTemperature, double classTemperature,
385 double classTopFrac, uint64_t seed_bits,
386 void* pred, void* scores, void* confidence) {
387 6 constexpr const char* lb = "maskedDiffusionScores";
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!need(lb, {logits, tokens, pred, scores, confidence})) return;
389
3/10
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
6 if (T < 1 || C < 1 || V < 1) { setError(std::string(lb) + ": T, C and V must be >= 1"); return; }
390
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!needRange(lb, "maskId", maskId, 0, static_cast<int64_t>(V) - 1)) return;
391 6 auto* L = toTensor(logits);
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 const int64_t R = guidanceScale != 0.0 ? 2 * static_cast<int64_t>(T) : T;
393
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 if (!needDtype(lb, "logits", L, brotensor::Dtype::FP32) || !needElems(lb, "logits", L, prod({R, C, V}))) return;
394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!needExtent(lb, "C*T", prod({C, T}))) return;
395 4 const uint64_t seed = bronze::embed::toUint64(bronze::Value{seed_bits});
396 BROTENSOR_API_TRY
397 4 std::vector<int32_t> tok;
398
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 auto* tk = toTensor(tokens);
399
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
4 if (!hostInt32(lb, "tokens", tk, prod({C, T}), tok)) return;
400 2 brotensor::Tensor scratch;
401
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 const brotensor::Tensor& tokI = int32Operand(*tk, tok, scratch);
402
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 brotensor::masked_diffusion_scores(*L, tokI, T, C, V, maskId, static_cast<float>(guidanceScale),
403 2 static_cast<float>(layerPenalty),
404 2 static_cast<float>(positionTemperature),
405 2 static_cast<float>(classTemperature),
406 2 static_cast<float>(classTopFrac), seed,
407
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 *toTensor(pred), *toTensor(scores), *toTensor(confidence));
408
2/15
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
4 BROTENSOR_API_CATCH(lb)
409 6 }
410
411 6 void bro_tensor_maskedDiffusionCommit(void* pred, void* idx, int32_t k, int32_t step, void* tokens,
412 void* unmaskStep) {
413 6 constexpr const char* lb = "maskedDiffusionCommit";
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!need(lb, {pred, idx, tokens, unmaskStep})) return;
415 6 auto* P = toTensor(pred);
416 6 auto* Tk = toTensor(tokens);
417 6 auto* U = toTensor(unmaskStep);
418
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 if (!needDtype(lb, "pred", P, brotensor::Dtype::INT32) || !needDtype(lb, "tokens", Tk, brotensor::Dtype::INT32) ||
419 6 !needDtype(lb, "unmaskStep", U, brotensor::Dtype::INT32)) return;
420
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
6 if (!needSameSize(lb, "tokens", Tk, P) || !needSameSize(lb, "unmaskStep", U, P)) return;
421
1/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 if (k < 0) { setError(std::string(lb) + ": k must be >= 0"); return; }
422
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (k == 0) return;
423 BROTENSOR_API_TRY
424
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 auto* I = toTensor(idx);
425 4 brotensor::Tensor scratch;
426 4 const brotensor::Tensor* use = I;
427
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (I->dtype == brotensor::Dtype::INT32) {
428
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (!needElems(lb, "idx", I, k)) return;
429 2 } else {
430 ✗ std::vector<int32_t> vals;
431 ✗ if (!hostInt32(lb, "idx", I, k, vals)) return;
432 ✗ use = &int32Operand(*I, vals, scratch);
433 ✗ }
434
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 brotensor::masked_diffusion_commit(*P, *use, k, step, *Tk, *U);
435
2/15
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
4 BROTENSOR_API_CATCH(lb)
436 6 }
437
438 } // extern "C"
439
440 namespace brotensor::api {
441
442 3 bool registerTensorNatives_extra(std::string* error) {
443 using namespace brotensor::api::reg;
444 3 return
445 6 fn("__bro_native.tensor.uploadInt32", p(&bro_tensor_uploadInt32), "void",
446
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, "i32[]"}, error) &&
447 6 fn("__bro_native.tensor.downloadInt32", p(&bro_tensor_downloadInt32), "i32[]",
448
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls}, error) &&
449 6 fn("__bro_native.tensor.addChannelBiasInplace", p(&bro_tensor_addChannelBiasInplace), "void",
450
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, "i32", "i32"}, error) &&
451 6 fn("__bro_native.tensor.addRowBiasInplace", p(&bro_tensor_addRowBiasInplace), "void",
452
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls}, error) &&
453 6 fn("__bro_native.tensor.axpbyInplace", p(&bro_tensor_axpbyInplace), "void",
454
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, "f64", "f64"}, error) &&
455
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 fn("__bro_native.tensor.sinForward", p(&bro_tensor_sinForward), "void", {kTensorCls, kTensorCls}, error) &&
456 6 fn("__bro_native.tensor.sinBackward", p(&bro_tensor_sinBackward), "void",
457
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, kTensorCls}, error) &&
458
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 fn("__bro_native.tensor.cosForward", p(&bro_tensor_cosForward), "void", {kTensorCls, kTensorCls}, error) &&
459 6 fn("__bro_native.tensor.cosBackward", p(&bro_tensor_cosBackward), "void",
460
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, kTensorCls}, error) &&
461
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 fn("__bro_native.tensor.rsqrtForward", p(&bro_tensor_rsqrtForward), "void", {kTensorCls, kTensorCls}, error) &&
462 6 fn("__bro_native.tensor.rsqrtBackward", p(&bro_tensor_rsqrtBackward), "void",
463
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, kTensorCls}, error) &&
464 6 fn("__bro_native.tensor.pixelNormForward", p(&bro_tensor_pixelNormForward), "void",
465
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, "f64", kTensorCls}, error) &&
466 6 fn("__bro_native.tensor.pixelNormBackward", p(&bro_tensor_pixelNormBackward), "void",
467
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, "f64", kTensorCls}, error) &&
468 6 fn("__bro_native.tensor.thresholdU8", p(&bro_tensor_thresholdU8), "void",
469
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, "f64", kTensorCls}, error) &&
470 6 fn("__bro_native.tensor.rowsCountAbove", p(&bro_tensor_rowsCountAbove), "void",
471
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, "f64", "f64", kTensorCls}, error) &&
472 6 fn("__bro_native.tensor.softmaxRowsForward", p(&bro_tensor_softmaxRowsForward), "void",
473
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, "i32", "i32"}, error) &&
474 6 fn("__bro_native.tensor.softmaxXent", p(&bro_tensor_softmaxXent), "f64",
475
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, kTensorCls, kTensorCls, kDyn}, error) &&
476 6 fn("__bro_native.tensor.copyD2DStrided", p(&bro_tensor_copyD2DStrided), "void",
477
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, "i32", "i32", kTensorCls, "i32", "i32", "i32", "i32"}, error) &&
478 6 fn("__bro_native.tensor.scatterRows", p(&bro_tensor_scatterRows), "void",
479
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, kTensorCls}, error) &&
480 6 fn("__bro_native.tensor.segmentSoftmaxStats", p(&bro_tensor_segmentSoftmaxStats), "void",
481
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, kTensorCls}, error) &&
482 6 fn("__bro_native.tensor.maskedDiffusionScores", p(&bro_tensor_maskedDiffusionScores), "void",
483 3 {kTensorCls, kTensorCls, "i32", "i32", "i32", "i32", "f64", "f64", "f64", "f64", "f64", kDyn,
484
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 kTensorCls, kTensorCls, kTensorCls}, error) &&
485 6 fn("__bro_native.tensor.maskedDiffusionCommit", p(&bro_tensor_maskedDiffusionCommit), "void",
486
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 {kTensorCls, kTensorCls, "i32", "i32", kTensorCls, kTensorCls}, error) &&
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 registerTensorNatives_extra_nn(error) &&
488 3 registerTensorNatives_extra_conv(error);
489 }
490
491 } // namespace brotensor::api
492