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

stillwater-sc / universal / 23218775201

17 Mar 2026 10:11PM UTC coverage: 84.305% (+0.2%) from 84.112%
23218775201

push

github

web-flow
feat(blas): add serialization regression tests and verify #509 fix (#589)

Add regression level 1 tests for the serialization facility:

serialization.cpp:
- Exercise ReportFormats for lns and dbns (the lns::fraction() stub
  that caused #509 is now implemented)
- Native float vector save/restore round-trip

typed_serialization.cpp:
- lns<8,2> vector round-trip (directly exercises #509 scenario)
- dbns<8,3> vector round-trip
- integer<32> vector round-trip
- Plus existing float, double, half, type-mismatch, multi-dataset tests

The lns::fraction() function is no longer a stub -- it correctly
extracts the lower rbits as the fractional part of the fixed-point
exponent. This means #509 is resolved.

Resolves #585
Relates to #509

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

51 of 69 new or added lines in 2 files covered. (73.91%)

1 existing line in 1 file now uncovered.

44180 of 52405 relevant lines covered (84.3%)

6014239.75 hits per line

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

15.38
/linalg/data/serialization.cpp
1
// serialization.cpp: test suite for serialization functions for data exchange
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 <cmath>
9
#include <iostream>
10
#include <iomanip>
11
#include <fstream>
12
#include <universal/number_systems.hpp>
13
#include <blas/blas.hpp>
14
#include <blas/generators.hpp>
15
#include <blas/serialization/datafile.hpp>
16
#include <universal/verification/test_suite.hpp>
17
#include <math/constants/double_constants.hpp>
18

19
void ReportNativeHexFormats() {
×
20
        using namespace sw::universal;
21

22
        float f;
23
        double d;
24
        single b;
25
        b.setbits(0x23456789);
×
26
        f = float(b);
×
27
        d = double(b);
×
28
        std::cout << to_hex(f, true, true) << '\n';
×
29
        std::cout << to_hex(d, true, true) << '\n';
×
30
        std::cout << to_binary(f) << " : " << to_hex(f) << " : " << f << '\n';
×
31
        std::cout << to_binary(d) << " : " << to_hex(d) << " : " << d << '\n';
×
32
        std::cout << to_binary(b) << " : " << to_hex(b) << " : " << b << '\n';
×
33
}
×
34

35
void ReportNumberSystemFormats() {
×
36
        using namespace sw::universal;
37

38
        {
39
                constexpr unsigned nbits = 40;
×
40
                integer<nbits, uint32_t, IntegerNumberType::NaturalNumber> a{123456789};
×
41
                integer<nbits, uint32_t, IntegerNumberType::WholeNumber> b{123456789};
×
42
                integer<nbits, uint32_t, IntegerNumberType::IntegerNumber> c{-123456789};
×
43
                ReportFormats(a);
×
44
                ReportFormats(b);
×
45
                ReportFormats(c);
×
46
        }
47
        {
48
                fixpnt<40, 32, Modulo, uint32_t> a(d_pi);
×
49
                ReportFormats(a);
×
50
                ReportFormats(-a);
×
51
                fixpnt<40, 32, Saturate, uint32_t> b(d_pi);
×
52
                ReportFormats(b);
×
53

54
        }
55
        {
56
                cfloat<64, 11, uint32_t, true, false, false> a(d_pi);
×
57
                ReportFormats(a);
×
58
        }
59
        {
60
                posit<64, 5> a(d_pi);
×
61
                ReportFormats(a);
×
62
        }
63
        {
64
                lns<64, 32> a(d_pi);
×
65
                ReportFormats(a);
×
66
        }
67
        {
68
                dbns<8,3,uint8_t> a(d_pi);
×
69
                ReportFormats(a);
×
70
                dbns<10, 4, uint8_t> b(d_pi);
×
71
                ReportFormats(b);
×
72
                dbns<12, 5, uint8_t> c(d_pi);
×
73
                ReportFormats(c);
×
74
        }
75
}
×
76

77
void TestSaveTypeId() {
×
78
        using namespace sw::universal;
79
        using namespace sw::blas;
80

81
        saveTypeId<char>(std::cout);
×
82
        saveTypeId<short>(std::cout);
×
83
        saveTypeId<int>(std::cout);
×
84
        saveTypeId<long>(std::cout);
×
85
        saveTypeId<long long>(std::cout);
×
86
        saveTypeId<float>(std::cout);
×
87
        saveTypeId<double>(std::cout);
×
88
        saveTypeId<long double>(std::cout);
×
89
        saveTypeId<integer<  8, uint8_t, IntegerNumberType::IntegerNumber>>(std::cout);
×
90
        saveTypeId<integer< 16, uint16_t, IntegerNumberType::IntegerNumber>>(std::cout);
×
91
        saveTypeId<integer< 32, uint32_t, IntegerNumberType::IntegerNumber>>(std::cout);
×
92
        saveTypeId<integer< 64, uint32_t, IntegerNumberType::IntegerNumber>>(std::cout);
×
93
        saveTypeId<integer<128, uint32_t, IntegerNumberType::IntegerNumber>>(std::cout);
×
94

95
        saveTypeId<fixpnt<32, 16, Modulo>>(std::cout);
×
96
        saveTypeId<fixpnt<64, 32, Saturate>>(std::cout);
×
97

98
        saveTypeId<cfloat<12, 8, uint16_t, true, true, false>>(std::cout);
×
99
        saveTypeId<quarter>(std::cout);
×
100
        saveTypeId<half>(std::cout);
×
101
        saveTypeId<single>(std::cout);
×
102
        saveTypeId<duble>(std::cout);
×
103
        saveTypeId<quad>(std::cout);
×
104

105
        saveTypeId<posit<  8, 2>>(std::cout);
×
106
        saveTypeId<posit< 16, 2>>(std::cout);
×
107
        saveTypeId<posit< 32, 2>>(std::cout);
×
108
        saveTypeId<posit< 64, 2>>(std::cout);
×
109
        saveTypeId<posit<128, 2>>(std::cout);
×
110
        saveTypeId<posit<256, 2>>(std::cout);
×
111

112
        saveTypeId<lns<16, 8, uint16_t>>(std::cout);
×
113
        saveTypeId<dbns<8, 3, uint8_t>>(std::cout);
×
114

115
        // or this ADL format
116
        half h;
117
        saveTypeId(std::cout, h);
×
118
}
×
119

120
template<typename Scalar>
121
void TestVectorSerialization() {
122
        using namespace sw::blas;
123
        using namespace sw::numeric::containers;
124
        vector<Scalar> v(5);
125
        gaussian_random(v, 0.0, 0.1);
126
        datafile<TextFormat> df;
127
        df.add(v, "testVector");
128
        std::cout << "datafile with a single vector(5) serialized using decimal format\n";
129
        df.save(std::cout, false);  // decimal format
130
        std::cout << "+--------------- end of df serialization using decimal ----\n";
131

132
        std::stringstream s;
133
        df.save(s, false);  // decimal format
134

135
        df.clear();
136
        df.restore(s);
137

138
        std::cout << "same datafile with a single vector(5) serialized using hex format\n";
139
        df.save(std::cout, true);
140
        std::cout << "+--------------- end of TestVectorSerialization -------------+\n";
141
}
142

143
template<typename Scalar>
144
void TestMatrixSerialization() {
145
        using namespace sw::blas;
146
        using namespace sw::numeric::containers;
147
        matrix<Scalar> m(5,5);
148
        gaussian_random(m, 0.0, 0.1);
149
        datafile<TextFormat> df;
150
        df.add(m, "testMatrix");
151
        std::cout << "datafile with a single matrix(5,5) serialized using decimal format\n";
152
        df.save(std::cout, false);  // decimal format
153
        std::cout << "+--------------- end of df serialization using decimal ----\n";
154

155
        std::stringstream s;
156
        df.save(s, false);  // decimal format
157

158
        df.clear();
159
        df.restore(s);
160

161
        std::cout << "same datafile with a single matrix(5,5) serialized using hex format\n";
162
        df.save(std::cout, true);
163
        std::cout << "+--------------- end of TestMatrixSerialization -------------+\n";
164
}
165

166
void TestCollectionSerialization() {
×
167
        using namespace sw::universal;
168
        using namespace sw::numeric::containers;
169
        using namespace sw::blas;
170

171
        // Create instances of different specialized collections
172
        vector<float> xfp32(7), yfp32(7);
×
173
        matrix<float> Afp32(9, 5);
×
174
//        sw::universal::tensor<float> Tfp32(5, 5); // TBD
175
        matrix<float> dpfp32(1, 1);
×
176
        gaussian_random(xfp32, 0.0, 0.1);
×
177
        gaussian_random(yfp32, 0.0, 0.1);
×
178
        gaussian_random(Afp32, 0.0, 1.0);
×
179
        auto zfp32 = Afp32 * xfp32;
×
180
        dpfp32 = xfp32 * yfp32;
×
181
        vector<half> x(7), y(7);
×
182
        matrix<half> A(5, 7);
×
183
        gaussian_random(A, 0.0, 1.0);
×
184
        matrix<half> dotProduct(1, 1);
×
185
        x = xfp32;
×
186
        y = yfp32;
×
187
        A = Afp32;
×
188
        auto z = A * x;
×
189
        dotProduct = x * y;
×
190

191
        // Use the base class reference to aggregate the collections
192
        datafile<TextFormat> df;
×
193
//        df.add(Tfp32);
194
        df.add(xfp32, "xfp32");
×
195
        df.add(yfp32, "yfp32");
×
196
        df.add(Afp32, "Afp32");
×
197
        df.add(dpfp32, "dpfp32");
×
198
        df.add(x, "xhalf");
×
199
        df.add(y, "yhalf");
×
200
        df.add(A, "Ahalf");
×
201
        df.add(z, "zhalf");
×
202
        df.add(dotProduct, "dotProduct_xy");
×
203
        df.save(std::cout, false);  // decimal format
×
204

205
        std::ofstream fo;
×
206
        fo.open("TestCollectionSerialization.txt");
×
207
        df.save(fo, false);
×
208
        fo.close();
×
209

210
        std::stringstream s;
×
211
        df.save(s, false);
×
212
        datafile<TextFormat> in;
×
213
        if (!in.restore(s)) {
×
214
                std::cerr << "Failed to load Universal Data File\n";
×
215
        }
216
        else {
217
                in.save(std::cout, false);
×
218
        }
219
        std::cout << "+--------------- end of TestCollectionSerialization -------------+\n";
×
220
}
×
221

222
// Regression testing guards: typically set by the cmake configuration, but MANUAL_TESTING is an override
223
#define MANUAL_TESTING 0
224
// REGRESSION_LEVEL_OVERRIDE is set by the cmake file to drive a specific regression intensity
225
// It is the responsibility of the regression test to organize the tests in a quartile progression.
226
//#undef REGRESSION_LEVEL_OVERRIDE
227
#ifndef REGRESSION_LEVEL_OVERRIDE
228
#undef REGRESSION_LEVEL_1
229
#undef REGRESSION_LEVEL_2
230
#undef REGRESSION_LEVEL_3
231
#undef REGRESSION_LEVEL_4
232
#define REGRESSION_LEVEL_1 1
233
#define REGRESSION_LEVEL_2 1
234
#define REGRESSION_LEVEL_3 1
235
#define REGRESSION_LEVEL_4 1
236
#endif
237

238
int main()
1✔
239
try {
240
        using namespace sw::universal;
241
        using namespace sw::numeric::containers;
242
        using namespace sw::blas;
243

244
        std::string test_suite = "serialization";
2✔
245
        std::string test_tag = "save/restore";
1✔
246
        bool reportTestCases = true;
1✔
247
        int nrOfFailedTestCases = 0;
1✔
248

249
        ReportTestSuiteHeader(test_suite, reportTestCases);
1✔
250

251
#if MANUAL_TESTING
252

253
        // manual test cases
254
        //nrOfFailedTestCases += ReportTestResult(VerifyCompress<quarter>(reportTestCases), "compress to quarter precision", "quarter precision");
255
        
256
        ReportNativeHexFormats();
257
        ReportNumberSystemFormats();
258

259
        // TODO: datafiles are not working yet: ETLO 3/25/2024
260
        TestCollectionSerialization();
261

262
        TestVectorSerialization<double>();
263
        TestVectorSerialization<dbns<8, 3>>();
264
        TestMatrixSerialization<float>();
265
        TestMatrixSerialization<half>();
266

267
//        TestSaveTypeId();
268
        
269
        unsigned N = 32;
270
        vector<double> x(N), y(N);
271
        double zeroMean = 0.0;
272
        double variance = 0.1;
273
        gaussian_random(x, zeroMean, variance);
274

275
        {
276
                vector<lns<8, 2, uint8_t>> v(N);
277
                v = x;
278
                save(std::cout, v);
279
        }
280
        {
281
                vector<lns<12, 4, uint8_t>> v(N);
282
                v = x;
283
                save(std::cout, v);
284
        }
285

286
        ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
287
        return EXIT_SUCCESS;
288
#else
289

290
#if REGRESSION_LEVEL_1
291

292
        // Test: ReportFormats for lns (exercises lns::fraction which was a stub in #509)
293
        {
294
                lns<8, 2, uint8_t> a(d_pi);
1✔
295
                ReportFormats(a);
1✔
296
        }
297

298
        // Test: ReportFormats for dbns
299
        {
300
                dbns<8, 3, uint8_t> a(d_pi);
1✔
301
                ReportFormats(a);
1✔
302
        }
303

304
        // Test: save/restore round-trip for native types
305
        {
306
                int start = nrOfFailedTestCases;
1✔
307
                using namespace sw::blas;
308
                vector<float> fv(5);
1✔
309
                for (unsigned i = 0; i < 5; ++i) fv[i] = float(i) * 1.5f;
6✔
310
                datafile<TextFormat> df;
1✔
311
                df.add(fv, "test_floats");
1✔
312
                std::stringstream s;
1✔
313
                df.save(s, false);
1✔
314

315
                datafile<TextFormat> df2;
1✔
316
                if (!df2.restore(s)) {
1✔
NEW
317
                        ++nrOfFailedTestCases;
×
NEW
318
                        if (reportTestCases) std::cerr << "FAIL: float vector save/restore\n";
×
319
                }
320
                if (nrOfFailedTestCases - start > 0) {
1✔
NEW
321
                        std::cout << "FAIL: native type round-trip\n";
×
322
                }
323
        }
1✔
324

325
#endif
326

327
#if REGRESSION_LEVEL_2
328

329
#endif
330

331
#if REGRESSION_LEVEL_3
332

333
#endif
334

335
#if REGRESSION_LEVEL_4
336

337
#endif
338

339
        ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
1✔
340
        return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
1✔
341
#endif
342
}
1✔
343
catch (char const* msg) {
×
344
        std::cerr << msg << std::endl;
×
345
        return EXIT_FAILURE;
×
346
}
×
347
catch (const sw::universal::universal_arithmetic_exception& err) {
×
348
        std::cerr << "Uncaught universal arithmetic exception: " << err.what() << std::endl;
×
349
        return EXIT_FAILURE;
×
350
}
×
351
catch (const sw::universal::universal_internal_exception& err) {
×
352
        std::cerr << "Uncaught universal internal exception: " << err.what() << std::endl;
×
353
        return EXIT_FAILURE;
×
354
}
×
355
catch (const std::runtime_error& err) {
×
356
        std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
×
357
        return EXIT_FAILURE;
×
358
}
×
359
catch (...) {
×
360
        std::cerr << "Caught unknown exception" << std::endl;
×
361
        return EXIT_FAILURE;
×
362
}
×
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