# NAME

Math::PlanePath::ImaginaryHalf -- half-plane replications in three directions

# SYNOPSIS

`````` use Math::PlanePath::ImaginaryBase;
my \$path = Math::PlanePath::ImaginaryBase->new (radix => 4);
my (\$x, \$y) = \$path->n_to_xy (123);``````

# DESCRIPTION

This is a half-plane variation on the `ImaginaryBase` path.

``````     54-55 50-51 62-63 58-59 22-23 18-19 30-31 26-27       3
\     \     \     \     \     \     \     \
52-53 48-49 60-61 56-57 20-21 16-17 28-29 24-25       2

38-39 34-35 46-47 42-43  6--7  2--3 14-15 10-11       1
\     \     \     \     \     \     \     \
36-37 32-33 44-45 40-41  4--5  0--1 12-13  8--9   <- Y=0

-------------------------------------------------
-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 X=0 1  2  3  4  5``````

The pattern can be seen by dividing into blocks,

``````    +---------------------------------+
| 22  23  18  19   30  31  26  27 |
|                                 |
| 20  21  16  17   28  29  24  25 |
+--------+-------+----------------+
|  6   7 | 2   3 | 14  15  10  11 |
|        +---+---+                |
|  4   5 | 0 | 1 | 12  13   8   9 |  <- Y=0
+--------+---+---+----------------+
^
X=0``````

N=0 is at the origin, then N=1 replicates it to the right. Those two repeat above as N=2 and N=3. Then that 2x2 repeats to the left as N=4 to N=7, then 4x2 repeats to the right as N=8 to N=15, and 8x2 above as N=16 to N=31, etc. The replications are successively to the right, above, left. The relative layout within a replication is unchanged.

This is similar to the `ImaginaryBase`, but where it repeats in 4 directions there's just 3 directions here. The `ZOrderCurve` is a 2 direction replication.

The `radix` parameter controls the radix used to break N into X,Y. For example `radix => 4` gives 4x4 blocks, with radix-1 replications of the preceding level at each stage.

``````     radix => 4

60 61 62 63 44 45 46 47 28 29 30 31 12 13 14 15      3
56 57 58 59 40 41 42 43 24 25 26 27  8  9 10 11      2
52 53 54 55 36 37 38 39 20 21 22 23  4  5  6  7      1
48 49 50 51 32 33 34 35 16 17 18 19  0  1  2  3  <- Y=0

--------------------------------------^-----------
-12-11-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 X=0 1  2  3``````

Notice for X negative the parts replicate successively towards -infinity, so the block N=16 to N=31 is first at X=-4, then N=32 at X=-8, N=48 at X=-12, and N=64 at X=-16 (not shown).

## Digit Order

The `digit_order` parameter controls the order digits from N are applied to X and Y. The default above is "XYX" so the replications go X then Y then negative X.

"XXY" goes to negative X before Y, so N=2,N=3 goes to negative X before repeating N=4 to N=7 in the Y direction.

``````    digit_order => "XXY"

38  39  36  37  46  47  44  45
34  35  32  33  42  43  40  41
6   7   4   5  14  15  12  13
2   3   0   1  10  11   8   9
---------^--------------------
-2  -1  X=0  1   2   3   4   5``````

The further options are as follows, for six permutations of each 3 digits from N.

``````    digit_order => "YXX"               digit_order => "XnYX"
38 39 36 37 46 47 44 45            19 23 18 22 51 55 50 54
34 35 32 33 42 43 40 41            17 21 16 20 49 53 48 52
6  7  4  5 14 15 12 13             3  7  2  6 35 39 34 38
2  3  0  1 10 11  8  9             1  5  0  4 33 37 32 36

digit_order => "XnXY"              digit_order => "YXnX"
37 39 36 38 53 55 52 54            11 15  9 13 43 47 41 45
33 35 32 34 49 51 48 50            10 14  8 12 42 46 40 44
5  7  4  6 21 23 20 22             3  7  1  5 35 39 33 37
1  3  0  2 17 19 16 18             2  6  0  4 34 38 32 36``````

"Xn" means the X negative direction. It's still spaced 2 apart (or whatever radix), so the result is not simply a -X,Y.

## Axis Values

N=0,1,4,5,8,9,etc on the X axis (positive and negative) are those integers with a 0 at every third bit starting from the second least significant bit. This is simply demanding that the bits going to the Y coordinate must be 0.

``````    X axis Ns = binary ...__0__0__0_     with _ either 0 or 1
in octal, digits 0,1,4,5 only``````

N=0,1,8,9,etc on the X positive axis have the highest 1-bit in the first slot of a 3-bit group. Or N=0,4,5,etc on the X negative axis have the high 1 bit in the third slot,

``````    X pos Ns = binary    1_0__0__0...0__0__0_
X neg Ns = binary  10__0__0__0...0__0__0_
^^^
three bit group

X pos Ns in octal have high octal digit 1
X neg Ns in octal high octal digit 4 or 5``````

N=0,2,16,18,etc on the Y axis are conversely those integers with a 0 in two of each three bits, demanding the bits going to the X coordinate must be 0.

``````    Y axis Ns = binary ..._00_00_00_0    with _ either 0 or 1
in octal has digits 0,2 only``````

For a radix other than binary the pattern is the same. Each "_" is any digit of the given radix, and each 0 must be 0. The high 1 bit for X positive and negative become a high non-zero digit.

## Level Ranges

Because the X direction replicates twice for each once in the Y direction the width grows at twice the rate, so after each 3 replications

``    width = height*height``

For this reason N values for a given Y grow quite rapidly.

## Proth Numbers

The Proth numbers, k*2^n+1 for k<2^n, fall in columns on the path.

``````    *                               *                               *

*                               *                               *

*                               *                               *

*               *               *               *               *

*               *               *               *               *

*       *       *       *

*       *       *       *       *       *       *       *       *

*   *   *   *   *       *
*
*       *       *       *   * *   * *   *       *       *       *

-----------------------------------------------------------------
-31    -23     -15     -7  -3-1 0 3 5   9      17       25     33``````

The height of the column is from the zeros in X ending binary ...1000..0001 since this limits the "k" part of the Proth numbers which can have N ending suitably. Or for X negative ending ...10111...11.

# FUNCTIONS

See "FUNCTIONS" in Math::PlanePath for behaviour common to all path classes.

`\$path = Math::PlanePath::ImaginaryBase->new ()`
`\$path = Math::PlanePath::ImaginaryBase->new (radix => \$r, digit_order => \$str)`

Create and return a new path object. The choices for `digit_order` are

``````    "XYX"
"XXY"
"YXX"
"XnYX"
"XnXY"
"YXnX"``````
`(\$x,\$y) = \$path->n_to_xy (\$n)`

Return the X,Y coordinates of point number `\$n` on the path. Points begin at 0 and if `\$n < 0` then the return is an empty list.

`(\$n_lo, \$n_hi) = \$path->rect_to_n_range (\$x1,\$y1, \$x2,\$y2)`

The returned range is exact, meaning `\$n_lo` and `\$n_hi` are the smallest and biggest in the rectangle.

## Level Methods

`(\$n_lo, \$n_hi) = \$path->level_to_n_range(\$level)`

Return `(0, \$radix**\$level - 1)`.

http://user42.tuxfamily.org/math-planepath/index.html