| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Copyright 2011, 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::CCurve; |
|
20
|
1
|
|
|
1
|
|
2022
|
use 5.004; |
|
|
1
|
|
|
|
|
4
|
|
|
21
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
36
|
|
|
22
|
1
|
|
|
1
|
|
7
|
use List::Util 'min','max','sum'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
84
|
|
|
23
|
|
|
|
|
|
|
|
|
24
|
1
|
|
|
1
|
|
6
|
use vars '$VERSION', '@ISA'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
71
|
|
|
25
|
|
|
|
|
|
|
$VERSION = 128; |
|
26
|
1
|
|
|
1
|
|
847
|
use Math::PlanePath; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
30
|
|
|
27
|
1
|
|
|
1
|
|
604
|
use Math::PlanePath::Base::NSEW; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
41
|
|
|
28
|
|
|
|
|
|
|
@ISA = ('Math::PlanePath::Base::NSEW', |
|
29
|
|
|
|
|
|
|
'Math::PlanePath'); |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
use Math::PlanePath::Base::Generic |
|
32
|
1
|
|
|
|
|
49
|
'is_infinite', |
|
33
|
1
|
|
|
1
|
|
6
|
'round_nearest'; |
|
|
1
|
|
|
|
|
2
|
|
|
34
|
|
|
|
|
|
|
use Math::PlanePath::Base::Digits |
|
35
|
1
|
|
|
|
|
85
|
'round_up_pow', |
|
36
|
|
|
|
|
|
|
'round_down_pow', |
|
37
|
|
|
|
|
|
|
'bit_split_lowtohigh', |
|
38
|
|
|
|
|
|
|
'digit_split_lowtohigh', |
|
39
|
1
|
|
|
1
|
|
641
|
'digit_join_lowtohigh'; |
|
|
1
|
|
|
|
|
3
|
|
|
40
|
|
|
|
|
|
|
*_divrem = \&Math::PlanePath::_divrem; |
|
41
|
|
|
|
|
|
|
*_divrem_mutate = \&Math::PlanePath::_divrem_mutate; |
|
42
|
|
|
|
|
|
|
|
|
43
|
1
|
|
|
1
|
|
714
|
use Math::PlanePath::KochCurve; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
50
|
|
|
44
|
|
|
|
|
|
|
*_digit_join_hightolow = \&Math::PlanePath::KochCurve::_digit_join_hightolow; |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# uncomment this to run the ### lines |
|
47
|
|
|
|
|
|
|
# use Smart::Comments; |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Not sure about this yet ... 2 or 4? With mirror images too 8 arms would |
|
51
|
|
|
|
|
|
|
# fill the plane everywhere 4-visited points double-traversed segments. |
|
52
|
|
|
|
|
|
|
# use constant parameter_info_array => [ { name => 'arms', |
|
53
|
|
|
|
|
|
|
# share_key => 'arms_2', |
|
54
|
|
|
|
|
|
|
# display => 'Arms', |
|
55
|
|
|
|
|
|
|
# type => 'integer', |
|
56
|
|
|
|
|
|
|
# minimum => 1, |
|
57
|
|
|
|
|
|
|
# maximum => 2, |
|
58
|
|
|
|
|
|
|
# default => 1, |
|
59
|
|
|
|
|
|
|
# width => 1, |
|
60
|
|
|
|
|
|
|
# description => 'Arms', |
|
61
|
|
|
|
|
|
|
# } ]; |
|
62
|
|
|
|
|
|
|
|
|
63
|
1
|
|
|
1
|
|
7
|
use constant n_start => 0; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
52
|
|
|
64
|
1
|
|
|
1
|
|
5
|
use constant x_negative_at_n => 6; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
42
|
|
|
65
|
1
|
|
|
1
|
|
7
|
use constant y_negative_at_n => 22; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
54
|
|
|
66
|
1
|
|
|
1
|
|
5
|
use constant 1.02 _UNDOCUMENTED__dxdy_list_at_n => 7; |
|
|
1
|
|
|
|
|
13
|
|
|
|
1
|
|
|
|
|
1585
|
|
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub new { |
|
72
|
3
|
|
|
3
|
1
|
72
|
my $self = shift->SUPER::new(@_); |
|
73
|
3
|
|
50
|
|
|
28
|
$self->{'arms'} = max(1, min(2, $self->{'arms'} || 1)); |
|
74
|
3
|
|
|
|
|
9
|
return $self; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub n_to_xy { |
|
79
|
1425
|
|
|
1425
|
1
|
27815
|
my ($self, $n) = @_; |
|
80
|
|
|
|
|
|
|
### CCurve n_to_xy(): $n |
|
81
|
|
|
|
|
|
|
|
|
82
|
1425
|
100
|
|
|
|
2806
|
if ($n < 0) { return; } |
|
|
1
|
|
|
|
|
3
|
|
|
83
|
1424
|
50
|
|
|
|
2686
|
if (is_infinite($n)) { return ($n, $n); } |
|
|
0
|
|
|
|
|
0
|
|
|
84
|
|
|
|
|
|
|
|
|
85
|
1424
|
|
|
|
|
2502
|
my $zero = ($n * 0); # inherit bignum 0 |
|
86
|
1424
|
|
|
|
|
1923
|
my $x = $zero; |
|
87
|
1424
|
|
|
|
|
2314
|
my $y = $zero; |
|
88
|
|
|
|
|
|
|
{ |
|
89
|
1424
|
|
|
|
|
1757
|
my $int = int($n); |
|
|
1424
|
|
|
|
|
1785
|
|
|
90
|
1424
|
|
|
|
|
1894
|
$x = $n - $int; # inherit possible BigFloat |
|
91
|
1424
|
|
|
|
|
1990
|
$n = $int; # BigFloat int() gives BigInt, use that |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# initial rotation from arm number $n mod $arms |
|
95
|
1424
|
|
|
|
|
2711
|
my $rot = _divrem_mutate ($n, $self->{'arms'}); |
|
96
|
|
|
|
|
|
|
|
|
97
|
1424
|
|
|
|
|
2064
|
my $len = $zero+1; |
|
98
|
1424
|
|
|
|
|
2619
|
foreach my $digit (digit_split_lowtohigh($n,4)) { |
|
99
|
|
|
|
|
|
|
### $digit |
|
100
|
|
|
|
|
|
|
|
|
101
|
6169
|
100
|
|
|
|
11806
|
if ($digit == 0) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
102
|
1194
|
|
|
|
|
2039
|
($x,$y) = ($y,-$x); # rotate -90 |
|
103
|
|
|
|
|
|
|
} elsif ($digit == 1) { |
|
104
|
1672
|
|
|
|
|
2149
|
$y -= $len; # at Y=-len |
|
105
|
|
|
|
|
|
|
} elsif ($digit == 2) { |
|
106
|
1654
|
|
|
|
|
2184
|
$x += $len; # at X=len,Y=-len |
|
107
|
1654
|
|
|
|
|
2162
|
$y -= $len; |
|
108
|
|
|
|
|
|
|
} else { |
|
109
|
|
|
|
|
|
|
### assert: $digit == 3 |
|
110
|
1649
|
|
|
|
|
2876
|
($x,$y) = (2*$len - $y, # at X=2len,Y=-len and rotate +90 |
|
111
|
|
|
|
|
|
|
$x-$len); |
|
112
|
|
|
|
|
|
|
} |
|
113
|
6169
|
|
|
|
|
7670
|
$rot++; # to keep initial direction |
|
114
|
6169
|
|
|
|
|
8495
|
$len *= 2; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
1424
|
100
|
|
|
|
2798
|
if ($rot & 2) { |
|
118
|
224
|
|
|
|
|
321
|
$x = -$x; |
|
119
|
224
|
|
|
|
|
295
|
$y = -$y; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
1424
|
100
|
|
|
|
2398
|
if ($rot & 1) { |
|
122
|
957
|
|
|
|
|
1700
|
($x,$y) = (-$y,$x); |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
### final: "$x,$y" |
|
126
|
1424
|
|
|
|
|
3160
|
return ($x,$y); |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# point N=2^(2k) at XorY=+/-2^k radius 2^k |
|
130
|
|
|
|
|
|
|
# N=2^(2k-1) at X=Y=+/-2^(k-1) radius sqrt(2)*2^(k-1) |
|
131
|
|
|
|
|
|
|
# radius = sqrt(2^level) |
|
132
|
|
|
|
|
|
|
# R(l)-R(l-1) = sqrt(2^level) - sqrt(2^(level-1)) |
|
133
|
|
|
|
|
|
|
# = sqrt(2^level) * (1 - 1/sqrt(2)) |
|
134
|
|
|
|
|
|
|
# about 0.29289 |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# len=1 extent of lower level 0 |
|
137
|
|
|
|
|
|
|
# len=4 extent of lower level 2 |
|
138
|
|
|
|
|
|
|
# len=8 extent of lower level 4+1 = 5 |
|
139
|
|
|
|
|
|
|
# len=16 extent of lower level 8+3 |
|
140
|
|
|
|
|
|
|
# len/2 + len/4-1 |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
my @digit_to_rot = (-1, 1, 0, 1); |
|
143
|
|
|
|
|
|
|
my @dir4_to_dsdd = ([1,-1],[1,1],[-1,1],[-1,-1]); |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub xy_to_n { |
|
146
|
61
|
|
|
61
|
1
|
12168
|
return scalar((shift->xy_to_n_list(@_))[0]); |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
sub xy_to_n_list { |
|
149
|
113
|
|
|
113
|
1
|
8392
|
my ($self, $x, $y) = @_; |
|
150
|
|
|
|
|
|
|
### CCurve xy_to_n(): "$x, $y" |
|
151
|
|
|
|
|
|
|
|
|
152
|
113
|
|
|
|
|
282
|
$x = round_nearest($x); |
|
153
|
113
|
|
|
|
|
239
|
$y = round_nearest($y); |
|
154
|
113
|
|
|
|
|
192
|
my $zero = $x*0*$y; |
|
155
|
|
|
|
|
|
|
|
|
156
|
113
|
|
|
|
|
224
|
($x,$y) = ($x + $y, $y - $x); # sum and diff |
|
157
|
113
|
50
|
|
|
|
225
|
if (is_infinite($x)) { return $x; } |
|
|
0
|
|
|
|
|
0
|
|
|
158
|
113
|
50
|
|
|
|
250
|
if (is_infinite($y)) { return $y; } |
|
|
0
|
|
|
|
|
0
|
|
|
159
|
|
|
|
|
|
|
|
|
160
|
113
|
|
|
|
|
190
|
my @n_list; |
|
161
|
113
|
|
|
|
|
203
|
foreach my $dsdd (@dir4_to_dsdd) { |
|
162
|
452
|
|
|
|
|
779
|
my ($ds,$dd) = @$dsdd; |
|
163
|
|
|
|
|
|
|
### attempt: "ds=$ds dd=$dd" |
|
164
|
452
|
|
|
|
|
608
|
my $s = $x; # sum X+Y |
|
165
|
452
|
|
|
|
|
577
|
my $d = $y; # diff Y-X |
|
166
|
452
|
|
|
|
|
588
|
my @nbits; |
|
167
|
|
|
|
|
|
|
|
|
168
|
452
|
|
100
|
|
|
1734
|
until ($s >= -1 && $s <= 1 && $d >= -1 && $d <= 1) { |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
169
|
|
|
|
|
|
|
### at: "s=$s, d=$d nbits=".join('',reverse @nbits) |
|
170
|
2852
|
|
|
|
|
1963
|
my $bit = $s % 2; |
|
171
|
2852
|
|
|
|
|
1932
|
push @nbits, $bit; |
|
172
|
2852
|
100
|
|
|
|
2292
|
if ($bit) { |
|
173
|
510
|
|
|
|
|
647
|
$s -= $ds; |
|
174
|
510
|
|
|
|
|
659
|
$d -= $dd; |
|
175
|
510
|
|
|
|
|
797
|
($ds,$dd) = ($dd,-$ds); # rotate -90 |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# divide 1/(1+i) = (1-i)/(1^2 - i^2) |
|
179
|
|
|
|
|
|
|
# = (1-i)/2 |
|
180
|
|
|
|
|
|
|
# so multiply (s + i*d) * (1-i)/2 |
|
181
|
|
|
|
|
|
|
# s = (s + d)/2 |
|
182
|
|
|
|
|
|
|
# d = (d - s)/2 |
|
183
|
|
|
|
|
|
|
# |
|
184
|
|
|
|
|
|
|
### assert: (($s+$d)%2)==0 |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# this form avoids overflow near DBL_MAX |
|
187
|
2852
|
|
|
|
|
1953
|
my $odd = $s % 2; |
|
188
|
2852
|
|
|
|
|
1716
|
$s -= $odd; |
|
189
|
2852
|
|
|
|
|
1693
|
$d -= $odd; |
|
190
|
2852
|
|
|
|
|
1888
|
$s /= 2; |
|
191
|
2852
|
|
|
|
|
1775
|
$d /= 2; |
|
192
|
2852
|
|
|
|
|
12594
|
($s,$d) = ($s+$d+$odd, $d-$s); |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# five final positions |
|
196
|
|
|
|
|
|
|
# . 0,1 . ds,dd |
|
197
|
|
|
|
|
|
|
# | |
|
198
|
|
|
|
|
|
|
# -1,0--0,0--1,0 |
|
199
|
|
|
|
|
|
|
# | |
|
200
|
|
|
|
|
|
|
# . 0,-1 . |
|
201
|
|
|
|
|
|
|
# |
|
202
|
|
|
|
|
|
|
### end: "s=$s d=$d ds=$ds dd=$dd" |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# last step must be East dx=1,dy=0 |
|
205
|
452
|
100
|
100
|
|
|
1055
|
unless ($ds == 1 && $dd == -1) { next; } |
|
|
288
|
|
|
|
|
544
|
|
|
206
|
|
|
|
|
|
|
|
|
207
|
164
|
100
|
100
|
|
|
533
|
if ($s == $ds && $d == $dd) { |
|
|
|
100
|
66
|
|
|
|
|
|
208
|
86
|
|
|
|
|
163
|
push @nbits, 1; |
|
209
|
|
|
|
|
|
|
} elsif ($s != 0 || $d != 0) { |
|
210
|
75
|
|
|
|
|
139
|
next; |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
# ended s=0,d=0 or s=ds,d=dd, found an N |
|
213
|
89
|
|
|
|
|
252
|
push @n_list, digit_join_lowtohigh(\@nbits, 2, $zero); |
|
214
|
|
|
|
|
|
|
### found N: "$n_list[-1]" |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
### @n_list |
|
217
|
113
|
|
|
|
|
376
|
return sort {$a<=>$b} @n_list; |
|
|
39
|
|
|
|
|
131
|
|
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# f = (1 - 1/sqrt(2) = .292 |
|
221
|
|
|
|
|
|
|
# 1/f = 3.41 |
|
222
|
|
|
|
|
|
|
# N = 2^level |
|
223
|
|
|
|
|
|
|
# Rend = sqrt(2)^level |
|
224
|
|
|
|
|
|
|
# Rmin = Rend / 2 maybe |
|
225
|
|
|
|
|
|
|
# Rmin^2 = (2^level)/4 |
|
226
|
|
|
|
|
|
|
# N = 4 * Rmin^2 |
|
227
|
|
|
|
|
|
|
# |
|
228
|
|
|
|
|
|
|
sub rect_to_n_range { |
|
229
|
5
|
|
|
5
|
1
|
970
|
my ($self, $x1,$y1, $x2,$y2) = @_; |
|
230
|
|
|
|
|
|
|
### CCurve rect_to_n_range(): "$x1,$y1 $x2,$y2" |
|
231
|
|
|
|
|
|
|
|
|
232
|
5
|
|
|
|
|
18
|
$x1 = round_nearest ($x1); |
|
233
|
5
|
|
|
|
|
13
|
$x2 = round_nearest ($x2); |
|
234
|
5
|
|
|
|
|
10
|
$y1 = round_nearest ($y1); |
|
235
|
5
|
|
|
|
|
11
|
$y2 = round_nearest ($y2); |
|
236
|
|
|
|
|
|
|
|
|
237
|
5
|
50
|
|
|
|
14
|
($x1,$x2) = ($x2,$x1) if $x1 > $x2; |
|
238
|
5
|
50
|
|
|
|
12
|
($y1,$y2) = ($y2,$y1) if $y1 > $y2; |
|
239
|
|
|
|
|
|
|
|
|
240
|
5
|
|
|
|
|
13
|
my ($len,$level) = _rect_to_k ($x1,$y1, $x2,$y2); |
|
241
|
5
|
50
|
|
|
|
14
|
if (is_infinite($level)) { |
|
242
|
0
|
|
|
|
|
0
|
return (0, $level); |
|
243
|
|
|
|
|
|
|
} |
|
244
|
5
|
|
|
|
|
19
|
return (0, 4*$len*$len*$self->{'arms'} - 1); |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# N=16 is Y=4 away k=2 |
|
248
|
|
|
|
|
|
|
# N=64 is Y=-8+1=-7 away k=3 |
|
249
|
|
|
|
|
|
|
# N=256=4^4 is X=2^4=16-3=-7 away k=4 |
|
250
|
|
|
|
|
|
|
# dist = 2^k - (2^(k-2)-1) |
|
251
|
|
|
|
|
|
|
# = 2^k - 2^(k-2) + 1 |
|
252
|
|
|
|
|
|
|
# = 4*2^(k-2) - 2^(k-2) + 1 |
|
253
|
|
|
|
|
|
|
# = 3*2^(k-2) + 1 |
|
254
|
|
|
|
|
|
|
# k=2 3*2^(2-2)+1=4 len=4^2=16 |
|
255
|
|
|
|
|
|
|
# k=3 3*2^(3-2)+1=7 len=4^3=64 |
|
256
|
|
|
|
|
|
|
# k=4 3*2^(4-2)+1=13 |
|
257
|
|
|
|
|
|
|
# 2^(k-2) = (dist-1)/3 |
|
258
|
|
|
|
|
|
|
# 2^k = (dist-1)*4/3 |
|
259
|
|
|
|
|
|
|
# |
|
260
|
|
|
|
|
|
|
# up = 3*2^(k-2+1) + 1 |
|
261
|
|
|
|
|
|
|
# 2^(k+1) = (dist-1)*4/3 |
|
262
|
|
|
|
|
|
|
# 2^k = (dist-1)*2/3 |
|
263
|
|
|
|
|
|
|
# |
|
264
|
|
|
|
|
|
|
# left = 3*2^(k-2+1) + 1 |
|
265
|
|
|
|
|
|
|
# 2^(k+1) = (dist-1)*4/3 |
|
266
|
|
|
|
|
|
|
# 2^k = (dist-1)*2/3 |
|
267
|
|
|
|
|
|
|
# |
|
268
|
|
|
|
|
|
|
# down = 3*2^(k-2+1) + 1 |
|
269
|
|
|
|
|
|
|
# 2^(k+1) = (dist-1)*4/3 |
|
270
|
|
|
|
|
|
|
# 2^k = (dist-1)*2/3 |
|
271
|
|
|
|
|
|
|
# |
|
272
|
|
|
|
|
|
|
# m=2 4*(2-1)/3=4/3=1 |
|
273
|
|
|
|
|
|
|
# m=4 4*(4-1)/3=4 |
|
274
|
|
|
|
|
|
|
sub _rect_to_k { |
|
275
|
5
|
|
|
5
|
|
12
|
my ($x1,$y1, $x2,$y2) = @_; |
|
276
|
|
|
|
|
|
|
### _rect_to_k(): $x1,$y1 |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
{ |
|
279
|
5
|
|
|
|
|
26
|
my $m = max(abs($x1),abs($y1),abs($x2),abs($y2)); |
|
|
5
|
|
|
|
|
21
|
|
|
280
|
5
|
50
|
|
|
|
12
|
if ($m < 2) { |
|
281
|
0
|
|
|
|
|
0
|
return (2, 1); |
|
282
|
|
|
|
|
|
|
} |
|
283
|
5
|
50
|
|
|
|
11
|
if ($m < 4) { |
|
284
|
0
|
|
|
|
|
0
|
return (4, 2); |
|
285
|
|
|
|
|
|
|
} |
|
286
|
|
|
|
|
|
|
### round_down: 4*($m-1)/3 |
|
287
|
5
|
|
|
|
|
21
|
my ($len, $k) = round_down_pow (4*($m-1)/3, 2); |
|
288
|
5
|
|
|
|
|
16
|
return ($len, $k); |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
0
|
|
|
|
|
0
|
my $len; |
|
292
|
0
|
|
|
|
|
0
|
my $k = 0; |
|
293
|
|
|
|
|
|
|
|
|
294
|
0
|
|
|
|
|
0
|
my $offset = -1; |
|
295
|
0
|
|
|
|
|
0
|
foreach my $m ($x2, $y2, -$x1, -$y1) { |
|
296
|
0
|
|
|
|
|
0
|
$offset++; |
|
297
|
|
|
|
|
|
|
### $offset |
|
298
|
|
|
|
|
|
|
### $m |
|
299
|
0
|
0
|
|
|
|
0
|
next if $m < 0; |
|
300
|
|
|
|
|
|
|
|
|
301
|
0
|
|
|
|
|
0
|
my ($len1, $k1); |
|
302
|
|
|
|
|
|
|
# if ($m < 2) { |
|
303
|
|
|
|
|
|
|
# $len1 = 1; |
|
304
|
|
|
|
|
|
|
# $k1 = 0; |
|
305
|
|
|
|
|
|
|
# } else { |
|
306
|
|
|
|
|
|
|
# } |
|
307
|
|
|
|
|
|
|
|
|
308
|
0
|
|
|
|
|
0
|
($len1, $k1) = round_down_pow (($m-1)/3, 2); |
|
309
|
0
|
0
|
|
|
|
0
|
next if $k1 < $offset; |
|
310
|
0
|
|
|
|
|
0
|
my $sub = ($offset-$k1) % 4; |
|
311
|
0
|
|
|
|
|
0
|
$k1 -= $sub; # round down to k1 == offset mod 4 |
|
312
|
|
|
|
|
|
|
|
|
313
|
0
|
0
|
|
|
|
0
|
if ($k1 > $k) { |
|
314
|
0
|
|
|
|
|
0
|
$k = $k1; |
|
315
|
0
|
|
|
|
|
0
|
$len = $len1 / 2**$sub; |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
### result: "k=$k len=$len" |
|
320
|
0
|
|
|
|
|
0
|
return ($len, 2*$k); |
|
321
|
|
|
|
|
|
|
} |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
my @dir4_to_dx = (1,0,-1,0); |
|
326
|
|
|
|
|
|
|
my @dir4_to_dy = (0,1,0,-1); |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# Not yet supporting "arms" parameter ... |
|
329
|
|
|
|
|
|
|
sub n_to_dxdy { |
|
330
|
2530
|
|
|
2530
|
1
|
49550
|
my ($self, $n) = @_; |
|
331
|
|
|
|
|
|
|
### n_to_dxdy(): $n |
|
332
|
|
|
|
|
|
|
|
|
333
|
2530
|
100
|
|
|
|
4445
|
if ($n < 0) { return; } |
|
|
3
|
|
|
|
|
18
|
|
|
334
|
2527
|
50
|
|
|
|
4415
|
if (is_infinite($n)) { return ($n,$n); } |
|
|
0
|
|
|
|
|
0
|
|
|
335
|
2527
|
|
|
|
|
4096
|
my $int = int($n); |
|
336
|
2527
|
|
|
|
|
3406
|
$n -= $int; # $n fraction part |
|
337
|
|
|
|
|
|
|
|
|
338
|
2527
|
|
|
|
|
4451
|
my @digits = bit_split_lowtohigh($int); |
|
339
|
2527
|
|
100
|
|
|
10986
|
my $dir = (sum(@digits)||0) & 3; # count of 1-bits |
|
340
|
2527
|
|
|
|
|
3862
|
my $dx = $dir4_to_dx[$dir]; |
|
341
|
2527
|
|
|
|
|
3319
|
my $dy = $dir4_to_dy[$dir]; |
|
342
|
|
|
|
|
|
|
|
|
343
|
2527
|
100
|
|
|
|
4059
|
if ($n) { |
|
344
|
|
|
|
|
|
|
# apply fraction part $n |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# count low 1-bits is right turn of N+1, apply as dir-(turn-1) so decr $dir |
|
347
|
8
|
|
|
|
|
17
|
while (shift @digits) { |
|
348
|
8
|
|
|
|
|
15
|
$dir--; |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# this with turn=count-1 turn which is dir++ worked into swap and negate |
|
352
|
|
|
|
|
|
|
# of dir4_to_dy parts |
|
353
|
8
|
|
|
|
|
16
|
$dir &= 3; |
|
354
|
8
|
|
|
|
|
21
|
$dx -= $n*($dir4_to_dy[$dir] + $dx); # with rot-90 instead of $dir+1 |
|
355
|
8
|
|
|
|
|
16
|
$dy += $n*($dir4_to_dx[$dir] - $dy); |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# this the equivalent with explicit dir++ for turn=count-1 |
|
358
|
|
|
|
|
|
|
# $dir++; |
|
359
|
|
|
|
|
|
|
# $dir &= 3; |
|
360
|
|
|
|
|
|
|
# $dx += $n*($dir4_to_dx[$dir] - $dx); |
|
361
|
|
|
|
|
|
|
# $dy += $n*($dir4_to_dy[$dir] - $dy); |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
### result: "$dx, $dy" |
|
365
|
2527
|
|
|
|
|
7178
|
return ($dx,$dy); |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
369
|
|
|
|
|
|
|
# k even |
|
370
|
|
|
|
|
|
|
# S[h] |
|
371
|
|
|
|
|
|
|
# --------- |
|
372
|
|
|
|
|
|
|
# / \ Z[h-1] |
|
373
|
|
|
|
|
|
|
# / \ |
|
374
|
|
|
|
|
|
|
# | | S[h-1] |
|
375
|
|
|
|
|
|
|
# \ / Z[h-2] |
|
376
|
|
|
|
|
|
|
# -- -- |
|
377
|
|
|
|
|
|
|
# Hb[k] = S[h] + 2*S[h-1] + S[h] + 2*(Z[h-1]/2 - Z[h-2]/2) |
|
378
|
|
|
|
|
|
|
# + sqrt(2)*(2*Z[h-1]/2 + 2*Z[h-2]/2) |
|
379
|
|
|
|
|
|
|
# = 2*S[h] + 2*S[h-1] + Z[h-1]-Z[h-2] + sqrt(2) * (Z[h-1] + Z[h-2]) |
|
380
|
|
|
|
|
|
|
# = 2*2^h + 2*2^(h-1) + 2*2^(h-1)-2 - (2*2^(h-2)-2) + sqrt(2) * (2*2^(h-1)-2 + 2*2^(h-2)-2) |
|
381
|
|
|
|
|
|
|
# = 3*2^h + 2*2^(h-1)-2 - 2*2^(h-2) + 2 + sqrt(2) * (3*2^(h-1) - 4) |
|
382
|
|
|
|
|
|
|
# = 3*2^h + 2^(h-1) + sqrt(2) * (3*2^(h-1) - 4) |
|
383
|
|
|
|
|
|
|
# = 7*2^(h-1) + sqrt(2) * (3*2^(h-1) - 4) |
|
384
|
|
|
|
|
|
|
# = 7*sqrt(2)^(2h-2) + sqrt(2) * (3*sqrt(2)^(2h-2) - 4) |
|
385
|
|
|
|
|
|
|
# = 7*sqrt(2)^(k-2) + sqrt(2) * (3*sqrt(2)^(k-2) - 4) |
|
386
|
|
|
|
|
|
|
# = 7*sqrt(2)^(k-2) + sqrt(2)*3*sqrt(2)^(k-2) - 4*sqrt(2) |
|
387
|
|
|
|
|
|
|
# = 7*sqrt(2)^(k-2) + 3*sqrt(2)*sqrt(2)^(k-2) - 4*sqrt(2) |
|
388
|
|
|
|
|
|
|
# = (7 + 3*sqrt(2))*sqrt(2)^(k-2) - 4*sqrt(2) |
|
389
|
|
|
|
|
|
|
# |
|
390
|
|
|
|
|
|
|
# S[2]=4 |
|
391
|
|
|
|
|
|
|
# 11--10--7,9--6---5 Z[1]=2 k=4 h=2 |
|
392
|
|
|
|
|
|
|
# | | | |
|
393
|
|
|
|
|
|
|
# 13--12 8 4---3 4 + 2*2 + 4+(2-0) = 14 |
|
394
|
|
|
|
|
|
|
# | | S[1]=2 (2+0) = 2 |
|
395
|
|
|
|
|
|
|
# 14 2 |
|
396
|
|
|
|
|
|
|
# | | |
|
397
|
|
|
|
|
|
|
# 15---16 0---1 Z[0] = 0 |
|
398
|
|
|
|
|
|
|
# |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
# k odd |
|
401
|
|
|
|
|
|
|
# S[h] |
|
402
|
|
|
|
|
|
|
# ---- |
|
403
|
|
|
|
|
|
|
# Z[h-1] / \ middle Z[h] |
|
404
|
|
|
|
|
|
|
# S[h-1] | \ |
|
405
|
|
|
|
|
|
|
# \ \ |
|
406
|
|
|
|
|
|
|
# | S[h] |
|
407
|
|
|
|
|
|
|
# | |
|
408
|
|
|
|
|
|
|
# \ / Z[h-1] |
|
409
|
|
|
|
|
|
|
# -- |
|
410
|
|
|
|
|
|
|
# S[h-1] |
|
411
|
|
|
|
|
|
|
# |
|
412
|
|
|
|
|
|
|
# Hb[k] = 2*S[h] + 2*S[h-1] + sqrt(2)*( Z[h]/2 + Z[h-1] + Z[h]/2 + S[h]-S[h-1] ) |
|
413
|
|
|
|
|
|
|
# = 2*S[h] + 2*S[h-1] + sqrt(2)*( Z[h] + Z[h-1] + S[h]-S[h-1] ) |
|
414
|
|
|
|
|
|
|
# = 2*2^h + 2*2^(h-1) + sqrt(2)*( 2*2^h-2 + 2*2^(h-1)-2 + 2^h - 2^(h-1) ) |
|
415
|
|
|
|
|
|
|
# = 3*2^h + sqrt(2)*( 3*2^h + 2^(h-1) - 4 ) |
|
416
|
|
|
|
|
|
|
# = 3*2^h + sqrt(2)*( 7*2^(h-1) - 4 ) |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
sub _UNDOCUMENTED_level_to_hull_boundary { |
|
419
|
0
|
|
|
0
|
|
|
my ($self, $level) = @_; |
|
420
|
0
|
0
|
|
|
|
|
my ($a, $b) = $self->_UNDOCUMENTED_level_to_hull_boundary_sqrt2($level) |
|
421
|
|
|
|
|
|
|
or return undef; |
|
422
|
0
|
|
|
|
|
|
return $a + $b*sqrt(2); |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
sub _UNDOCUMENTED_level_to_hull_boundary_sqrt2 { |
|
425
|
0
|
|
|
0
|
|
|
my ($self, $level) = @_; |
|
426
|
0
|
0
|
|
|
|
|
if ($level <= 2) { |
|
427
|
0
|
0
|
|
|
|
|
if ($level < 0) { return; } |
|
|
0
|
|
|
|
|
|
|
|
428
|
0
|
0
|
|
|
|
|
if ($level == 2) { return (6,0); } |
|
|
0
|
|
|
|
|
|
|
|
429
|
0
|
0
|
|
|
|
|
return (2, ($level == 0 ? 0 : 1)); |
|
430
|
|
|
|
|
|
|
} |
|
431
|
|
|
|
|
|
|
|
|
432
|
0
|
|
|
|
|
|
my ($h, $rem) = _divrem($level, 2); |
|
433
|
0
|
|
|
|
|
|
my $pow = 2**($h-1); |
|
434
|
|
|
|
|
|
|
|
|
435
|
0
|
0
|
|
|
|
|
if ($rem) { |
|
436
|
0
|
|
|
|
|
|
return (6*$pow, 7*$pow-4); |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
# return (2*S_formula($h) + 2*S_formula($h-1), |
|
439
|
|
|
|
|
|
|
# Z_formula($h)/2 + Z_formula($h-1) |
|
440
|
|
|
|
|
|
|
# + Z_formula($h)/2 + (S_formula($h)-S_formula($h-1)) ); |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
} else { |
|
443
|
0
|
|
|
|
|
|
return (7*$pow, 3*$pow-4); |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
# return (S_formula($h) + 2*S_formula($h-1) + S_formula($h)+(Z_formula($h-1)-Z_formula($h-2)), |
|
446
|
|
|
|
|
|
|
# (Z_formula($h-1) + Z_formula($h-2))); |
|
447
|
|
|
|
|
|
|
} |
|
448
|
|
|
|
|
|
|
} |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
451
|
|
|
|
|
|
|
{ |
|
452
|
|
|
|
|
|
|
my @_UNDOCUMENTED_level_to_hull_area = (0, 1/2, 2); |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
sub _UNDOCUMENTED_level_to_hull_area { |
|
455
|
0
|
|
|
0
|
|
|
my ($self, $level) = @_; |
|
456
|
|
|
|
|
|
|
|
|
457
|
0
|
0
|
|
|
|
|
if ($level < 3) { |
|
458
|
0
|
0
|
|
|
|
|
if ($level < 0) { return undef; } |
|
|
0
|
|
|
|
|
|
|
|
459
|
0
|
|
|
|
|
|
return $_UNDOCUMENTED_level_to_hull_area[$level]; |
|
460
|
|
|
|
|
|
|
} |
|
461
|
0
|
|
|
|
|
|
my ($h, $rem) = _divrem($level, 2); |
|
462
|
0
|
0
|
|
|
|
|
return 35*2**($level-4) - ($rem ? 13 : 10)*2**($h-1) + 2; |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
# if ($rem) { |
|
465
|
|
|
|
|
|
|
# return 35*2**($level-4) - 13*$pow + 2; |
|
466
|
|
|
|
|
|
|
# |
|
467
|
|
|
|
|
|
|
# my $width = S_formula($h) + Z_formula($h)/2 + Z_formula($h-1)/2; |
|
468
|
|
|
|
|
|
|
# my $ul = Z_formula($h-1)/2; |
|
469
|
|
|
|
|
|
|
# my $ur = Z_formula($h)/2; |
|
470
|
|
|
|
|
|
|
# my $bl = $width - Z_formula($h-1)/2 - S_formula($h-1); |
|
471
|
|
|
|
|
|
|
# my $br = Z_formula($h-1)/2; |
|
472
|
|
|
|
|
|
|
# return $width**2 - $ul**2/2 - $ur**2/2 - $bl**2/2 - $br**2/2; |
|
473
|
|
|
|
|
|
|
# |
|
474
|
|
|
|
|
|
|
# } else { |
|
475
|
|
|
|
|
|
|
# return 35*2**($level-4) - 10*$pow + 2; |
|
476
|
|
|
|
|
|
|
# return 0; |
|
477
|
|
|
|
|
|
|
# return 35*2**($level-4) - 5*2**$h + 2; |
|
478
|
|
|
|
|
|
|
# |
|
479
|
|
|
|
|
|
|
# # my $width = S_formula($h) + Z_formula($h-1); |
|
480
|
|
|
|
|
|
|
# # my $upper = Z_formula($h-1)/2; |
|
481
|
|
|
|
|
|
|
# # my $lower = Z_formula($h-2)/2; |
|
482
|
|
|
|
|
|
|
# # my $height = S_formula($h-1) + $upper + $lower; |
|
483
|
|
|
|
|
|
|
# # return $width; # * $height - $upper*$upper - $lower*$lower; |
|
484
|
|
|
|
|
|
|
# } |
|
485
|
|
|
|
|
|
|
# } |
|
486
|
|
|
|
|
|
|
} |
|
487
|
|
|
|
|
|
|
} |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
490
|
|
|
|
|
|
|
# levels |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
sub level_to_n_range { |
|
493
|
0
|
|
|
0
|
1
|
|
my ($self, $level) = @_; |
|
494
|
0
|
|
|
|
|
|
return (0, 2**$level); |
|
495
|
|
|
|
|
|
|
} |
|
496
|
|
|
|
|
|
|
sub n_to_level { |
|
497
|
0
|
|
|
0
|
1
|
|
my ($self, $n) = @_; |
|
498
|
0
|
0
|
|
|
|
|
if ($n < 0) { return undef; } |
|
|
0
|
|
|
|
|
|
|
|
499
|
0
|
0
|
|
|
|
|
if (is_infinite($n)) { return $n; } |
|
|
0
|
|
|
|
|
|
|
|
500
|
0
|
|
|
|
|
|
$n = round_nearest($n); |
|
501
|
0
|
|
|
|
|
|
my ($pow, $exp) = round_up_pow ($n, 2); |
|
502
|
0
|
|
|
|
|
|
return $exp; |
|
503
|
|
|
|
|
|
|
} |
|
504
|
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
506
|
|
|
|
|
|
|
1; |
|
507
|
|
|
|
|
|
|
__END__ |