#include #include #include #include "rat.h" #include "queue.h" enum { STK = 8192 }; typedef struct Ps Ps; struct Ps { char @close; char @req; Rat @dat; }; int debug; int threadcount; Rat getr(Ps *f) { Rat r; f->req @= 0; r = @f->dat; return r; } Ps* psmk(int nel) { Ps *d; d = malloc(sizeof(*d)); chanset(d->close, 0); chanset(d->req, 0); chanset(d->dat, nel); return d; } void psfree(Ps *d) { chanfree(d->close); chanfree(d->req); chanfree(d->dat); free(d); } static void _split(Ps *f, Ps *s, Rat @qchan, char @close) { Queue q; Rat r; queueset(&q); for(;;) switch @{ alt @s->req: if(q.front == nil) { r = getr(f); qchan @= r; s->dat @= r; } else s->dat @= delete(&q); break; alt r = @qchan: insert(&q, r); break; alt @s->close: while(q.front != nil) delete(&q); psfree(s); if(chanclosing(qchan) == -1) { if(close != nil) { close @= 0; chanfree(close); } chanclose(qchan); } else { chanfree(qchan); f->close @= 0; } if(debug) threadcount--; threadexits(0); } } void split(Ps *f, Ps *s[2], char @splitclose) { Rat @q; int i; chanset(q, 0); for(i = 0; i < 2; i++) { s[i] = psmk(0); cothread(_split(f, s[i], q, splitclose), STK); if(debug) threadcount++; } } static void _mkconst(Rat c, Ps *o) { for(;;) switch @{ alt @o->req: o->dat @= c; break; alt @o->close: if(debug) threadcount--; threadexits(0); } } Ps* mkconst(Rat c) { Ps *o; o = psmk(0); cothread(_mkconst(c, o), STK); if(debug) threadcount++; return o; } Ps* binop(void (*oper)(Ps*, Ps*, Ps*), Ps *f, Ps *g) { Ps *o; o = psmk(0); cothread(oper(f, g, o), STK); if(debug) threadcount++; return o; } static void _psadd(Ps *f, Ps *g, Ps *s) { for(;;) switch @{ alt @s->req: s->dat @= ratadd(getr(f), getr(g)); break; alt @s->close: psfree(s); f->close @= 0; g->close @= 0; if(debug) threadcount--; threadexits(0); } } Ps* psadd(Ps *f, Ps *g) { return binop(_psadd, f, g); } static void _psderiv(Ps *f, Ps *d) { Rat r; int i; getr(f); for(i = 1;; i++) { switch @{ alt @d->req: r = getr(f); d->dat @= ratmk(i * r.num, r.den); break; alt @d->close: psfree(d); f->close @= 0; if(debug) threadcount--; threadexits(0); } } } Ps* psderiv(Ps *f) { Ps *d; d = psmk(0); cothread(_psderiv(f, d), STK); if(debug) threadcount++; return d; } void psprint(Ps *ps, int n) { int i; for(i = 0; i < n - 1; i++) print("%R ", getr(ps)); print("%R\n", getr(ps)); } static void _psinteg(Ps *f, Rat c, Ps *i) { int j; switch @{ alt @i->req: i->dat @= c; break; alt @i->close: goto End; } for(j = 1;; j++) { switch @{ alt @i->req: i->dat @= ratmul(getr(f), ratmk(1, j)); break; alt @i->close: goto End; } } End: psfree(i); f->close @= 0; if(debug) threadcount--; threadexits(0); } Ps* psinteg(Ps *ps, Rat c) { Ps *i; i = psmk(0); cothread(_psinteg(ps, c, i), STK); if(debug) threadcount++; return i; } static void _pscmul(Ps *f, Rat c, Ps *o) { for(;;) switch @{ alt @o->req: o->dat @= ratmul(c, getr(f)); break; alt @o->close: psfree(o); f->close @= 0; if(debug) threadcount--; threadexits(0); } } Ps* pscmul(Rat c, Ps* f) { Ps *o; o = psmk(0); cothread(_pscmul(f, c, o), STK); if(debug) threadcount++; return o; } static void _psmul(Ps *f, Ps *g, Ps *p) { Queue fq, gq; Node *fnode, *gnode; Rat sum; queueset(&fq); queueset(&gq); for(;;) switch @{ alt @p->req: insert(&fq, getr(f)); frontinsert(&gq, getr(g)); fnode = fq.front; gnode = gq.front; sum = ratmk(0, 1); while(fnode != nil) { sum = ratadd(sum, ratmul(fnode->val, gnode->val)); fnode = fnode->link; gnode = gnode->link; } p->dat @= sum; break; alt @p->close: psfree(p); while(fq.front != nil) delete(&fq); while(gq.front != nil) delete(&gq); f->close @= 0; g->close @= 0; if(debug) threadcount--; threadexits(0); } } Ps* psmul(Ps *f, Ps *g) { return binop(_psmul, f, g); } static void _psrecip(Ps *f, Ps *r, Ps *rr, char @close) { Ps *recip; Rat g; switch @{ alt @r->req: g = ratrecip(getr(f)); r->dat @= g; break; alt @close: rr->close @= 0; f->close @= 0; goto End; } recip = pscmul(ratneg(g), psmul(f, rr)); for(;;) switch @{ alt @r->req: r->dat @= getr(recip); break; alt @close: recip->close @= 0; goto End; } End: @r->close; psfree(r); if(debug) threadcount--; threadexits(0); } Ps* psrecip(Ps *f) { Ps *rr[2], *r; char @close; r = psmk(0); chanset(close, 0); split(r, rr, close); cothread(_psrecip(f, r, rr[0], close), STK); if(debug) threadcount++; return rr[1]; } static void _psmsubst(Ps *f, Rat c, int deg, Ps *m) { Rat zero; int i, j; zero = ratmk(0, 1); for(i = 0;; i++) { switch @{ alt @m->req: m->dat @= ratmul(getr(f), ratpow(c, i)); for(j = 0; j < deg - 1; j++){ switch @{ alt @m->req: m->dat @= zero; break; alt @m->close: goto End; } } break; alt @m->close: goto End; } } End: psfree(m); f->close @= 0; if(debug) threadcount--; threadexits(0); } Ps* psmsubst(Ps *f, Rat c, int deg) { Ps *m; m = psmk(0); cothread(_psmsubst(f, c, deg, m), STK); if(debug) threadcount++; return m; } Ps *pssubst(Ps*, Ps*); static void _pssubst(Ps *f, Ps *g, Ps *o) { Ps *gg[2], *subst; switch @{ alt @o->req: o->dat @= getr(f); break; alt @o->close: psfree(o); f->close @= 0; g->close @= 0; if(debug) threadcount--; threadexits(0); } split(g, gg, nil); getr(gg[0]); subst = psmul(gg[0], pssubst(f, gg[1])); for(;;) switch @{ alt @o->req: o->dat @= getr(subst); break; alt @o->close: psfree(o); subst->close @= 0; if(debug) threadcount--; threadexits(0); } } Ps* pssubst(Ps *f, Ps *g) { return binop(_pssubst, f, g); } static void _psrev(Ps *f, Ps *r, Ps *rr, char @close) { Ps *rever; Rat g; g = ratmk(0, 1); switch @{ alt @r->req: r->dat @= g; break; alt @close: rr->close @= 0; f->close @= 0; goto End; } getr(f); rever = psrecip(pssubst(f, rr)); for(;;) switch @{ alt @r->req: r->dat @= getr(rever); break; alt @close: rever->close @= 0; goto End; } End: @r->close; psfree(r); if(debug) threadcount--; threadexits(0); } Ps* psrev(Ps *f) { Ps *rr[2], *r; char @close; chanset(close, 0); r = psmk(0); split(r, rr, close); cothread(_psrev(f, r, rr[0], close), STK); if(debug) threadcount++; return rr[1]; } void threadmain(int, char **) { Ps *ps1, *ps2, *pssum, *ints, *tanx, *pspair[2]; Rat one, zero; debug = 1; ratfmtinstall(); zero = ratmk(0, 1); one = ratmk(1, 1); ps1 = mkconst(one); print("1/1-x\n"); print("1 1 1 1 1 1 1 1 1 1\n"); psprint(ps1, 10); print("\n"); ps2 = mkconst(one); pssum = psadd(ps1, ps2); print("1/1-x + 1/1-x\n"); print("2 2 2 2 2 2 2 2 2 2\n"); psprint(pssum, 10); print("\n"); send(pssum->close, nil); ps1 = mkconst(one); ints = psderiv(ps1); print("d/dx(1/1-x)\n"); print("1 2 3 4 5 6 7 8 9 10\n"); psprint(ints, 10); print("\n"); send(ints->close, nil); ps1 = mkconst(one); ps2 = psinteg(ps1, one); print("integral of 1/1-x\n"); print("1 1 1/2 1/3 1/4 1/5 1/6 1/7 1/8 1/9\n"); psprint(ps2, 10); print("\n"); send(ps2->close, nil); ps1 = mkconst(one); ints = psderiv(ps1); split(ints, pspair, nil); print("d/dx(1/1-x) split into two streams\n"); print("1 2 3 4 5 6 7 8 9 10\n"); print("1 2 3 4 5 6 7 8 9 10\n"); psprint(pspair[0], 10); psprint(pspair[1], 10); print("\n"); send(pspair[0]->close, nil); send(pspair[1]->close, nil); ps1 = mkconst(one); ps2 = pscmul(ratmk(2, 1), ps1); print("2*(1/1-x)\n"); print("2 2 2 2 2 2 2 2 2 2\n"); psprint(ps2, 10); print("\n"); send(ps2->close, nil); ps1 = mkconst(one); split(ps1, pspair, nil); ps2 = psmul(pspair[0], pspair[1]); print("1/1-x split into two streams and then multiplied\n"); print("1 2 3 4 5 6 7 8 9 10\n"); psprint(ps2, 10); print("\n"); send(ps2->close, nil); ps1 = mkconst(one); ps2 = psrecip(ps1); print("1/(1/1-x)\n"); print("1 -1 0 0 0 0 0 0 0 0\n"); psprint(ps2, 10); print("\n"); send(ps2->close, nil); ps1 = mkconst(one); tanx = psrev(psinteg(psmsubst(ps1, ratmk(-1, 1), 2), zero)); print("tan(x)\n"); print("0 1 0 1/3 0 2/15 0 17/315 0 62/2835 0 1382/155925\n"); psprint(tanx, 12); send(tanx->close, nil); threadexitsall(0); }