1 // posit256.c: example test of the posit API for C programs using 256-bit 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 
7 #define POSIT_NO_GENERICS // MSVC doesn't support _Generic so we'll leave it out from these tests
8 #include <universal/number/posit/posit_c_api.h>
9 
main(int argc,char * argv[])10 int main(int argc, char* argv[])
11 {
12 	const int maxNr = 96;
13 	posit256_t pa, pb, pc;
14 	char str[posit256_str_SIZE];
15 	bool failures = false;
16 	bool bReportIndividualTestCases = false;
17 
18 	// special case values
19 	pa = NAR256;
20 	pb = ZERO256;
21 	pc = posit256_add(pa, pb);
22 	posit256_str(str, pc);
23 	printf("posit value = %s\n", str);
24 
25 	pa = NAR256;
26 	pb = ZERO256;
27 	pc = posit256_sub(pa, pb);
28 	posit256_str(str, pc);
29 	printf("posit value = %s\n", str);
30 
31 	pa = NAR256;
32 	pb = ZERO256;
33 	pc = posit256_mul(pa, pb);
34 	posit256_str(str, pc);
35 	printf("posit value = %s\n", str);
36 
37 	pa = NAR256;
38 	pb = ZERO256;
39 	pc = posit256_div(pa, pb);
40 	posit256_str(str, pc);
41 	printf("posit value = %s\n", str);
42 
43 	bool noReference = true;
44 	printf("Sizeof (long double) is %zu, which isn't sufficiently precise to validate posit<<256,4>>\n", sizeof(long double));
45 
46 	// partial state space
47 	int fails = 0;
48 	for (int a = 0; a < maxNr; ++a) {
49 		pa = posit256_reinterpret( (uint64_t[]){ a, 0, 0, 0 } );
50 		for (int b = 0; b < maxNr; ++b) {
51 			pb = posit256_reinterpret( (uint64_t[]){ b, 0, 0, 0 } );
52 			pc = posit256_add(pa, pb);
53 
54 			long double da, db, dref;
55 			da = posit256_told(pa);
56 			db = posit256_told(pb);
57 			dref = da + db;
58 
59 			posit256_t pref = posit256_fromld(dref);
60 
61 			if (posit256_cmp(pref, pc)) {
62 				char sa[posit256_str_SIZE], sb[posit256_str_SIZE], sc[posit256_str_SIZE], sref[posit256_str_SIZE];
63 				posit256_str(sa, pa);
64 				posit256_str(sb, pb);
65 				posit256_str(sc, pc);
66 				posit256_str(sref, pref);
67 
68 				if (bReportIndividualTestCases) printf("FAIL: %s + %s produced %s instead of %s\n", sa, sb, sc, sref);
69 				++fails;
70 			}
71 		}
72 	}
73 	if (fails) {
74 		if (noReference) {
75 			printf("addition        uncertain\n");
76 		}
77 		else {
78 			printf("addition        FAIL\n");
79 			failures = true;
80 		}
81 	}
82 	else {
83 		printf("addition        PASS\n");
84 	}
85 
86 	// partial state space
87 	fails = 0;
88 	for (int a = 0; a < maxNr; ++a) {
89 		pa = posit256_reinterpret( (uint64_t[]){ a, 0, 0, 0 } );
90 		for (int b = 0; b < maxNr; ++b) {
91 			pb = posit256_reinterpret( (uint64_t[]){ b, 0, 0, 0 } );
92 			pc = posit256_sub(pa, pb);
93 
94 			long double da, db, dref;
95 			da = posit256_told(pa);
96 			db = posit256_told(pb);
97 			dref = da - db;
98 
99 			posit256_t pref = posit256_fromld(dref);
100 			if (posit256_cmp(pref, pc)) {
101 				char sa[posit256_str_SIZE], sb[posit256_str_SIZE], sc[posit256_str_SIZE], sref[posit256_str_SIZE];
102 				posit256_str(sa, pa);
103 				posit256_str(sb, pb);
104 				posit256_str(sc, pc);
105 				posit256_str(sref, pref);
106 
107 				if (bReportIndividualTestCases) printf("FAIL: %s - %s produced %s instead of %s\n", sa, sb, sc, sref);
108 				++fails;
109 			}
110 		}
111 	}
112 	if (fails) {
113 		if (noReference) {
114 			printf("subtraction     uncertain\n");
115 		}
116 		else {
117 			printf("subtraction     FAIL\n");
118 			failures = true;
119 		}
120 	}
121 	else {
122 		printf("subtraction     PASS\n");
123 	}
124 
125 	// partial state space
126 	fails = 0;
127 	for (int a = 0; a < maxNr; ++a) {
128 		pa = posit256_reinterpret( (uint64_t[]){ a, 0, 0, 0 } );
129 		for (int b = 0; b < maxNr; ++b) {
130 			pb = posit256_reinterpret( (uint64_t[]){ b, 0, 0, 0 } );
131 			pc = posit256_mul(pa, pb);
132 
133 			long double da, db, dref;
134 			da = posit256_told(pa);
135 			db = posit256_told(pb);
136 			dref = da * db;
137 
138 			posit256_t pref = posit256_fromld(dref);
139 
140 			if (posit256_cmp(pref, pc)) {
141 				char sa[posit256_str_SIZE], sb[posit256_str_SIZE], sc[posit256_str_SIZE], sref[posit256_str_SIZE];
142 				posit256_str(sa, pa);
143 				posit256_str(sb, pb);
144 				posit256_str(sc, pc);
145 				posit256_str(sref, pref);
146 
147 				if (bReportIndividualTestCases) printf("FAIL: %s * %s produced %s instead of %s\n", sa, sb, sc, sref);
148 				++fails;
149 			}
150 		}
151 	}
152 	if (fails) {
153 		if (noReference) {
154 			printf("multiplication  uncertain\n");
155 		}
156 		else {
157 			printf("multiplication  FAIL\n");
158 			failures = true;
159 		}
160 	}
161 	else {
162 		printf("multiplication  PASS\n");
163 	}
164 
165 	// partial state space
166 	fails = 0;
167 	for (int a = 0; a < maxNr; ++a) {
168 		pa = posit256_reinterpret( (uint64_t[]){ a, 0, 0, 0 } );
169 		for (int b = 0; b < maxNr; ++b) {
170 			pb = posit256_reinterpret( (uint64_t[]){ b, 0, 0, 0 } );
171 			pc = posit256_div(pa, pb);
172 
173 			long double da, db, dref;
174 			da = posit256_told(pa);
175 			db = posit256_told(pb);
176 			dref = da / db;
177 
178 			posit256_t pref = posit256_fromld(dref);
179 
180 			if (posit256_cmp(pref, pc)) {
181 				char sa[posit256_str_SIZE], sb[posit256_str_SIZE], sc[posit256_str_SIZE], sref[posit256_str_SIZE];
182 				posit256_str(sa, pa);
183 				posit256_str(sb, pb);
184 				posit256_str(sc, pc);
185 				posit256_str(sref, pref);
186 
187 				if (bReportIndividualTestCases) printf("FAIL: %s / %s produced %s instead of %s\n", sa, sb, sc, sref);
188 				++fails;
189 			}
190 		}
191 	}
192 	if (fails) {
193 		if (noReference) {
194 			printf("division        uncertain\n");
195 		}
196 		else {
197 			printf("division        FAIL\n");
198 			failures = true;
199 		}
200 	}
201 	else {
202 		printf("division        PASS\n");
203 	}
204 
205 	return failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
206 }
207