1 ///
2 /// @file   iroot.cpp
3 /// @brief  Test integer nth root function.
4 ///
5 /// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
6 ///
7 /// This file is distributed under the BSD License. See the COPYING
8 /// file in the top level directory.
9 ///
10 
11 #include <imath.hpp>
12 #include <int128_t.hpp>
13 
14 #include <stdint.h>
15 #include <iostream>
16 #include <cmath>
17 #include <cstdlib>
18 
19 using namespace primecount;
20 
check(bool OK)21 void check(bool OK)
22 {
23   std::cout << "   " << (OK ? "OK" : "ERROR") << "\n";
24   if (!OK)
25     std::exit(1);
26 }
27 
main()28 int main()
29 {
30   uint64_t n;
31   uint64_t res1;
32   double res2;
33 
34   if (sizeof(long double) > 8)
35   {
36     for (n = 0; n < 100000; n++)
37     {
38       res1 = iroot<2>(n);
39       res2 = std::sqrt((long double) n);
40       std::cout << "iroot<2>(" << n << ") = " << res1;
41       check(res1 == (uint64_t) res2);
42     }
43 
44     for (n = 0; n < 100000; n++)
45     {
46       res1 = iroot<3>(n);
47       res2 = std::cbrt((long double) n);
48       std::cout << "iroot<3>(" << n << ") = " << res1;
49       check(res1 == (uint64_t) res2);
50     }
51 
52     for (n = 0; n < 100000; n++)
53     {
54       res1 = iroot<4>(n);
55       res2 = std::pow((long double) n, 1.0L / 4);
56       std::cout << "iroot<4>(" << n << ") = " << res1;
57       check(res1 == (uint64_t) res2);
58     }
59 
60     for (n = 0; n < 100000; n++)
61     {
62       res1 = iroot<6>(n);
63       res2 = std::pow((long double) n, 1.0L / 6);
64       std::cout << "iroot<6>(" << n << ") = " << res1;
65       check(res1 == (uint64_t) res2);
66     }
67   }
68 
69   n = 18446744073709551615ull;
70   res1 = iroot<2>(n);
71   std::cout << "iroot<2>(" << n << ") = " << res1;
72   check(res1 == 4294967295ull);
73 
74   n = 18446744073709551615ull;
75   res1 = iroot<3>(n);
76   std::cout << "iroot<3>(" << n << ") = " << res1;
77   check(res1 == 2642245);
78 
79   for (uint64_t i = 2000000; i <= 2100000; i++)
80   {
81     n = ipow(i, 3);
82     res1 = iroot<3>(n);
83     std::cout << "iroot<3>(" << n << ") = " << res1;
84     check(res1 == i);
85 
86     res1 = iroot<3>(n - 1);
87     std::cout << "iroot<3>(" << n - 1 << ") = " << res1;
88     check(res1 == i - 1);
89   }
90 
91   n = 18446744073709551615ull;
92   res1 = iroot<4>(n);
93   std::cout << "iroot<4>(" << n << ") = " << res1;
94   check(res1 == 65535);
95 
96   n = 18446744073709551615ull;
97   res1 = iroot<6>(n);
98   std::cout << "iroot<6>(" << n << ") = " << res1;
99   check(res1 == 1625);
100 
101   for (uint64_t i = 1; i <= 1625; i++)
102   {
103     n = ipow(i, 6);
104     res1 = iroot<6>(n);
105     std::cout << "iroot<6>(" << n << ") = " << res1;
106     check(res1 == i);
107 
108     res1 = iroot<6>(n - 1);
109     std::cout << "iroot<6>(" << n - 1 << ") = " << res1;
110     check(res1 == i - 1);
111   }
112 
113 #ifdef HAVE_INT128_T
114 
115   int128_t m;
116   int128_t res;
117 
118   if (sizeof(long double) > 8)
119   {
120     for (m = 0; m < 100000; m++)
121     {
122       res = iroot<2>(m);
123       res2 = std::sqrt((long double) m);
124       std::cout << "iroot<2>(" << m << ") = " << res;
125       check(res == (int128_t) res2);
126     }
127 
128     for (m = 0; m < 100000; m++)
129     {
130       res = iroot<3>(m);
131       res2 = std::cbrt((long double) m);
132       std::cout << "iroot<3>(" << m << ") = " << res;
133       check(res == (int128_t) res2);
134     }
135 
136     for (m = 0; m < 100000; m++)
137     {
138       res = iroot<4>(m);
139       res2 = std::pow((long double) m, 1.0L / 4);
140       std::cout << "iroot<4>(" << m << ") = " << res;
141       check(res == (int128_t) res2);
142     }
143 
144     for (m = 0; m < 100000; m++)
145     {
146       res = iroot<6>(m);
147       res2 = std::pow((long double) m, 1.0L / 6);
148       std::cout << "iroot<6>(" << m << ") = " << res;
149       check(res == (int128_t) res2);
150     }
151   }
152 
153   m = ipow((int128_t) 10, 30);
154   res = iroot<2>(m);
155   std::cout << "iroot<2>(" << m << ") = " << res;
156   check(res == ipow(10ll, 15));
157 
158   res = iroot<2>(m - 1);
159   std::cout << "iroot<2>(" << m - 1 << ") = " << res;
160   check(res == ipow(10ll, 15) - 1);
161 
162   res = iroot<3>(m);
163   std::cout << "iroot<3>(" << m << ") = " << res;
164   check(res == ipow(10ll, 10));
165 
166   res = iroot<3>(m - 1);
167   std::cout << "iroot<3>(" << m - 1 << ") = " << res;
168   check(res == ipow(10ll, 10) - 1);
169 
170   res = iroot<6>(m);
171   std::cout << "iroot<6>(" << m << ") = " << res;
172   check(res == ipow(10, 5));
173 
174   res = iroot<6>(m - 1);
175   std::cout << "iroot<6>(" << m - 1 << ") = " << res;
176   check(res == ipow(10, 5) - 1);
177 
178   m = ipow((int128_t) 10, 28);
179   res = iroot<4>(m);
180   std::cout << "iroot<4>(" << m << ") = " << res;
181   check(res == ipow(10ll, 7));
182 
183   res = iroot<4>(m - 1);
184   std::cout << "iroot<4>(" << m - 1 << ") = " << res;
185   check(res == ipow(10ll, 7) - 1);
186 
187 #endif
188 
189   std::cout << std::endl;
190   std::cout << "All tests passed successfully!" << std::endl;
191 
192   return 0;
193 }
194