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