1 // posit_integer.cpp : test suite for conversions between integers and posits
2 //
3 // Copyright (C) 2017-2021 Stillwater Supercomputing, Inc.
4 //
5 // This file is part of the universal numbers project, which is released under an MIT Open Source license.
6 #include <iostream>
7 #include <string>
8 // enable conversion between posits and integers
9 #include <universal/adapters/adapt_integer_and_posit.hpp>
10 // configure the integer arithmetic class
11 #define INTEGER_THROW_ARITHMETIC_EXCEPTION 1
12 #include <universal/number/integer/integer.hpp>
13 // configure the posit arithmetic class
14 #define POSIT_THROW_ARITHMETIC_EXCEPTION 1
15 #include <universal/number/posit/posit.hpp>
16
17
18 // is representable
19 #include <universal/functions/isrepresentable.hpp>
20 #include <universal/verification/test_status.hpp> // ReportTestResult
21
22 // generate a posit conversion test case
23 // process to convert an integer to a posit is to
24 // transform the integer into a 1.####eExp format
25 // find msb -> scale is msb
26 // shift all the msb-1 bits into a fraction, making the msb the hidden bit
27 // round the bits we have with respect to the scale of the number
28 template<size_t nbits, size_t es, size_t ibits>
GeneratePositConversionTestCase(sw::universal::posit<nbits,es> & p,const sw::universal::integer<ibits> & w)29 void GeneratePositConversionTestCase(sw::universal::posit<nbits, es>& p, const sw::universal::integer<ibits>& w) {
30 using namespace std;
31 using namespace sw::universal;
32
33 internal::value<ibits> v;
34
35 bool sign = w < 0;
36 bool isZero = w == 0;
37 bool isInf = false;
38 bool isNan = false;
39 long _scale = scale(w);
40 int msb = findMsb(w);
41 internal::bitblock<ibits> fraction_without_hidden_bit;
42 int fbit = ibits - 1;
43 for (int i = msb - 1; i >= 0; --i) {
44 fraction_without_hidden_bit.set(fbit, w.at(i));
45 --fbit;
46 }
47 v.set(sign, _scale, fraction_without_hidden_bit, isZero, isInf, isNan);
48 cout << "integer is " << w << endl;
49 cout << "value is " << v << endl;
50 p = v;
51 cout << "posit is " << color_print(p) << " " << p << " " << hex_format(p) << endl;
52 }
53
54 template<size_t ibits, size_t pbits, size_t pes>
VerifyInteger2PositConversion(const std::string & tag,bool bReportIndividualTestCases)55 int VerifyInteger2PositConversion(const std::string& tag, bool bReportIndividualTestCases) {
56 using namespace std;
57 using namespace sw::universal;
58 int nrOfFailedTests = 0;
59 posit<pbits, pes> p;
60 integer<ibits> i;
61 constexpr size_t NR_INTEGERS = (1 << ibits);
62 //for (integer<ibits> i = min_int<ibits>(); i <= max_int<ibits>(); ++i) { // this doesn't work for signed integers
63 for (size_t pattern = 0; pattern < NR_INTEGERS; ++pattern) {
64 i.setbits(pattern);
65 p = i;
66 // p = i requires ADAPTER_POSIT_AND_INTEGER to be set which is accomplished by
67 // #include <universal/adapters/adapt_integer_and_posit.hpp>
68 // we need to enhance this with an integer type concept
69 long diff = long(p) - long(i);
70 cout << setw(ibits) << i << " " << to_binary(i) << " -> " << color_print(p) << setw(ibits) << p << " diff is " << diff << std::endl;
71 if (diff != 0) ++nrOfFailedTests;
72 }
73 return nrOfFailedTests;
74 }
75
76 template<size_t ibits, size_t pbits, size_t pes>
VerifyPosit2IntegerConversion(const std::string & tag,bool bReportIndividualTestCases)77 int VerifyPosit2IntegerConversion(const std::string& tag, bool bReportIndividualTestCases) {
78 using namespace std;
79 using namespace sw::universal;
80 int nrOfFailedTests = 0;
81 posit<pbits, pes> p;
82 integer<ibits> i;
83 constexpr size_t NR_POSITS = (1 << pbits);
84 for (size_t pattern = 0; pattern < NR_POSITS; ++pattern) {
85 p.setbits(pattern);
86 long diff;
87 if (p.isnar()) {
88 i = 0;
89 diff = 0;
90 }
91 else {
92 // i = p requires ADAPTER_POSIT_AND_INTEGER to be set which is accomplished by
93 // #include <universal/adapters/adapt_integer_and_posit.hpp>
94 // we need to enhance this with an integer type concept
95 diff = long(p) - long(i);
96 }
97 cout << setw(ibits) << i << " " << to_binary(i) << " <- " << color_print(p) << setw(12) << p << " diff is " << diff << std::endl;
98 if (diff != 0) ++nrOfFailedTests;
99 }
100 return nrOfFailedTests;
101 }
102
103 #define MANUAL_TESTING 0
104 #define STRESS_TESTING 0
105
main()106 int main()
107 try {
108 using namespace std;
109 using namespace sw::universal;
110
111 std::string tag = "Conversion between integer and posit failed";
112
113 #if MANUAL_TESTING
114
115 using int128_t = sw::universal::integer<128>;
116 using int256_t = sw::universal::integer<256>;
117 using posit8_t = sw::universal::posit<8,0>;
118 using posit16_t = sw::universal::posit<16,1>;
119 using posit32_t = sw::universal::posit<32,2>;
120 using posit64_t = sw::universal::posit<64,3>;
121 using posit128_t = sw::universal::posit<128,4>;
122 using posit256_t = sw::universal::posit<256,5>;
123
124
125 int128_t int128;
126 int256_t int256;
127 posit8_t p8;
128 posit16_t p16;
129 posit32_t p32;
130 posit64_t p64;
131 posit128_t p128;
132 posit256_t p256;
133
134 // decimal
135 int128.assign("1234567890");
136 cout << to_binary(int128) << " " << int128 << " " << hexfloat << scale(int128) << defaultfloat << endl;
137
138 // octal
139 // int128.assign("01234567");
140 //cout << to_binary(int128) << " " << int128 << endl;
141
142 // hex
143 int128.assign("0x5555'5555");
144 cout << to_binary(int128) << " " << int128 << " " << hexfloat << scale(int128) << defaultfloat << endl;
145 int128.assign("0x5555'5555'5555'5555");
146 cout << to_binary(int128) << " " << int128 << " " << hexfloat << scale(int128) << defaultfloat << endl;
147 int128.assign("0x5555'5555'5555'5555'5555'5555'5555'5555");
148 cout << to_binary(int128) << " " << int128 << " " << hexfloat << scale(int128) << defaultfloat << endl;
149 int128.assign("0x8000'0000'0000'0000'0000'0000'0000'0000");
150 cout << to_binary(int128) << " " << int128 << " " << hexfloat << scale(int128) << defaultfloat << endl;
151 int128.assign("0xAAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA");
152 cout << to_binary(int128) << " " << int128 << " " << hexfloat << scale(int128) << defaultfloat << endl;
153 int128.assign("0xffff'ffff'ffff'ffff'ffff'ffff'ffff'ffff");
154 cout << to_binary(int128) << " " << int128 << " " << hexfloat << scale(int128) << defaultfloat << endl;
155
156 int128.assign("0x5555'5555'5555'5555'5555'5555'5555'5555");
157 posit<32, 5> p;
158 GeneratePositConversionTestCase(p, int128);
159
160 int256.assign("0xAAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA'AAAA");
161
162 integer<5> bla = -15;
163 posit<12, 1> p;
164 convert_i2p(bla, p);
165 cout << color_print(p) << " " << p << endl;
166
167 cout << "done" << endl;
168
169 return EXIT_SUCCESS;
170 #else
171 std::cout << "Integer to posit conversion verfication" << std::endl;
172
173 bool bReportIndividualTestCases = false;
174 int nrOfFailedTestCases = 0;
175
176 nrOfFailedTestCases += ReportTestResult(VerifyInteger2PositConversion<5, 5, 1>(tag, bReportIndividualTestCases), "integer<5> -> posit<5,1>", "=");
177 nrOfFailedTestCases += ReportTestResult(VerifyInteger2PositConversion<5, 8, 1>(tag, bReportIndividualTestCases), "integer<5> -> posit<8,1>", "=");
178 nrOfFailedTestCases += ReportTestResult(VerifyInteger2PositConversion<5, 12, 1>(tag, bReportIndividualTestCases), "integer<5> -> posit<12,1>", "=");
179
180 nrOfFailedTestCases += ReportTestResult(VerifyPosit2IntegerConversion<5, 5, 1>(tag, bReportIndividualTestCases), "posit<5,1> -> integer<5>", "=");
181 nrOfFailedTestCases += ReportTestResult(VerifyPosit2IntegerConversion<5, 5, 2>(tag, bReportIndividualTestCases), "posit<5,2> -> integer<5>", "=");
182
183 nrOfFailedTestCases = 0; // TODO: our test plan is not automated yet
184
185 #if STRESS_TESTING
186 nrOfFailedTestCases += ReportTestResult(VerifyInteger2PositConversion<16, 16, 1>(tag, bReportIndividualTestCases), "integer<16> -> posit<16,1>", "=");
187
188 #endif // STRESS_TESTING
189
190 return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
191
192 #endif // MANUAL_TESTING
193 }
194 catch (char const* msg) {
195 std::cerr << msg << '\n';
196 return EXIT_FAILURE;
197 }
198 catch (const std::runtime_error& err) {
199 std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
200 return EXIT_FAILURE;
201 }
202 catch (...) {
203 std::cerr << "Caught unknown exception" << '\n';
204 return EXIT_FAILURE;
205 }
206