#include #include #include #include #include char piprog[] = "1sq180sr60st2si[3li*1+d1+*3*suli27*12-lq*5lr*+lt5*/d48+Psy10lqlid2*1-***" "10lulqli5*2-*lr+lylt*-**srsqlult*stli1+silmx]smlmx"; typedef struct mp mp; struct mp { char neg; int s; int ld; int ref; uint32_t *w; }; mp **stack, **stp; int stsize; mp *reg[256]; void mpfree(mp *r) { free(r->w); free(r); } void mpgrow(mp *r, int s) { if(r->s > s) return; r->s = (s + 16) & -16; r->w = (uint32_t*) realloc(r->w, r->s * 4); } int mpcmp(mp *a, mp *b) { int i; if(a->ld != b->ld) return a->ld - b->ld; for(i = a->ld; i >= 0; i--){ if(a->w[i] > b->w[i]) return 1; if(a->w[i] < b->w[i]) return -1; } return 0; } mp * mpint(int n) { mp *m; if(n < 0){ m = mpint(-n); m->neg = 1; return m; } m = (mp*) malloc(sizeof(mp)); m->ref = 0; m->neg = 0; m->s = 16; m->w = (uint32_t*) malloc(64); m->ld = 0; m->w[0] = n; return m; } mp * mpdup(mp *a) { mp *r; r = (mp*) malloc(sizeof(mp)); r->ref = 0; r->neg = a->neg; r->s = a->s; r->w = (uint32_t*) malloc(a->s * 4); r->ld = a->ld; memcpy(r->w, a->w, (a->ld + 1) * 4); return r; } void mpcpy(mp *r, mp *a) { if(r == a) return; mpgrow(r, a->ld); memcpy(r->w, a->w, (a->ld + 1) * 4); r->neg = a->neg; r->ld = a->ld; } void mpsub(mp *r, mp *a, mp *b); void mpadd(mp *r, mp *a, mp *b) { int c, nc, i, l, rld; uint32_t aw, bw; if(a->neg && !b->neg){ a->neg = 0; mpsub(r, b, a); if(r != a) a->neg = 1; return; } if(b->neg && !a->neg){ b->neg = 0; mpsub(r, a, b); if(r != b) b->neg = 1; return; } r->neg = a->neg; c = 0; if(a->ld > b->ld) l = a->ld + 1; else l = b->ld + 1; mpgrow(r, l); rld = 0; for(i = 0; i <= l; i++){ aw = i <= a->ld ? a->w[i] : 0; bw = i <= b->ld ? b->w[i] : 0; if(c) nc = aw >= ~bw; else nc = aw > ~bw; r->w[i] = aw + bw + c; if(r->w[i] != 0) rld = i; c = nc; } r->ld = rld; } void mpsub(mp *r, mp *a, mp *b) { int i, c, nc, l, rld; uint32_t aw, bw; if(a->neg && !b->neg){ b->neg = 1; mpadd(r, a, b); if(r != b) b->neg = 0; return; } if(!a->neg && b->neg){ b->neg = 0; mpadd(r, a, b); if(r != b) b->neg = 1; return; } if(a->neg && b->neg){ a->neg = b->neg = 0; mpsub(r, b, a); if(r != a) a->neg = 1; if(r != b) b->neg = 1; return; } if(mpcmp(a, b) < 0){ mpsub(r, b, a); r->neg = 1; return; } r->neg = 0; c = 0; mpgrow(r, a->ld); l = a->ld; rld = 0; for(i = 0; i <= l; i++){ aw = a->w[i]; bw = i <= b->ld ? b->w[i] : 0; if(c) nc = aw <= bw; else nc = aw < bw; r->w[i] = aw - bw - c; if(r->w[i] != 0) rld = i; c = nc; } r->ld = rld; } void digadd(uint32_t *r, uint32_t a) { int c; c = *r > ~a; *r++ += a; while(c){ c = ~*r == 0; (*r++)++; } } void mpmul(mp *r, mp *a, mp *b) { int i, j, k; uint64_t x; uint32_t aw, bw; mpgrow(r, a->ld + b->ld + 1); r->neg = a->neg ^ b->neg; memset(r->w, 0, r->s * 4); for(i = 0; i <= a->ld; i++){ aw = a->w[i]; for(j = 0; j <= b->ld; j++){ bw = b->w[j]; x = (uint64_t) aw * bw; digadd(r->w+i+j, x); digadd(r->w+i+j+1, x>>32); } } for(i = a->ld + b->ld + 1; i >= 0; i--) if(r->w[i] != 0) break; r->ld = i; } void mpsh(mp *r, mp *a, int n) { int i, k; if(n == 0){ mpcpy(r, a); return; } if(n > 0){ k = n >> 5; mpgrow(r, a->ld + k + 1); n &= 31; r->w[a->ld + k + 1] = 0; for(i = a->ld; i >= 0; i--){ if(n != 0) r->w[i+k+1] |= a->w[i] >> 32 - n; r->w[i+k] = a->w[i] << n; } for(i = 0; i < k; i++) r->w[i] = 0; r->ld = a->ld + k + (r->w[a->ld+k+1] != 0); }else{ n = -n; k = n >> 5; if(k > a->ld){ r->ld = 0; r->w[0] = 0; } n &= 31; for(i = 0; i <= a->ld; i++){ if(i >= k+1 && n != 0) r->w[i-k-1] |= a->w[i] << 32 - n; if(i >= k) r->w[i-k] = a->w[i] >> n; } r->ld = a->ld - k - (r->w[a->ld-k] == 0); } } int mpbitcnt(mp *a) { int r; uint32_t w; static char ld[16] = {0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3}; r = a->ld << 5; w = a->w[a->ld]; if(w >= 0x10000){ w >>= 16; r += 16; } if(w >= 0x100){ w >>= 8; r += 8; } if(w >= 0x10){ w >>= 4; r += 4; } return r + ld[w]; } void mpdiv(mp *q, mp *a, mp *b) { mp *tq, *ta, *tb; int n, an, bn; if(a->neg || b->neg){ an = a->neg; bn = b->neg; a->neg = b->neg = 0; mpdiv(q, a, b); q->neg = an ^ bn; a->neg = an; b->neg = bn; return; } if(b->ld == 0 && b->w[0] == 0){ printf("division by zero\n"); exit(1); } q->ld = 0; q->w[0] = 0; if(a->ld < b->ld) return; ta = mpdup(a); tb = mpdup(b); n = mpbitcnt(a) - mpbitcnt(b); tq = mpint(1); mpsh(tq, tq, n); mpsh(tb, tb, n); while(n-- >= 0){ if(mpcmp(ta, tb) >= 0){ mpsub(ta, ta, tb); mpadd(q, tq, q); } mpsh(tb, tb, -1); mpsh(tq, tq, -1); } mpfree(ta); mpfree(tb); mpfree(tq); } void mpprint(mp *a) { int i; if(a->neg) printf("-"); printf("0x%x", a->w[a->ld]); for(i = a->ld - 1; i >= 0; i--) printf("%.8x", a->w[i]); printf(" "); } void push(mp *m) { mp **n; if(stp >= stack + stsize){ n = (mp**) realloc(stack, (stsize + 16) * sizeof(mp*)); stsize += 16; stp = n + (stp - stack); stack = n; } *stp++ = m; m->ref++; } mp * pop(void) { assert(stp > stack); return *--stp; } void decref(mp *m) { if(m != NULL && --m->ref == 0) mpfree(m); } void eval(char *s) { mp *m, *a, *b; char c, *p; for(; *s != 0; s++) switch(*s){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': push(mpint(strtol(s, &s, 0))); s--; break; case 's': decref(reg[c = *++s]); reg[c] = pop(); break; case 'l': push(reg[*++s]); break; case '[': s++; p = strchr(s, ']'); assert(p != NULL); m = mpint(0); mpgrow(m, p - s); memcpy(m->w, s, p - s); m->w[p - s] = 0; push(m); s = p; break; case 'x': m = pop(); eval((char*)(m->w)); decref(m); break; case '+': a = pop(); b = pop(); m = mpint(0); mpadd(m, b, a); push(m); decref(a); decref(b); break; case '-': a = pop(); b = pop(); m = mpint(0); mpsub(m, b, a); push(m); decref(a); decref(b); break; case '*': a = pop(); b = pop(); m = mpint(0); mpmul(m, a, b); push(m); decref(a); decref(b); break; case '/': a = pop(); b = pop(); m = mpint(0); mpdiv(m, b, a); push(m); decref(a); decref(b); break; case 'd': assert(stp > stack); push(stp[-1]); break; case 'P': m = pop(); putchar(m->w[0]); decref(m); break; default: printf("unknown char %c\n", *s); } } int main() { setbuf(stdout, NULL); eval(piprog); }