Task: Formal power series




Go: package main

import (
    "fmt"
    "math"
)












type fps interface {
    extract(int) float64
}












func one() fps {
    return &oneFps{}
}

func add(s1, s2 fps) fps {
    return &sum{s1: s1, s2: s2}
}

func sub(s1, s2 fps) fps {
    return &diff{s1: s1, s2: s2}
}

func mul(s1, s2 fps) fps {
    return &prod{s1: s1, s2: s2}
}

func div(s1, s2 fps) fps {
    return &quo{s1: s1, s2: s2}
}

func differentiate(s1 fps) fps {
    return &deriv{s1: s1}
}

func integrate(s1 fps) fps {
    return &integ{s1: s1}
}







func sinCos() (fps, fps) {
    sin := &integ{}
    cos := sub(one(), integrate(sin))
    sin.s1 = cos
    return sin, cos
}




















type oneFps struct{}



func (*oneFps) extract(n int) float64 {
    if n == 0 {
        return 1
    }
    return 0
}



type sum struct {
    s      []float64
    s1, s2 fps
}

func (s *sum) extract(n int) float64 {
    for i := len(s.s); i <= n; i++ {
        s.s = append(s.s, s.s1.extract(i)+s.s2.extract(i))
    }
    return s.s[n]
}





type diff struct {
    s      []float64
    s1, s2 fps
}

func (s *diff) extract(n int) float64 {
    for i := len(s.s); i <= n; i++ {
        s.s = append(s.s, s.s1.extract(i)-s.s2.extract(i))
    }
    return s.s[n]
}

type prod struct {
    s      []float64
    s1, s2 fps
}

func (s *prod) extract(n int) float64 {
    for i := len(s.s); i <= n; i++ {
        c := 0.
        for k := 0; k <= i; k++ {
            c += s.s1.extract(k) * s.s1.extract(n-k)
        }
        s.s = append(s.s, c)
    }
    return s.s[n]
}



type quo struct {
    s1, s2 fps
    inv    float64   
    c      []float64 
    s      []float64
}




func (s *quo) extract(n int) float64 {
    switch {
    case len(s.s) > 0:
    case !math.IsInf(s.inv, 1):
        a0 := s.s2.extract(0)
        s.inv = 1 / a0
        if a0 != 0 {
            break
        }
        fallthrough
    default:
        return math.NaN()
    }
    for i := len(s.s); i <= n; i++ {
        c := 0.
        for k := 1; k <= i; k++ {
            c += s.s2.extract(k) * s.c[n-k]
        }
        c = s.s1.extract(i) - c*s.inv
        s.c = append(s.c, c)
        s.s = append(s.s, c*s.inv)
    }
    return s.s[n]
}




type deriv struct {
    s   []float64
    s1  fps
}

func (s *deriv) extract(n int) float64 {
    for i := len(s.s); i <= n; {
        i++
        s.s = append(s.s, float64(i)*s.s1.extract(i))
    }
    return s.s[n]
}

type integ struct {
    s   []float64
    s1  fps
}

func (s *integ) extract(n int) float64 {
    if n == 0 {
        return 0 
    }
    
    for i := len(s.s) + 1; i <= n; i++ {
        s.s = append(s.s, s.s1.extract(i-1)/float64(i))
    }
    return s.s[n-1]
}


func main() {
    
    partialSeries := func(f fps) (s string) {
        for i := 0; i < 6; i++ {
            s = fmt.Sprintf("%s %8.5f ", s, f.extract(i))
        }
        return
    }
    sin, cos := sinCos()
    fmt.Println("sin:", partialSeries(sin))
    fmt.Println("cos:", partialSeries(cos))
}








Ada: with Generic_Rational;

generic
   with package Rational_Numbers is new Generic_Rational (<>);
package Generic_Taylor_Series is
   use Rational_Numbers;
   type Taylor_Series is array (Natural range <>) of Rational;
   
   function "+" (A : Taylor_Series) return Taylor_Series;
   function "-" (A : Taylor_Series) return Taylor_Series;

   function "+" (A, B : Taylor_Series) return Taylor_Series;
   function "-" (A, B : Taylor_Series) return Taylor_Series;
   function "*" (A, B : Taylor_Series) return Taylor_Series;

   function Integral (A : Taylor_Series) return Taylor_Series;
   function Differential (A : Taylor_Series) return Taylor_Series;

   function Value (A : Taylor_Series; X : Rational) return Rational;

   Zero : constant Taylor_Series := (0 => Rational_Numbers.Zero);
   One  : constant Taylor_Series := (0 => Rational_Numbers.One);
end Generic_Taylor_Series;