-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain_odd.cpp
115 lines (85 loc) · 2.27 KB
/
main_odd.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "fact.hpp"
#if _MSC_VER || __APPLE__ || __SIZEOF_LONG__ == 4
#define FMT64 "%llu"
#else
#define FMT64 "%lu"
#endif
#define FMT32 "%u"
#if NUM_64BIT
typedef uint64_t Number;
#define NUM_FMT FMT64
#else
typedef uint32_t Number;
#define NUM_FMT FMT32
#endif
// use scalar bitness as a conservative estimate of the limit of unique prime factors
Factor< Number > buf[sizeof(Number) * 8];
static Number ipow(const Number base, Number power)
{
Number res = 1;
while (power--)
res *= base;
return res;
}
Number count_trailing_zeroes(const Number x)
{
if (sizeof(unsigned int) >= sizeof(x))
return __builtin_ctz(x);
if (sizeof(unsigned long) >= sizeof(x))
return __builtin_ctzl(x);
return __builtin_ctzll(x);
}
int main(int argc, char** argv)
{
uint64_t temp;
if (2 != argc || 1 != sscanf(argv[1], FMT64, &temp)) {
fprintf(stderr, "usage: %s positive-integer\n", argv[0]);
return EXIT_FAILURE;
}
if (1 == temp)
return EXIT_SUCCESS;
Storage factors(buf);
Number number = Number(temp);
Number candidateFactor = 1;
Number power = 0;
// factorization by 2 is handled in advance
power = count_trailing_zeroes(number);
number >>= power;
factors.push_back_nonzero(2, power);
if (number == 1)
goto printout;
while (true) {
candidateFactor += 2;
power = 0;
while (true) {
const Number quotient = number / candidateFactor;
const Number remainder = number % candidateFactor;
// when looking for factors, as soon as candidateFactor crosses the sqrt(number) mark
// we should add current number to factors and break the main loop
if (quotient < candidateFactor)
goto main_loop_done;
if (remainder)
break;
power++;
number = quotient;
}
factors.push_back_nonzero(candidateFactor, power);
}
main_loop_done:
if (number != candidateFactor) {
factors.push_back_nonzero(candidateFactor, power);
factors.push_back(number, 1);
}
else
factors.push_back(candidateFactor, power + 1);
printout:
for (const Factor< Number > *it = factors.begin(); it != factors.end(); ++it) {
const Number factor = it->prime;
const Number power = it->power;
printf("prime: " NUM_FMT ", power: " NUM_FMT " (" NUM_FMT ")\n", factor, power, ipow(factor, power));
}
return EXIT_SUCCESS;
}