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

stillwater-sc / universal / 24938409354

25 Apr 2026 07:07PM UTC coverage: 84.36% (+0.03%) from 84.333%
24938409354

Pull #760

github

web-flow
Merge f5c69dac3 into 5182a1d7b
Pull Request #760: feat(internal): blockbinary mul/div/mod constexpr foundation

89 of 97 new or added lines in 3 files covered. (91.75%)

3 existing lines in 1 file now uncovered.

45027 of 53375 relevant lines covered (84.36%)

6420083.09 hits per line

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

80.95
/internal/blockbinary/api/conversion.cpp
1
//  conversion.cpp : test suite runner for blockbinary construction and conversion of blockbinary
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 <universal/utility/long_double.hpp>
9
#include <iostream>
10

11
#include <universal/internal/blockbinary/blockbinary.hpp>
12
#include <universal/verification/test_suite.hpp>
13

14
int main()
1✔
15
try {
16
        using namespace sw::universal;
17

18
        std::string test_suite  = "blockbinary conversion validation";
2✔
19
        std::string test_tag    = "conversion";
1✔
20
        bool reportTestCases    = true;
1✔
21
        int nrOfFailedTestCases = 0;
1✔
22

23
        ReportTestSuiteHeader(test_suite, reportTestCases);
1✔
24

25
        {
26
                // scenario that happens in unrounded add/sub where blockbinary is used as storage type for fraction or significant
27
                constexpr size_t fbits = 8;
1✔
28
                constexpr size_t fhbits = fbits + 1;
1✔
29
                constexpr size_t abits = fhbits + 3;
1✔
30
                constexpr size_t sumbits = abits + 1;
1✔
31
                size_t msbMask = 1;
1✔
32
                blockbinary<fhbits, uint8_t> a;
33
                for (size_t i = 0; i < fbits; ++i) {
9✔
34
                        a.setbits(msbMask);
8✔
35
                        blockbinary<sumbits, uint8_t> b(a);
8✔
36
                        std::cout << to_binary(a, true) << '\n';
8✔
37
                        std::cout << to_binary(b, true) << '\n';
8✔
38
                        msbMask <<= 1;
8✔
39
                }
40
        }
41

42
        // Cross-template (widening) copy ctor: Signed must sign-extend, Unsigned must
43
        // zero-extend. Regression for the assign() bug surfaced on PR #760: widening
44
        // 0x80 (Unsigned 8-bit) was sign-extending to 0xFF80 instead of 0x0080.
45
        {
46
                std::cout << "+----- cross-template widening (Signed sign-extend, Unsigned zero-extend)\n";
1✔
47

48
                const int failures_before = nrOfFailedTestCases;
1✔
49
                auto check = [&](const char* name, bool ok) {
16✔
50
                        if (!ok) { ++nrOfFailedTestCases; std::cout << "FAIL " << name << '\n'; }
16✔
51
                };
17✔
52

53
                // Signed: negative widens by sign-extension
54
                {
55
                        using S8  = blockbinary<8,  std::uint8_t, BinaryNumberType::Signed>;
56
                        using S16 = blockbinary<16, std::uint8_t, BinaryNumberType::Signed>;
57
                        S16 sx_neg(S8(-1));
1✔
58
                        check("Signed widen -1: low byte == 0xFF",  sx_neg.block(0) == 0xFF);
1✔
59
                        check("Signed widen -1: high byte == 0xFF (sign-ext)", sx_neg.block(1) == 0xFF);
1✔
60
                        check("Signed widen -1: to_sll() == -1",    sx_neg.to_sll() == -1LL);
1✔
61

62
                        // Signed: positive (high bit clear) -- no extension, high bytes are zero
63
                        S16 sx_pos(S8(0x7F));
1✔
64
                        check("Signed widen 0x7F: low byte == 0x7F", sx_pos.block(0) == 0x7F);
1✔
65
                        check("Signed widen 0x7F: high byte == 0x00", sx_pos.block(1) == 0x00);
1✔
66
                        check("Signed widen 0x7F: to_sll() == 127",   sx_pos.to_sll() == 127LL);
1✔
67
                }
68

69
                // Unsigned: high bit is data, MUST zero-extend (regression: was sign-extending)
70
                {
71
                        using U8  = blockbinary<8,  std::uint8_t, BinaryNumberType::Unsigned>;
72
                        using U16 = blockbinary<16, std::uint8_t, BinaryNumberType::Unsigned>;
73
                        U16 zx_msb(U8(0x80));
1✔
74
                        check("Unsigned widen 0x80: low byte == 0x80",  zx_msb.block(0) == 0x80);
1✔
75
                        check("Unsigned widen 0x80: high byte == 0x00 (zero-ext, NOT 0xFF)", zx_msb.block(1) == 0x00);
1✔
76

77
                        U16 zx_all(U8(0xFF));
1✔
78
                        check("Unsigned widen 0xFF: low byte == 0xFF",  zx_all.block(0) == 0xFF);
1✔
79
                        check("Unsigned widen 0xFF: high byte == 0x00 (zero-ext, NOT 0xFF)", zx_all.block(1) == 0x00);
1✔
80
                }
81

82
                // Multi-block widening (uint16 limbs, 32 -> 64 bits): same Signed/Unsigned semantics
83
                {
84
                        using U32 = blockbinary<32, std::uint16_t, BinaryNumberType::Unsigned>;
85
                        using U64 = blockbinary<64, std::uint16_t, BinaryNumberType::Unsigned>;
86
                        U32 src; src.setbits(0xFFFFFFFFull);
1✔
87
                        U64 widened(src);
1✔
88
                        check("Unsigned 32->64 widen 0xFFFFFFFF: low limb",        widened.block(0) == 0xFFFF);
1✔
89
                        check("Unsigned 32->64 widen 0xFFFFFFFF: limb 1",          widened.block(1) == 0xFFFF);
1✔
90
                        check("Unsigned 32->64 widen 0xFFFFFFFF: limb 2 zero",     widened.block(2) == 0x0000);
1✔
91
                        check("Unsigned 32->64 widen 0xFFFFFFFF: limb 3 zero",     widened.block(3) == 0x0000);
1✔
92
                }
93

94
                // Sanity: blockdecimal-flavored use (blockbinary<N, bt, Unsigned> via uint64 limbs)
95
                {
96
                        using U64u64 = blockbinary<64,  std::uint64_t, BinaryNumberType::Unsigned>;
97
                        using U128u64 = blockbinary<128, std::uint64_t, BinaryNumberType::Unsigned>;
98
                        U64u64 src; src.setbits(static_cast<uint64_t>(-1));  // all 64 bits set
1✔
99
                        U128u64 widened(src);
1✔
100
                        check("Unsigned 64->128 widen UINT64_MAX: low limb is all-ones",  widened.block(0) == static_cast<uint64_t>(-1));
1✔
101
                        check("Unsigned 64->128 widen UINT64_MAX: high limb is zero",     widened.block(1) == 0);
1✔
102
                }
103

104
                if (nrOfFailedTestCases == failures_before) {
1✔
105
                        std::cout << "+----- cross-template widening regression: PASS\n";
1✔
106
                }
107
        }
108

109
        ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
1✔
110
        return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
1✔
111
}
1✔
112
catch (char const* msg) {
×
113
        std::cerr << msg << '\n';
×
114
        return EXIT_FAILURE;
×
115
}
×
116
catch (const std::runtime_error& err) {
×
117
        std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
×
118
        return EXIT_FAILURE;
×
119
}
×
UNCOV
120
catch (...) {
×
UNCOV
121
        std::cerr << "Caught unknown exception" << '\n';
×
UNCOV
122
        return EXIT_FAILURE;
×
123
}
×
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