diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-09 21:18:43 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-09 21:18:43 +0200 |
commit | ee7f75d94f2a70d61a71eca9416d51a3268859d7 (patch) | |
tree | e6273417231ae83178cf8d5050d02bc59ff195d9 /coreutils | |
parent | 87ae0fe095686b169ab1aeeb25c8ac3f5be30feb (diff) | |
download | busybox-w32-ee7f75d94f2a70d61a71eca9416d51a3268859d7.tar.gz busybox-w32-ee7f75d94f2a70d61a71eca9416d51a3268859d7.tar.bz2 busybox-w32-ee7f75d94f2a70d61a71eca9416d51a3268859d7.zip |
factor: new applet
thus far only able to factor up to ULLONG_MAX
function old new delta
factor_main - 378 +378
packed_usage 31427 31502 +75
applet_names 2590 2597 +7
applet_main 1500 1504 +4
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 3/0 up/down: 464/0) Total: 464 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/factor.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/coreutils/factor.c b/coreutils/factor.c new file mode 100644 index 000000000..0f838a735 --- /dev/null +++ b/coreutils/factor.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com> | ||
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | //config:config FACTOR | ||
7 | //config: bool "factor" | ||
8 | //config: default y | ||
9 | //config: help | ||
10 | //config: factor factorizes integers | ||
11 | |||
12 | //applet:IF_FACTOR(APPLET(factor, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||
13 | |||
14 | //kbuild:lib-$(CONFIG_FACTOR) += factor.o | ||
15 | |||
16 | //usage:#define factor_trivial_usage | ||
17 | //usage: "NUMBER..." | ||
18 | //usage:#define factor_full_usage "\n\n" | ||
19 | //usage: "Print prime factors" | ||
20 | |||
21 | #include "libbb.h" | ||
22 | |||
23 | #if ULLONG_MAX == (UINT_MAX * UINT_MAX + 2 * UINT_MAX) | ||
24 | /* "unsigned" is half as wide as ullong */ | ||
25 | typedef unsigned half_t; | ||
26 | #define HALF_FMT "" | ||
27 | #elif ULLONG_MAX == (ULONG_MAX * ULONG_MAX + 2 * ULONG_MAX) | ||
28 | /* long is half as wide as ullong */ | ||
29 | typedef unsigned long half_t; | ||
30 | #define HALF_FMT "l" | ||
31 | #else | ||
32 | #error Cant find an integer type which is half as wide as ullong | ||
33 | #endif | ||
34 | |||
35 | static void factorize(const char *numstr) | ||
36 | { | ||
37 | unsigned long long N, factor2; | ||
38 | half_t factor; | ||
39 | unsigned count3; | ||
40 | |||
41 | /* Coreutils compat */ | ||
42 | numstr = skip_whitespace(numstr); | ||
43 | if (*numstr == '+') | ||
44 | numstr++; | ||
45 | |||
46 | N = bb_strtoull(numstr, NULL, 10); | ||
47 | if (errno) | ||
48 | bb_show_usage(); | ||
49 | |||
50 | printf("%llu:", N); | ||
51 | |||
52 | if (N < 4) | ||
53 | goto end; | ||
54 | while (!(N & 1)) { | ||
55 | printf(" 2"); | ||
56 | N >>= 1; | ||
57 | } | ||
58 | |||
59 | count3 = 3; | ||
60 | factor = 3; | ||
61 | factor2 = 3 * 3; | ||
62 | for (;;) { | ||
63 | unsigned long long nfactor2; | ||
64 | |||
65 | while ((N % factor) == 0) { | ||
66 | N = N / factor; | ||
67 | printf(" %u"HALF_FMT"", factor); | ||
68 | } | ||
69 | next_factor: | ||
70 | /* (f + 2)^2 = f^2 + 4*f + 4 = f^2 + 4*(f+1) */ | ||
71 | nfactor2 = factor2 + 4 * (factor + 1); | ||
72 | if (nfactor2 < factor2) /* overflow? */ | ||
73 | break; | ||
74 | factor2 = nfactor2; | ||
75 | if (factor2 > N) | ||
76 | break; | ||
77 | factor += 2; | ||
78 | /* Rudimentary wheel sieving: skip multiples of 3: | ||
79 | * Every third odd number is divisible by three and thus isn't a prime: | ||
80 | * 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37... | ||
81 | * ^ ^ ^ ^ ^ ^ ^ _ ^ ^ _ ^ (^primes) | ||
82 | */ | ||
83 | --count3; | ||
84 | if (count3 == 0) { | ||
85 | count3 = 3; | ||
86 | goto next_factor; | ||
87 | } | ||
88 | } | ||
89 | end: | ||
90 | if (N > 1) | ||
91 | printf(" %llu", N); | ||
92 | bb_putchar('\n'); | ||
93 | } | ||
94 | |||
95 | int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
96 | int factor_main(int argc UNUSED_PARAM, char **argv) | ||
97 | { | ||
98 | //// coreutils has undocumented option ---debug (three dashes) | ||
99 | //getopt32(argv, ""); | ||
100 | //argv += optind; | ||
101 | argv++; | ||
102 | |||
103 | if (!*argv) | ||
104 | //TODO: read from stdin | ||
105 | bb_show_usage(); | ||
106 | |||
107 | do { | ||
108 | factorize(*argv); | ||
109 | } while (*++argv); | ||
110 | |||
111 | fflush_stdout_and_exit(EXIT_SUCCESS); | ||
112 | } | ||