Math-NumSeq
view release on metacpan or search on metacpan
lib/Math/NumSeq/RadixWithoutDigit.pm view on Meta::CPAN
# = (9^len - 1)/8 - 1
# = (9^len - 1 - 8)/8
# = (9^len - 9)/8
# 8*i + 1 = 9^level
#
# add sentinel 1*9^len, so
# from = i - (9^len - 9)/8 + 9^len
# = i + (- 9^len + 9)/8 + 9^len
# = i + (- 9^len + 9 + 8*9^len)/8
# = i + (7*9^len + 9) / 8
#
# and which is then a high digit 2*9^len too big
#
sub ith {
my ($self, $i) = @_;
### RadixWithoutDigit ith(): $i
$i -= $self->i_start; # i_start=0 or i_start=1 both begin at value=0
if (_is_infinite($i)) {
return $i; # don't loop forever if $i is +infinity
}
my $radix = $self->{'radix'};
my $digit = $self->{'digit'};
if ($radix == 2) {
if ($digit == 0) {
my $base = ($i < 30 ? 2 : Math::NumSeq::_to_bigint(2));
return ($base ** ($i+1)) - 1;
} else {
### radix 2 without 1 no values ...
return undef;
}
}
if ($digit == -1) {
$digit = $radix-1;
}
my $r1 = $radix - 1;
# if ($i < $r1) {
# return $i + ($i >= $digit);
# }
my $r2 = $radix - 2;
### $radix
### $r1
### $r2
my $value = 0;
if ($digit == 0) {
my $len = 1;
while (($r1**$len - $r1) / $r2 <= $i) {
$len++;
}
$len--;
### $len
### base: ($r1**$len - $r1) / $r2
### sentinel: $r1**$len
### adj add: $r1**$len - ($r1**$len - $r1) / $r2
### adj formula: (($r2-1)*$r1**$len + $r1) / $r2
### assert: $i >= ($r1 ** $len - $r1) / $r2
### assert: $i < ($r1 ** $len - $r1) / $r2 + $r1 ** $len
$i += (($r2-1)*$r1**$len + $r1) / $r2;
$value = -2 * $radix**$len;
### i remainder: $i
### $value
### assert: $i >= $r1 ** $len
### assert: $i < 2 * $r1 ** $len
}
# $i converted to radix-1 digits, built back up as radix
my $power = 1;
while ($i > 0) {
my $d = $i % $r1;
$i = int($i/$r1);
### $value
### $d
### $power
if ($d >= $digit) {
$d++;
### inc to d: $d
}
$value += $power * $d;
$power *= $radix;
}
### stop at i: $i
$value += $power * $i;
### $value
return $value;
# my $digit = 1;
# my $x = $i;
# while ($x) {
# ### x mod $radix: $x%$radix
# if (($x % $radix) == $digit) {
# ### add: $digit
# $i += $digit;
# $x++;
# }
# $x = int($x/$radix);
# $digit *= $radix;
# }
# return (($self->{'i'} = $i),
# 1);
}
sub pred {
my ($self, $value) = @_;
my $radix = $self->{'radix'};
my $digit = $self->{'digit'};
if ($digit == -1) {
$digit = $radix-1;
}
if ($value < 0
( run in 0.649 second using v1.01-cache-2.11-cpan-df04353d9ac )