Rev 30 | Rev 37 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 30 | Rev 32 | ||
---|---|---|---|
1 | package de.viathinksoft.immortal.genX; |
1 | package de.viathinksoft.immortal.genX; |
2 | 2 | ||
3 | import java.io.BufferedReader; |
3 | import java.io.BufferedReader; |
4 | import java.io.BufferedWriter; |
4 | import java.io.BufferedWriter; |
5 | import java.io.File; |
5 | import java.io.File; |
6 | import java.io.FileNotFoundException; |
6 | import java.io.FileNotFoundException; |
7 | import java.io.FileReader; |
7 | import java.io.FileReader; |
8 | import java.io.FileWriter; |
8 | import java.io.FileWriter; |
9 | import java.io.IOException; |
9 | import java.io.IOException; |
10 | import java.math.BigInteger; |
10 | import java.math.BigInteger; |
11 | 11 | ||
12 | /** |
12 | /** |
13 | * Immortable Iterator |
13 | * Immortable Iterator |
14 | * |
14 | * |
15 | * @author Daniel Marschall, Big thanks to the users of MatheBoard.de |
15 | * @author Daniel Marschall, Big thanks to the users of MatheBoard.de |
16 | * @see http://www.matheboard.de/archive/435725/thread.html |
16 | * @see http://www.matheboard.de/archive/435725/thread.html |
17 | */ |
17 | */ |
18 | public class ImmortableNumberSearch { |
18 | public class ImmortalNumberSearch { |
19 | 19 | ||
20 | private static final String SIGNATURE = "Immortal Number Report File Version 2.02"; |
20 | private static final String SIGNATURE = "Immortal Number Report File Version 2.02"; |
21 | private static final String SIGNATURE_MINOR = "Iterator GenX Java (100k save-interval, load-integrity-check, int32-r, array-object) r29"; |
21 | private static final String SIGNATURE_MINOR = "Iterator GenX Java (100k save-interval, load-integrity-check, int32-r, array-object) r29"; |
22 | private static final String END_SIG = "END OF REPORT"; |
22 | private static final String END_SIG = "END OF REPORT"; |
23 | private static final int SOFTBREAK = 76; |
23 | private static final int SOFTBREAK = 76; |
24 | 24 | ||
25 | private ByteArray a; |
25 | private ByteArray a; |
26 | private String filename; |
26 | private String filename; |
27 | private int saveInterval = 100000; |
27 | private int saveInterval = 100000; |
28 | private int u = -1; |
28 | private int u = -1; |
29 | private int r = -1; // FUTURE: r als BigInteger |
29 | private int r = -1; // FUTURE: r als BigInteger |
30 | private String creation_time; |
30 | private String creation_time; |
31 | private String backupDir = "backup"; |
31 | private String backupDir = "backup"; |
32 | 32 | ||
33 | private static final int INITIAL_SIZE = 1000000; |
33 | private static final int INITIAL_SIZE = 1000000; |
34 | private static final int EXPANSION_SIZE = 1000000; |
34 | private static final int EXPANSION_SIZE = 1000000; |
35 | 35 | ||
36 | private boolean do_integrity_test = false; |
36 | private boolean do_integrity_test = false; |
37 | private boolean verbose = false; |
37 | private boolean verbose = false; |
38 | 38 | ||
39 | public boolean isDo_integrity_test() { |
39 | public boolean isDo_integrity_test() { |
40 | return do_integrity_test; |
40 | return do_integrity_test; |
41 | } |
41 | } |
42 | 42 | ||
43 | public void setDo_integrity_test(boolean doIntegrityTest) { |
43 | public void setDo_integrity_test(boolean doIntegrityTest) { |
44 | do_integrity_test = doIntegrityTest; |
44 | do_integrity_test = doIntegrityTest; |
45 | } |
45 | } |
46 | 46 | ||
47 | public boolean isVerbose() { |
47 | public boolean isVerbose() { |
48 | return verbose; |
48 | return verbose; |
49 | } |
49 | } |
50 | 50 | ||
51 | public void setVerbose(boolean verbose) { |
51 | public void setVerbose(boolean verbose) { |
52 | this.verbose = verbose; |
52 | this.verbose = verbose; |
53 | } |
53 | } |
54 | 54 | ||
55 | protected void log(String s) { |
55 | protected void log(String s) { |
56 | if (verbose) { |
56 | if (verbose) { |
57 | String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
57 | String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
58 | System.out.println(timestamp + " - " + s); // FURUE: In eine |
58 | System.out.println(timestamp + " - " + s); // FURUE: In eine |
59 | // Log-Datei schreiben |
59 | // Log-Datei schreiben |
60 | } |
60 | } |
61 | } |
61 | } |
62 | 62 | ||
63 | public ImmortableNumberSearch(String filename) throws LoadException { |
63 | public ImmortalNumberSearch(String filename) throws LoadException { |
64 | this.filename = filename; |
64 | this.filename = filename; |
65 | load(); |
65 | load(); |
66 | } |
66 | } |
67 | 67 | ||
68 | public String getBackupDir() { |
68 | public String getBackupDir() { |
69 | return backupDir; |
69 | return backupDir; |
70 | } |
70 | } |
71 | 71 | ||
72 | public void setBackupDir(String backupDir) { |
72 | public void setBackupDir(String backupDir) { |
73 | this.backupDir = backupDir; |
73 | this.backupDir = backupDir; |
74 | } |
74 | } |
75 | 75 | ||
76 | public int getSaveInterval() { |
76 | public int getSaveInterval() { |
77 | return this.saveInterval; |
77 | return this.saveInterval; |
78 | } |
78 | } |
79 | 79 | ||
80 | public ByteArray getA() { |
80 | public ByteArray getA() { |
81 | return a; |
81 | return a; |
82 | } |
82 | } |
83 | 83 | ||
84 | public int getU() { |
84 | public int getU() { |
85 | return u; |
85 | return u; |
86 | } |
86 | } |
87 | 87 | ||
88 | public int getR() { |
88 | public int getR() { |
89 | return r; |
89 | return r; |
90 | } |
90 | } |
91 | 91 | ||
92 | public String getFilename() { |
92 | public String getFilename() { |
93 | return filename; |
93 | return filename; |
94 | } |
94 | } |
95 | 95 | ||
96 | public void setSaveInterval(int saveInterval) { |
96 | public void setSaveInterval(int saveInterval) { |
97 | this.saveInterval = saveInterval; |
97 | this.saveInterval = saveInterval; |
98 | } |
98 | } |
99 | 99 | ||
100 | private boolean savePointExists() { |
100 | private boolean savePointExists() { |
101 | return new File(filename).exists(); |
101 | return new File(filename).exists(); |
102 | } |
102 | } |
103 | 103 | ||
104 | private void load() throws LoadException { |
104 | private void load() throws LoadException { |
105 | if (!savePointExists()) { |
105 | if (!savePointExists()) { |
106 | this.a = new ByteArray(INITIAL_SIZE, EXPANSION_SIZE); |
106 | this.a = new ByteArray(INITIAL_SIZE, EXPANSION_SIZE); |
107 | return; |
107 | return; |
108 | } |
108 | } |
109 | 109 | ||
110 | BufferedReader f; |
110 | BufferedReader f; |
111 | try { |
111 | try { |
112 | f = new BufferedReader(new FileReader(filename)); |
112 | f = new BufferedReader(new FileReader(filename)); |
113 | } catch (FileNotFoundException e) { |
113 | } catch (FileNotFoundException e) { |
114 | // Will not happen because of savePointExists(). |
114 | // Will not happen because of savePointExists(). |
115 | return; |
115 | return; |
116 | } |
116 | } |
117 | 117 | ||
118 | u = -1; |
118 | u = -1; |
119 | r = -1; |
119 | r = -1; |
120 | 120 | ||
121 | try { |
121 | try { |
122 | try { |
122 | try { |
123 | String s = f.readLine(); |
123 | String s = f.readLine(); |
124 | if (!s.equals(SIGNATURE)) { |
124 | if (!s.equals(SIGNATURE)) { |
125 | throw new LoadException("Corrupt: Wrong signature"); |
125 | throw new LoadException("Corrupt: Wrong signature"); |
126 | } |
126 | } |
127 | 127 | ||
128 | f.readLine(); // Minor. signature |
128 | f.readLine(); // Minor. signature |
129 | f.readLine(); // "" |
129 | f.readLine(); // "" |
130 | 130 | ||
131 | f.readLine(); // "(Starting time)" |
131 | f.readLine(); // "(Starting time)" |
132 | creation_time = f.readLine(); |
132 | creation_time = f.readLine(); |
133 | f.readLine(); // "" |
133 | f.readLine(); // "" |
134 | 134 | ||
135 | f.readLine(); // "(Save timestamp)" |
135 | f.readLine(); // "(Save timestamp)" |
136 | f.readLine(); // Timestamp |
136 | f.readLine(); // Timestamp |
137 | f.readLine(); // "" |
137 | f.readLine(); // "" |
138 | 138 | ||
139 | f.readLine(); // "(Digits)" |
139 | f.readLine(); // "(Digits)" |
140 | s = f.readLine(); |
140 | s = f.readLine(); |
141 | u = Integer.parseInt(s) - 1; |
141 | u = Integer.parseInt(s) - 1; |
142 | f.readLine(); // "" |
142 | f.readLine(); // "" |
143 | 143 | ||
144 | f.readLine(); // "(r)" |
144 | f.readLine(); // "(r)" |
145 | s = f.readLine(); |
145 | s = f.readLine(); |
146 | r = Integer.parseInt(s); // FUTURE: (1) Multi-Line-Support? |
146 | r = Integer.parseInt(s); // FUTURE: (1) Multi-Line-Support? |
147 | f.readLine(); // "" |
147 | f.readLine(); // "" |
148 | 148 | ||
149 | this.a = new ByteArray(u + 1 + EXPANSION_SIZE, EXPANSION_SIZE); |
149 | this.a = new ByteArray(u + 1 + EXPANSION_SIZE, EXPANSION_SIZE); |
150 | 150 | ||
151 | f.readLine(); // "(M5 reversed)" |
151 | f.readLine(); // "(M5 reversed)" |
152 | do { |
152 | do { |
153 | s = f.readLine(); |
153 | s = f.readLine(); |
154 | for (int i = 0; i < s.length(); i++) { |
154 | for (int i = 0; i < s.length(); i++) { |
155 | a.add(Byte.parseByte(s.substring(i, i + 1))); |
155 | a.add(Byte.parseByte(s.substring(i, i + 1))); |
156 | } |
156 | } |
157 | } while (!s.equals("")); |
157 | } while (!s.equals("")); |
158 | 158 | ||
159 | if (u + 1 != a.count()) { |
159 | if (u + 1 != a.count()) { |
160 | throw new LoadException( |
160 | throw new LoadException( |
161 | "Corrupt: Formal and actual length mismatch!"); |
161 | "Corrupt: Formal and actual length mismatch!"); |
162 | } |
162 | } |
163 | 163 | ||
164 | s = f.readLine(); |
164 | s = f.readLine(); |
165 | if (!s.equals(END_SIG)) { |
165 | if (!s.equals(END_SIG)) { |
166 | throw new LoadException("Corrupt: End-signature mismatch."); |
166 | throw new LoadException("Corrupt: End-signature mismatch."); |
167 | } |
167 | } |
168 | } finally { |
168 | } finally { |
169 | f.close(); |
169 | f.close(); |
170 | } |
170 | } |
171 | } catch (IOException e) { |
171 | } catch (IOException e) { |
172 | throw new LoadException(e); |
172 | throw new LoadException(e); |
173 | } |
173 | } |
174 | } |
174 | } |
175 | 175 | ||
176 | private void save(boolean integrityTest) throws SaveException { |
176 | private void save(boolean integrityTest) throws SaveException { |
177 | if ((integrityTest) && (do_integrity_test)) { |
177 | if ((integrityTest) && (do_integrity_test)) { |
178 | log("Beginne Selbsttest vor erster Speicherung..."); |
178 | log("Beginne Selbsttest vor erster Speicherung..."); |
179 | 179 | ||
180 | if (!integryTest()) { |
180 | if (!integryTest()) { |
181 | throw new SaveException( |
181 | throw new SaveException( |
182 | "Integrity test failed. (Loaded file broken?) Will not save."); |
182 | "Integrity test failed. (Loaded file broken?) Will not save."); |
183 | } |
183 | } |
184 | } |
184 | } |
185 | 185 | ||
186 | log("Speichere bei u=" + (u + 1)); |
186 | log("Speichere bei u=" + (u + 1)); |
187 | 187 | ||
188 | String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
188 | String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
189 | String timestamp_filename = DateUtils.now("dd-MM-yyyy_HH-mm-ss"); |
189 | String timestamp_filename = DateUtils.now("dd-MM-yyyy_HH-mm-ss"); |
190 | 190 | ||
191 | try { |
191 | try { |
192 | BufferedWriter f = new BufferedWriter(new FileWriter(filename)); |
192 | BufferedWriter f = new BufferedWriter(new FileWriter(filename)); |
193 | 193 | ||
194 | try { |
194 | try { |
195 | f.write(SIGNATURE + "\r\n"); |
195 | f.write(SIGNATURE + "\r\n"); |
196 | 196 | ||
197 | f.write(SIGNATURE_MINOR + "\r\n"); |
197 | f.write(SIGNATURE_MINOR + "\r\n"); |
198 | f.write("\r\n"); |
198 | f.write("\r\n"); |
199 | 199 | ||
200 | f.write("(Starting time)\r\n"); |
200 | f.write("(Starting time)\r\n"); |
201 | f.write(creation_time + "\r\n"); |
201 | f.write(creation_time + "\r\n"); |
202 | f.write("\r\n"); |
202 | f.write("\r\n"); |
203 | 203 | ||
204 | f.write("(Save timestamp)\r\n"); |
204 | f.write("(Save timestamp)\r\n"); |
205 | f.write(timestamp + "\r\n"); |
205 | f.write(timestamp + "\r\n"); |
206 | f.write("\r\n"); |
206 | f.write("\r\n"); |
207 | 207 | ||
208 | f.write("(Digits)\r\n"); |
208 | f.write("(Digits)\r\n"); |
209 | f.write((u + 1) + "\r\n"); |
209 | f.write((u + 1) + "\r\n"); |
210 | f.write("\r\n"); |
210 | f.write("\r\n"); |
211 | 211 | ||
212 | f.write("(r)\r\n"); |
212 | f.write("(r)\r\n"); |
213 | f.write(r + "\r\n"); // FUTURE: (1) Multi-Line-Support? |
213 | f.write(r + "\r\n"); // FUTURE: (1) Multi-Line-Support? |
214 | f.write("\r\n"); |
214 | f.write("\r\n"); |
215 | 215 | ||
216 | f.write("(M5 reversed)\r\n"); |
216 | f.write("(M5 reversed)\r\n"); |
217 | int i; |
217 | int i; |
218 | for (i = 0; i < a.count(); i++) { |
218 | for (i = 0; i < a.count(); i++) { |
219 | byte xa = a.get(i); |
219 | byte xa = a.get(i); |
220 | f.write("" + xa); |
220 | f.write("" + xa); |
221 | if ((i + 1) % SOFTBREAK == 0) { |
221 | if ((i + 1) % SOFTBREAK == 0) { |
222 | f.write("\r\n"); |
222 | f.write("\r\n"); |
223 | } |
223 | } |
224 | } |
224 | } |
225 | if ((i + 1) % SOFTBREAK != 0) { |
225 | if ((i + 1) % SOFTBREAK != 0) { |
226 | f.write("\r\n"); |
226 | f.write("\r\n"); |
227 | } |
227 | } |
228 | f.write("\r\n"); |
228 | f.write("\r\n"); |
229 | 229 | ||
230 | f.write(END_SIG); |
230 | f.write(END_SIG); |
231 | } finally { |
231 | } finally { |
232 | f.close(); |
232 | f.close(); |
233 | } |
233 | } |
234 | } catch (IOException e) { |
234 | } catch (IOException e) { |
235 | throw new SaveException("Could not save master file.", e); |
235 | throw new SaveException("Could not save master file.", e); |
236 | } |
236 | } |
237 | 237 | ||
238 | // Make backup |
238 | // Make backup |
239 | 239 | ||
240 | new File(backupDir).mkdir(); |
240 | new File(backupDir).mkdir(); |
241 | String bak_filename = backupDir + "/immortal_" + timestamp_filename |
241 | String bak_filename = backupDir + "/immortal_" + timestamp_filename |
242 | + "_" + (u + 1) + ".txt"; |
242 | + "_" + (u + 1) + ".txt"; |
243 | try { |
243 | try { |
244 | FileUtils.copyFile(new File(filename), new File(bak_filename)); |
244 | FileUtils.copyFile(new File(filename), new File(bak_filename)); |
245 | } catch (IOException e) { |
245 | } catch (IOException e) { |
246 | throw new SaveException("Could not make backup", e); |
246 | throw new SaveException("Could not make backup", e); |
247 | } |
247 | } |
248 | 248 | ||
249 | if ((integrityTest) && (do_integrity_test)) { |
249 | if ((integrityTest) && (do_integrity_test)) { |
250 | log("Erste Speicherung absolviert. Stabile Phase hat begonnen."); |
250 | log("Erste Speicherung absolviert. Stabile Phase hat begonnen."); |
251 | } |
251 | } |
252 | } |
252 | } |
253 | 253 | ||
254 | public void calcIterate(int amount) throws SaveException { |
254 | public void calcIterate(int amount) throws SaveException { |
255 | log("Beginn der Rechenarbeit..."); |
255 | log("Beginn der Rechenarbeit..."); |
256 | 256 | ||
257 | int cnt = 0; |
257 | int cnt = 0; |
258 | 258 | ||
259 | // Wir führen beim ersten Speichern einen weiteren |
259 | // Wir führen beim ersten Speichern einen weiteren |
260 | // integrity-Test durch. Grund: Wäre bei einer Fortsetzung einer |
260 | // integrity-Test durch. Grund: Wäre bei einer Fortsetzung einer |
261 | // Datei das "r" falsch (der Datenteil aber korrekt), dann würde |
261 | // Datei das "r" falsch (der Datenteil aber korrekt), dann würde |
262 | // diese Datei beim Speichern ungültige Daten enthalten (Zahl |
262 | // diese Datei beim Speichern ungültige Daten enthalten (Zahl |
263 | // nicht immortabel). |
263 | // nicht immortabel). |
264 | boolean firstSave = true; |
264 | boolean firstSave = true; |
265 | 265 | ||
266 | if (a.isEmpty()) { |
266 | if (a.isEmpty()) { |
267 | creation_time = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
267 | creation_time = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
268 | a.add((byte) 5); |
268 | a.add((byte) 5); |
269 | a.add((byte) 2); |
269 | a.add((byte) 2); |
270 | u = 1; |
270 | u = 1; |
271 | r = 2; |
271 | r = 2; |
272 | cnt += 2; |
272 | cnt += 2; |
273 | } |
273 | } |
274 | 274 | ||
275 | int s, m, k; |
275 | int s, m, k; |
276 | 276 | ||
277 | do { |
277 | do { |
278 | r = (r /* - a.get(u) */) / 10 + a.get(u); |
278 | r = (r /* - a.get(u) */) / 10 + a.get(u); |
279 | s = 0; |
279 | s = 0; |
280 | for (m = 1, k = u; m < k; m++, k--) { |
280 | for (m = 1, k = u; m < k; m++, k--) { |
281 | s += a.get(m) * a.get(k); |
281 | s += a.get(m) * a.get(k); |
282 | } |
282 | } |
283 | r += 2 * s; |
283 | r += 2 * s; |
284 | if (m == k) { |
284 | if (m == k) { |
285 | r += a.get(m) * a.get(m); |
285 | r += a.get(m) * a.get(m); |
286 | } |
286 | } |
287 | u++; |
287 | u++; |
288 | a.add((byte) (r % 10)); |
288 | a.add((byte) (r % 10)); |
289 | 289 | ||
290 | cnt++; |
290 | cnt++; |
291 | if (cnt % saveInterval == 0) { |
291 | if (cnt % saveInterval == 0) { |
292 | save(firstSave); |
292 | save(firstSave); |
293 | firstSave = false; |
293 | firstSave = false; |
294 | } |
294 | } |
295 | } while (cnt != amount); |
295 | } while (cnt != amount); |
296 | 296 | ||
297 | // Wir brauchen nicht zwei Mal zu speichern |
297 | // Wir brauchen nicht zwei Mal zu speichern |
298 | if (cnt - 1 % saveInterval != 0) { |
298 | if (cnt - 1 % saveInterval != 0) { |
299 | log("Letzte Speicherung vor Ende..."); |
299 | log("Letzte Speicherung vor Ende..."); |
300 | save(firstSave); |
300 | save(firstSave); |
301 | // firstSave = false; |
301 | // firstSave = false; |
302 | } |
302 | } |
303 | 303 | ||
304 | log("Ende der Rechenarbeit..."); |
304 | log("Ende der Rechenarbeit..."); |
305 | } |
305 | } |
306 | 306 | ||
307 | public byte getDigitReverse(int u) { |
307 | public byte getDigitReverse(int u) { |
308 | return a.get(u); |
308 | return a.get(u); |
309 | } |
309 | } |
310 | 310 | ||
311 | public StringBuilder M5_StringBuilder(int u) { |
311 | public StringBuilder M5_StringBuilder(int u) { |
312 | StringBuilder s = new StringBuilder(); |
312 | StringBuilder s = new StringBuilder(); |
313 | for (int i = 0; i < a.count(); i++) { |
313 | for (int i = 0; i < a.count(); i++) { |
314 | byte xa = a.get(i); |
314 | byte xa = a.get(i); |
315 | s.append("" + xa); |
315 | s.append("" + xa); |
316 | } |
316 | } |
317 | s.reverse(); |
317 | s.reverse(); |
318 | return s; |
318 | return s; |
319 | } |
319 | } |
320 | 320 | ||
321 | public String M5_String(int u) { |
321 | public String M5_String(int u) { |
322 | return M5_StringBuilder(u).toString(); |
322 | return M5_StringBuilder(u).toString(); |
323 | } |
323 | } |
324 | 324 | ||
325 | public BigInteger M5_BigInteger(int u) { |
325 | public BigInteger M5_BigInteger(int u) { |
326 | return new BigInteger(M5_String(u)); |
326 | return new BigInteger(M5_String(u)); |
327 | } |
327 | } |
328 | 328 | ||
329 | public StringBuilder M6_StringBuilder(int u) { |
329 | public StringBuilder M6_StringBuilder(int u) { |
330 | StringBuilder s = new StringBuilder(); |
330 | StringBuilder s = new StringBuilder(); |
331 | for (int i = 0; i < a.count(); i++) { |
331 | for (int i = 0; i < a.count(); i++) { |
332 | byte xa = a.get(i); |
332 | byte xa = a.get(i); |
333 | if (i > 0) { |
333 | if (i > 0) { |
334 | s.append("" + (9 - xa)); |
334 | s.append("" + (9 - xa)); |
335 | } else { |
335 | } else { |
336 | s.append("" + (11 - xa)); |
336 | s.append("" + (11 - xa)); |
337 | } |
337 | } |
338 | } |
338 | } |
339 | s.reverse(); |
339 | s.reverse(); |
340 | return s; |
340 | return s; |
341 | } |
341 | } |
342 | 342 | ||
343 | public String M6_String(int u) { |
343 | public String M6_String(int u) { |
344 | return M6_StringBuilder(u).toString(); |
344 | return M6_StringBuilder(u).toString(); |
345 | } |
345 | } |
346 | 346 | ||
347 | public BigInteger M6_BigInteger(int u) { |
347 | public BigInteger M6_BigInteger(int u) { |
348 | return new BigInteger(M6_String(u)); |
348 | return new BigInteger(M6_String(u)); |
349 | } |
349 | } |
350 | 350 | ||
351 | protected static boolean isImmortable(BigInteger num, int m) { |
351 | protected static boolean isImmortable(BigInteger num, int m) { |
352 | // Alternativ |
352 | // Alternativ |
353 | // return num.pow(2).toString().endsWith(num.toString()); |
353 | // return num.pow(2).toString().endsWith(num.toString()); |
354 | 354 | ||
355 | // n² === n (mod 10^m) <===> n²%10^m == n%10^m == n |
355 | // n² === n (mod 10^m) <===> n²%10^m == n%10^m == n |
356 | 356 | ||
357 | BigInteger m_pow = BigInteger.TEN.pow(m); |
357 | BigInteger m_pow = BigInteger.TEN.pow(m); |
358 | return num.pow(2).mod(m_pow).equals(num); |
358 | return num.pow(2).mod(m_pow).equals(num); |
359 | } |
359 | } |
360 | 360 | ||
361 | protected static boolean isImmortable(BigInteger num) { |
361 | protected static boolean isImmortable(BigInteger num) { |
362 | int m = num.toString().length(); |
362 | int m = num.toString().length(); |
363 | return isImmortable(num, m); |
363 | return isImmortable(num, m); |
364 | } |
364 | } |
365 | 365 | ||
366 | public boolean integryTest() { |
366 | public boolean integryTest() { |
367 | // return isImmortable(M5_BigInteger(u), a.count()); |
367 | // return isImmortable(M5_BigInteger(u), a.count()); |
368 | return isImmortable(M6_BigInteger(u), a.count()); |
368 | return isImmortable(M6_BigInteger(u), a.count()); |
369 | } |
369 | } |
370 | } |
370 | } |
371 | 371 |