/*
PROGRAM FOR DISMAL ARITHMETIC
David Applegate (david(AT)research.att.com), Nov 11 2003
*************************************************************************
DESCRIPTION
Dismal arithmetic was invented by Marc LeBrun in 2003.
The following is a C program for doing dismal arithmetic
and dismal number theory.
The operations of dismal addition and dismal multiplication are
described in sequences A087061 (addition) and A087062 (multiplication)
in the On-Line Encyclopedia of Integer Sequences.
(A087062 also has Maple code for addition and multiplication.)
Once this C program is compiled, you can type
dismal help
and it will reply
Usage: dismal cmd [args...]
available cmds are:
div a b Outputs c such that b*c = a
divs a Outputs b such that b*c = a for some c
add a b Outputs a+b
mul a b Outputs a*b
pcount a b Counts the primes in [a,b]
dinfo a Outputs info about divisors of a
dinfo a b Outputs info about divisors of n, a<=n<=b
pdinfo a Outputs info about prime divisors of a
pdinfo a b Outputs info about prime divisors of n, a<=n<=b
help_dinfo Describes the output of dinfo and pdinfo
help Outputs this text
For example,
dismal divs 10
will produce all dismal divisors of 10 in some random order:
1
10
20
30
40
50
60
70
80
90
2
3
4
5
6
7
8
9
(Note that 10 has just one dismal prime divisor, 90 !)
**************************************************************************
INSTALLATION:
call this file dismal_eis.c and compile it, for example using
cc -o dismal_eis dismal_eis.c
**************************************************************************
*/
#include
#include
#include
#include
#include
#include
typedef char digit;
#define SWAP(a,b,t) ((t)=(a),(a)=(b),(b)=(t))
char *my_strdup (char *s)
{
char *p = (char *) malloc ((strlen(s)+1) * sizeof (char));
if (p == (char *) NULL) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
strcpy (p, s);
return p;
}
int isprime (unsigned int p)
{
unsigned int i;
if ((p&1) == 0) return 0;
for (i=3; i*i<=p; i+=2) {
if (p%i == 0) return 0;
}
return 1;
}
unsigned int nextprime (unsigned int x)
{
if (x < 3) return 3;
x |= 1;
while (!isprime (x)) x += 2;
return x;
}
typedef struct digithash {
unsigned int size;
unsigned int nelems;
unsigned int full;
digit **table;
} digithash;
#define DIGITHASH_INITSIZE 1019
#define DIGITHASH_HIDENS 0.75
#define DIGITHASH_LODENS 0.35
void digithash_init (digithash *h)
{
unsigned int i;
h->size = nextprime (DIGITHASH_INITSIZE);
h->nelems = 0;
h->full = (int) (DIGITHASH_HIDENS * h->size);
h->table = (digit **) malloc (h->size * sizeof (digit *));
if (!h->table) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
for (i=0; isize; i++) h->table[i] = (digit *) NULL;
}
void digithash_free (digithash *h)
{
unsigned int i;
if (!h->table) return;
for (i=0; isize; i++) {
if (h->table[i]) free (h->table[i]);
}
free (h->table);
}
unsigned int digithash_hash (digit *n)
{
unsigned int v = 0;
while (*n) v = v * 11 + *n++;
return v;
}
int digithash_add_work (digithash *h, digit *n, int add)
{
unsigned int loc = digithash_hash (n) % h->size;
while (h->table[loc]) {
if (!strcmp (h->table[loc], n)) return 0;
loc++;
if (loc >= h->size) loc = 0;
}
if (add) {
h->table[loc] = n;
h->nelems++;
}
return 1;
}
void digithash_resize (digithash *h)
{
unsigned int newsize = nextprime ((unsigned int) (h->nelems /
DIGITHASH_LODENS) + 1);
unsigned int oldsize = h->size;
digit **oldtable = h->table;
unsigned int i;
h->table = (digit **) malloc (newsize * sizeof (digit *));
if (!h->table) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
for (i=0; itable[i] = (digit *) NULL;
}
h->size = newsize;
for (i=0; ifull = (int) (DIGITHASH_HIDENS * h->size);
}
int digithash_add (digithash *h, digit *n)
{
digit *ncopy = my_strdup (n);
if (h->nelems >= h->full) {
digithash_resize (h);
}
if (digithash_add_work (h, ncopy, 1)) {
return 1;
} else {
free (ncopy);
return 0;
}
}
int digithash_find (digithash *h, digit *n)
{
return !digithash_add_work (h, n, 0);
}
int nfound = 0;
int ndeadend = 0;
int ndup = 0;
typedef struct dig_range {
digit min;
digit max;
} dig_range;
typedef struct div_num {
int len;
dig_range *digs;
} div_num;
typedef struct divide_help {
div_num a;
int numlen;
int *numorder;
digit *res;
digithash reshash;
} divide_help;
typedef struct stack_elem {
int idx;
digit d;
} stack_elem;
typedef struct stack {
int top;
int maxtop;
stack_elem *ents;
} stack;
#define PUSH(s,id,dig) { \
if ((s)->top >= (s)->maxtop) { \
fprintf (stderr, "Out of stack space\n"); \
exit (1); \
} \
(s)->ents[(s)->top].idx = (id); \
(s)->ents[(s)->top].d = (dig); \
(s)->top++; \
}
#define POP(s,id,dig) { \
if ((s)->top <= 0) { \
fprintf (stderr, "stack underflow\n"); \
exit (1); \
} \
(s)->top--; \
(id) = (s)->ents[(s)->top].idx; \
(dig) = (s)->ents[(s)->top].d; \
}
typedef struct divisor_help {
div_num a;
div_num b;
int numlen;
int *numorder;
digit *res;
stack amaxstack;
stack bmaxstack;
digithash reshash;
} divisor_help;
typedef int (div_callback) (digit *, void *);
void create_stack (stack *s, int size)
{
s->ents = (stack_elem *) malloc (size * sizeof (stack_elem));
if (!s->ents) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
s->maxtop = size;
s->top = 0;
}
void free_stack (stack *s)
{
free (s->ents);
s->maxtop = 0;
s->top = 0;
}
void dismal_mul (digit *a, digit *b, digit *res)
{
int reslen = strlen(a) + strlen(b) - 1;
int i;
int j;
for (i=0; i res[i+j]) res[i+j] = a[i];
if (b[j] < a[i] && b[j] > res[i+j]) res[i+j] = b[j];
}
}
}
void dismal_add (digit *a, digit *b, digit *res)
{
int alen = strlen(a);
int blen = strlen(b);
while (*a && alen > blen) {
*res++ = *a++;
alen--;
}
while (*b && blen > alen) {
*res++ = *b++;
blen--;
}
while (*a) {
if (*a > *b) *res = *a;
else *res = *b;
a++;
b++;
res++;
}
*res = '\0';
}
int spin (digit *res, div_num *n, digithash *reshash, int depth,
div_callback *callback, void *u_data)
{
digit d;
int nsol = 0;
if (depth >= n->len) {
res[depth] = '\0';
while (res[0] == '0') res++;
if (digithash_add (reshash, res)) {
nfound++;
nsol = (*callback)(res, u_data);
return nsol;
} else {
ndup++;
return 0;
}
}
for (d = n->digs[depth].min; d <= n->digs[depth].max; d++) {
res[depth] = d;
nsol += spin (res, n, reshash, depth+1, callback, u_data);
}
return nsol;
}
int divide_work (digit *num, digit *den, divide_help *h,
int depth, div_callback *callback, void *u_data)
{
int i;
int j;
int alen = h->a.len;
int omin;
int omax;
int nsol = 0;
int rval;
int ncall = 0;
if (depth >= h->numlen) {
nsol = spin (h->res, &h->a, &h->reshash, 0, callback, u_data);
return nsol;
}
i = h->numorder[depth];
for (j=(i>=alen?i-alen+1:0); j<=i && den[j]; j++) {
if (den[j] > num[i] && h->a.digs[i-j].min <= num[i] &&
h->a.digs[i-j].max >= num[i]) {
omin = h->a.digs[i-j].min;
omax = h->a.digs[i-j].max;
h->a.digs[i-j].min = num[i];
h->a.digs[i-j].max = num[i];
ncall++;
rval = divide_work (num, den, h, depth+1, callback, u_data);
if (rval < 0) return rval;
nsol += rval;
h->a.digs[i-j].min = omin;
h->a.digs[i-j].max = omax;
} else if (den[j] == num[i] && h->a.digs[i-j].max >= num[i]) {
omin = h->a.digs[i-j].min;
if (omin < num[i]) h->a.digs[i-j].min = num[i];
ncall++;
rval = divide_work (num, den, h, depth+1, callback, u_data);
if (rval < 0) return rval;
nsol += rval;
h->a.digs[i-j].min = omin;
}
}
if (ncall == 0) ndeadend++;
return nsol;
}
void min_change (digit *num, int numlen, div_num *a, int j,
div_num *b, stack *s)
{
int k;
digit m = a->digs[j].min;
for (k=0; klen && j+k < numlen; k++) {
if (m > num[j+k] && b->digs[k].max > num[j+k]) {
PUSH (s, k, b->digs[k].max);
b->digs[k].max = num[j+k];
}
}
}
void unroll_stack (stack *s, int loc, div_num *a)
{
int i;
digit d;
while (s->top > loc) {
POP (s, i, d);
a->digs[i].max = d;
}
}
int divisor_work (digit *num, divisor_help *h, int depth,
div_callback *callback, void *u_data)
{
int rval;
int rval2;
int i;
int j;
int nsol = 0;
int ncall = 0;
int omina;
int omaxa;
int ominb;
int omaxb;
int astackloc;
int bstackloc;
if (depth >= h->numlen) {
rval = spin (h->res, &h->a, &h->reshash, 0, callback, u_data);
if (rval < 0) return rval;
rval2 = spin (h->res, &h->b, &h->reshash, 0, callback, u_data);
if (rval2 < 0) return rval2;
return rval + rval2;
}
i = h->numorder[depth];
for (j=(i>=h->a.len?i-h->a.len+1:0); j<=i && j < h->b.len; j++) {
if (h->a.digs[i-j].max < num[i] || h->b.digs[j].max < num[i]) continue;
if (h->a.digs[i-j].min <= num[i]) {
omina = h->a.digs[i-j].min;
omaxa = h->a.digs[i-j].max;
ominb = h->b.digs[j].min;
h->a.digs[i-j].min = num[i];
h->a.digs[i-j].max = num[i];
astackloc = h->amaxstack.top;
bstackloc = h->bmaxstack.top;
min_change (num, h->numlen, &h->a, i-j, &h->b, &h->bmaxstack);
if (h->b.digs[j].min < num[i]) {
h->b.digs[j].min = num[i];
min_change (num, h->numlen, &h->b, j, &h->a, &h->amaxstack);
}
ncall++;
rval = divisor_work (num, h, depth+1, callback, u_data);
if (rval < 0) return rval;
nsol += rval;
unroll_stack (&h->amaxstack, astackloc, &h->a);
h->b.digs[j].min = ominb;
unroll_stack (&h->bmaxstack, bstackloc, &h->b);
h->a.digs[i-j].min = omina;
h->a.digs[i-j].max = omaxa;
}
if (h->b.digs[j].min <= num[i]) {
ominb = h->b.digs[j].min;
omaxb = h->b.digs[j].max;
omina = h->a.digs[i-j].min;
h->b.digs[j].min = num[i];
h->b.digs[j].max = num[i];
astackloc = h->amaxstack.top;
bstackloc = h->bmaxstack.top;
min_change (num, h->numlen, &h->b, j, &h->a, &h->amaxstack);
if (h->a.digs[i-j].min < num[i]) {
h->a.digs[i-j].min = num[i];
min_change (num, h->numlen, &h->a, i-j, &h->b, &h->bmaxstack);
}
ncall++;
rval = divisor_work (num, h, depth+1, callback, u_data);
if (rval < 0) return rval;
nsol += rval;
unroll_stack (&h->bmaxstack, bstackloc, &h->b);
h->a.digs[i-j].min = omina;
unroll_stack (&h->amaxstack, astackloc, &h->a);
h->b.digs[j].min = ominb;
h->b.digs[j].max = omaxb;
}
}
if (ncall == 0) ndeadend++;
return nsol;
}
int dismal_divide (digit *num, digit *den, div_callback *callback,
void *u_data)
{
int numlen = strlen(num);
int reslen = numlen + 1 - strlen(den);
divide_help h;
int i;
int j;
int *nmatch;
int *nloc;
int t;
int rval;
if (reslen <= 0) {
fprintf (stderr, "result length %d -> no solutions\n", reslen);
return 0;
}
h.res = (digit *) malloc ((reslen + 1) * sizeof (digit));
if (!h.res) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
for (i=0; i<=reslen; i++) {
h.res[i] = '\0';
}
h.a.len = reslen;
h.numlen = numlen;
h.a.digs = (dig_range *) malloc (reslen * sizeof (dig_range));
h.numorder = (int *) malloc (numlen * sizeof (int));
nmatch = (int *) malloc (numlen * sizeof (int));
nloc = (int *) malloc (numlen * sizeof (int));
if (!h.a.digs || !h.numorder || !nmatch || !nloc) {
fprintf (stderr, "out of memory\n");
exit (1);
}
for (i=0; i=reslen?i-reslen+1:0); j<=i && den[j]; j++) {
if (den[j] > num[i] && h.a.digs[i-j].max > num[i]) {
h.a.digs[i-j].max = num[i];
}
}
}
for (i=0; i=reslen?i-reslen+1:0); j<=i && den[j]; j++) {
if (den[j] >= num[i] && h.a.digs[i-j].max >= num[i]) {
nmatch[i]++;
}
}
}
#if 0
printf ("result digit max: ");
for (i=0; i=0; i--) {
for (j=0; j nmatch[j+1]) {
SWAP (h.numorder[j], h.numorder[j+1], t);
SWAP (nmatch[j], nmatch[j+1], t);
}
}
}
for (i=0; inum = a;
di->len = strlen (a);
if (!strcmp (a, "8") || !strcmp (a, "9")) {
di->is_prime = 0;
} else {
di->is_prime = 1;
}
di->is_pseudoprime = 1;
di->ndivisors = 0;
di->nbounded_divisors = 0;
di->sum_divisors = 0.0;
di->sum_bounded_divisors = 0.0;
di->sum_bounded_divisors2 = 0.0;
di->sum_ne_divisors = 0.0;
di->dismal_sum_divisors = (digit *) malloc ((di->len+1) * sizeof (digit));
di->dismal_sum_bounded_divisors = (digit *) malloc ((di->len+1) * sizeof (digit));
di->dismal_sum_bounded_divisors2 = (digit *) malloc ((di->len+1) * sizeof (digit));
di->dismal_sum_ne_divisors = (digit *) malloc ((di->len+1) * sizeof (digit));
di->nprime_divisors = 0;
di->dismal_sum_prime_divisors = (digit *) malloc ((di->len+1) * sizeof (digit));
di->dismal_prod_prime_divisors = (digit *) malloc ((DIV_PROD_MUL*di->len+1) * sizeof (digit));
di->sum_work = (digit *) malloc ((DIV_PROD_MUL*di->len+1) * sizeof (digit));
if (!di->dismal_sum_divisors || !di->dismal_sum_bounded_divisors ||
!di->dismal_sum_bounded_divisors2 || !di->dismal_sum_ne_divisors ||
!di->dismal_sum_prime_divisors || !di->dismal_prod_prime_divisors ||
!di->sum_work) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
di->dismal_sum_divisors[0] = '0';
di->dismal_sum_bounded_divisors[0] = '0';
di->dismal_sum_bounded_divisors2[0] = '0';
di->dismal_sum_ne_divisors[0] = '0';
di->dismal_sum_prime_divisors[0] = '0';
di->dismal_prod_prime_divisors[0] = '9';
di->sum_work[0] = '0';
di->dismal_sum_divisors[1] = '\0';
di->dismal_sum_bounded_divisors[1] = '\0';
di->dismal_sum_bounded_divisors2[1] = '\0';
di->dismal_sum_ne_divisors[1] = '\0';
di->dismal_sum_prime_divisors[1] = '\0';
di->dismal_prod_prime_divisors[1] = '\0';
di->sum_work[1] = '\0';
}
void free_div_inf (div_inf *di)
{
free (di->dismal_sum_divisors);
free (di->dismal_sum_bounded_divisors);
free (di->dismal_sum_bounded_divisors2);
free (di->dismal_sum_ne_divisors);
free (di->dismal_sum_prime_divisors);
free (di->dismal_prod_prime_divisors);
free (di->sum_work);
}
div_callback gather_inf;
int gather_inf (digit *res, void *u_data)
{
div_inf *di = (div_inf *) u_data;
unsigned int reslen = strlen (res);
unsigned int numlen = strlen (di->num);
int numcmp = strcmp (res, di->num);
double resf = atof (res);
unsigned int i;
if (numcmp && strcmp (res, "9")) {
di->is_prime = 0;
}
if (reslen > 1 && reslen < numlen) di->is_pseudoprime = 0;
di->ndivisors++;
dismal_add (res, di->dismal_sum_divisors, di->sum_work);
strcpy (di->dismal_sum_divisors, di->sum_work);
di->sum_divisors += resf;
if (reslen < numlen || numcmp <= 0) {
di->nbounded_divisors++;
dismal_add (res, di->dismal_sum_bounded_divisors, di->sum_work);
strcpy (di->dismal_sum_bounded_divisors, di->sum_work);
di->sum_bounded_divisors += resf;
if (reslen < numlen || numcmp < 0) {
dismal_add (res, di->dismal_sum_bounded_divisors2, di->sum_work);
strcpy (di->dismal_sum_bounded_divisors2, di->sum_work);
di->sum_bounded_divisors2 += resf;
}
}
if (numcmp != 0) {
dismal_add (res, di->dismal_sum_ne_divisors, di->sum_work);
strcpy (di->dismal_sum_ne_divisors, di->sum_work);
di->sum_ne_divisors += resf;
}
if (digithash_find (di->primehash, res)) {
di->nprime_divisors++;
dismal_add (res, di->dismal_sum_prime_divisors, di->sum_work);
strcpy (di->dismal_sum_prime_divisors, di->sum_work);
if (reslen + strlen (di->dismal_prod_prime_divisors) <= DIV_PROD_MUL*numlen) {
dismal_mul (res, di->dismal_prod_prime_divisors, di->sum_work);
strcpy (di->dismal_prod_prime_divisors, di->sum_work);
} else {
for (i=0; idismal_prod_prime_divisors[i] = '9';
di->dismal_prod_prime_divisors[DIV_PROD_MUL*numlen] = '\0';
}
}
return 0;
}
div_callback proper_divisor;
int proper_divisor (digit *res, void *u_data)
{
digit *num = (digit *) u_data;
if (!strcmp (res, num) || !strcmp (res, "9")) {
return 0;
} else {
return 1;
}
}
void incr_digit_num (digit *n)
{
int i = strlen (n) - 1;
while (i >= 0) {
if (n[i] != '9') {
n[i]++;
return;
} else {
n[i] = '0';
i--;
}
}
n[0] = '1';
i = strlen (n);
n[i] = '0';
n[i+1] = '\0';
return;
}
void help_dinfo (void)
{
printf ("dinfo and pdinfo output a header row, and then a row for each\n");
printf ("number requested. Each row consists of '|' separated fields.\n");
printf ("\n");
printf ("The fields are:\n");
printf (" n the number\n");
printf (" 9ish 1 if n contains a 9, 0 otherwise\n");
printf (" prime 1 if n is prime, 0 otherwise\n");
printf (" n is prime if n != 9, and if n=a*b, \n");
printf (" then either a==9 or b==9\n");
printf (" pseudoprime 1 if n has a divisor with length in [2,n)\n");
printf (" divisors the number of divisors of n\n");
printf (" bd_divisors the number of divisors of n in [1,n]\n");
printf (" dsum_divisors the dismal sum of the divisors of n\n");
printf (" dsum_bd_divisors the dismal sum of the divisors of n in [1,n]\n");
printf (" dsum_bd_divisors2 the dismal sum of the divisors of n in [1,n)\n");
printf (" dsum_ne_divisors the dismal sum of the divisors of n that are != n\n");
printf (" 2*n the dismal product 2*n\n");
printf (" sum_divisors the normal sum of the divisors of n\n");
printf (" sum_bd_divisors the normal sum of the divisors of n in [1,n]\n");
printf (" sum_bd_divisors2 the normal sum of the divisors of n in [1,n)\n");
printf (" sum_ne_divisors the normal sum of the divisors of n that are != n\n");
printf ("\n");
printf ("In addition, pdinfo includes the following fields about prime divisors\n");
printf (" prime_divisors the number of prime divisors of n\n");
printf (" sum_prime_divisors the dismal sum of the prime divisors of n\n");
printf (" prod_prime_divisors the dismal product of the prime divisors of n\n");
printf (" because numbers like 111...111 have very many\n");
printf (" prime divisors, this product is capped at\n");
printf (" length %d*length(n)\n", DIV_PROD_MUL);
}
void collect_primes (digithash *primehash, digit *hi, digit *x)
{
unsigned int hilen = strlen (hi);
if (!x) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
x[0] = '1';
x[1] = '\0';
while (strlen (x) <= hilen) {
if (strcmp (x, "8") && strcmp (x, "9") &&
dismal_divisors (x, proper_divisor, x) == 0) {
digithash_add (primehash, x);
}
incr_digit_num (x);
}
}
void dinfo_range (digit *lo, digit *hi, int primefields)
{
digit *x = (digit *) malloc ((strlen (hi)+2)*sizeof (digit));
digit *x2 = (digit *) malloc ((strlen (hi)+2)*sizeof (digit));
div_inf di;
digithash primehash;
if (!x || !x2) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
digithash_init (&primehash);
if (primefields) {
collect_primes (&primehash, hi, x);
}
strcpy (x, lo);
printf ("n|9ish|prime|pseudoprime|divisors|bd_divisors|dsum_divisors|dsum_bd_divisors|dsum_bd_divisors2|dsum_ne_divisors|2*n|sum_divisors|sum_bd_divisors|sum_bd_divisors2|sum_ne_divisors");
if (primefields) printf ("|prime_divisors|sum_prime_divisors|prod_prime_divisors");
printf ("\n");
while (strlen (x) < strlen (hi) ||
(strlen (x) == strlen (hi) && strcmp (x, hi) <= 0)) {
init_div_inf (&di, x);
di.primehash = &primehash;
dismal_divisors (x, gather_inf, &di);
dismal_mul (x, "2", x2);
printf ("%s|%d|%d|%d|%d|%d|%s|%s|%s|%s|%s|%.0f|%.0f|%.0f|%.0f",
x, index(x, '9') != NULL, di.is_prime, di.is_pseudoprime,
di.ndivisors, di.nbounded_divisors, di.dismal_sum_divisors,
di.dismal_sum_bounded_divisors, di.dismal_sum_bounded_divisors2,
di.dismal_sum_ne_divisors, x2, di.sum_divisors,
di.sum_bounded_divisors, di.sum_bounded_divisors2,
di.sum_ne_divisors);
if (primefields) {
printf ("|%d|%s|%s", di.nprime_divisors, di.dismal_sum_prime_divisors,
di.dismal_prod_prime_divisors);
}
printf ("\n");
free_div_inf (&di);
incr_digit_num (x);
}
digithash_free (&primehash);
free (x2);
free (x);
}
void pcount_range (digit *lo, digit *hi)
{
digit *x = (digit *) malloc ((strlen (hi)+2)*sizeof (digit));
int pcount = 0;
unsigned int output_length = strlen (lo);
if (!x) {
fprintf (stderr, "Out of memory\n");
exit (1);
}
strcpy (x, lo);
while (strlen (x) < strlen (hi) ||
(strlen (x) == strlen (hi) && strcmp (x, hi) <= 0)) {
if (strcmp (x, "8") && strcmp (x, "9") &&
dismal_divisors (x, proper_divisor, x) == 0) {
pcount++;
}
incr_digit_num (x);
if (strlen (x) > output_length) {
printf ("%d primes with <= %d digits\n", pcount, output_length);
fflush (stdout);
output_length++;
}
}
printf ("%d primes in [%s,%s]\n", pcount, lo, hi);
free (x);
}
int main (int ac, char **av)
{
digit *res;
if (ac < 2) usage (av[0]);
if (!strcmp (av[1], "div") && ac == 4) {
dismal_divide (av[2], av[3], div_print, (void *) NULL);
} else if (!strcmp (av[1], "divs") && ac == 3) {
dismal_divisors (av[2], div_print, (void *) NULL);
} else if (!strcmp (av[1], "add") && ac == 4) {
res = result_space (av[2], av[3]);
dismal_add (av[2], av[3], res);
div_print (res, (void *) NULL);
free (res);
} else if (!strcmp (av[1], "mul") && ac == 4) {
res = result_space (av[2], av[3]);
dismal_mul (av[2], av[3], res);
div_print (res, (void *) NULL);
free (res);
} else if (!strcmp (av[1], "dinfo") && ac == 3) {
dinfo_range (av[2], av[2], 0);
} else if (!strcmp (av[1], "dinfo") && ac == 4) {
dinfo_range (av[2], av[3], 0);
} else if (!strcmp (av[1], "pdinfo") && ac == 3) {
dinfo_range (av[2], av[2], 1);
} else if (!strcmp (av[1], "pdinfo") && ac == 4) {
dinfo_range (av[2], av[3], 1);
} else if (!strcmp (av[1], "pcount") && ac == 4) {
pcount_range (av[2], av[3]);
} else if (!strcmp (av[1], "help_dinfo")) {
help_dinfo ();
} else {
usage (av[0]);
}
return 0;
}