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

stillwater-sc / universal / 24937901030

25 Apr 2026 06:40PM UTC coverage: 84.314% (-0.02%) from 84.333%
24937901030

Pull #760

github

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

90 of 98 new or added lines in 3 files covered. (91.84%)

15 existing lines in 3 files now uncovered.

45001 of 53373 relevant lines covered (84.31%)

6422634.75 hits per line

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

80.33
/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
                auto check = [&](const char* name, bool ok) {
16✔
49
                        if (!ok) { ++nrOfFailedTestCases; std::cout << "FAIL " << name << '\n'; }
16✔
50
                };
17✔
51

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

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

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

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

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

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

103
                std::cout << "+----- cross-template widening regression: PASS\n";
1✔
104
        }
105

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