Skip to content

Commit

Permalink
- Added support for Quadratic, Gauss, Poly, Fraction, Quaternion.
Browse files Browse the repository at this point in the history
  • Loading branch information
trizen committed Nov 6, 2021
1 parent e295179 commit 51504cb
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Build.PL
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ my $builder = Module::Build->new(

requires => {
'perl' => '5.16.0',
'Sidef' => '3.97',
'Sidef' => '3.99',
'Math::AnyNum' => '0.36',
'Exporter' => '0',
},
Expand Down
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ META.yml
README.md
t/00-load.t
t/basic.t
t/extra.t
utils/auto_perltidy.sh
utils/bak_cleaner.sh
2 changes: 1 addition & 1 deletion Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ WriteMakefile
'PREREQ_PM' => {
'Exporter' => '0',
'Math::AnyNum' => '0.36',
'Sidef' => '3.97',
'Sidef' => '3.99',
'Test::More' => 0
},
'INSTALLDIRS' => 'site',
Expand Down
160 changes: 145 additions & 15 deletions lib/Math/Sidef.pm
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,94 @@ our $VERSION = '0.04';
use Sidef;
use Math::AnyNum;

my $sidef_number = 'Sidef::Types::Number::Number';
my $sidef_array = 'Sidef::Types::Array::Array';
my $sidef_string = 'Sidef::Types::String::String';
my $sidef_bool = 'Sidef::Types::Bool::Bool';
use Sidef::Types::Number::Number;
use Sidef::Types::Number::Gauss;
use Sidef::Types::Number::Quadratic;
use Sidef::Types::Number::Quaternion;
use Sidef::Types::Number::Mod;
use Sidef::Types::Number::Polynomial;
use Sidef::Types::Number::Fraction;

my $sidef_number = 'Sidef::Types::Number::Number';
my $sidef_gauss = 'Sidef::Types::Number::Gauss';
my $sidef_quadratic = 'Sidef::Types::Number::Quadratic';
my $sidef_quaternion = 'Sidef::Types::Number::Quaternion';
my $sidef_mod = 'Sidef::Types::Number::Mod';
my $sidef_polynomial = 'Sidef::Types::Number::Polynomial';
my $sidef_fraction = 'Sidef::Types::Number::Fraction';
my $sidef_array = 'Sidef::Types::Array::Array';
my $sidef_string = 'Sidef::Types::String::String';
my $sidef_bool = 'Sidef::Types::Bool::Bool';

my @number_methods = grep { /^\w+\z/ } keys %{$sidef_number->methods->get_value};
my @gauss_methods = grep { /^\w+\z/ } keys %{$sidef_gauss->methods->get_value};
my @quadratic_methods = grep { /^\w+\z/ } keys %{$sidef_quadratic->methods->get_value};
my @quaternion_methods = grep { /^\w+\z/ } keys %{$sidef_quaternion->methods->get_value};
my @mod_methods = grep { /^\w+\z/ } keys %{$sidef_mod->methods->get_value};
my @polynomial_methods = grep { /^\w+\z/ } keys %{$sidef_polynomial->methods->get_value};
my @fraction_methods = grep { /^\w+\z/ } keys %{$sidef_fraction->methods->get_value};

my @names = (
@number_methods, @gauss_methods, @quadratic_methods, @quaternion_methods,
@mod_methods, @polynomial_methods, @fraction_methods
);

@names = do { # remove duplicates
my %seen;
grep { !$seen{$_}++ } @names;
};

my @constructors = qw(Number Gauss Quadratic Quaternion Mod Poly Polynomial Fraction);

our @ISA = qw(Exporter);
our @EXPORT_OK = (@names, @constructors);
our %EXPORT_TAGS = (
number => ['Number', @number_methods],
gauss => ['Gauss', @gauss_methods],
quadratic => ['Quadratic', @quadratic_methods],
quaternion => ['Quaternion', @quaternion_methods],
mod => ['Mod', @mod_methods],
poly => ['Poly', @polynomial_methods],
polynomial => ['Polynomial', @polynomial_methods],
fraction => ['Fraction', @fraction_methods],
all => [@names, @constructors],
);

sub Number {
_pack_value(@_);
}

my @names = grep { /^\w+\z/ } keys %{$sidef_number->methods->get_value};
sub Gauss {
$sidef_gauss->new(map { _pack_value($_) } @_);
}

our @ISA = qw(Exporter);
our @EXPORT_OK = @names;
our %EXPORT_TAGS = (all => \@names);
sub Quadratic {
$sidef_quadratic->new(map { _pack_value($_) } @_);
}

sub Quaternion {
$sidef_quaternion->new(map { _pack_value($_) } @_);
}

sub Mod {
$sidef_mod->new(map { _pack_value($_) } @_);
}

sub Polynomial {
$sidef_polynomial->new(
map {
ref($_) eq 'ARRAY'
? $sidef_array->new([map { _pack_value($_) } @$_])
: _pack_value($_)
} @_
);
}

*Poly = \&Polynomial;

sub Fraction {
$sidef_fraction->new(map { _pack_value($_) } @_);
}

sub _unpack_value {
my ($r) = @_;
Expand Down Expand Up @@ -56,6 +134,16 @@ sub _pack_value {
return $sidef_number->new($$r);
}

if ( $ref eq $sidef_gauss
or $ref eq $sidef_quadratic
or $ref eq $sidef_quaternion
or $ref eq $sidef_mod
or $ref eq $sidef_fraction
or $ref eq $sidef_polynomial
or $ref eq $sidef_number) {
return $r;
}

return $sidef_number->new($r);
}

Expand All @@ -78,11 +166,14 @@ sub _pack_value {
}
)
: ref($_) eq 'ARRAY'
? [map { ref($_) eq 'Math::AnyNum' ? $sidef_number->new($$_) : $sidef_number->new($_) } @$_]
: $sidef_number->new($_)
? [map { ref($_) eq 'Math::AnyNum' ? $sidef_number->new($$_) : _pack_value($_) } @$_]
: _pack_value($_)
} @args;

my @r = &{$sidef_number . '::' . $name}(@args);
my $self = shift(@args);
my @r = $self->$name(@args);

#my @r = &{$sidef_number . '::' . $name}(@args);

if (scalar(@r) == 1) {

Expand Down Expand Up @@ -128,18 +219,36 @@ Math::Sidef - Perl interface to Sidef's mathematical library.
# Prime factorization of 2^128 + 1
say join ' * ', factor(ipow(2, 128) + 1);
# Iterate over prime numbers in range 1..100
Math::Sidef::each_prime(1, 100, sub {
# Iterate over prime numbers in range 50..100
Math::Sidef::each_prime(50, 100, sub {
say $_[0];
});
=head1 DESCRIPTION
B<Math::Sidef> provides an easy interface to the numerical built-in system of L<Sidef>.
It supports all the numerical functions provided by L<Sidef::Types::Number::Number>.
It supports all the numerical functions provided by:
=over 4
The returned values are L<Math::AnyNum> objects.
=item * L<Sidef::Types::Number::Number>
=item * L<Sidef::Types::Number::Mod>
=item * L<Sidef::Types::Number::Gauss>
=item * L<Sidef::Types::Number::Quadratic>
=item * L<Sidef::Types::Number::Quaternion>
=item * L<Sidef::Types::Number::Polynomial>
=item * L<Sidef::Types::Number::Fraction>
=back
The returned numerical values are returned as L<Math::AnyNum> objects.
=head1 IMPORT
Expand All @@ -151,10 +260,31 @@ Additionally, for importing all the functions, use:
use Math::Sidef qw(:all);
It's also possible to import only functions for specific uses:
:number export Number functions, with Number() constructor
:gauss export Gauss functions, with Gauss() constructor
:quadratic export Quadratic functions, with Quadratic() constructor
:quaternion export Quaternion functions, with Quaternion() constructor
:mod export Mod functions, with Mod() constructor
:poly export Poly functions, with Poly() constructor
:fraction export Fraction functions, with Fraction() constructor
Example:
use Math::Sidef qw(:gauss :quadratic);
say pow(Gauss(3,4), 10);
say powmod(Quadratic(3, 4, 100), 10, 97);
The list of functions available for importing, can be listed with:
CORE::say join ", ", sort @Math::Sidef::EXPORT_OK;
while the methods for a specific group (e.g.: quadratic), can be listed with:
CORE::say join ", ", sort @{$Math::Sidef::EXPORT_TAGS{quadratic}};
=head1 SEE ALSO
=over 4
Expand Down
36 changes: 36 additions & 0 deletions t/extra.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!perl -T

use 5.006;
use strict;
use warnings;
use Test::More;

plan tests => 10;

use Math::Sidef qw(:all);

is(pow(Gauss(3,4), 10), Gauss(-9653287, Number("1476984")));
is(pow(Fraction(3,4), 10), Fraction(ipow(3, 10), ipow(4, 10)));
is(pow(Quadratic(3,4,2), 10), Quadratic(Number("1181882441"), Number("835704696"), 2));
is(pow(Quaternion(3,4,2,5), 10), Quaternion("222969024", "-239345280", "-119672640", "-299181600"));
is(pow(Poly([3,4,5]), 2), Polynomial(0 => 25, 1 => 40, 2 => 46, 3 => 24, 4 => 9));

is(pow(Mod(42, 97), 10), Mod(8, 97));
is(powmod(Quadratic(3, 4, 100), 10, 97), Quadratic(72, 72, 100));
is(cyclotomic_polynomial(10), Polynomial(0 => 1, 1 => -1, 2 => 1, 3 => -1, 4 => 1));

#is(binomial(Poly(1), 3), Polynomial(1 => div(1,3), 2 => div(-1,2), 3 => div(1,6)));

my $x = Polynomial(1 => div(1,6), 2 => div(1,2), 3 => div(1,3));

is_deeply(
[map { Math::Sidef::eval($x, $_) } 0..10],
[0, 1, 5, 14, 30, 55, 91, 140, 204, 285, 385]
);

my $y = Polynomial(1 => Fraction(1,6), 2 => Fraction(1,2), 3 => Fraction(1,3));

is_deeply(
[map { round(Math::Sidef::eval($y, $_)) } 0..10],
[0, 1, 5, 14, 30, 55, 91, 140, 204, 285, 385]
);

0 comments on commit 51504cb

Please sign in to comment.