Skip to content

Commit

Permalink
- Extended the ranges to support floating point numbers.
Browse files Browse the repository at this point in the history
Example:
	1.23 ... 10.45 -> each { |i| say i }

This is also true for `..`, `^..` and `..^`

- Added the `reduce` method to the RangeNumber object, which allows reducing large ranges to a single value efficiently.

Example:
	1..1e5 -> reduce { |a,b| a + b }	# sums all numbs from 1 to 1e5
  • Loading branch information
trizen committed Dec 31, 2015
1 parent 69ad567 commit 2faee2a
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 11 deletions.
14 changes: 14 additions & 0 deletions lib/Sidef/Types/Number/Inf.pm
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,16 @@ package Sidef::Types::Number::Inf {
*zeta = \&tanh;
*erf = \&tanh;

sub array_to { Sidef::Types::Array::Array->new }

*arr_to = \&array_to;
*arr_downto = \&array_to;
*array_downto = \&array_to;

# Probably, this ones should return each a RangeNumber object instead
*to = \&array_to;
*downto = \&array_to;

sub chr { state $x = Sidef::Types::String::String->new('') }
sub sign { state $x = Sidef::Types::String::String->new('+') }

Expand Down Expand Up @@ -361,6 +371,10 @@ package Sidef::Types::Number::Inf {
*{__PACKAGE__ . '::' . '=='} = \&eq;
*{__PACKAGE__ . '::' . '!='} = \≠
*{__PACKAGE__ . '::' . ''} = \≠
*{__PACKAGE__ . '::' . '..'} = \&array_to;
*{__PACKAGE__ . '::' . '...'} = \&to;
*{__PACKAGE__ . '::' . '..^'} = \&to;
*{__PACKAGE__ . '::' . '^..'} = \&downto;
*{__PACKAGE__ . '::' . '>'} = \>
*{__PACKAGE__ . '::' . '>='} = \≥
*{__PACKAGE__ . '::' . ''} = \≥
Expand Down
14 changes: 14 additions & 0 deletions lib/Sidef/Types/Number/Ninf.pm
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,16 @@ package Sidef::Types::Number::Ninf {
*acot = \&zero;
*acoth = \&zero;

sub array_to { Sidef::Types::Array::Array->new }

*arr_to = \&array_to;
*arr_downto = \&array_to;
*array_downto = \&array_to;

# Probably, this ones should return each a RangeNumber object instead
*to = \&array_to;
*downto = \&array_to;

sub chr { state $x = Sidef::Types::String::String->new('') }
sub sign { state $x = Sidef::Types::String::String->new('-') }

Expand Down Expand Up @@ -360,6 +370,10 @@ package Sidef::Types::Number::Ninf {
*{__PACKAGE__ . '::' . '=='} = \&eq;
*{__PACKAGE__ . '::' . '!='} = \≠
*{__PACKAGE__ . '::' . ''} = \≠
*{__PACKAGE__ . '::' . '..'} = \&array_to;
*{__PACKAGE__ . '::' . '...'} = \&to;
*{__PACKAGE__ . '::' . '..^'} = \&to;
*{__PACKAGE__ . '::' . '^..'} = \&downto;
*{__PACKAGE__ . '::' . '>'} = \>
*{__PACKAGE__ . '::' . '>='} = \≥
*{__PACKAGE__ . '::' . ''} = \≥
Expand Down
20 changes: 13 additions & 7 deletions lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ package Sidef::Types::Number::Number {
my $dz = Math::GMPz::Rmpz_init();
Math::GMPq::Rmpq_get_den($dz, $x);

state $one_z = Math::GMPz::Rmpz_init_set_str(1, 10);
state $one_z = Math::GMPz::Rmpz_init_set_ui(1);
not Math::GMPz::Rmpz_cmp($dz, $one_z);
}

Expand Down Expand Up @@ -1745,20 +1745,24 @@ package Sidef::Types::Number::Number {
sub array_to {
my ($x, $y, $step) = @_;

my @array;
if (not defined($step)) {

_valid($y);
_valid($y);

my @array;
if (not defined($step) and _is_int($$x) and _is_int($$y)) {
foreach my $i (Math::GMPq::Rmpq_get_d($$x) .. Math::GMPq::Rmpq_get_d($$y)) {
my $n = Math::GMPq::Rmpq_init();
Math::GMPq::Rmpq_set_str($n, $i, 10);
Math::GMPq::Rmpq_set_si($n, $i, 1);
push @array, bless(\$n, __PACKAGE__);
}
}
else {

_valid($y, $step);
if (not defined $step) {
$step = $ONE;
}
else {
_valid($step);
}

my $xq = $$x;
my $yq = $$y;
Expand Down Expand Up @@ -1807,6 +1811,8 @@ package Sidef::Types::Number::Number {
Sidef::Types::Array::Array->new(@array);
}

*arr_downto = \&array_downto;

# TODO: find a better solution which doesn't use Math::BigRat
sub roundf {
my ($x, $prec) = @_;
Expand Down
54 changes: 50 additions & 4 deletions lib/Sidef/Types/Range/RangeNumber.pm
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ package Sidef::Types::Range::RangeNumber {
my $from = $self->{from};
my $to = $self->{to};

if ($step == 1 and $to < (-1 >> 1) and $from < (-1 >> 1)) {
if ( $step == 1
and $to < (-1 >> 1)
and $from < (-1 >> 1)
and (ref($from) ? Sidef::Types::Number::Number::_is_int($from) : 1)
and (ref($to) ? Sidef::Types::Number::Number::_is_int($to) : 1)) {
foreach my $i ($from .. $to) {
if (defined(my $res = $code->_run_code(Sidef::Types::Number::Number::_new_int($i)))) {
return $res;
Expand Down Expand Up @@ -138,7 +142,11 @@ package Sidef::Types::Range::RangeNumber {
my $to = $self->{to};

my @values;
if ($step == 1 and $to < (-1 >> 1) and $from < (-1 >> 1)) {
if ( $step == 1
and $to < (-1 >> 1)
and $from < (-1 >> 1)
and (ref($from) ? Sidef::Types::Number::Number::_is_int($from) : 1)
and (ref($to) ? Sidef::Types::Number::Number::_is_int($to) : 1)) {
foreach my $i ($from .. $to) {
push @values, $code->run(Sidef::Types::Number::Number::_new_int($i));
}
Expand Down Expand Up @@ -167,9 +175,13 @@ package Sidef::Types::Range::RangeNumber {
my $to = $self->{to};

my @values;
if ($step == 1 and $to < (-1 >> 1) and $from < (-1 >> 1)) {
if ( $step == 1
and $to < (-1 >> 1)
and $from < (-1 >> 1)
and (ref($from) ? Sidef::Types::Number::Number::_is_int($from) : 1)
and (ref($to) ? Sidef::Types::Number::Number::_is_int($to) : 1)) {
foreach my $i ($from .. $to) {
my $num = Sidef::Types::Number::Number::_new_uint($i);
my $num = Sidef::Types::Number::Number::_new_int($i);
push(@values, $num) if $code->run($num);
}
}
Expand All @@ -192,6 +204,40 @@ package Sidef::Types::Range::RangeNumber {
*filter = \&grep;
*select = \&grep;

sub reduce {
my ($self, $code) = @_;

my $step = $self->{step};
my $from = $self->{from};
my $to = $self->{to};

my $value = Sidef::Types::Number::Number->new($from);
if ( $step == 1
and $to < (-1 >> 1)
and $from < (-1 >> 1)
and (ref($from) ? Sidef::Types::Number::Number::_is_int($from) : 1)
and (ref($to) ? Sidef::Types::Number::Number::_is_int($to) : 1)) {
foreach my $i ($from + 1 .. $to) {
my $num = Sidef::Types::Number::Number::_new_int($i);
$value = $code->run($value, $num);
}
}
elsif ($step > 0) {
for (my $i = $from + $step ; $i <= $to ; $i += $step) {
my $num = Sidef::Types::Number::Number->new($i);
$value = $code->run($value, $num);
}
}
else {
for (my $i = $from + $step ; $i >= $to ; $i += $step) {
my $num = Sidef::Types::Number::Number->new($i);
$value = $code->run($value, $num);
}
}

$value;
}

our $AUTOLOAD;
sub DESTROY { }

Expand Down

0 comments on commit 2faee2a

Please sign in to comment.