use warnings; use strict; use 5.012; use Scalar::Util; use Math::BigInt; sub _make { my($o, @v) = @_; bless \@v, Scalar::Util::blessed($o) || $o; } sub zero { my($o) = @_; $o->_make(); } sub one { my($o) = @_; $o->_make(1); } sub _comps { my($o, $b) = @_; my @v = @$o; my($u, $v) = (0, @v < 44 ? 1 : Math::BigInt->bone); for my $d (@v) { $v = $v + $u; $u = $v - $u; if ($d) { &$b($v); } } } sub str { # return the string representation showing terms my($o) = @_; my @r; $o->_comps(sub { push @r, $_[0] }); @r ? "(" . join(" + ", @r) . ")" : "0"; } sub val { # return the value as a perl number my($o) = @_; my $r = 0; $o->_comps(sub { $r += $_[0]; }); $r; }