Skip to content

Commit

Permalink
- Fixed the modulo operator for negative integers.
Browse files Browse the repository at this point in the history
- Added tests for the modulo operator.
- Improved the initialization of Complex numbers -- the precision is respected correctly
- Added the Number.isqrt() and Number.iroot() methods to calculate the integer square root and the integer root of a number.

Example:
	say 123.isqrt		# prints: 11
	say 125.iroot(3);	# prints: 5

- Added the Complex.root(n) method, which calculates x^(1/n)
- Minor fixes and improvements inside the Complex classs.
  • Loading branch information
trizen committed Jan 1, 2016
1 parent c700e26 commit 0c85c73
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 68 deletions.
2 changes: 1 addition & 1 deletion MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,6 @@ scripts/RosettaCode/reverse_a_string.sf
scripts/RosettaCode/reverse_words_in_a_string.sf
scripts/RosettaCode/roots_of_a_quadratic_function.sf
scripts/RosettaCode/roots_of_unity_1.sf
scripts/RosettaCode/roots_of_unity_2.sf
scripts/RosettaCode/rpn_calculator_algorithm.sf
scripts/RosettaCode/rpn_to_infix_conversion.sf
scripts/RosettaCode/runge-kutta_method.sf
Expand Down Expand Up @@ -647,6 +646,7 @@ scripts/Tests/Module/YouTube.sm
scripts/Tests/module_definition.sf
scripts/Tests/module_loading.sf
scripts/Tests/module_order_and_redeclaration.sf
scripts/Tests/modulo.sf
scripts/Tests/multi_file_edit.sf
scripts/Tests/multi_functions.sf
scripts/Tests/multi_methods.sf
Expand Down
2 changes: 1 addition & 1 deletion lib/Sidef/Parser.pm
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ package Sidef::Parser {
| Ref\b (?{ state $x = bless({}, 'Sidef::Variable::Ref') })
| LazyMethod\b (?{ state $x = Sidef::Variable::LazyMethod->new })
| Time\b (?{ state $x = Sidef::Time::Time->new })
| Complex\b (?{ state $x = Sidef::Types::Number::Complex->new })
| Complex\b (?{ state $x = Sidef::Types::Number::Complex->new(0, 0) })
| Sig\b (?{ state $x = Sidef::Sys::Sig->new })
| Sys\b (?{ state $x = Sidef::Sys::Sys->new })
| Regexp?\b (?{ state $x = Sidef::Types::Regex::Regex->new('') })
Expand Down
2 changes: 1 addition & 1 deletion lib/Sidef/Types/Array/Array.pm
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ package Sidef::Types::Array::Array {
sub all {
my ($self, $code) = @_;

@{$self} || return state $x = Sidef::Types::Bool::Bool->false;
@{$self} || return state $z = Sidef::Types::Bool::Bool->false;

foreach my $val (@{$self}) {
if (not $code->run($val)) {
Expand Down
2 changes: 1 addition & 1 deletion lib/Sidef/Types/Hash/Hash.pm
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ package Sidef::Types::Hash::Hash {

sub to_list {
my ($self) = @_;
map { (Sidef::Types::String::String->new($_), $self->{$_}) } keys %$self;
map { (Sidef::Types::String::String->new($_), $self->{$_}) } CORE::keys %$self;
}

*as_list = \&to_list;
Expand Down
81 changes: 65 additions & 16 deletions lib/Sidef/Types/Number/Complex.pm
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ package Sidef::Types::Number::Complex {
}

if (not defined($y)) {
return bless(\Math::MPC->new($x // 0), __PACKAGE__);
my $r = Math::MPC::Rmpc_init2($PREC);
if (ref($x) eq 'Math::GMPq') {
Math::MPC::Rmpc_set_q($r, $x, $ROUND);
}
else {
Math::MPC::Rmpc_set_str($r, $x, 10, $ROUND);
}

return (bless \$r, __PACKAGE__);
}
elsif (ref($y) eq 'Sidef::Types::Number::Number') {
$y = $$y;
Expand All @@ -54,7 +62,38 @@ package Sidef::Types::Number::Complex {
$y = $y->get_value;
}

bless \Math::MPC->new($x, $y), __PACKAGE__;
my $r = Math::MPC::Rmpc_init2($PREC);

if (ref($x) eq 'Math::GMPq') {
if (ref($y) eq 'Math::GMPq') {
Math::MPC::Rmpc_set_q_q($r, $x, $y, $ROUND);
}
else {
my $y_fr = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_set_str($y_fr, $y, 10, $Sidef::Types::Number::Number::ROUND);
Math::MPC::Rmpc_set_q_fr($r, $x, $y_fr, $ROUND);
}
}
elsif (ref($y) eq 'Math::GMPq') {
my $x_fr = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_set_str($x_fr, $x, 10, $Sidef::Types::Number::Number::ROUND);
Math::MPC::Rmpc_set_fr_q($r, $x_fr, $y, $ROUND);
}
else {
my $x_fr = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_set_str($x_fr, $x, 10, $Sidef::Types::Number::Number::ROUND);

my $y_fr = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_set_str($y_fr, $y, 10, $Sidef::Types::Number::Number::ROUND);

Math::MPC::Rmpc_set_fr_fr($r, $x_fr, $y_fr, $ROUND);

#my $x_q = Math::GMPq->new(Sidef::Types::Number::Number::_str2rat($x), 10);
#my $y_q = Math::GMPq->new(Sidef::Types::Number::Number::_str2rat($y), 10);
#Math::MPC::Rmpc_set_q_q($r, $x_q, $y_q, $ROUND);
}

bless \$r, __PACKAGE__;
}

*call = \&new;
Expand Down Expand Up @@ -129,16 +168,16 @@ package Sidef::Types::Number::Complex {

sub pi {
my $pi = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_const_pi($pi, $ROUND);
Math::MPFR::Rmpfr_const_pi($pi, $Sidef::Types::Number::Number::ROUND);
my $cplx_pi = Math::MPC::Rmpc_init2($PREC);
Math::MPC::Rmpc_set_fr($cplx_pi, $pi, $ROUND);
_new($cplx_pi);
}

sub e {
state $one_f = (Math::MPFR::Rmpfr_init_set_ui(1, $ROUND))[0];
state $one_f = (Math::MPFR::Rmpfr_init_set_ui(1, $Sidef::Types::Number::Number::ROUND))[0];
my $e = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_exp($e, $one_f, $ROUND);
Math::MPFR::Rmpfr_exp($e, $one_f, $Sidef::Types::Number::Number::ROUND);
my $cplx_e = Math::MPC::Rmpc_init2($PREC);
Math::MPC::Rmpc_set_fr($cplx_e, $e, $ROUND);
_new($cplx_e);
Expand All @@ -153,14 +192,14 @@ package Sidef::Types::Number::Complex {
}

sub phi {
state $one_f = (Math::MPFR::Rmpfr_init_set_ui(1, $ROUND))[0];
state $two_f = (Math::MPFR::Rmpfr_init_set_ui(2, $ROUND))[0];
state $five_f = (Math::MPFR::Rmpfr_init_set_ui(5, $ROUND))[0];
state $one_f = (Math::MPFR::Rmpfr_init_set_ui(1, $Sidef::Types::Number::Number::ROUND))[0];
state $two_f = (Math::MPFR::Rmpfr_init_set_ui(2, $Sidef::Types::Number::Number::ROUND))[0];
state $five_f = (Math::MPFR::Rmpfr_init_set_ui(5, $Sidef::Types::Number::Number::ROUND))[0];

my $phi = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_sqrt($phi, $five_f, $ROUND);
Math::MPFR::Rmpfr_add($phi, $phi, $one_f, $ROUND);
Math::MPFR::Rmpfr_div($phi, $phi, $two_f, $ROUND);
Math::MPFR::Rmpfr_sqrt($phi, $five_f, $Sidef::Types::Number::Number::ROUND);
Math::MPFR::Rmpfr_add($phi, $phi, $one_f, $Sidef::Types::Number::Number::ROUND);
Math::MPFR::Rmpfr_div($phi, $phi, $two_f, $Sidef::Types::Number::Number::ROUND);

my $cplx_phi = Math::MPC::Rmpc_init2($PREC);
Math::MPC::Rmpc_set_fr($cplx_phi, $phi, $ROUND);
Expand All @@ -187,15 +226,19 @@ package Sidef::Types::Number::Complex {

sub real {
my $mpfr = Math::MPFR::Rmpfr_init2($PREC);
Math::MPC::Rmpc_real($mpfr, ${$_[0]}, $ROUND);
Math::MPC::RMPC_RE($mpfr, ${$_[0]});

#Math::MPC::Rmpc_real($mpfr, ${$_[0]}, $ROUND);
Sidef::Types::Number::Number::_mpfr2rat($mpfr);
}

*re = \ℜ

sub imag {
my $mpfr = Math::MPFR::Rmpfr_init2($PREC);
Math::MPC::Rmpc_imag($mpfr, ${$_[0]}, $ROUND);
Math::MPC::RMPC_IM($mpfr, ${$_[0]});

#Math::MPC::Rmpc_imag($mpfr, ${$_[0]}, $ROUND);
Sidef::Types::Number::Number::_mpfr2rat($mpfr);
}

Expand Down Expand Up @@ -294,6 +337,12 @@ package Sidef::Types::Number::Complex {
_new($r);
}

sub root {
my ($x, $y) = @_;
state $one = __PACKAGE__->new(1);
return $x->pow($one->div($y));
}

sub sqrt {
my ($x) = @_;
my $r = Math::MPC::Rmpc_init2($PREC);
Expand Down Expand Up @@ -321,7 +370,7 @@ package Sidef::Types::Number::Complex {
}
else {
my $baseln = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_log($baseln, $y->_as_float(), $ROUND);
Math::MPFR::Rmpfr_log($baseln, $y->_as_float(), $Sidef::Types::Number::Number::ROUND);
Math::MPC::Rmpc_div_fr($r, $r, $baseln, $ROUND);
}
}
Expand All @@ -341,10 +390,10 @@ package Sidef::Types::Number::Complex {
my $r = Math::MPC::Rmpc_init2($PREC);
Math::MPC::Rmpc_log($r, $$x, $ROUND);

state $two = (Math::MPFR::Rmpfr_init_set_ui(2, $ROUND))[0];
state $two = (Math::MPFR::Rmpfr_init_set_ui(2, $Sidef::Types::Number::Number::ROUND))[0];

my $baseln = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_log($baseln, $two, $ROUND);
Math::MPFR::Rmpfr_log($baseln, $two, $Sidef::Types::Number::Number::ROUND);
Math::MPC::Rmpc_div_fr($r, $r, $baseln, $ROUND);

_new($r);
Expand Down
2 changes: 2 additions & 0 deletions lib/Sidef/Types/Number/Inf.pm
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ package Sidef::Types::Number::Inf {
*max = \&inf;
*abs = \&inf;
*sqrt = \&inf;
*isqrt = \&inf;
*cbrt = \&inf;
*root = \&inf;
*iroot = \&inf;
*sqr = \&inf;
*log = \&inf;
*log2 = \&inf;
Expand Down
10 changes: 9 additions & 1 deletion lib/Sidef/Types/Number/Ninf.pm
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,15 @@ package Sidef::Types::Number::Ninf {
#
sub asin { state $x = Sidef::Types::Number::Complex->new(0, '@inf@') }

*sqrt = \&asin;
*sqrt = \&asin;
*isqrt = \&asin;

#
## (-inf)^(1/x) = i^(1/x) * inf
## However, returning inf*i is good enough!
#
*root = \&asin;
*iroot = \&asin;

#
## acos(-inf) = -inf*i
Expand Down
Loading

0 comments on commit 0c85c73

Please sign in to comment.