Rev 14 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 14 | Rev 32 | ||
---|---|---|---|
1 | package de.viathinksoft.immortable.gen2; |
1 | package de.viathinksoft.immortal.gen2; |
2 | 2 | ||
3 | import java.math.BigInteger; |
3 | import java.math.BigInteger; |
4 | 4 | ||
5 | import de.viathinksoft.immortable.gen2.math.CoPrimeExpectedException; |
5 | import de.viathinksoft.immortal.gen2.math.CoPrimeExpectedException; |
6 | import de.viathinksoft.immortable.gen2.math.MathUtils; |
6 | import de.viathinksoft.immortal.gen2.math.MathUtils; |
7 | import de.viathinksoft.immortable.gen2.math.MathUtils2; |
7 | import de.viathinksoft.immortal.gen2.math.MathUtils2; |
8 | 8 | ||
9 | /** |
9 | /** |
10 | * Immortable Number Generator (ING) |
10 | * Immortable Number Generator (ING) |
11 | * |
11 | * |
12 | * @author Daniel Marschall |
12 | * @author Daniel Marschall |
13 | */ |
13 | */ |
14 | 14 | ||
15 | public class Immortable { |
15 | public class Immortal { |
16 | 16 | ||
17 | /** |
17 | /** |
18 | * Calculates M5 or M6 |
18 | * Calculates M5 or M6 |
19 | * |
19 | * |
20 | * @param base |
20 | * @param base |
21 | * @param u |
21 | * @param u |
22 | * @return |
22 | * @return |
23 | */ |
23 | */ |
24 | public static BigInteger M(ImmortableBase base, BigInteger u) { |
24 | public static BigInteger M(ImmortalBase base, BigInteger u) { |
25 | BigInteger p, q; |
25 | BigInteger p, q; |
26 | 26 | ||
27 | if (base == ImmortableBase.M5) { |
27 | if (base == ImmortalBase.M5) { |
28 | p = BigInteger.ONE; |
28 | p = BigInteger.ONE; |
29 | q = BigInteger.ZERO; |
29 | q = BigInteger.ZERO; |
30 | } else if (base == ImmortableBase.M6) { |
30 | } else if (base == ImmortalBase.M6) { |
31 | p = BigInteger.ZERO; |
31 | p = BigInteger.ZERO; |
32 | q = BigInteger.ONE; |
32 | q = BigInteger.ONE; |
33 | } else { |
33 | } else { |
34 | p = null; |
34 | p = null; |
35 | q = null; |
35 | q = null; |
36 | } |
36 | } |
37 | 37 | ||
38 | BigInteger a = MathUtils2.pow(new BigInteger("2"), u); |
38 | BigInteger a = MathUtils2.pow(new BigInteger("2"), u); |
39 | BigInteger b = MathUtils2.pow(new BigInteger("5"), u); |
39 | BigInteger b = MathUtils2.pow(new BigInteger("5"), u); |
40 | 40 | ||
41 | // To calculate M5: |
41 | // To calculate M5: |
42 | // x = 2^u = a mod 1 |
42 | // x = 2^u = a mod 1 |
43 | // x = 5^u = b mod 0 |
43 | // x = 5^u = b mod 0 |
44 | 44 | ||
45 | // To calculate M6: |
45 | // To calculate M6: |
46 | // x = 2^u = a mod 0 |
46 | // x = 2^u = a mod 0 |
47 | // x = 5^u = b mod 1 |
47 | // x = 5^u = b mod 1 |
48 | 48 | ||
49 | try { |
49 | try { |
50 | return MathUtils.chineseRemainder(p, a, q, b); |
50 | return MathUtils.chineseRemainder(p, a, q, b); |
51 | } catch (CoPrimeExpectedException e) { |
51 | } catch (CoPrimeExpectedException e) { |
52 | // Can never happen since 2^u and 5^u are always coprimes. |
52 | // Can never happen since 2^u and 5^u are always coprimes. |
53 | return null; |
53 | return null; |
54 | } |
54 | } |
55 | } |
55 | } |
56 | 56 | ||
57 | /** |
57 | /** |
58 | * Gets M5(u) |
58 | * Gets M5(u) |
59 | * |
59 | * |
60 | * @param u |
60 | * @param u |
61 | * Length of number |
61 | * Length of number |
62 | * @return |
62 | * @return |
63 | */ |
63 | */ |
64 | public static BigInteger M5(BigInteger u) { |
64 | public static BigInteger M5(BigInteger u) { |
65 | return M(ImmortableBase.M5, u); |
65 | return M(ImmortalBase.M5, u); |
66 | } |
66 | } |
67 | 67 | ||
68 | /** |
68 | /** |
69 | * Gets M6(u) |
69 | * Gets M6(u) |
70 | * |
70 | * |
71 | * @param u |
71 | * @param u |
72 | * Length of number |
72 | * Length of number |
73 | * @return |
73 | * @return |
74 | */ |
74 | */ |
75 | public static BigInteger M6(BigInteger u) { |
75 | public static BigInteger M6(BigInteger u) { |
76 | return M(ImmortableBase.M6, u); |
76 | return M(ImmortalBase.M6, u); |
77 | } |
77 | } |
78 | 78 | ||
79 | /** |
79 | /** |
80 | * Toggles between M5 and M6 base. |
80 | * Toggles between M5 and M6 base. |
81 | * |
81 | * |
82 | * @param cur |
82 | * @param cur |
83 | * Number |
83 | * Number |
84 | * @param u |
84 | * @param u |
85 | * Length of number (because of possible leading zeros) |
85 | * Length of number (because of possible leading zeros) |
86 | * @return Number in opposide base. |
86 | * @return Number in opposide base. |
87 | * @throws Exception |
87 | * @throws Exception |
88 | */ |
88 | */ |
89 | public static BigInteger toggleBase(BigInteger cur, BigInteger u) |
89 | public static BigInteger toggleBase(BigInteger cur, BigInteger u) |
90 | throws Exception { |
90 | throws Exception { |
91 | // Converts M6(u) <-> M5(u) |
91 | // Converts M6(u) <-> M5(u) |
92 | // M6(u) = 1 + 10^u - M5(u) |
92 | // M6(u) = 1 + 10^u - M5(u) |
93 | // M5(u) = 1 + 10^u - M6(u) |
93 | // M5(u) = 1 + 10^u - M6(u) |
94 | 94 | ||
95 | if (u.compareTo(MathUtils2.length(cur)) < 0) { |
95 | if (u.compareTo(MathUtils2.length(cur)) < 0) { |
96 | throw new InvalidLengthException(); |
96 | throw new InvalidLengthException(); |
97 | } |
97 | } |
98 | 98 | ||
99 | return BigInteger.ONE.add(MathUtils2.pow(BigInteger.TEN, u)).subtract(cur); |
99 | return BigInteger.ONE.add(MathUtils2.pow(BigInteger.TEN, u)).subtract(cur); |
100 | } |
100 | } |
101 | 101 | ||
102 | /** |
102 | /** |
103 | * Toggles between M5 and M6 base. The length of the current number is |
103 | * Toggles between M5 and M6 base. The length of the current number is |
104 | * assumed (and no leading zero). |
104 | * assumed (and no leading zero). |
105 | * |
105 | * |
106 | * @param cur |
106 | * @param cur |
107 | * @return |
107 | * @return |
108 | * @throws Exception |
108 | * @throws Exception |
109 | */ |
109 | */ |
110 | public static BigInteger toggleBase(BigInteger cur) throws Exception { |
110 | public static BigInteger toggleBase(BigInteger cur) throws Exception { |
111 | try { |
111 | try { |
112 | return toggleBase(cur, MathUtils2.length(cur)); |
112 | return toggleBase(cur, MathUtils2.length(cur)); |
113 | } catch (InvalidLengthException e) { |
113 | } catch (InvalidLengthException e) { |
114 | // Should never happen |
114 | // Should never happen |
115 | return null; |
115 | return null; |
116 | } |
116 | } |
117 | } |
117 | } |
118 | 118 | ||
119 | public static boolean isImmortable(BigInteger num) { |
119 | public static boolean isImmortable(BigInteger num) { |
120 | // Alternativ: n²%10^m == n%10^m |
120 | // Alternativ: n²%10^m == n%10^m |
121 | return num.pow(2).toString().endsWith(num.toString()); |
121 | return num.pow(2).toString().endsWith(num.toString()); |
122 | } |
122 | } |
123 | 123 | ||
124 | public static String findNextImmortable(String num) { |
124 | public static String findNextImmortable(String num) { |
125 | if (!isImmortable(new BigInteger(num))) { |
125 | if (!isImmortable(new BigInteger(num))) { |
126 | return null; |
126 | return null; |
127 | } |
127 | } |
128 | for (int i=1; i<=9; i++) { |
128 | for (int i=1; i<=9; i++) { |
129 | String s = i+num; |
129 | String s = i+num; |
130 | if (isImmortable(new BigInteger(s))) { |
130 | if (isImmortable(new BigInteger(s))) { |
131 | return s; |
131 | return s; |
132 | } |
132 | } |
133 | } |
133 | } |
134 | return "0"+num; |
134 | return "0"+num; |
135 | } |
135 | } |
136 | 136 | ||
137 | private Immortable() { |
137 | private Immortal() { |
138 | } |
138 | } |
139 | 139 | ||
140 | } |
140 | } |
141 | 141 |