Skip to content

Instantly share code, notes, and snippets.

Created October 9, 2012 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3861090 to your computer and use it in GitHub Desktop.
Save anonymous/3861090 to your computer and use it in GitHub Desktop.
Rosetta Code for Formal Power Series
class DerFPS { ... }
class IntFPS { ... }
class FPS {
has @.coeffs;
method differentiate { DerFPS.new(:x(self)) }
method integrate { IntFPS.new(:x(self)) }
method pretty($n) {
sub super($i) { $i.trans('0123456789' => '⁰¹²³⁴⁵⁶⁷⁸⁹') }
my $str = $.coeffs[0].perl;
for 1..$n Z $.coeffs[1..$n] -> $i, $_ {
when * > 0 { $str ~= " + {(+$_).perl}∙x{super($i)}" }
when * < 0 { $str ~= " - {(-$_).perl}∙x{super($i)}" }
}
$str;
}
}
class SumFPS is FPS {
has FPS ($.x, $.y);
method coeffs { $.x.coeffs Z+ $.y.coeffs }
}
class DifFPS is FPS {
has FPS ($.x, $.y);
method coeffs { $.x.coeffs Z- $.y.coeffs }
}
class ProFPS is FPS {
has FPS ($.x, $.y);
method coeffs { (0..*).map: { [+] ($.x.coeffs[0..$_] Z* $.y.coeffs[$_...0]) } }
}
class InvFPS is FPS {
has FPS $.x;
method coeffs {
# see http://en.wikipedia.org/wiki/Formal_power_series#Inverting_series
gather {
my @a := $.x.coeffs;
@a[0] != 0 or fail "Cannot invert power series with zero constant term.";
take my @b = (1 / @a[0]);
take @b[$_] = -@b[0] * [+] (@a[1..$_] Z* @b[$_-1...0]) for 1..*;
}
}
}
class DerFPS is FPS {
has FPS $.x;
method coeffs { (1..*).map: { $_ * $.x.coeffs[$_] } }
}
class IntFPS is FPS {
has FPS $.x is rw;
method coeffs { 0, (0..*).map: { $.x.coeffs[$_] / ($_+1) } }
}
class DeferredFPS is FPS {
has FPS $.realized is rw;
method coeffs { $.realized.coeffs }
}
# some arithmetic operations for formal power series
multi infix:<+>(FPS $x, FPS $y) { SumFPS.new(:$x, :$y) }
multi infix:<->(FPS $x, FPS $y) { DifFPS.new(:$x, :$y) }
multi infix:<*>(FPS $x, FPS $y) { ProFPS.new(:$x, :$y) }
multi infix:</>(FPS $x, FPS $y) { $x * InvFPS.new(:x($y)) }
# an example for a mixed-type operator:
multi infix:<->(Numeric $x, FPS $y) { FPS.new(:coeffs($x, 0 xx *)) - $y }
# define sine and cosine in terms of each other
my $sin = DeferredFPS.new;
my $cos = 1 - $sin.integrate;
$sin.realized = $cos.integrate;
#define tangent in terms of sine and cosine
my $tan = $sin / $cos;
say 'sin(x) ≈ ', $sin.pretty(10);
say 'cos(x) ≈ ', $cos.pretty(10);
say 'tan(x) ≈ ', $tan.pretty(10);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment