| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Copyright 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Kevin Ryde |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# This file is part of Math-PlanePath. |
|
4
|
|
|
|
|
|
|
# |
|
5
|
|
|
|
|
|
|
# Math-PlanePath is free software; you can redistribute it and/or modify |
|
6
|
|
|
|
|
|
|
# it under the terms of the GNU General Public License as published by the |
|
7
|
|
|
|
|
|
|
# Free Software Foundation; either version 3, or (at your option) any later |
|
8
|
|
|
|
|
|
|
# version. |
|
9
|
|
|
|
|
|
|
# |
|
10
|
|
|
|
|
|
|
# Math-PlanePath is distributed in the hope that it will be useful, but |
|
11
|
|
|
|
|
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
12
|
|
|
|
|
|
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13
|
|
|
|
|
|
|
# for more details. |
|
14
|
|
|
|
|
|
|
# |
|
15
|
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License along |
|
16
|
|
|
|
|
|
|
# with Math-PlanePath. If not, see . |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
package Math::PlanePath::CfracDigits; |
|
20
|
1
|
|
|
1
|
|
1305
|
use 5.004; |
|
|
1
|
|
|
|
|
4
|
|
|
21
|
1
|
|
|
1
|
|
5
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
22
|
|
|
|
|
|
|
|
|
23
|
1
|
|
|
1
|
|
5
|
use vars '$VERSION', '@ISA'; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
74
|
|
|
24
|
|
|
|
|
|
|
$VERSION = 129; |
|
25
|
1
|
|
|
1
|
|
794
|
use Math::PlanePath; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
48
|
|
|
26
|
|
|
|
|
|
|
@ISA = ('Math::PlanePath'); |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
use Math::PlanePath::Base::Generic |
|
29
|
1
|
|
|
|
|
46
|
'is_infinite', |
|
30
|
1
|
|
|
1
|
|
6
|
'round_nearest'; |
|
|
1
|
|
|
|
|
2
|
|
|
31
|
|
|
|
|
|
|
use Math::PlanePath::Base::Digits |
|
32
|
1
|
|
|
|
|
66
|
'round_down_pow', |
|
33
|
|
|
|
|
|
|
'digit_split_lowtohigh', |
|
34
|
1
|
|
|
1
|
|
604
|
'digit_join_lowtohigh'; |
|
|
1
|
|
|
|
|
13
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
1
|
|
|
1
|
|
780
|
use Math::PlanePath::RationalsTree; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
43
|
|
|
37
|
|
|
|
|
|
|
*_xy_to_quotients = \&Math::PlanePath::RationalsTree::_xy_to_quotients; |
|
38
|
|
|
|
|
|
|
|
|
39
|
1
|
|
|
1
|
|
7
|
use Math::PlanePath::CoprimeColumns; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
46
|
|
|
40
|
|
|
|
|
|
|
*_coprime = \&Math::PlanePath::CoprimeColumns::_coprime; |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# uncomment this to run the ### lines |
|
43
|
|
|
|
|
|
|
#use Smart::Comments; |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
|
|
46
|
1
|
|
|
|
|
54
|
use constant parameter_info_array => |
|
47
|
|
|
|
|
|
|
[ { name => 'radix', |
|
48
|
|
|
|
|
|
|
share_key => 'radix2_min1', |
|
49
|
|
|
|
|
|
|
display => 'Radix', |
|
50
|
|
|
|
|
|
|
type => 'integer', |
|
51
|
|
|
|
|
|
|
minimum => 1, |
|
52
|
|
|
|
|
|
|
default => 2, |
|
53
|
|
|
|
|
|
|
width => 3, |
|
54
|
|
|
|
|
|
|
}, |
|
55
|
1
|
|
|
1
|
|
6
|
]; |
|
|
1
|
|
|
|
|
2
|
|
|
56
|
|
|
|
|
|
|
|
|
57
|
1
|
|
|
1
|
|
6
|
use constant n_start => 0; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
39
|
|
|
58
|
1
|
|
|
1
|
|
5
|
use constant class_x_negative => 0; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
54
|
|
|
59
|
1
|
|
|
1
|
|
6
|
use constant class_y_negative => 0; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
56
|
|
|
60
|
1
|
|
|
1
|
|
7
|
use constant x_minimum => 1; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
52
|
|
|
61
|
1
|
|
|
1
|
|
7
|
use constant y_minimum => 2; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
56
|
|
|
62
|
1
|
|
|
1
|
|
7
|
use constant diffxy_maximum => -1; # upper octant X<=Y-1 so X-Y<=-1 |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
62
|
|
|
63
|
1
|
|
|
1
|
|
6
|
use constant gcdxy_maximum => 1; # no common factor |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1325
|
|
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# FIXME: believe this is right, but check N+1 always changes Y |
|
66
|
|
|
|
|
|
|
sub absdy_minimum { |
|
67
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
|
68
|
0
|
0
|
|
|
|
0
|
return ($self->{'radix'} < 3 ? 0 : 1); |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# radix=1 N=1 has dir4=0 |
|
72
|
|
|
|
|
|
|
# radix=2 N=5628 has dir4=0 dx=9,dy=0 |
|
73
|
|
|
|
|
|
|
# radix=3 N=1189140 has dir4=0 dx=1,dy=0 |
|
74
|
|
|
|
|
|
|
# radix=4 N=169405 has dir4=0 dx=2,dy=0 |
|
75
|
|
|
|
|
|
|
# always eventually 0 ? |
|
76
|
|
|
|
|
|
|
# use constant dir_minimum_dxdy => (1,0); # the default |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# radix=1 N=4 dX=1,dY=-1 for dir4=3.5 |
|
79
|
|
|
|
|
|
|
# radix=2 N=4413 dX=9,dY=-1 |
|
80
|
|
|
|
|
|
|
# radix=3 N=9492 dX=3,dY=-1 |
|
81
|
|
|
|
|
|
|
# ENHANCE-ME: suspect believe approaches 360 degrees, eventually, but proof? |
|
82
|
|
|
|
|
|
|
# use constant dir_maximum_dxdy => (0,0); # the default |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub turn_any_straight { |
|
85
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
|
86
|
0
|
|
|
|
|
0
|
return ($self->{'radix'} != 1); # radix=1 never straight |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub _UNDOCUMENTED__turn_any_left_at_n { |
|
90
|
0
|
|
|
0
|
|
0
|
my ($self) = @_; |
|
91
|
0
|
|
|
|
|
0
|
return $self->{'radix'} + 1; |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
sub _UNDOCUMENTED__turn_any_right_at_n { |
|
94
|
0
|
|
|
0
|
|
0
|
my ($self) = @_; |
|
95
|
0
|
|
|
|
|
0
|
return $self->{'radix'}; |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub new { |
|
102
|
3
|
|
|
3
|
1
|
600
|
my $self = shift->SUPER::new (@_); |
|
103
|
3
|
50
|
33
|
|
|
17
|
unless ($self->{'radix'} && $self->{'radix'} >= 1) { |
|
104
|
3
|
|
|
|
|
6
|
$self->{'radix'} = 2; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
3
|
|
|
|
|
7
|
return $self; |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub n_to_xy { |
|
110
|
1
|
|
|
1
|
1
|
9
|
my ($self, $n) = @_; |
|
111
|
|
|
|
|
|
|
### CfracDigits n_to_xy(): "$n" |
|
112
|
|
|
|
|
|
|
|
|
113
|
1
|
50
|
|
|
|
4
|
if ($n < 0) { return; } |
|
|
0
|
|
|
|
|
0
|
|
|
114
|
1
|
50
|
|
|
|
4
|
if (is_infinite($n)) { return ($n,$n); } |
|
|
0
|
|
|
|
|
0
|
|
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
{ |
|
117
|
1
|
|
|
|
|
3
|
my $int = int($n); |
|
|
1
|
|
|
|
|
2
|
|
|
118
|
1
|
50
|
|
|
|
4
|
if ($n != $int) { |
|
119
|
|
|
|
|
|
|
### frac ... |
|
120
|
0
|
|
|
|
|
0
|
my $frac = $n - $int; # inherit possible BigFloat/BigRat |
|
121
|
0
|
|
|
|
|
0
|
my ($x1,$y1) = $self->n_to_xy($int); |
|
122
|
0
|
|
|
|
|
0
|
my ($x2,$y2) = $self->n_to_xy($int+1); |
|
123
|
0
|
|
|
|
|
0
|
my $dx = $x2-$x1; |
|
124
|
0
|
|
|
|
|
0
|
my $dy = $y2-$y1; |
|
125
|
|
|
|
|
|
|
### x1,y1: "$x1, $y1" |
|
126
|
|
|
|
|
|
|
### x2,y2: "$x2, $y2" |
|
127
|
|
|
|
|
|
|
### dx,dy: "$dx, $dy" |
|
128
|
|
|
|
|
|
|
### result: ($frac*$dx + $x1).', '.($frac*$dy + $y1) |
|
129
|
0
|
|
|
|
|
0
|
return ($frac*$dx + $x1, $frac*$dy + $y1); |
|
130
|
|
|
|
|
|
|
} |
|
131
|
1
|
|
|
|
|
3
|
$n = $int; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
1
|
|
|
|
|
2
|
my $radix = $self->{'radix'}; |
|
135
|
1
|
|
|
|
|
1
|
my $zero = ($n * 0); # inherit bignum 0 |
|
136
|
1
|
|
|
|
|
2
|
my $x = $zero; |
|
137
|
1
|
|
|
|
|
2
|
my $y = 1 + $zero; # inherit bignum 1 |
|
138
|
|
|
|
|
|
|
|
|
139
|
1
|
|
|
|
|
4
|
foreach my $q (_n_to_quotients_bottomtotop($n,$radix,$zero)) { # bottom to top |
|
140
|
|
|
|
|
|
|
### at: "$x,$y q=$q" |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# 1/(q + X/Y) = 1/((qY+X)/Y) |
|
143
|
|
|
|
|
|
|
# = Y/(qY+X) |
|
144
|
4
|
|
|
|
|
7
|
($x,$y) = ($y, $q*$y + $x); |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
### return: "$x,$y" |
|
148
|
1
|
|
|
|
|
4
|
return ($x,$y); |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# Return a list of quotients bottom to top. The base3 digits of N are split |
|
152
|
|
|
|
|
|
|
# by "3" delimiters and the parts adjusted so the first bottom-most q>=2 and |
|
153
|
|
|
|
|
|
|
# the rest q>=1. The values are ready to be used as continued fraction |
|
154
|
|
|
|
|
|
|
# terms. |
|
155
|
|
|
|
|
|
|
# |
|
156
|
|
|
|
|
|
|
sub _n_to_quotients_bottomtotop { |
|
157
|
6
|
|
|
6
|
|
364
|
my ($n, $radix, $zero) = @_; |
|
158
|
|
|
|
|
|
|
### _n_to_quotients_bottomtotop(): $n |
|
159
|
|
|
|
|
|
|
|
|
160
|
6
|
|
|
|
|
10
|
my $radix_plus_1 = $radix + 1; |
|
161
|
6
|
|
|
|
|
10
|
my @ret; |
|
162
|
|
|
|
|
|
|
my @group; |
|
163
|
6
|
|
|
|
|
10
|
foreach my $digit (_digit_split_1toR_lowtohigh($n,$radix_plus_1)) { |
|
164
|
21
|
100
|
|
|
|
30
|
if ($digit == $radix_plus_1) { |
|
165
|
|
|
|
|
|
|
### @group |
|
166
|
7
|
|
|
|
|
15
|
push @ret, _digit_join_1toR_destructive(\@group, $radix, $zero) + 1; |
|
167
|
7
|
|
|
|
|
24
|
@group = (); |
|
168
|
|
|
|
|
|
|
} else { |
|
169
|
14
|
|
|
|
|
28
|
push @group, $digit; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
### final group: @group |
|
173
|
6
|
|
|
|
|
11
|
push @ret, _digit_join_1toR_destructive(\@group, $radix, $zero) + 1; |
|
174
|
|
|
|
|
|
|
|
|
175
|
6
|
|
|
|
|
9
|
$ret[0] += 1; # bottom-most is +2 rather than +1 |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
### _n_to_quotients_bottomtotop result: @ret |
|
178
|
6
|
|
|
|
|
17
|
return @ret; |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# Return a list of digits 1 <= d <= R which is $n written in $radix, low to |
|
182
|
|
|
|
|
|
|
# high digits. |
|
183
|
|
|
|
|
|
|
sub _digit_split_1toR_lowtohigh { |
|
184
|
28
|
|
|
28
|
|
697
|
my ($n, $radix) = @_; |
|
185
|
|
|
|
|
|
|
### assert: $radix >= 1 |
|
186
|
|
|
|
|
|
|
### assert: $n >= 0 |
|
187
|
|
|
|
|
|
|
|
|
188
|
28
|
50
|
|
|
|
57
|
if ($radix == 1) { |
|
189
|
0
|
|
|
|
|
0
|
return (1) x $n; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
28
|
|
|
|
|
69
|
my @digits = digit_split_lowtohigh($n,$radix); |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# mangle 0 -> R |
|
194
|
28
|
|
|
|
|
44
|
my $borrow = 0; |
|
195
|
28
|
|
|
|
|
46
|
foreach my $digit (@digits) { # low to high |
|
196
|
61
|
100
|
|
|
|
122
|
if ($borrow = (($digit -= $borrow) <= 0)) { # modify array contents |
|
197
|
26
|
|
|
|
|
40
|
$digit += $radix; |
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
} |
|
200
|
28
|
100
|
|
|
|
46
|
if ($borrow) { |
|
201
|
|
|
|
|
|
|
### assert: $digits[-1] == $radix |
|
202
|
6
|
|
|
|
|
17
|
pop @digits; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
|
|
205
|
28
|
|
|
|
|
81
|
return @digits; |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub _digit_join_1toR_destructive { |
|
209
|
18
|
|
|
18
|
|
34
|
my ($aref, $radix, $zero) = @_; |
|
210
|
|
|
|
|
|
|
### assert: $radix >= 1 |
|
211
|
|
|
|
|
|
|
|
|
212
|
18
|
50
|
|
|
|
108
|
if ($radix == 1) { |
|
213
|
0
|
|
|
|
|
0
|
return scalar(@$aref); |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# mangle any digit==$radix down to digit=0 |
|
217
|
18
|
|
|
|
|
27
|
my $carry = 0; |
|
218
|
18
|
|
|
|
|
28
|
foreach my $digit (@$aref) { # low to high |
|
219
|
34
|
100
|
|
|
|
65
|
if ($carry = (($digit += $carry) >= $radix)) { # modify array contents |
|
220
|
16
|
|
|
|
|
25
|
$digit -= $radix; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
|
|
|
|
|
|
} |
|
223
|
18
|
100
|
|
|
|
31
|
if ($carry) { |
|
224
|
6
|
|
|
|
|
10
|
push @$aref, 1; |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
### _digit_join_1toR_destructive() result: digit_join_lowtohigh($aref, $radix, $zero) |
|
228
|
18
|
|
|
|
|
42
|
return digit_join_lowtohigh($aref, $radix, $zero); |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub xy_is_visited { |
|
232
|
0
|
|
|
0
|
1
|
0
|
my ($self, $x, $y) = @_; |
|
233
|
0
|
|
|
|
|
0
|
$x = round_nearest ($x); |
|
234
|
0
|
|
|
|
|
0
|
$y = round_nearest ($y); |
|
235
|
0
|
|
0
|
|
|
0
|
return (! ($x < 1 || $y < 2 || $x >= $y) |
|
236
|
|
|
|
|
|
|
&& _coprime($x,$y)); |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub xy_to_n { |
|
240
|
1
|
|
|
1
|
1
|
122
|
my ($self, $x, $y) = @_; |
|
241
|
1
|
|
|
|
|
4
|
$x = round_nearest ($x); |
|
242
|
1
|
|
|
|
|
2
|
$y = round_nearest ($y); |
|
243
|
|
|
|
|
|
|
### CfracDigits xy_to_n(): "$x,$y" |
|
244
|
|
|
|
|
|
|
|
|
245
|
1
|
50
|
|
|
|
3
|
if (is_infinite($x)) { return $x; } |
|
|
0
|
|
|
|
|
0
|
|
|
246
|
1
|
50
|
|
|
|
13
|
if (is_infinite($y)) { return $y; } |
|
|
0
|
|
|
|
|
0
|
|
|
247
|
1
|
50
|
33
|
|
|
10
|
if ($x < 1 || $y < 2 || $x >= $y) { |
|
|
|
|
33
|
|
|
|
|
|
248
|
0
|
|
|
|
|
0
|
return undef; |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
|
|
251
|
1
|
50
|
|
|
|
4
|
my @quotients = _xy_to_quotients($x,$y) |
|
252
|
|
|
|
|
|
|
or return undef; # $x,$y have a common factor |
|
253
|
|
|
|
|
|
|
### @quotients |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
# drop initial 0 integer part |
|
256
|
|
|
|
|
|
|
### assert: $quotients[0] == 0 |
|
257
|
1
|
|
|
|
|
10
|
shift @quotients; |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
return _cfrac_join_toptobottom(\@quotients, |
|
260
|
1
|
|
|
|
|
5
|
$self->{'radix'}, |
|
261
|
|
|
|
|
|
|
$x * 0 * $y); # inherit bignum 0 |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# $aref is a list of continued fraction quotients from top-most to |
|
265
|
|
|
|
|
|
|
# bottom-most. There's no initial integer term in $aref. Each quotient is |
|
266
|
|
|
|
|
|
|
# q >= 1 except the bottom-most which q-1 and so also >=1. |
|
267
|
|
|
|
|
|
|
# |
|
268
|
|
|
|
|
|
|
sub _cfrac_join_toptobottom { |
|
269
|
5
|
|
|
5
|
|
334
|
my ($aref, $radix, $zero) = @_; |
|
270
|
|
|
|
|
|
|
### _cfrac_join_toptobottom(): $aref |
|
271
|
|
|
|
|
|
|
|
|
272
|
5
|
|
|
|
|
8
|
my @digits; |
|
273
|
5
|
|
|
|
|
9
|
foreach my $q (reverse @$aref) { |
|
274
|
|
|
|
|
|
|
### assert: $q >= 1 |
|
275
|
12
|
|
|
|
|
25
|
push @digits, _digit_split_1toR_lowtohigh($q-1, $radix), $radix+1; |
|
276
|
|
|
|
|
|
|
} |
|
277
|
5
|
|
|
|
|
7
|
pop @digits; # no high delimiter |
|
278
|
|
|
|
|
|
|
### groups digits 1toR: @digits |
|
279
|
5
|
|
|
|
|
12
|
return _digit_join_1toR_destructive(\@digits, $radix+1, $zero); |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# X/Y = F[k]/F[k+1] quotients all 1 |
|
284
|
|
|
|
|
|
|
# N = all delimiter digits R,R,...,R |
|
285
|
|
|
|
|
|
|
# = 1222...2221 |
|
286
|
|
|
|
|
|
|
# = R^k + 2*(R^k+1)/(R-1) - 1 |
|
287
|
|
|
|
|
|
|
# = (RR^k - R^k + 2R^k + 2 - R + 1) / (R-1) |
|
288
|
|
|
|
|
|
|
# = (RR^k + R^k - R + 3) / (R-1) |
|
289
|
|
|
|
|
|
|
# = ((R+1)R^k - R + 3) / (R-1) |
|
290
|
|
|
|
|
|
|
# take high as "12" = R+2 |
|
291
|
|
|
|
|
|
|
# k = log(Y)/log(phi) |
|
292
|
|
|
|
|
|
|
# N = (R+2) * R ** k |
|
293
|
|
|
|
|
|
|
# N = Y ** (log(R)/log(phi)) |
|
294
|
|
|
|
|
|
|
# |
|
295
|
|
|
|
|
|
|
# not exact |
|
296
|
|
|
|
|
|
|
sub rect_to_n_range { |
|
297
|
2
|
|
|
2
|
1
|
266
|
my ($self, $x1,$y1, $x2,$y2) = @_; |
|
298
|
|
|
|
|
|
|
### rect_to_n_range() |
|
299
|
|
|
|
|
|
|
|
|
300
|
2
|
|
|
|
|
7
|
$x1 = round_nearest ($x1); |
|
301
|
2
|
|
|
|
|
14
|
$y1 = round_nearest ($y1); |
|
302
|
2
|
|
|
|
|
5
|
$x2 = round_nearest ($x2); |
|
303
|
2
|
|
|
|
|
4
|
$y2 = round_nearest ($y2); |
|
304
|
|
|
|
|
|
|
|
|
305
|
2
|
50
|
|
|
|
6
|
($x1,$x2) = ($x2,$x1) if $x1 > $x2; |
|
306
|
2
|
50
|
|
|
|
5
|
($y1,$y2) = ($y2,$y1) if $y1 > $y2; |
|
307
|
|
|
|
|
|
|
### $x2 |
|
308
|
|
|
|
|
|
|
### $y2 |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# | / |
|
311
|
|
|
|
|
|
|
# | / x1 |
|
312
|
|
|
|
|
|
|
# | / +-----y2 |
|
313
|
|
|
|
|
|
|
# | / | |
|
314
|
|
|
|
|
|
|
# |/ +----- |
|
315
|
|
|
|
|
|
|
# |
|
316
|
2
|
50
|
33
|
|
|
21
|
if ($x2 < 1 || $y2 < 2 || $x1 >= $y2) { |
|
|
|
|
33
|
|
|
|
|
|
317
|
|
|
|
|
|
|
### no values, rect outside upper octant ... |
|
318
|
0
|
|
|
|
|
0
|
return (1,0); |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
2
|
|
|
|
|
4
|
my $zero = ($x1 * 0 * $y1 * $x2 * $y2); # inherit bignum |
|
322
|
2
|
|
|
|
|
5
|
my $radix = $self->{'radix'}; |
|
323
|
|
|
|
|
|
|
|
|
324
|
2
|
50
|
|
|
|
7
|
return (0, |
|
325
|
|
|
|
|
|
|
($radix+3) |
|
326
|
|
|
|
|
|
|
* ($radix+1 + $zero) ** ($radix == 1 |
|
327
|
|
|
|
|
|
|
? $y2 |
|
328
|
|
|
|
|
|
|
: _log_phi_estimate($y2,$radix))); |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# Return an estimate of log base phi of $x, that being log($x)/log(phi), |
|
332
|
|
|
|
|
|
|
# where phi=(1+sqrt(5))/2 the golden ratio. |
|
333
|
|
|
|
|
|
|
# |
|
334
|
|
|
|
|
|
|
sub _log_phi_estimate { |
|
335
|
2
|
|
|
2
|
|
5
|
my ($x) = @_; |
|
336
|
2
|
|
|
|
|
5
|
my ($pow,$exp) = round_down_pow ($x, 2); |
|
337
|
2
|
|
|
|
|
8
|
return int ($exp * (log(2) / log((1+sqrt(5))/2))); |
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
1; |
|
341
|
|
|
|
|
|
|
__END__ |