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

stillwater-sc / universal / 21383017444

27 Jan 2026 03:10AM UTC coverage: 83.925%. First build
21383017444

Pull #499

github

web-flow
Merge 74f95de7d into f1f1d0fc7
Pull Request #499: V3.93: UBSan fixes, image demo, and coverage workflow

951 of 1356 new or added lines in 22 files covered. (70.13%)

33879 of 40368 relevant lines covered (83.93%)

6473684.2 hits per line

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

66.25
/linalg/blas/vector_ops.cpp
1
// vector_ops.cpp: example program to show sw::universal::blas::vector operators
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
// enable the following define to show the intermediate steps in the fused-dot product
9
// #define ALGORITHM_VERBOSE_OUTPUT
10
//#define ALGORITHM_TRACE_MUL
11
//#define QUIRE_TRACE_ADD
12
// configure posit environment using fast posits
13
#define POSIT_FAST_POSIT_8_0 1
14
#define POSIT_FAST_POSIT_16_1 1
15
#define POSIT_FAST_POSIT_32_2 1
16
#include <universal/number/posit/posit.hpp>
17
#include <universal/number/cfloat/cfloat.hpp>
18
#include <universal/number/lns/lns.hpp>
19
#include <blas/blas.hpp>
20
#include <universal/verification/test_suite.hpp>
21

22
template<unsigned nbits, unsigned es>
23
void PrintProducts(const sw::numeric::containers::vector<sw::universal::posit<nbits,es>>& a,
24
                           const sw::numeric::containers::vector<sw::universal::posit<nbits,es>>& b)
25
{
26
        sw::universal::quire<nbits, es> q(0);
27
        for (unsigned i = 0; i < a.size(); ++i) {
28
                q += sw::universal::quire_mul(a[i], b[i]);
29
                std::cout << a[i] << " * " << b[i] << " = " << a[i] * b[i] << std::endl << "quire " << q << std::endl;
30
        }
31
        sw::universal::posit<nbits,es> sum;
32
        sw::universal::convert(q.to_value(), sum);     // one and only rounding step of the fused-dot product
33
        std::cout << "fdp result " << sum << std::endl;
34
}
35

36
template<typename Scalar>
37
int VerifyErrorFreeFusedDotProduct(Scalar maxpos) {
3✔
38
        using namespace sw::universal;
39
        using namespace sw::numeric::containers;
40

41
        // Setting up a dot product with catastrophic cancellation
42
        //            a:   maxpos     1       1    ...    1     maxpos
43
        //            b:    -1     epsilon epsilon ... epsilon    1
44
        //         The two maxpos values will cancel out leaving the 32k epsilon's accumulated
45
        //         The dot product will experience catastrophic cancellation, 
46
        //  fdp will calculate the sum of products correctly
47
        using namespace sw::blas;
48
        constexpr unsigned vectorSize = SIZE_32K + 2;
3✔
49
        vector<Scalar> a(vectorSize), b(vectorSize);
3✔
50
        Scalar epsilon = std::numeric_limits<Scalar>::epsilon();
3✔
51
        for (unsigned i = 1; i < vectorSize - 1; ++i) {
98,307✔
52
                a[i] = 1;
98,304✔
53
                b[i] = epsilon;
98,304✔
54
        }
55
        a[0] = a[vectorSize - 1] = maxpos;
3✔
56
        b[0] = -1;  b[vectorSize - 1] = 1;
3✔
57
        std::cout << "a:   maxpos     1       1    ...    1     maxpos\n";
3✔
58
        std::cout << "b:    -1     epsilon epsilon ... epsilon    1\n";
3✔
59
        ReportValue(a[0], "a[0]");
6✔
60
        ReportValue(b[0], "b[0]");
6✔
61
        ReportValue(a[1], "a[1]");
6✔
62
        ReportValue(b[1], "b[1]");
3✔
63

64
        // dot: 0
65
        // fdp: 0.000244141
66
        Scalar errorFullDot = dot(a, b);
3✔
67
        Scalar errorFreeFDP = fdp(a, b);
3✔
68
        std::cout << "\naccumulation of 32k epsilons (" << epsilon << ") for a " << type_tag(Scalar()) << " yields:\n";
3✔
69
        std::cout << "dot            : " << errorFullDot << " : " << to_binary(errorFullDot) << '\n';
3✔
70
        std::cout << "fdp            : " << errorFreeFDP << " : " << to_binary(errorFreeFDP) << '\n';
3✔
71
        Scalar validation = (vectorSize - 2) * epsilon;
3✔
72
        std::cout << "32k * epsilon  : " << validation << " : " << to_binary(validation) << '\n';
3✔
73

74
        return (validation != errorFreeFDP) ? 1 : 0;
6✔
75
}
3✔
76

77
template<typename Scalar>
78
int VerifyVectorScale(unsigned vectorSize ) {
3✔
79
        // scale a vector
80
        using namespace sw::numeric::containers;
81

82
        vector<Scalar> a(vectorSize), b(vectorSize);
3✔
83
        Scalar epsilon = std::numeric_limits<Scalar>::epsilon();
3✔
84

85
        for (unsigned i = 0; i < vectorSize; ++i) {
303✔
86
                a[i] = 1;
300✔
87
                b[i] = epsilon;
300✔
88
        }
89
        a *= epsilon; // a * epsilon -> b
3✔
90
        bool success = true;
3✔
91
        for (unsigned i = 0; i < size(a); ++i) {
303✔
92
                if (a[i] != b[i]) {
300✔
93
                        std::cout << a[i] << " != " << b[i] << '\n';
×
94
                        success = false;
×
95
                        break;
×
96
                }
97
        }
98
        return (success ? 0 : 1);
6✔
99
}
3✔
100

101
// Regression testing guards: typically set by the cmake configuration, but MANUAL_TESTING is an override
102
#define MANUAL_TESTING 0
103
// REGRESSION_LEVEL_OVERRIDE is set by the cmake file to drive a specific regression intensity
104
// It is the responsibility of the regression test to organize the tests in a quartile progression.
105
//#undef REGRESSION_LEVEL_OVERRIDE
106
#ifndef REGRESSION_LEVEL_OVERRIDE
107
#undef REGRESSION_LEVEL_1
108
#undef REGRESSION_LEVEL_2
109
#undef REGRESSION_LEVEL_3
110
#undef REGRESSION_LEVEL_4
111
#define REGRESSION_LEVEL_1 1
112
#define REGRESSION_LEVEL_2 1
113
#define REGRESSION_LEVEL_3 1
114
#define REGRESSION_LEVEL_4 1
115
#endif
116

117
int main()
1✔
118
try {
119
        using namespace sw::universal;
120

121
        std::string test_suite  = "error free FDP";
2✔
122
        std::string test_tag    = "fdp";
1✔
123
        bool reportTestCases    = true;
1✔
124
        int nrOfFailedTestCases = 0;
1✔
125

126
        ReportTestSuiteHeader(test_suite, reportTestCases);
1✔
127

128
        std::cout << "error full and error free dot products\n";
1✔
129
        // posit<8,0> is failing on 32k sums of epsilon
130
        nrOfFailedTestCases += ReportTestResult(VerifyErrorFreeFusedDotProduct(std::numeric_limits<posit<8, 2> >::max()), test_tag, "error free posit<8,2> dot");
2✔
131
        nrOfFailedTestCases += ReportTestResult(VerifyErrorFreeFusedDotProduct(std::numeric_limits<posit<16, 2> >::max()), test_tag, "error free posit<16,2> dot");
2✔
132
        nrOfFailedTestCases += ReportTestResult(VerifyErrorFreeFusedDotProduct(std::numeric_limits<posit<32, 2> >::max()), test_tag, "error free posit<32,2> dot");
1✔
133
        // TBD: no fdp yet for cfloat or lns
134
        // nrOfFailedTestCases += ReportTestResult(VerifyErrorFreeFusedDotProduct(std::numeric_limits< bfloat_t >::max()), test_tag, "error free bfloat16 dot");
135
        // nrOfFailedTestCases += ReportTestResult(VerifyErrorFreeFusedDotProduct(std::numeric_limits< lns<16, 8> >::max()), test_tag, "error free lns dot");
136

137
        std::cout << "Verify Vector scaling for different arithmetic types\n";
1✔
138
        nrOfFailedTestCases += ReportTestResult(VerifyVectorScale< posit<32, 2> >(100), "vector scale", "scale posit vector");
4✔
139
        nrOfFailedTestCases += ReportTestResult(VerifyVectorScale< bfloat_t >(100), "vector scale", "scale bfloat16 vector");
4✔
140
        nrOfFailedTestCases += ReportTestResult(VerifyVectorScale< lns<16, 8> >(100), "vector scale", "scale lns vector");
3✔
141

142
        ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
1✔
143
        return (nrOfFailedTestCases == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1✔
144
}
1✔
NEW
145
catch (char const* msg) {
×
146
        std::cerr << msg << std::endl;
×
147
        return EXIT_FAILURE;
×
148
}
×
149
catch (const sw::universal::posit_arithmetic_exception& err) {
×
150
        std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
×
151
        return EXIT_FAILURE;
×
152
}
×
153
catch (const sw::universal::quire_exception& err) {
×
154
        std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
×
155
        return EXIT_FAILURE;
×
156
}
×
157
catch (const sw::universal::posit_internal_exception& err) {
×
158
        std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
×
159
        return EXIT_FAILURE;
×
160
}
×
161
catch (const std::runtime_error& err) {
×
162
        std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
×
163
        return EXIT_FAILURE;
×
164
}
×
165
catch (...) {
×
166
        std::cerr << "Caught unknown exception" << std::endl;
×
167
        return EXIT_FAILURE;
×
168
}
×
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