• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stillwater-sc / universal / 23224573073

18 Mar 2026 01:24AM UTC coverage: 84.312% (+0.007%) from 84.305%
23224573073

push

github

web-flow
feat(cmake): enable serialization tests in CI_LITE (#590)

* feat(cmake): enable serialization tests in CI_LITE

Add UNIVERSAL_BUILD_LINEAR_ALGEBRA_DATA to the CI_LITE cascade so
serialization tests (data_serialization, data_typed_serialization,
data_translation) are built and run in CI on every PR.

Previously these tests only ran with UNIVERSAL_BUILD_ALL, which is
not used in CI. This meant serialization regressions (like the
lns::fraction() stub in #509) were invisible to CI.

Resolves #586

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(blas): add value verification to serialization round-trip tests

Tests 6-8 (lns, dbns, integer) now verify bit-exact fidelity by
comparing the serialized text after a save->restore->re-save cycle.
If the re-serialized text differs from the original, the round-trip
lost data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(blas): guard value comparison on successful restore

Make the re-save/compare check conditional on restore succeeding
so a failed restore doesn't double-count as a value mismatch.
Applied to lns, dbns, and integer round-trip tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(fixpnt): silence uninitialized warning in numeric_limits

fixpnt's epsilon(), round_error(), and denorm_min() declared a local
FixedPoint without initialization, then called setbit() on it. GCC
warned that the underlying blockbinary storage was uninitialized.

Fix: value-initialize with {} and call clear() before setbit() to
ensure all bits are zero before setting the ULP bit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(blockbinary): silence GCC -Warray-bounds false positive in setbit

GCC at -O3 produces false-positive -Warray-bounds warnings when
template inlining causes it to confuse blockbinary instantiations
across fixpnt's convert() -> setbit() chain. The existing guard
(blockIndex < nrBlocks) is correct but GCC's analyzer loses track
of which instan... (continued)

43 of 49 new or added lines in 6 files covered. (87.76%)

3 existing lines in 1 file now uncovered.

44203 of 52428 relevant lines covered (84.31%)

5934176.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.46
/linalg/data/typed_serialization.cpp
1
// typed_serialization.cpp: test suite for client-directed serialization
2
//
3
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
4
// SPDX-License-Identifier: MIT
5
//
6
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
7
#include <universal/utility/directives.hpp>
8
#include <iostream>
9
#include <sstream>
10
#include <universal/number_systems.hpp>
11
#include <blas/blas.hpp>
12
#include <blas/generators.hpp>
13
#include <blas/serialization/datafile.hpp>
14
#include <blas/serialization/typed_datafile.hpp>
15
#include <universal/verification/test_suite.hpp>
16

17
#define MANUAL_TESTING 0
18
#ifndef REGRESSION_LEVEL_OVERRIDE
19
#undef REGRESSION_LEVEL_1
20
#define REGRESSION_LEVEL_1 1
21
#endif
22

23
int main()
1✔
24
try {
25
        using namespace sw::universal;
26
        using namespace sw::numeric::containers;
27
        using namespace sw::blas;
28

29
        std::string test_suite = "client-directed typed serialization";
2✔
30
        std::string test_tag = "typed_datafile";
1✔
31
        bool reportTestCases = true;
1✔
32
        int nrOfFailedTestCases = 0;
1✔
33

34
        ReportTestSuiteHeader(test_suite, reportTestCases);
1✔
35

36
#if MANUAL_TESTING
37

38
        {
39
                // declare a client type list
40
                using ClientTypes = type_list<float, double, half>;
41

42
                // create and populate a vector
43
                vector<float> v(5);
44
                for (unsigned i = 0; i < 5; ++i) v[i] = float(i) * 1.5f;
45

46
                // save
47
                typed_datafile<ClientTypes> df;
48
                df.add(v, "test_vector");
49
                std::stringstream ss;
50
                df.save(ss);
51

52
                std::cout << "Saved datafile:\n" << ss.str() << '\n';
53

54
                // restore
55
                typed_datafile<ClientTypes> df2;
56
                if (df2.restore(ss)) {
57
                        std::cout << "Restored successfully, " << df2.size() << " datasets\n";
58
                        std::cout << "Dataset name: " << df2.name(0) << '\n';
59
                }
60
                else {
61
                        std::cout << "Restore failed\n";
62
                }
63
        }
64

65
        ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
66
        return EXIT_SUCCESS;
67
#else
68

69
#if REGRESSION_LEVEL_1
70

71
        // Test 1: float vector round-trip
72
        {
73
                int start = nrOfFailedTestCases;
1✔
74
                using ClientTypes = type_list<float, double>;
75

76
                vector<float> original(10);
1✔
77
                for (unsigned i = 0; i < 10; ++i) original[i] = float(i) * 0.5f;
11✔
78

79
                typed_datafile<ClientTypes> saver;
1✔
80
                saver.add(original, "float_vec");
1✔
81
                std::stringstream ss;
1✔
82
                saver.save(ss);
1✔
83

84
                typed_datafile<ClientTypes> loader;
1✔
85
                if (!loader.restore(ss)) {
1✔
86
                        ++nrOfFailedTestCases;
×
87
                        if (reportTestCases) std::cerr << "FAIL: float vector restore failed\n";
×
88
                }
89
                if (loader.size() != 1) {
1✔
90
                        ++nrOfFailedTestCases;
×
91
                        if (reportTestCases) std::cerr << "FAIL: expected 1 dataset, got " << loader.size() << '\n';
×
92
                }
93
                if (nrOfFailedTestCases - start > 0) {
1✔
94
                        std::cout << "FAIL: float vector round-trip\n";
×
95
                }
96
        }
1✔
97

98
        // Test 2: double vector round-trip
99
        {
100
                int start = nrOfFailedTestCases;
1✔
101
                using ClientTypes = type_list<float, double>;
102

103
                vector<double> original(8);
1✔
104
                for (unsigned i = 0; i < 8; ++i) original[i] = double(i) * 1.25;
9✔
105

106
                typed_datafile<ClientTypes> saver;
1✔
107
                saver.add(original, "double_vec");
1✔
108
                std::stringstream ss;
1✔
109
                saver.save(ss);
1✔
110

111
                typed_datafile<ClientTypes> loader;
1✔
112
                if (!loader.restore(ss)) {
1✔
113
                        ++nrOfFailedTestCases;
×
114
                        if (reportTestCases) std::cerr << "FAIL: double vector restore failed\n";
×
115
                }
116
                if (nrOfFailedTestCases - start > 0) {
1✔
117
                        std::cout << "FAIL: double vector round-trip\n";
×
118
                }
119
        }
1✔
120

121
        // Test 3: cfloat (half) vector round-trip
122
        {
123
                int start = nrOfFailedTestCases;
1✔
124
                using ClientTypes = type_list<float, double, half>;
125

126
                vector<half> original(6);
1✔
127
                for (unsigned i = 0; i < 6; ++i) original[i] = half(float(i) * 0.25f);
7✔
128

129
                typed_datafile<ClientTypes> saver;
1✔
130
                saver.add(original, "half_vec");
1✔
131
                std::stringstream ss;
1✔
132
                saver.save(ss);
1✔
133

134
                typed_datafile<ClientTypes> loader;
1✔
135
                if (!loader.restore(ss)) {
1✔
136
                        ++nrOfFailedTestCases;
×
137
                        if (reportTestCases) std::cerr << "FAIL: half vector restore failed\n";
×
138
                }
139
                if (nrOfFailedTestCases - start > 0) {
1✔
140
                        std::cout << "FAIL: half vector round-trip\n";
×
141
                }
142
        }
1✔
143

144
        // Test 4: type mismatch -- save with half, restore without half in registry
145
        {
146
                int start = nrOfFailedTestCases;
1✔
147
                using SaveTypes = type_list<float, double, half>;
148
                using LoadTypes = type_list<float, double>;  // no half!
149

150
                vector<half> original(4);
1✔
151
                for (unsigned i = 0; i < 4; ++i) original[i] = half(float(i));
5✔
152

153
                typed_datafile<SaveTypes> saver;
1✔
154
                saver.add(original, "half_data");
1✔
155
                std::stringstream ss;
1✔
156
                saver.save(ss);
1✔
157

158
                // restore with a registry that lacks half -- should report unsupported type
159
                typed_datafile<LoadTypes> loader;
1✔
160
                // restore returns true even if some types are unsupported (skipped)
161
                loader.restore(ss);
1✔
162
                // the dataset should not have been restored
163
                if (loader.size() != 0) {
1✔
164
                        ++nrOfFailedTestCases;
×
165
                        if (reportTestCases) std::cerr << "FAIL: type mismatch should result in 0 restored datasets\n";
×
166
                }
167
                if (nrOfFailedTestCases - start > 0) {
1✔
168
                        std::cout << "FAIL: type mismatch test\n";
×
169
                }
170
        }
1✔
171

172
        // Test 5: multiple datasets in one file
173
        {
174
                int start = nrOfFailedTestCases;
1✔
175
                using ClientTypes = type_list<float, double>;
176

177
                vector<float> fv(3);
1✔
178
                fv[0] = 1.0f; fv[1] = 2.0f; fv[2] = 3.0f;
1✔
179
                vector<double> dv(2);
1✔
180
                dv[0] = 4.5; dv[1] = 5.5;
1✔
181

182
                typed_datafile<ClientTypes> saver;
1✔
183
                saver.add(fv, "floats");
2✔
184
                saver.add(dv, "doubles");
1✔
185
                std::stringstream ss;
1✔
186
                saver.save(ss);
1✔
187

188
                typed_datafile<ClientTypes> loader;
1✔
189
                if (!loader.restore(ss)) {
1✔
190
                        ++nrOfFailedTestCases;
×
191
                        if (reportTestCases) std::cerr << "FAIL: multi-dataset restore failed\n";
×
192
                }
193
                if (loader.size() != 2) {
1✔
194
                        ++nrOfFailedTestCases;
×
195
                        if (reportTestCases) std::cerr << "FAIL: expected 2 datasets, got " << loader.size() << '\n';
×
196
                }
197
                if (nrOfFailedTestCases - start > 0) {
1✔
198
                        std::cout << "FAIL: multiple datasets\n";
×
199
                }
200
        }
1✔
201

202
        // Test 6: lns vector round-trip with value verification
203
        // Verify bit-exact fidelity: save -> restore -> re-save -> compare text
204
        {
205
                int start = nrOfFailedTestCases;
1✔
206
                using ClientTypes = type_list<float, lns<8, 2, uint8_t>>;
207

208
                vector<lns<8, 2, uint8_t>> v(4);
1✔
209
                v[0] = 1.0; v[1] = 2.0; v[2] = 0.5; v[3] = -1.0;
1✔
210

211
                typed_datafile<ClientTypes> saver;
1✔
212
                saver.add(v, "lns_vec");
1✔
213
                std::stringstream ss1;
1✔
214
                saver.save(ss1);
1✔
215
                std::string original = ss1.str();
1✔
216

217
                std::stringstream ss2(original);
1✔
218
                typed_datafile<ClientTypes> loader;
1✔
219
                if (!loader.restore(ss2)) {
1✔
220
                        ++nrOfFailedTestCases;
×
221
                        if (reportTestCases) std::cerr << "FAIL: lns vector restore failed\n";
×
222
                }
223
                else {
224
                        // re-save and compare serialized text for value verification
225
                        std::stringstream ss3;
1✔
226
                        loader.save(ss3);
1✔
227
                        if (ss3.str() != original) {
1✔
NEW
228
                                ++nrOfFailedTestCases;
×
NEW
229
                                if (reportTestCases) std::cerr << "FAIL: lns round-trip value mismatch\n";
×
230
                        }
231
                }
1✔
232
                if (nrOfFailedTestCases - start > 0) {
1✔
233
                        std::cout << "FAIL: lns vector round-trip\n";
×
234
                }
235
        }
1✔
236

237
        // Test 7: dbns vector round-trip with value verification
238
        {
239
                int start = nrOfFailedTestCases;
1✔
240
                using ClientTypes = type_list<float, dbns<8, 3, uint8_t>>;
241

242
                vector<dbns<8, 3, uint8_t>> v(3);
1✔
243
                v[0] = 1.0; v[1] = 2.0; v[2] = 4.0;
1✔
244

245
                typed_datafile<ClientTypes> saver;
1✔
246
                saver.add(v, "dbns_vec");
1✔
247
                std::stringstream ss1;
1✔
248
                saver.save(ss1);
1✔
249
                std::string original = ss1.str();
1✔
250

251
                std::stringstream ss2(original);
1✔
252
                typed_datafile<ClientTypes> loader;
1✔
253
                if (!loader.restore(ss2)) {
1✔
254
                        ++nrOfFailedTestCases;
×
255
                        if (reportTestCases) std::cerr << "FAIL: dbns vector restore failed\n";
×
256
                }
257
                else {
258
                        std::stringstream ss3;
1✔
259
                        loader.save(ss3);
1✔
260
                        if (ss3.str() != original) {
1✔
NEW
261
                                ++nrOfFailedTestCases;
×
NEW
262
                                if (reportTestCases) std::cerr << "FAIL: dbns round-trip value mismatch\n";
×
263
                        }
264
                }
1✔
265
                if (nrOfFailedTestCases - start > 0) {
1✔
266
                        std::cout << "FAIL: dbns vector round-trip\n";
×
267
                }
268
        }
1✔
269

270
        // Test 8: integer vector round-trip with value verification
271
        {
272
                int start = nrOfFailedTestCases;
1✔
273
                using ClientTypes = type_list<float, integer<32, uint32_t, IntegerNumberType::IntegerNumber>>;
274

275
                vector<integer<32, uint32_t, IntegerNumberType::IntegerNumber>> v(4);
1✔
276
                v[0] = 1; v[1] = -2; v[2] = 100; v[3] = -999;
1✔
277

278
                typed_datafile<ClientTypes> saver;
1✔
279
                saver.add(v, "int_vec");
1✔
280
                std::stringstream ss1;
1✔
281
                saver.save(ss1);
1✔
282
                std::string original = ss1.str();
1✔
283

284
                std::stringstream ss2(original);
1✔
285
                typed_datafile<ClientTypes> loader;
1✔
286
                if (!loader.restore(ss2)) {
1✔
287
                        ++nrOfFailedTestCases;
×
288
                        if (reportTestCases) std::cerr << "FAIL: integer vector restore failed\n";
×
289
                }
290
                else {
291
                        std::stringstream ss3;
1✔
292
                        loader.save(ss3);
1✔
293
                        if (ss3.str() != original) {
1✔
NEW
294
                                ++nrOfFailedTestCases;
×
NEW
295
                                if (reportTestCases) std::cerr << "FAIL: integer round-trip value mismatch\n";
×
296
                        }
297
                }
1✔
298
                if (nrOfFailedTestCases - start > 0) {
1✔
299
                        std::cout << "FAIL: integer vector round-trip\n";
×
300
                }
301
        }
1✔
302

303
#endif
304

305
        ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
1✔
306
        return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
1✔
307
#endif
308
}
1✔
309
catch (char const* msg) {
×
310
        std::cerr << "Caught ad-hoc exception: " << msg << std::endl;
×
311
        return EXIT_FAILURE;
×
312
}
×
313
catch (const std::runtime_error& err) {
×
314
        std::cerr << "Caught runtime exception: " << err.what() << std::endl;
×
315
        return EXIT_FAILURE;
×
316
}
×
317
catch (...) {
×
318
        std::cerr << "Caught unknown exception" << std::endl;
×
319
        return EXIT_FAILURE;
×
320
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc