diff options
Diffstat (limited to 'coreutils')
| -rw-r--r-- | coreutils/factor.c | 31 |
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) | |||
| 86 | static NOINLINE half_t isqrt_odd(wide_t N) | 86 | static 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: |
