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 // Like powser1.go but uses channels of interfaces.
10 // Has not been cleaned up as much as powser1.go, to keep
11 // it distinct and therefore a different test.
13 // Power series package
14 // A power series is a channel, along which flow rational
15 // coefficients. A denominator of zero signifies the end.
16 // Original code in Newsqueak by Doug McIlroy.
17 // See Squinting at Power Series by Doug McIlroy,
18 // http://www.cs.bell-labs.com/who/rsc/thread/squint.pdf
25 num, den int64 // numerator, denominator
37 print(u.num, "/", u.den)
42 func (u *rat) eq(c item) bool {
44 return u.num == c1.num && u.den == c1.den
60 c := chnameserial % len(chnames)
63 d.req = make(chan int)
64 d.dat = make(chan item)
76 // split reads a single demand channel and replicates its
77 // output onto two, which may be read at different rates.
78 // A process is created at first demand for an item and dies
79 // after the item has been sent to both outputs.
81 // When multiple generations of split exist, the newest
82 // will service requests on one channel, which is
83 // always renamed to be out[0]; the oldest will service
84 // requests on the other channel, out[1]. All generations but the
85 // newest hold queued data that has already been sent to
86 // out[0]. When data has finally been sent to out[1],
87 // a signal on the release-wait channel tells the next newer
88 // generation to begin servicing out[1].
90 func dosplit(in *dch, out *dch2, wait chan int ){
91 both := false // do not service both channels
102 out[0],out[1] = out[1], out[0]
108 release := make(chan int)
109 go dosplit(in, out, release)
120 func split(in *dch, out *dch2){
121 release := make(chan int)
122 go dosplit(in, out, release)
126 func put(dat item, out *dch){
131 func get(in *dch) *rat {
134 return (<-in.dat).(*rat)
137 // Get one item from each of n demand channels
139 func getn(in []*dch) []item {
141 if n != 2 { panic("bad n in getn") }
142 req := make([] chan int, 2)
143 dat := make([] chan item, 2)
144 out := make([]item, 2)
151 for n=2*n; n>0; n-- {
155 case req[0] <- seqno:
158 case req[1] <- seqno:
172 // Get one item from each of 2 demand channels
174 func get2(in0 *dch, in1 *dch) []item {
175 return getn([]*dch{in0, in1})
178 func copy(in *dch, out *dch){
185 func repeat(dat item, out *dch){
191 type PS *dch // power series
192 type PS2 *[2] PS // pair of power series
206 // Upper-case for power series.
207 // Lower-case for rationals.
208 // Input variables: U,V,...
209 // Output variables: ...,Y,Z
211 // Integer gcd; needed for rational arithmetic
213 func gcd (u, v int64) int64{
214 if u < 0 { return gcd(-u, v) }
215 if u == 0 { return v }
219 // Make a rational from two ints and from one int
221 func i2tor(u, v int64) *rat{
234 func itor(u int64) *rat{
242 // End mark and end test
246 func end(u *rat) int64 {
247 if u.den==0 { return 1 }
251 // Operations on rationals
253 func add(u, v *rat) *rat {
254 g := gcd(u.den,v.den)
255 return i2tor(u.num*(v.den/g)+v.num*(u.den/g),u.den*(v.den/g))
258 func mul(u, v *rat) *rat{
259 g1 := gcd(u.num,v.den)
260 g2 := gcd(u.den,v.num)
262 r.num =(u.num/g1)*(v.num/g2)
263 r.den = (u.den/g2)*(v.den/g1)
267 func neg(u *rat) *rat{
268 return i2tor(-u.num, u.den)
271 func sub(u, v *rat) *rat{
272 return add(u, neg(v))
275 func inv(u *rat) *rat{ // invert a rat
276 if u.num == 0 { panic("zero divide in inv") }
277 return i2tor(u.den, u.num)
280 // print eval in floating point of PS at x=c to n terms
281 func Evaln(c *rat, U PS, n int) {
283 x := float64(c.num)/float64(c.den)
290 val = val + x * float64(u.num)/float64(u.den)
296 // Print n terms of a power series
297 func Printn(U PS, n int){
299 for ; !done && n>0; n-- {
314 // Evaluate n terms of power series U at x=c
315 func eval(c *rat, U PS, n int) *rat{
316 if n==0 { return zero }
318 if end(y) != 0 { return zero }
319 return add(y,mul(c,eval(c,U,n-1)))
322 // Power-series constructors return channels on which power
323 // series flow. They start an encapsulated generator that
324 // puts the terms of the series on the channel.
326 // Make a pair of power series identical to a given power series
328 func Split(U PS) *dch2{
334 // Add two power series
335 func Add(U, V PS) PS{
342 switch end(uv[0].(*rat))+2*end(uv[1].(*rat)) {
344 Z.dat <- add(uv[0].(*rat), uv[1].(*rat))
359 // Multiply a power series by a constant
360 func Cmul(c *rat,U PS) PS{
362 go func(c *rat, U, Z PS){
380 func Sub(U, V PS) PS{
381 return Add(U, Cmul(neg(one), V))
384 // Multiply a power series by the monomial x^n
386 func Monmul(U PS, n int) PS{
388 go func(n int, U PS, Z PS){
389 for ; n>0; n-- { put(zero,Z) }
409 func Mon(c *rat, n int) PS{
411 go func(c *rat, n int, Z PS){
413 for ; n>0; n=n-1 { put(zero,Z) }
421 func Shift(c *rat, U PS) PS{
423 go func(c *rat, U, Z PS){
430 // simple pole at 1: 1/(1-x) = 1 1 1 1 1 ...
432 // Convert array of coefficients, constant term first
433 // to a (finite) power series
436 func Poly(a [] *rat) PS{
438 begin func(a [] *rat, Z PS){
441 for j=len(a); !done&&j>0; j=j-1)
442 if(a[j-1].num!=0) done=1
444 for(; i<j; i=i+1) put(a[i],Z)
451 // Multiply. The algorithm is
454 // then UV = u*v + x*(u*VV+v*UU) + x*x*UU*VV
456 func Mul(U, V PS) PS{
461 if end(uv[0].(*rat))!=0 || end(uv[1].(*rat)) != 0 {
464 Z.dat <- mul(uv[0].(*rat),uv[1].(*rat))
467 W := Add(Cmul(uv[0].(*rat),VV[0]),Cmul(uv[1].(*rat),UU[0]))
470 copy(Add(W,Mul(UU[1],VV[1])),Z)
485 for i:=1; !done; i++ {
490 Z.dat <- mul(itor(int64(i)),u)
500 // Integrate, with const of integration
501 func Integ(c *rat,U PS) PS{
503 go func(c *rat, U, Z PS){
506 for i:=1; !done; i++ {
509 if end(u) != 0 { done= true }
510 Z.dat <- mul(i2tor(1,int64(i)),u)
517 // Binomial theorem (1+x)^c
519 func Binom(c *rat) PS{
521 go func(c *rat, Z PS){
526 t = mul(mul(t,c),i2tor(1,int64(n)))
535 // Reciprocal of a power series
538 // (u+x*UU)*(z+x*ZZ) = 1
540 // u*ZZ + z*UU +x*UU*ZZ = 0
541 // ZZ = -UU*(z+x*ZZ)/u
550 split(Mul(Cmul(neg(z),U),Shift(z,ZZ[0])),ZZ)
556 // Exponential of a power series with constant term 0
557 // (nonzero constant term would make nonrational coefficients)
558 // bug: the constant term is simply ignored
561 // integrate to get Z
565 split(Integ(one,Mul(ZZ[0],Diff(U))),ZZ)
569 // Substitute V for x in U, where the leading term of V is zero
572 // then S(U,V) = u + VV*S(V,UU)
573 // bug: a nonzero constant term is ignored
575 func Subst(U, V PS) PS {
577 go func(U, V, Z PS) {
583 if end(get(VV[0])) != 0 {
586 copy(Mul(VV[0],Subst(U,VV[1])),Z)
593 // Monomial Substition: U(c x^n)
594 // Each Ui is multiplied by c^i and followed by n-1 zeros
596 func MonSubst(U PS, c0 *rat, n int) PS {
598 go func(U, Z PS, c0 *rat, n int) {
609 for i := 1; i < n; i++ {
622 chnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
630 func check(U PS, c *rat, count int, str string) {
631 for i := 0; i < count; i++ {
645 func checka(U PS, a []*rat, str string) {
646 for i := 0; i < N; i++ {
647 check(U, a[i], 1, str)
653 if len(os.Args) > 1 { // print
654 print("Ones: "); Printn(Ones, 10)
655 print("Twos: "); Printn(Twos, 10)
656 print("Add: "); Printn(Add(Ones, Twos), 10)
657 print("Diff: "); Printn(Diff(Ones), 10)
658 print("Integ: "); Printn(Integ(zero, Ones), 10)
659 print("CMul: "); Printn(Cmul(neg(one), Ones), 10)
660 print("Sub: "); Printn(Sub(Ones, Twos), 10)
661 print("Mul: "); Printn(Mul(Ones, Ones), 10)
662 print("Exp: "); Printn(Exp(Ones), 15)
663 print("MonSubst: "); Printn(MonSubst(Ones, neg(one), 2), 10)
664 print("ATan: "); Printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
666 check(Ones, one, 5, "Ones")
667 check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
668 check(Add(Ones, Twos), itor(3), 0, "Add Ones Twos") // 3 3 3 3 3
671 for i:=0; i < N; i++ {
672 a[i] = itor(int64(i+1))
674 checka(d, a, "Diff") // 1 2 3 4 5
675 in := Integ(zero, Ones)
676 a[0] = zero // integration constant
677 for i:=1; i < N; i++ {
678 a[i] = i2tor(1, int64(i))
680 checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
681 check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
682 check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
684 for i:=0; i < N; i++ {
685 a[i] = itor(int64(i+1))
687 checka(m, a, "Mul") // 1 2 3 4 5
695 a[6] = i2tor(4051,720)
696 a[7] = i2tor(37633,5040)
697 a[8] = i2tor(43817,4480)
698 a[9] = i2tor(4596553,362880)
699 checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
700 at := Integ(zero, MonSubst(Ones, neg(one), 2))
701 for c, i := 1, 0; i < N; i++ {
705 a[i] = i2tor(int64(c), int64(i))
709 checka(at, a, "ATan"); // 0 -1 0 -1/3 0 -1/5
711 t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
721 a[9] = i2tor(62,2835)
722 checka(t, a, "Tan") // 0 1 0 1/3 0 2/15