aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-04-10 11:47:48 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-04-10 11:47:48 +0200
commit4908c79a018cdea41d2899ebcef59831117a07cd (patch)
tree9597ce58bf51c045b135ba6f11e5723dc3f682ad /coreutils
parentf428f1dc6cb9e9d3cfcfe3c555d44b6a7686cc88 (diff)
downloadbusybox-w32-4908c79a018cdea41d2899ebcef59831117a07cd.tar.gz
busybox-w32-4908c79a018cdea41d2899ebcef59831117a07cd.tar.bz2
busybox-w32-4908c79a018cdea41d2899ebcef59831117a07cd.zip
factor: better comments, slightl more clever conversion even->odd
function old new delta isqrt_odd 114 111 -3 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/factor.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/coreutils/factor.c b/coreutils/factor.c
index 5c4d124a8..aa2f63089 100644
--- a/coreutils/factor.c
+++ b/coreutils/factor.c
@@ -86,8 +86,9 @@ static inline half_t isqrt(wide_t N)
86static NOINLINE half_t isqrt_odd(wide_t N) 86static NOINLINE half_t isqrt_odd(wide_t N)
87{ 87{
88 half_t s = isqrt(N); 88 half_t s = isqrt(N);
89 if (s && !(s & 1)) /* even? */ 89 /* Subtract 1 from even s, odd s won't change: */
90 s--; 90 /* (doesnt work for zero, but we know that s != 0 here) */
91 s = (s - 1) | 1;
91 return s; 92 return s;
92} 93}
93 94
@@ -107,6 +108,16 @@ static NOINLINE void factorize(wide_t N)
107 N >>= 1; 108 N >>= 1;
108 } 109 }
109 110
111 /* The code needs to be optimized for the case where
112 * there are large prime factors. For example,
113 * this is not hard:
114 * 8262075252869367027 = 3 7 17 23 47 101 113 127 131 137 823
115 * (the largest factor to test is only ~sqrt(823) = 28)
116 * but this is:
117 * 18446744073709551601 = 53 348051774975651917
118 * the last factor requires testing up to
119 * 589959129 - about 100 million iterations.
120 */
110 max_factor = isqrt_odd(N); 121 max_factor = isqrt_odd(N);
111 count3 = 3; 122 count3 = 3;
112 count5 = 6; 123 count5 = 6;
@@ -130,18 +141,28 @@ static NOINLINE void factorize(wide_t N)
130 * 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47... 141 * 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47...
131 * ^ ^ ^ ^ ^ ^ ^ _ ^ ^ _ ^ ^ ^ ^ 142 * ^ ^ ^ ^ ^ ^ ^ _ ^ ^ _ ^ ^ ^ ^
132 * (^ = primes, _ = would-be-primes-if-not-divisible-by-5) 143 * (^ = primes, _ = would-be-primes-if-not-divisible-by-5)
144 * The numbers with space under them are excluded by sieve 3.
133 */ 145 */
134 count7--; 146 count7--;
135 count5--; 147 count5--;
136 count3--; 148 count3--;
137 if (count3 && count5 && count7) 149 if (count3 && count5 && count7)
138 continue; 150 continue;
139 if (count3 == 0) 151 /*
152 * "factor" is multiple of 3 33% of the time (count3 reached 0),
153 * else, multiple of 5 13% of the time,
154 * else, multiple of 7 7.6% of the time.
155 * Cumulatively, with 3,5,7 sieving we are here 54.3% of the time.
156 */
157 if (count3 == 0) {
140 count3 = 3; 158 count3 = 3;
141 if (count5 == 0) 159 }
160 if (count5 == 0) {
142 count5 = 5; 161 count5 = 5;
143 if (count7 == 0) 162 }
163 if (count7 == 0) {
144 count7 = 7; 164 count7 = 7;
165 }
145 goto next_factor; 166 goto next_factor;
146 } 167 }
147 end: 168 end: