aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-04-09 21:18:43 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-04-09 21:18:43 +0200
commitee7f75d94f2a70d61a71eca9416d51a3268859d7 (patch)
treee6273417231ae83178cf8d5050d02bc59ff195d9 /coreutils
parent87ae0fe095686b169ab1aeeb25c8ac3f5be30feb (diff)
downloadbusybox-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.c112
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 */
25typedef 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 */
29typedef 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
35static 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
95int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
96int 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}