long int AP_modi(T x, long int y) { long int rem; T r; unsigned char d[sizeof (unsigned long)]; struct T t; t.size = sizeof d; t.digits = d; r = AP_mod(x, set(&t, y)); rem = XP_toint(r->ndigits, r->digits); AP_free(&r); return rem; }
T AP_pow(T x, T y, T p) { T z; assert(x); assert(y); assert(y->sign == 1); assert( (!p) || (p->sign==1 && !iszero(p) && !isone(p))); if (iszero(x)) return AP_new(0); if (iszero(y)) return AP_new(1); if (isone(x)) return AP_new((((y)->digits[0]&1) == 0) ? 1 : x->sign); if (p) if (isone(y)) z = AP_mod(x, p); else { T y2 = AP_rshift(y, 1), t = AP_pow(x, y2, p); z = mulmod(t, t, p); AP_free(&y2); AP_free(&t); if (!(((y)->digits[0]&1) == 0)) { z = mulmod(y2 = AP_mod(x, p), t = z, p); AP_free(&y2); AP_free(&t); } } else if (isone(y)) z = AP_addi(x, 0); else { T y2 = AP_rshift(y, 1), t = AP_pow(x, y2, NULL); z = AP_mul(t, t); AP_free(&y2); AP_free(&t); if (!(((y)->digits[0]&1) == 0)) { z = AP_mul(x, t = z); AP_free(&t); } } return z; }
int main(int argc, char *argv[]) { int c; sp = Stack_new(); Fmt_register('D', AP_fmt); while ((c = getchar()) != EOF) switch (c) { case ' ': case '\t': case '\n': case '\f': case '\r': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { char buf[512]; { int i = 0; for ( ; c != EOF && isdigit(c); c = getchar(), i++) if (i < (int)sizeof (buf) - 1) buf[i] = c; if (i > (int)sizeof (buf) - 1) { i = (int)sizeof (buf) - 1; Fmt_fprint(stderr, "?integer constant exceeds %d digits\n", i); } buf[i] = 0; if (c != EOF) ungetc(c, stdin); } Stack_push(sp, AP_fromstr(buf, 10, NULL)); break; } case '+': { AP_T y = pop(), x = pop(); Stack_push(sp, AP_add(x, y)); AP_free(&x); AP_free(&y); break; } case '-': { AP_T y = pop(), x = pop(); Stack_push(sp, AP_sub(x, y)); AP_free(&x); AP_free(&y); break; } case '*': { AP_T y = pop(), x = pop(); Stack_push(sp, AP_mul(x, y)); AP_free(&x); AP_free(&y); break; } case '/': { AP_T y = pop(), x = pop(); if (AP_cmpi(y, 0) == 0) { Fmt_fprint(stderr, "?/ by 0\n"); Stack_push(sp, AP_new(0)); } else Stack_push(sp, AP_div(x, y)); AP_free(&x); AP_free(&y); break; } case '%': { AP_T y = pop(), x = pop(); if (AP_cmpi(y, 0) == 0) { Fmt_fprint(stderr, "?%% by 0\n"); Stack_push(sp, AP_new(0)); } else Stack_push(sp, AP_mod(x, y)); AP_free(&x); AP_free(&y); break; } case '^': { AP_T y = pop(), x = pop(); if (AP_cmpi(y, 0) <= 0) { Fmt_fprint(stderr, "?nonpositive power\n"); Stack_push(sp, AP_new(0)); } else Stack_push(sp, AP_pow(x, y, NULL)); AP_free(&x); AP_free(&y); break; } case 'd': { AP_T x = pop(); Stack_push(sp, x); Stack_push(sp, AP_addi(x, 0)); break; } case 'p': { AP_T x = pop(); Fmt_print("%D\n", x); Stack_push(sp, x); break; } case 'f': if (!Stack_empty(sp)) { Stack_T tmp = Stack_new(); while (!Stack_empty(sp)) { AP_T x = pop(); Fmt_print("%D\n", x); Stack_push(tmp, x); } while (!Stack_empty(tmp)) Stack_push(sp, Stack_pop(tmp)); Stack_free(&tmp); } break; case '~': { AP_T x = pop(); Stack_push(sp, AP_neg(x)); AP_free(&x); break; } case 'c': while (!Stack_empty(sp)) { AP_T x = Stack_pop(sp); AP_free(&x); } break; case 'q': while (!Stack_empty(sp)) { AP_T x = Stack_pop(sp); AP_free(&x); } Stack_free(&sp); return EXIT_SUCCESS; default: if (isprint(c)) Fmt_fprint(stderr, "?'%c'", c); else Fmt_fprint(stderr, "?'\\%03o'", c); Fmt_fprint(stderr, " is unimplemented\n"); break; } while (!Stack_empty(sp)) { AP_T x = Stack_pop(sp); AP_free(&x); } Stack_free(&sp); return EXIT_SUCCESS; }
static T mulmod(T x, T y, T p) { T z, xy = AP_mul(x, y); z = AP_mod(xy, p); AP_free(&xy); return z; }