1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Cavium, Inc
3  */
4 
5 #include "test.h"
6 
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <inttypes.h>
10 
11 #include <rte_common.h>
12 #include <rte_cycles.h>
13 #include <rte_random.h>
14 #include <rte_reciprocal.h>
15 
16 #define MAX_ITERATIONS	(1ULL << 32)
17 #define DIVIDE_ITER	(100)
18 
19 static int
test_reciprocal(void)20 test_reciprocal(void)
21 {
22 	int result = 0;
23 	uint32_t divisor_u32 = 0;
24 	uint32_t dividend_u32;
25 	uint32_t nresult_u32;
26 	uint32_t rresult_u32;
27 	uint64_t i, j;
28 	uint64_t divisor_u64 = 0;
29 	uint64_t dividend_u64;
30 	uint64_t nresult_u64;
31 	uint64_t rresult_u64;
32 	struct rte_reciprocal reci_u32 = {0};
33 	struct rte_reciprocal_u64 reci_u64 = {0};
34 
35 	rte_srand(rte_rdtsc());
36 	printf("Validating unsigned 32bit division.\n");
37 	for (i = 0; i < MAX_ITERATIONS; i++) {
38 		/* Change divisor every DIVIDE_ITER iterations. */
39 		if (i % DIVIDE_ITER == 0) {
40 			divisor_u32 = rte_rand();
41 			reci_u32 = rte_reciprocal_value(divisor_u32);
42 		}
43 
44 		dividend_u32 = rte_rand();
45 		nresult_u32 = dividend_u32 / divisor_u32;
46 		rresult_u32 = rte_reciprocal_divide(dividend_u32,
47 				reci_u32);
48 		if (nresult_u32 != rresult_u32) {
49 			printf("Division failed, %"PRIu32"/%"PRIu32" = "
50 					"expected %"PRIu32" result %"PRIu32"\n",
51 					dividend_u32, divisor_u32,
52 					nresult_u32, rresult_u32);
53 			result = 1;
54 			break;
55 		}
56 	}
57 
58 	printf("Validating unsigned 64bit division.\n");
59 	for (i = 0; i < MAX_ITERATIONS; i++) {
60 		/* Change divisor every DIVIDE_ITER iterations. */
61 		if (i % DIVIDE_ITER == 0) {
62 			divisor_u64 = rte_rand();
63 			reci_u64 = rte_reciprocal_value_u64(divisor_u64);
64 		}
65 
66 		dividend_u64 = rte_rand();
67 		nresult_u64 = dividend_u64 / divisor_u64;
68 		rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
69 				&reci_u64);
70 		if (nresult_u64 != rresult_u64) {
71 			printf("Division failed,  %"PRIu64"/%"PRIu64" = "
72 					"expected %"PRIu64" result %"PRIu64"\n",
73 					dividend_u64, divisor_u64,
74 					nresult_u64, rresult_u64);
75 			result = 1;
76 			break;
77 		}
78 	}
79 
80 	printf("Validating unsigned 64bit division with 32bit divisor.\n");
81 	for (i = 0; i < MAX_ITERATIONS; i++) {
82 		/* Change divisor every DIVIDE_ITER iterations. */
83 		if (i % DIVIDE_ITER == 0) {
84 			divisor_u64 = rte_rand() >> 32;
85 			reci_u64 = rte_reciprocal_value_u64(divisor_u64);
86 		}
87 
88 		dividend_u64 = rte_rand();
89 
90 		nresult_u64 = dividend_u64 / divisor_u64;
91 		rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
92 				&reci_u64);
93 
94 		if (nresult_u64 != rresult_u64) {
95 			printf("Division failed, %"PRIu64"/%"PRIu64" = "
96 					"expected %"PRIu64" result %"PRIu64"\n",
97 					dividend_u64, divisor_u64,
98 					nresult_u64, rresult_u64);
99 			result = 1;
100 			break;
101 		}
102 	}
103 
104 	printf("Validating division by power of 2.\n");
105 	for (i = 0; i < 32; i++) {
106 		divisor_u64 = 1ull << i;
107 		reci_u64 = rte_reciprocal_value_u64(divisor_u64);
108 		reci_u32 = rte_reciprocal_value((uint32_t)divisor_u64);
109 
110 		for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
111 			dividend_u64 = rte_rand();
112 
113 			nresult_u64 = dividend_u64 / divisor_u64;
114 			rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
115 					&reci_u64);
116 
117 			if (nresult_u64 != rresult_u64) {
118 				printf(
119 				"Division 64 failed, %"PRIu64"/%"PRIu64" = "
120 					"expected %"PRIu64" result %"PRIu64"\n",
121 						dividend_u64, divisor_u64,
122 						nresult_u64, rresult_u64);
123 				result = 1;
124 			}
125 
126 			nresult_u32 = (dividend_u64 >> 32) / divisor_u64;
127 			rresult_u32 = rte_reciprocal_divide(
128 					(dividend_u64 >> 32), reci_u32);
129 
130 			if (nresult_u32 != rresult_u32) {
131 				printf(
132 				"Division 32 failed, %"PRIu64"/%"PRIu64" = "
133 					"expected %"PRIu64" result %"PRIu64"\n",
134 						dividend_u64 >> 32, divisor_u64,
135 						nresult_u64, rresult_u64);
136 				result = 1;
137 				break;
138 			}
139 		}
140 	}
141 
142 	for (; i < 64; i++) {
143 		divisor_u64 = 1ull << i;
144 		reci_u64 = rte_reciprocal_value_u64(divisor_u64);
145 
146 		for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
147 			dividend_u64 = rte_rand();
148 
149 			nresult_u64 = dividend_u64 / divisor_u64;
150 			rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
151 					&reci_u64);
152 
153 			if (nresult_u64 != rresult_u64) {
154 				printf("Division failed, %"PRIu64"/%"PRIu64" = "
155 					"expected %"PRIu64" result %"PRIu64"\n",
156 						dividend_u64, divisor_u64,
157 						nresult_u64, rresult_u64);
158 				result = 1;
159 				break;
160 			}
161 		}
162 	}
163 
164 	return result;
165 }
166 
167 REGISTER_TEST_COMMAND(reciprocal_division, test_reciprocal);
168