From 51504cbd0f82a5ae848ec218689ee297a162191c Mon Sep 17 00:00:00 2001 From: trizen Date: Sat, 6 Nov 2021 15:42:57 +0200 Subject: [PATCH] - Added support for Quadratic, Gauss, Poly, Fraction, Quaternion. --- Build.PL | 2 +- MANIFEST | 1 + Makefile.PL | 2 +- lib/Math/Sidef.pm | 160 +++++++++++++++++++++++++++++++++++++++++----- t/extra.t | 36 +++++++++++ 5 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 t/extra.t diff --git a/Build.PL b/Build.PL index 095ba89..6770b17 100644 --- a/Build.PL +++ b/Build.PL @@ -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', }, diff --git a/MANIFEST b/MANIFEST index 036d8a1..4cad22e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -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 diff --git a/Makefile.PL b/Makefile.PL index 8e1d8cf..e956eff 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -8,7 +8,7 @@ WriteMakefile 'PREREQ_PM' => { 'Exporter' => '0', 'Math::AnyNum' => '0.36', - 'Sidef' => '3.97', + 'Sidef' => '3.99', 'Test::More' => 0 }, 'INSTALLDIRS' => 'site', diff --git a/lib/Math/Sidef.pm b/lib/Math/Sidef.pm index d3a3103..46b04ab 100644 --- a/lib/Math/Sidef.pm +++ b/lib/Math/Sidef.pm @@ -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) = @_; @@ -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); } @@ -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) { @@ -128,8 +219,8 @@ 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]; }); @@ -137,9 +228,27 @@ Math::Sidef - Perl interface to Sidef's mathematical library. B provides an easy interface to the numerical built-in system of L. -It supports all the numerical functions provided by L. +It supports all the numerical functions provided by: + +=over 4 -The returned values are L objects. +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +The returned numerical values are returned as L objects. =head1 IMPORT @@ -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 diff --git a/t/extra.t b/t/extra.t new file mode 100644 index 0000000..1fcd144 --- /dev/null +++ b/t/extra.t @@ -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] +);