Rev 37 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 37 | Rev 38 | ||
---|---|---|---|
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 ImmortalNumberSearch { |
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) r38"; |
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 = true; |
36 | private boolean do_integrity_test = true; |
37 | private boolean verbose = true; |
37 | private boolean verbose = true; |
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 | // FUTURE: In eine Log-Datei schreiben |
58 | // FUTURE: In eine Log-Datei schreiben |
59 | System.out.println(timestamp + " - " + s); |
59 | System.out.println(timestamp + " - " + s); |
60 | } |
60 | } |
61 | } |
61 | } |
62 | 62 | ||
63 | public ImmortalNumberSearch(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 + 1) + " digits"); |
186 | log("Speichere bei " + (u + 1) + " digits"); |
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 % SOFTBREAK != 0) { /* nicht +1, da i++ am Ende */ |
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 | f.write("\r\n"); |
231 | f.write("\r\n"); |
232 | } finally { |
232 | } finally { |
233 | f.close(); |
233 | f.close(); |
234 | } |
234 | } |
235 | } catch (IOException e) { |
235 | } catch (IOException e) { |
236 | throw new SaveException("Could not save master file.", e); |
236 | throw new SaveException("Could not save master file.", e); |
237 | } |
237 | } |
238 | 238 | ||
239 | // Make backup |
239 | // Make backup |
240 | 240 | ||
241 | new File(backupDir).mkdir(); |
241 | new File(backupDir).mkdir(); |
242 | String bak_filename = backupDir + "/immortal_" + timestamp_filename |
242 | String bak_filename = backupDir + "/immortal_" + timestamp_filename |
243 | + "_" + (u + 1) + ".txt"; |
243 | + "_" + (u + 1) + ".txt"; |
244 | try { |
244 | try { |
245 | FileUtils.copyFile(new File(filename), new File(bak_filename)); |
245 | FileUtils.copyFile(new File(filename), new File(bak_filename)); |
246 | } catch (IOException e) { |
246 | } catch (IOException e) { |
247 | throw new SaveException("Could not make backup", e); |
247 | throw new SaveException("Could not make backup", e); |
248 | } |
248 | } |
249 | 249 | ||
250 | if ((integrityTest) && (do_integrity_test)) { |
250 | if ((integrityTest) && (do_integrity_test)) { |
251 | log("Erste Speicherung absolviert. Stabile Phase hat begonnen."); |
251 | log("Erste Speicherung absolviert. Stabile Phase hat begonnen."); |
252 | } |
252 | } |
253 | } |
253 | } |
254 | 254 | ||
255 | public void calcIterate(int amount) throws SaveException { |
255 | public void calcIterate(int amount) throws SaveException { |
256 | log("Beginn der Rechenarbeit..."); |
256 | log("Beginn der Rechenarbeit..."); |
257 | 257 | ||
258 | int cnt = 0; |
258 | int cnt = 0; |
259 | 259 | ||
260 | // Wir führen beim ersten Speichern einen weiteren |
260 | // Wir führen beim ersten Speichern einen weiteren |
261 | // integrity-Test durch. Grund: Wäre bei einer Fortsetzung einer |
261 | // integrity-Test durch. Grund: Wäre bei einer Fortsetzung einer |
262 | // Datei das "r" falsch (der Datenteil aber korrekt), dann würde |
262 | // Datei das "r" falsch (der Datenteil aber korrekt), dann würde |
263 | // diese Datei beim Speichern ungültige Daten enthalten (Zahl |
263 | // diese Datei beim Speichern ungültige Daten enthalten (Zahl |
264 | // nicht immortabel). |
264 | // nicht immortabel). |
265 | boolean firstSave = true; |
265 | boolean firstSave = true; |
266 | 266 | ||
267 | if (a.isEmpty()) { |
267 | if (a.isEmpty()) { |
268 | creation_time = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
268 | creation_time = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
269 | a.add((byte) 5); |
269 | a.add((byte) 5); |
270 | a.add((byte) 2); |
270 | a.add((byte) 2); |
271 | u = 1; |
271 | u = 1; |
272 | r = 2; |
272 | r = 2; |
273 | cnt += 2; |
273 | cnt += 2; |
274 | } |
274 | } |
275 | 275 | ||
276 | int s, m, k; |
276 | int s, m, k; |
277 | 277 | ||
278 | do { |
278 | do { |
279 | r = (r /* - a.get(u) */) / 10 + a.get(u); |
279 | r = (r /* - a.get(u) */) / 10 + a.get(u); |
280 | s = 0; |
280 | s = 0; |
281 | for (m = 1, k = u; m < k; m++, k--) { |
281 | for (m = 1, k = u; m < k; m++, k--) { |
282 | s += a.get(m) * a.get(k); |
282 | s += a.get(m) * a.get(k); |
283 | } |
283 | } |
284 | r += 2 * s; |
284 | r += 2 * s; |
285 | if (m == k) { |
285 | if (m == k) { |
286 | r += a.get(m) * a.get(m); |
286 | r += a.get(m) * a.get(m); |
287 | } |
287 | } |
288 | u++; |
288 | u++; |
289 | a.add((byte) (r % 10)); |
289 | a.add((byte) (r % 10)); |
290 | 290 | ||
291 | cnt++; |
291 | cnt++; |
292 | if (cnt % saveInterval == 0) { |
292 | if (cnt % saveInterval == 0) { |
293 | save(firstSave); |
293 | save(firstSave); |
294 | firstSave = false; |
294 | firstSave = false; |
295 | } |
295 | } |
296 | } while (cnt != amount); |
296 | } while (cnt != amount); |
297 | 297 | ||
298 | // Wir brauchen nicht zwei Mal zu speichern |
298 | // Wir brauchen nicht zwei Mal zu speichern |
299 | if (cnt - 1 % saveInterval != 0) { |
299 | if (cnt - 1 % saveInterval != 0) { |
300 | log("Letzte Speicherung vor Ende..."); |
300 | log("Letzte Speicherung vor Ende..."); |
301 | save(firstSave); |
301 | save(firstSave); |
302 | // firstSave = false; |
302 | // firstSave = false; |
303 | } |
303 | } |
304 | 304 | ||
305 | log("Ende der Rechenarbeit..."); |
305 | log("Ende der Rechenarbeit..."); |
306 | } |
306 | } |
307 | 307 | ||
308 | public byte getDigitReverse(int u) { |
308 | public byte getDigitReverse(int u) { |
309 | return a.get(u); |
309 | return a.get(u); |
310 | } |
310 | } |
311 | 311 | ||
312 | public StringBuilder M5_StringBuilder(int u) { |
312 | public StringBuilder M5_StringBuilder(int u) { |
313 | StringBuilder s = new StringBuilder(); |
313 | StringBuilder s = new StringBuilder(); |
314 | for (int i = 0; i < a.count(); i++) { |
314 | for (int i = 0; i < a.count(); i++) { |
315 | byte xa = a.get(i); |
315 | byte xa = a.get(i); |
316 | s.append("" + xa); |
316 | s.append("" + xa); |
317 | } |
317 | } |
318 | s.reverse(); |
318 | s.reverse(); |
319 | return s; |
319 | return s; |
320 | } |
320 | } |
321 | 321 | ||
322 | public String M5_String(int u) { |
322 | public String M5_String(int u) { |
323 | return M5_StringBuilder(u).toString(); |
323 | return M5_StringBuilder(u).toString(); |
324 | } |
324 | } |
325 | 325 | ||
326 | public BigInteger M5_BigInteger(int u) { |
326 | public BigInteger M5_BigInteger(int u) { |
327 | return new BigInteger(M5_String(u)); |
327 | return new BigInteger(M5_String(u)); |
328 | } |
328 | } |
329 | 329 | ||
330 | public StringBuilder M6_StringBuilder(int u) { |
330 | public StringBuilder M6_StringBuilder(int u) { |
331 | StringBuilder s = new StringBuilder(); |
331 | StringBuilder s = new StringBuilder(); |
332 | for (int i = 0; i < a.count(); i++) { |
332 | for (int i = 0; i < a.count(); i++) { |
333 | byte xa = a.get(i); |
333 | byte xa = a.get(i); |
334 | if (i > 0) { |
334 | if (i > 0) { |
335 | s.append("" + (9 - xa)); |
335 | s.append("" + (9 - xa)); |
336 | } else { |
336 | } else { |
337 | s.append("" + (11 - xa)); |
337 | s.append("" + (11 - xa)); |
338 | } |
338 | } |
339 | } |
339 | } |
340 | s.reverse(); |
340 | s.reverse(); |
341 | return s; |
341 | return s; |
342 | } |
342 | } |
343 | 343 | ||
344 | public String M6_String(int u) { |
344 | public String M6_String(int u) { |
345 | return M6_StringBuilder(u).toString(); |
345 | return M6_StringBuilder(u).toString(); |
346 | } |
346 | } |
347 | 347 | ||
348 | public BigInteger M6_BigInteger(int u) { |
348 | public BigInteger M6_BigInteger(int u) { |
349 | return new BigInteger(M6_String(u)); |
349 | return new BigInteger(M6_String(u)); |
350 | } |
350 | } |
351 | 351 | ||
352 | protected static boolean isImmortable(BigInteger num, int m) { |
352 | protected static boolean isImmortable(BigInteger num, int m) { |
353 | // Alternativ |
353 | // Alternativ |
354 | // return num.pow(2).toString().endsWith(num.toString()); |
354 | // return num.pow(2).toString().endsWith(num.toString()); |
355 | 355 | ||
356 | // n² === n (mod 10^m) <===> n²%10^m == n%10^m == n |
356 | // n² === n (mod 10^m) <===> n²%10^m == n%10^m == n |
357 | 357 | ||
358 | BigInteger m_pow = BigInteger.TEN.pow(m); |
358 | BigInteger m_pow = BigInteger.TEN.pow(m); |
359 | return num.pow(2).mod(m_pow).equals(num); |
359 | return num.pow(2).mod(m_pow).equals(num); |
360 | } |
360 | } |
361 | 361 | ||
362 | protected static boolean isImmortable(BigInteger num) { |
362 | protected static boolean isImmortable(BigInteger num) { |
363 | int m = num.toString().length(); |
363 | int m = num.toString().length(); |
364 | return isImmortable(num, m); |
364 | return isImmortable(num, m); |
365 | } |
365 | } |
366 | 366 | ||
367 | public boolean integryTest() { |
367 | public boolean integryTest() { |
368 | // return isImmortable(M5_BigInteger(u), a.count()); |
368 | // return isImmortable(M5_BigInteger(u), a.count()); |
369 | return isImmortable(M6_BigInteger(u), a.count()); |
369 | return isImmortable(M6_BigInteger(u), a.count()); |
370 | } |
370 | } |
371 | } |
371 | } |
372 | 372 |