severalgos/3np1 mod problem C++  June 21, 2020
lib_3np1_mod.cpp
Go to the documentation of this file.
1 /* -*- coding: latin-1 -*- */
2 /** \file lib_3np1_mod.cpp
3  *
4  * Piece of severalgos.
5  * https://bitbucket.org/OPiMedia/severalgos
6  *
7  * GPLv3 --- Copyright (C) 2015 Olivier Pirson
8  * http://www.opimedia.be/
9  */
10 
11 #include <iostream>
12 #include <limits>
13 #include <set>
14 #include <unordered_set>
15 #include <vector>
16 
17 #include "lib_3np1_mod.hpp"
18 
19 
20 
21 namespace lib_3np1_mod {
22 
23 std::set<value_type>
25  if (mask == 4294967295u) {
27  } else if (mask == 18446744073709551615ull) {
29  }
30 
31 #ifndef NVERBOSE
32  const value_type verbose_mask(mask > (static_cast<value_type>(1) << 26) - 1
33  ? (static_cast<value_type>(1) << 26) - 1
34  : 0);
35 #endif
36 
37  std::set<value_type> exceptions;
38  std::unordered_set<value_type> visited_values;
39 
40  exceptions.insert(0);
41 
42 #ifndef NVERBOSE
43  if (verbose_mask != 0) {
44  std::cerr << '[';
45  std::cerr.flush();
46  }
47 #endif
48 
49  for (value_type start_n(1); start_n <= mask; start_n += 2) {
50  value_type n(start_n);
51 
52 #ifndef NVERBOSE
53  if ((start_n & verbose_mask) == 1) {
54  std::cerr << ' ' << start_n;
55  std::cerr.flush();
56  }
57 #endif
58 
59  do {
60  assert((n & 1) != 0);
61 
62  n = (n*3 + 1) & mask;
63  if (n != 0) {
64  n >>= m2(n);
65 
66  if (!visited_values.insert(n).second) {
67  n = 0;
68  }
69  }
70  } while (n > start_n);
71 
72  visited_values.clear();
73 
74  if (exceptions.find(n) != exceptions.cend()) {
75  exceptions.insert(start_n);
76 
77 #ifndef NVERBOSE
78  std::cerr << "* Exception: " << start_n << "*";
79  std::cerr.flush();
80 #endif
81  }
82  }
83 
84 #ifndef NVERBOSE
85  if (verbose_mask != 0) {
86  std::cerr << ']' << std::endl;
87  std::cerr.flush();
88  }
89 #endif
90 
91  return exceptions;
92 }
93 
94 
95 std::set<value_type>
97  assert(std::numeric_limits<value_type>::digits >= 32);
98 
99 #ifndef NVERBOSE
100  const value_type verbose_mask((static_cast<value_type>(1) << 26) - 1);
101 #endif
102 
103  std::set<value_type> exceptions;
104  std::unordered_set<value_type> visited_values;
105 
106  exceptions.insert(0);
107 
108 #ifndef NVERBOSE
109  std::cerr << '[';
110  std::cerr.flush();
111 #endif
112 
113  for (uint32_t start_n(3); start_n != 1; start_n += 2) {
114  uint32_t n(start_n);
115 
116 #ifndef NVERBOSE
117  if ((start_n & verbose_mask) == 1) {
118  std::cerr << ' ' << start_n;
119  std::cerr.flush();
120  }
121 #endif
122 
123  do {
124  assert((n & 1) != 0);
125 
126  n = n*3 + 1;
127  if (n != 0) {
128  n >>= m2(n);
129 
130  if (!visited_values.insert(n).second) {
131  n = 0;
132  }
133  }
134  } while (n > start_n);
135 
136  visited_values.clear();
137 
138  if (exceptions.find(n) != exceptions.cend()) {
139  exceptions.insert(start_n);
140 
141 #ifndef NVERBOSE
142  std::cerr << "* Exception: " << start_n << "*";
143  std::cerr.flush();
144 #endif
145  }
146  }
147 
148 #ifndef NVERBOSE
149  std::cerr << ']' << std::endl;
150  std::cerr.flush();
151 #endif
152 
153  return exceptions;
154 }
155 
156 
157 std::set<value_type>
159  assert(std::numeric_limits<value_type>::digits >= 64);
160 
161 #ifndef NVERBOSE
162  const value_type verbose_mask((static_cast<value_type>(1) << 26) - 1);
163 #endif
164 
165  std::set<value_type> exceptions;
166  std::unordered_set<value_type> visited_values;
167 
168  exceptions.insert(0);
169 
170 #ifndef NVERBOSE
171  std::cerr << '[';
172  std::cerr.flush();
173 #endif
174 
175  for (uint64_t start_n(3); start_n != 1; start_n += 2) {
176  uint64_t n(start_n);
177 
178 #ifndef NVERBOSE
179  if ((start_n & verbose_mask) == 1) {
180  std::cerr << ' ' << start_n;
181  std::cerr.flush();
182  }
183 #endif
184 
185  do {
186  assert((n & 1) != 0);
187 
188  n = n*3 + 1;
189  if (n != 0) {
190  n >>= m2(n);
191 
192  if (!visited_values.insert(n).second) {
193  n = 0;
194  }
195  }
196  } while (n > start_n);
197 
198  visited_values.clear();
199 
200  if (exceptions.find(n) != exceptions.cend()) {
201  exceptions.insert(start_n);
202 
203 #ifndef NVERBOSE
204  std::cerr << "* Exception: " << start_n << "*";
205  std::cerr.flush();
206 #endif
207  }
208  }
209 
210 #ifndef NVERBOSE
211  std::cerr << ']' << std::endl;
212  std::cerr.flush();
213 #endif
214 
215  return exceptions;
216 }
217 
218 
219 std::vector<value_type>
221  operation_mask_type operation_mask, value_type mask) {
222  assert(n <= mask);
223 
224  const value_type start_n(n);
225 
226  std::vector<value_type> path{n};
227  std::unordered_set<value_type> visited_values;
228 
229  while ((n >= start_n) && visited_values.insert(n).second) {
230  n = operation_mask(n, mask);
231  path.push_back(n);
232  }
233 
234  return path;
235 }
236 
237 } // namespace lib_3np1_mod
value_type m2(value_type n)
function.
std::vector< value_type > start_path_mask(value_type n, operation_mask_type operation_mask, value_type mask)
Given operation, return the start of path from n to the first value < n or to the first repeated valu...
std::set< value_type > search_mask_exceptions_32()
Calculate and return all null and odd exceptions for the 3n + 1 problem with modulo ...
Function definitions.
value_type(* operation_mask_type)(value_type, value_type)
std::set< value_type > search_mask_exceptions_64()
Calculate and return all null and odd exceptions for the 3n + 1 problem with modulo ...
std::set< value_type > search_mask_exceptions(value_type mask)
Calculate and return all null and odd exceptions for the 3n + 1 problem with modulo (mask + 1)...
uint64_t value_type