Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Start to modify for Polynomial.

  • Loading branch information...
commit 89563887dfd18671c5a8ca415a79785119996fdd 1 parent 539567a
Solomon Foster authored
4 CREDITS
View
@@ -1,5 +1,5 @@
-Vector was originally written by "SF" (http://lastofthecarelessmen.blogspot.com/)
+Polynomial was originally written by "SF" (http://lastofthecarelessmen.blogspot.com/)
last.of.the.careless.men@gmail.com
-Solomon Foster (Rakudo * port, switch to Math::Vector)
+Solomon Foster (Rakudo * port, switch to Math::Polynomial)
colomon@gmail.com
6 README
View
@@ -1,8 +1,6 @@
-This is a simple attempt to create a working Vector class. Initially intended
-to support 3D vectors, it turned out to be easier to support vectors of
-any dimension.
+This is a simple attempt to create a working polynomial in one-variable class.
-Math::Vector requires Rakudo from 7/25/2010 or later.
+Math::Polynomial requires Rakudo from 7/25/2010 or later.
Build sequence:
2  deps.proto
View
@@ -1 +1 @@
-# Math::Vector has no dependencies at this time.
+# Math::Polynomial has no dependencies at this time.
142 lib/Math/Polynomial.pm
View
@@ -0,0 +1,142 @@
+use v6;
+
+class Math::Polynomial
+{
+ has @.coefficients;
+
+ multi method new (*@x is copy)
+ {
+ while @x.elems > 1 && @x[*-1].abs < 1e-13
+ {
+ say @x.perl;
+ say @x[*-1];
+ @x.pop;
+ }
+
+ if (@x.elems == 0)
+ {
+ self.bless(*, coefficients => 0);
+ }
+ else
+ {
+ self.bless(*, coefficients => @x);
+ }
+ }
+
+ multi method new (@x is copy)
+ {
+ while @x.elems > 1 && @x[*-1].abs < 1e-13
+ {
+ # say @x.perl;
+ # say @x[*-1];
+ @x.pop;
+ }
+
+ if (@x.elems == 0)
+ {
+ self.bless(*, coefficients => 0);
+ }
+ else
+ {
+ self.bless(*, coefficients => @x);
+ }
+ }
+
+ our Str multi method Str()
+ {
+ (^(@.coefficients.elems)).map({"{@.coefficients[$_]} x^$_"}).reverse.join(" + ");
+ }
+
+ our Str multi method perl()
+ {
+ self.WHAT.perl ~ ".new(" ~ @.coefficients.map({.perl}).join(', ') ~ ")";
+ }
+
+ our multi method evaluate($x)
+ {
+ # would be more elegant with Z+, once that works
+ my $result = @.coefficients[0] * 0;
+ for @.coefficients Z (1, $x, $x * $x ... *) -> $a, $z {
+ $result = $result + $a * $z;
+ }
+ $result;
+ }
+
+ multi sub infix:<+>(Math::Polynomial $a, Math::Polynomial $b) is export(:DEFAULT)
+ {
+ my @poly = gather for ^(+$a.coefficients max +$b.coefficients) -> $i {
+ if $i < +$a.coefficients && $i < +$b.coefficients {
+ take $a.coefficients[$i] + $b.coefficients[$i];
+ } elsif $i < +$a.coefficients {
+ take $a.coefficients[$i];
+ } else {
+ take $b.coefficients[$i];
+ }
+ }
+
+ Math::Polynomial.new(@poly);
+ }
+
+ multi sub infix:<+>(Math::Polynomial $a, $b) is export(:DEFAULT)
+ {
+ my @ac = $a.coefficients;
+ @ac[0] += $b;
+ return Math::Polynomial.new(@ac);
+ }
+
+ multi sub infix:<+>($b, Math::Polynomial $a) is export(:DEFAULT)
+ {
+ $a + $b;
+ }
+
+ multi sub prefix:<->(Math::Polynomial $a) is export(:DEFAULT)
+ {
+ Math::Polynomial.new($a.coefficients.map({-$_}));
+ }
+
+ multi sub infix:<->(Math::Polynomial $a, Math::Polynomial $b) is export(:DEFAULT)
+ {
+ -$b + $a;
+ }
+
+ multi sub infix:<->(Math::Polynomial $a, $b) is export(:DEFAULT)
+ {
+ my @ac = $a.coefficients;
+ @ac[0] -= $b;
+ return Math::Polynomial.new(@ac);
+ }
+
+ multi sub infix:<->($b, Math::Polynomial $a) is export(:DEFAULT)
+ {
+ -$a + $b;
+ }
+
+ multi sub infix:<*>(Math::Polynomial $a, Math::Polynomial $b) is export(:DEFAULT)
+ {
+ my @coef = 0.0 xx ($a.coefficients.elems + $b.coefficients.elems - 1);
+ for ^($a.coefficients.elems) -> $m
+ {
+ for ^($b.coefficients.elems) -> $n
+ {
+ @coef[$m + $n] += $a.coefficients[$m] * $b.coefficients[$n];
+ }
+ }
+
+ return Math::Polynomial.new(@coef);
+ }
+
+ multi sub infix:<*>(Math::Polynomial $a, $b) is export(:DEFAULT)
+ {
+ Math::Polynomial.new($a.coefficients >>*>> $b);
+ }
+
+ multi sub infix:<*>($b, Math::Polynomial $a) is export(:DEFAULT)
+ {
+ Math::Polynomial.new($a.coefficients >>*>> $b);
+ }
+
+ multi sub infix:</>(Math::Polynomial $a, $b) is export(:DEFAULT)
+ {
+ Math::Polynomial.new($a.coefficients >>/>> $b);
+ }
+}
112 t/01-basics.t
View
@@ -0,0 +1,112 @@
+use v6;
+use Math::Polynomial;
+use Test;
+
+plan *;
+
+my $p = Math::Polynomial.new(1.0, 2.0, 3.0);
+my $p2 = Math::Polynomial.new(0.0, 0.0, 3.0, 5.0, 6.0);
+my $p3 = Math::Polynomial.new();
+my $p4 = Math::Polynomial.new(1.0);
+my $p5 = Math::Polynomial.new(0, 0, 3, 5, 6, 0.0, 0);
+
+isa_ok($p, Math::Polynomial, "Variable is of type Math::Polynomial");
+isa_ok($p2, Math::Polynomial, "Variable is of type Math::Polynomial");
+isa_ok($p3, Math::Polynomial, "Variable is of type Math::Polynomial");
+isa_ok($p4, Math::Polynomial, "Variable is of type Math::Polynomial");
+isa_ok($p5, Math::Polynomial, "Variable is of type Math::Polynomial");
+
+is(~$p3, "0 x^0", "Empty Math::Polynomial.new generates constant 0");
+is(~$p, "3 x^2 + 2 x^1 + 1 x^0", "Math::Polynomial.Str works correctly");
+is(~eval($p.perl), ~$p, ".perl works, tested with Str");
+isa_ok(eval($p.perl), Math::Polynomial, ".perl works, tested with isa");
+
+is($p5.coefficients.elems, 5, "Leading zero coefficients deleted");
+
+is_approx($p.evaluate(0.0), 1.0, "\$p.evaluate(0.0) == 1");
+is_approx($p.evaluate(1.0), 6.0, "\$p.evaluate(1.0) == 6");
+
+my $sum = $p + -$p;
+is($sum.coefficients.elems, 1, "p + (-p) has only one coefficient");
+is_approx($sum.coefficients[0], 0, "p + (-p) has only one coefficient == 0");
+
+$sum = $p + $p2;
+
+for ^10 -> $x
+{
+ is_approx($sum.evaluate($x), $p.evaluate($x) + $p2.evaluate($x), "sum = p + p2 for $x");
+}
+
+$sum = $sum + 3; # was +=, but that doesn't work any more
+for ^10 -> $x
+{
+ is_approx($sum.evaluate($x), $p.evaluate($x) + $p2.evaluate($x) + 3, "sum + 3 = p + p2 + 3 for $x");
+}
+
+$sum = 5 + $sum;
+for ^10 -> $x
+{
+ is_approx($sum.evaluate($x), $p.evaluate($x) + $p2.evaluate($x) + 8, "5 + (sum + 3) = p + p2 + 8 for $x");
+}
+
+$sum = -$sum;
+for ^10 -> $x
+{
+ is_approx($sum.evaluate($x), -($p.evaluate($x) + $p2.evaluate($x) + 8), "-(5 + (sum + 3)) = -(p + p2 + 8) for $x");
+}
+
+my $product = $sum * $p4;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), $sum.evaluate($x), "sum * (1 x^0) = sum for $x");
+}
+
+$product = $sum * $p3;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), 0.0, "sum * (0 x^0) = 0 for $x");
+}
+
+$product = $sum * 1;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), $sum.evaluate($x), "sum * 1 = sum for $x");
+}
+
+$product = $sum * 0;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), 0.0, "sum * 0 = 0 for $x");
+}
+
+$product = 2.5 * $sum;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), 2.5 * $sum.evaluate($x), "sum * 2.5 = sum * 2.5 for $x");
+}
+
+$product = 1 * $sum;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), $sum.evaluate($x), "sum * 1 = sum for $x");
+}
+
+$product = 0 * $sum;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), 0.0, "sum * 0 = 0 for $x");
+}
+
+$product = $p * $p2;
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), $p.evaluate($x) * $p2.evaluate($x), "product = p * p2 for $x");
+}
+
+$product = $product / 5.5; # was /=, but that doesn't work in current Rakudo
+for ^10 -> $x
+{
+ is_approx($product.evaluate($x), $p.evaluate($x) * $p2.evaluate($x) / 5.5, "product / 5.5 = p * p2 / 5.5 for $x");
+}
+
+done_testing;
Please sign in to comment.
Something went wrong with that request. Please try again.