3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 // Test concurrency primitives: power series.
9 // Power series package
10 // A power series is a channel, along which flow rational
11 // coefficients. A denominator of zero signifies the end.
12 // Original code in Newsqueak by Doug McIlroy.
13 // See Squinting at Power Series by Doug McIlroy,
14 // http://www.cs.bell-labs.com/who/rsc/thread/squint.pdf
21 num, den int64 // numerator, denominator
28 print(u.num, "/", u.den)
33 func (u rat) eq(c rat) bool {
34 return u.num == c.num && u.den == c.den
50 c := chnameserial % len(chnames)
53 d.req = make(chan int)
54 d.dat = make(chan rat)
66 // split reads a single demand channel and replicates its
67 // output onto two, which may be read at different rates.
68 // A process is created at first demand for a rat and dies
69 // after the rat has been sent to both outputs.
71 // When multiple generations of split exist, the newest
72 // will service requests on one channel, which is
73 // always renamed to be out[0]; the oldest will service
74 // requests on the other channel, out[1]. All generations but the
75 // newest hold queued data that has already been sent to
76 // out[0]. When data has finally been sent to out[1],
77 // a signal on the release-wait channel tells the next newer
78 // generation to begin servicing out[1].
80 func dosplit(in *dch, out *dch2, wait chan int ) {
81 both := false // do not service both channels
92 out[0], out[1] = out[1], out[0]
98 release := make(chan int)
99 go dosplit(in, out, release)
110 func split(in *dch, out *dch2) {
111 release := make(chan int)
112 go dosplit(in, out, release)
116 func put(dat rat, out *dch) {
121 func get(in *dch) rat {
127 // Get one rat from each of n demand channels
129 func getn(in []*dch) []rat {
131 if n != 2 { panic("bad n in getn") }
132 req := new([2] chan int)
133 dat := new([2] chan rat)
134 out := make([]rat, 2)
141 for n=2*n; n>0; n-- {
145 case req[0] <- seqno:
148 case req[1] <- seqno:
162 // Get one rat from each of 2 demand channels
164 func get2(in0 *dch, in1 *dch) []rat {
165 return getn([]*dch{in0, in1})
168 func copy(in *dch, out *dch) {
175 func repeat(dat rat, out *dch) {
181 type PS *dch // power series
182 type PS2 *[2] PS // pair of power series
196 // Upper-case for power series.
197 // Lower-case for rationals.
198 // Input variables: U,V,...
199 // Output variables: ...,Y,Z
201 // Integer gcd; needed for rational arithmetic
203 func gcd (u, v int64) int64 {
204 if u < 0 { return gcd(-u, v) }
205 if u == 0 { return v }
209 // Make a rational from two ints and from one int
211 func i2tor(u, v int64) rat {
224 func itor(u int64) rat {
232 // End mark and end test
236 func end(u rat) int64 {
237 if u.den==0 { return 1 }
241 // Operations on rationals
243 func add(u, v rat) rat {
244 g := gcd(u.den,v.den)
245 return i2tor(u.num*(v.den/g)+v.num*(u.den/g),u.den*(v.den/g))
248 func mul(u, v rat) rat {
249 g1 := gcd(u.num,v.den)
250 g2 := gcd(u.den,v.num)
252 r.num = (u.num/g1)*(v.num/g2)
253 r.den = (u.den/g2)*(v.den/g1)
257 func neg(u rat) rat {
258 return i2tor(-u.num, u.den)
261 func sub(u, v rat) rat {
262 return add(u, neg(v))
265 func inv(u rat) rat { // invert a rat
266 if u.num == 0 { panic("zero divide in inv") }
267 return i2tor(u.den, u.num)
270 // print eval in floating point of PS at x=c to n terms
271 func evaln(c rat, U PS, n int) {
273 x := float64(c.num)/float64(c.den)
280 val = val + x * float64(u.num)/float64(u.den)
286 // Print n terms of a power series
287 func printn(U PS, n int) {
289 for ; !done && n>0; n-- {
300 // Evaluate n terms of power series U at x=c
301 func eval(c rat, U PS, n int) rat {
302 if n==0 { return zero }
304 if end(y) != 0 { return zero }
305 return add(y,mul(c,eval(c,U,n-1)))
308 // Power-series constructors return channels on which power
309 // series flow. They start an encapsulated generator that
310 // puts the terms of the series on the channel.
312 // Make a pair of power series identical to a given power series
314 func Split(U PS) *dch2 {
320 // Add two power series
321 func Add(U, V PS) PS {
328 switch end(uv[0])+2*end(uv[1]) {
330 Z.dat <- add(uv[0], uv[1])
345 // Multiply a power series by a constant
346 func Cmul(c rat,U PS) PS {
366 func Sub(U, V PS) PS {
367 return Add(U, Cmul(neg(one), V))
370 // Multiply a power series by the monomial x^n
372 func Monmul(U PS, n int) PS {
375 for ; n>0; n-- { put(zero,Z) }
395 func Mon(c rat, n int) PS {
399 for ; n>0; n=n-1 { put(zero,Z) }
407 func Shift(c rat, U PS) PS {
416 // simple pole at 1: 1/(1-x) = 1 1 1 1 1 ...
418 // Convert array of coefficients, constant term first
419 // to a (finite) power series
422 func Poly(a []rat) PS {
424 begin func(a []rat, Z PS) {
427 for j=len(a); !done&&j>0; j=j-1)
428 if(a[j-1].num!=0) done=1
430 for(; i<j; i=i+1) put(a[i],Z)
437 // Multiply. The algorithm is
440 // then UV = u*v + x*(u*VV+v*UU) + x*x*UU*VV
442 func Mul(U, V PS) PS {
447 if end(uv[0])!=0 || end(uv[1]) != 0 {
450 Z.dat <- mul(uv[0],uv[1])
453 W := Add(Cmul(uv[0],VV[0]),Cmul(uv[1],UU[0]))
456 copy(Add(W,Mul(UU[1],VV[1])),Z)
471 for i:=1; !done; i++ {
476 Z.dat <- mul(itor(int64(i)),u)
486 // Integrate, with const of integration
487 func Integ(c rat,U PS) PS {
492 for i:=1; !done; i++ {
495 if end(u) != 0 { done= true }
496 Z.dat <- mul(i2tor(1,int64(i)),u)
503 // Binomial theorem (1+x)^c
505 func Binom(c rat) PS {
512 t = mul(mul(t,c),i2tor(1,int64(n)))
521 // Reciprocal of a power series
524 // (u+x*UU)*(z+x*ZZ) = 1
526 // u*ZZ + z*UU +x*UU*ZZ = 0
527 // ZZ = -UU*(z+x*ZZ)/u
529 func Recip(U PS) PS {
536 split(Mul(Cmul(neg(z),U),Shift(z,ZZ[0])),ZZ)
542 // Exponential of a power series with constant term 0
543 // (nonzero constant term would make nonrational coefficients)
544 // bug: the constant term is simply ignored
547 // integrate to get Z
551 split(Integ(one,Mul(ZZ[0],Diff(U))),ZZ)
555 // Substitute V for x in U, where the leading term of V is zero
558 // then S(U,V) = u + VV*S(V,UU)
559 // bug: a nonzero constant term is ignored
561 func Subst(U, V PS) PS {
569 if end(get(VV[0])) != 0 {
572 copy(Mul(VV[0],Subst(U,VV[1])),Z)
579 // Monomial Substition: U(c x^n)
580 // Each Ui is multiplied by c^i and followed by n-1 zeros
582 func MonSubst(U PS, c0 rat, n int) PS {
595 for i := 1; i < n; i++ {
608 chnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
616 func check(U PS, c rat, count int, str string) {
617 for i := 0; i < count; i++ {
631 func checka(U PS, a []rat, str string) {
632 for i := 0; i < N; i++ {
633 check(U, a[i], 1, str)
639 if len(os.Args) > 1 { // print
640 print("Ones: "); printn(Ones, 10)
641 print("Twos: "); printn(Twos, 10)
642 print("Add: "); printn(Add(Ones, Twos), 10)
643 print("Diff: "); printn(Diff(Ones), 10)
644 print("Integ: "); printn(Integ(zero, Ones), 10)
645 print("CMul: "); printn(Cmul(neg(one), Ones), 10)
646 print("Sub: "); printn(Sub(Ones, Twos), 10)
647 print("Mul: "); printn(Mul(Ones, Ones), 10)
648 print("Exp: "); printn(Exp(Ones), 15)
649 print("MonSubst: "); printn(MonSubst(Ones, neg(one), 2), 10)
650 print("ATan: "); printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
652 check(Ones, one, 5, "Ones")
653 check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
654 check(Add(Ones, Twos), itor(3), 0, "Add Ones Twos") // 3 3 3 3 3
657 for i:=0; i < N; i++ {
658 a[i] = itor(int64(i+1))
660 checka(d, a, "Diff") // 1 2 3 4 5
661 in := Integ(zero, Ones)
662 a[0] = zero // integration constant
663 for i:=1; i < N; i++ {
664 a[i] = i2tor(1, int64(i))
666 checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
667 check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
668 check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
670 for i:=0; i < N; i++ {
671 a[i] = itor(int64(i+1))
673 checka(m, a, "Mul") // 1 2 3 4 5
681 a[6] = i2tor(4051,720)
682 a[7] = i2tor(37633,5040)
683 a[8] = i2tor(43817,4480)
684 a[9] = i2tor(4596553,362880)
685 checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
686 at := Integ(zero, MonSubst(Ones, neg(one), 2))
687 for c, i := 1, 0; i < N; i++ {
691 a[i] = i2tor(int64(c), int64(i))
695 checka(at, a, "ATan") // 0 -1 0 -1/3 0 -1/5
697 t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
707 a[9] = i2tor(62,2835)
708 checka(t, a, "Tan") // 0 1 0 1/3 0 2/15