10f66f451Sopenharmony_ci/* factor.c - Factor integers
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2014 Rob Landley <rob@landley.net>
40f66f451Sopenharmony_ci *
50f66f451Sopenharmony_ci * No standard, but it's in coreutils
60f66f451Sopenharmony_ci
70f66f451Sopenharmony_ciUSE_FACTOR(NEWTOY(factor, 0, TOYFLAG_USR|TOYFLAG_BIN))
80f66f451Sopenharmony_ci
90f66f451Sopenharmony_ciconfig FACTOR
100f66f451Sopenharmony_ci  bool "factor"
110f66f451Sopenharmony_ci  default y
120f66f451Sopenharmony_ci  help
130f66f451Sopenharmony_ci    usage: factor NUMBER...
140f66f451Sopenharmony_ci
150f66f451Sopenharmony_ci    Factor integers.
160f66f451Sopenharmony_ci*/
170f66f451Sopenharmony_ci
180f66f451Sopenharmony_ci#include "toys.h"
190f66f451Sopenharmony_ci
200f66f451Sopenharmony_cistatic void factor(char *s)
210f66f451Sopenharmony_ci{
220f66f451Sopenharmony_ci  unsigned long long l, ll;
230f66f451Sopenharmony_ci
240f66f451Sopenharmony_ci  for (;;) {
250f66f451Sopenharmony_ci    char *err = s;
260f66f451Sopenharmony_ci    int dash = 0;
270f66f451Sopenharmony_ci
280f66f451Sopenharmony_ci    while(isspace(*s)) s++;
290f66f451Sopenharmony_ci    if (*s=='-') dash = *s++;
300f66f451Sopenharmony_ci    if (!*s) return;
310f66f451Sopenharmony_ci
320f66f451Sopenharmony_ci    errno = 0;
330f66f451Sopenharmony_ci    l = strtoull(s, &s, 0);
340f66f451Sopenharmony_ci    if (errno || (*s && !isspace(*s))) {
350f66f451Sopenharmony_ci      error_msg("%s: not integer", err);
360f66f451Sopenharmony_ci      while (*s && !isspace(*s)) s++;
370f66f451Sopenharmony_ci      continue;
380f66f451Sopenharmony_ci    }
390f66f451Sopenharmony_ci
400f66f451Sopenharmony_ci    printf("-%llu:"+!dash, l);
410f66f451Sopenharmony_ci
420f66f451Sopenharmony_ci    // Negative numbers have -1 as a factor
430f66f451Sopenharmony_ci    if (dash) printf(" -1");
440f66f451Sopenharmony_ci
450f66f451Sopenharmony_ci    // Nothing below 4 has factors
460f66f451Sopenharmony_ci    if (l < 4) {
470f66f451Sopenharmony_ci      printf(" %llu\n", l);
480f66f451Sopenharmony_ci      continue;
490f66f451Sopenharmony_ci    }
500f66f451Sopenharmony_ci
510f66f451Sopenharmony_ci    // Special case factors of 2
520f66f451Sopenharmony_ci    while (l && !(l&1)) {
530f66f451Sopenharmony_ci      printf(" 2");
540f66f451Sopenharmony_ci      l >>= 1;
550f66f451Sopenharmony_ci    }
560f66f451Sopenharmony_ci
570f66f451Sopenharmony_ci    // test odd numbers until square is > remainder or integer wrap.
580f66f451Sopenharmony_ci    for (ll=3; ;ll += 2) {
590f66f451Sopenharmony_ci      long lll = ll*ll;
600f66f451Sopenharmony_ci
610f66f451Sopenharmony_ci      if (lll>l || lll<ll) {
620f66f451Sopenharmony_ci        if (l>1) printf(" %llu", l);
630f66f451Sopenharmony_ci        break;
640f66f451Sopenharmony_ci      }
650f66f451Sopenharmony_ci      while (!(l%ll)) {
660f66f451Sopenharmony_ci        printf(" %llu", ll);
670f66f451Sopenharmony_ci        l /= ll;
680f66f451Sopenharmony_ci      }
690f66f451Sopenharmony_ci    }
700f66f451Sopenharmony_ci    xputc('\n');
710f66f451Sopenharmony_ci  }
720f66f451Sopenharmony_ci}
730f66f451Sopenharmony_ci
740f66f451Sopenharmony_civoid factor_main(void)
750f66f451Sopenharmony_ci{
760f66f451Sopenharmony_ci  if (toys.optc) {
770f66f451Sopenharmony_ci    char **ss;
780f66f451Sopenharmony_ci
790f66f451Sopenharmony_ci    for (ss = toys.optargs; *ss; ss++) factor(*ss);
800f66f451Sopenharmony_ci  } else for (;;) {
810f66f451Sopenharmony_ci    char *s = 0;
820f66f451Sopenharmony_ci    size_t len = 0;
830f66f451Sopenharmony_ci
840f66f451Sopenharmony_ci    if (-1 == getline(&s, &len, stdin)) break;
850f66f451Sopenharmony_ci    factor(s);
860f66f451Sopenharmony_ci  }
870f66f451Sopenharmony_ci}
88