Math::...Octant(3pm)
๐ธ NAME ๐ธ
okay so welcome to the manual page for Math::...Octant(3pm), bestie ๐
Math::PlanePath::DiagonalsOctant โ points in diagonal stripes for an eighth of the plane โจ
๐ฆ SYNOPSIS ๐ฆ
use Math::PlanePath::DiagonalsOctant;
my $path = Math::PlanePath::DiagonalsOctant->new;
my ($x, $y) = $path->n_to_xy (123);
๐ DESCRIPTION ๐
so the vibe is: this path walks successive diagonals downwards from the Y axis all the way down to the X=Y centre line, cruising through the eighth of the plane that sits on and above X=Y. it's giving orderly. it's giving diagonal. ๐ฅ
8 | 21 27 33 40 47 55 63 72 81
| \ \ \ \ \ \ \
7 | 17 22 28 34 41 48 56 64
| \ \ \ \ \ \
6 | 13 18 23 29 35 42 49
| \ \ \ \ \
5 | 10 14 19 24 30 36
| \ \ \ \
4 | 7 11 15 20 25
| \ \ \
3 | 5 8 12 16
| \ \
2 | 3 6 9
| \
1 | 2 4
|
Y=0 | 1
+ ----------------------------
X=0 1 2 3 4 5 6 7 8
N=1,4,9,16,etc sitting right on the X=Y leading diagonal? those are the perfect squares ๐ and N=2,6,12,20,etc chilling at the ends of the other diagonals are the pronic numbers k*(k+1). math ate, no cap ๐
fun little aside: "octant" normally means an eighth of a 3-dimensional coordinate space. but since PlanePath is only 2 dimensions there's zero confusion, and at the risk of abusing nomenclature, half a quadrant gets reckoned as an "octant" here ๐
๐ Pyramid Rows ๐
ok so take two diagonals running from k^2+1 to (k+1)^2 โ that's literally the same thing as a row of the step=2 PyramidRows (peep Math::PlanePath::PyramidRows). each endpoint is identical, except here it's two diagonals instead of one row. for example, in PyramidRows the Y=3 row runs from N=10 to N=16, ending at X=3,Y=3. here that same thing is two diagonals โ N=10 to N=12 and then N=13 to N=16 โ and that N=16 endpoint is the exact same X=3,Y=3. iconic parallel โจ
๐ง Direction ๐ง
the option direction => 'up' flips the order inside each diagonal and counts upward from the centre out to the Y axis ๐
8 | 25 29 34 39 45 51 58 65 73
| \ \ \ \ \ \ \
7 | 20 24 28 33 38 44 50 57
| \ \ \ \ \ \
6 | 16 19 23 27 32 37 43
| \ \ \ \ \
5 | 12 15 18 22 26 31
| \ \ \ \
4 | 9 11 14 17 21 direction => "up"
| \ \ \
3 | 6 8 10 13
| \ \
2 | 4 5 7
| \
1 | 2 3
|
Y=0 | 1
+---------------------------
X=0 1 2 3 4 5 6 7 8
in this arrangement N=1,2,4,6,9,etc on the Y axis are alternately the squares and the pronic numbers โ squares land on even Y and pronic on odd Y. alternating queen ๐
๐ N Start ๐
default behaviour is numbering points starting at N=1, just like the picture up there. but there's an optional n_start that lets you kick things off somewhere else, keeping the same diagonals sequence. for example, starting at 0:
n_start => 0 n_start=>0
direction => "down" direction=>"up"
6 | 12 | 15
5 | 9 13 | 11 14
4 | 6 10 14 | 8 10 13
3 | 4 7 11 15 | 5 7 9 12
2 | 2 5 8 | 3 4 6
1 | 1 3 | 1 2
Y=0 | 0 | 0
+-------------- +--------------
X=0 1 2 3 X=0 1 2 3
๐ FUNCTIONS ๐
if you want the behaviour that every path class shares, go read "FUNCTIONS" in Math::PlanePath ๐ซถ
$path = Math::PlanePath::DiagonalsOctant->new ()$path = Math::PlanePath::DiagonalsOctant->new (direction => $str, n_start => $n)โ creates and returns a brand new path object. fresh out the box ๐($x,$y) = $path->n_to_xy ($n)โ returns the X,Y coordinates of point number$non the path. โ heads up tho: for"$n < 0.5"the return is an empty list, because the path is considered to begin at 1. no point number 0 energy here ๐$n = $path->xy_to_n ($x,$y)โ returns the point number for coordinates"$x,$y". both$xand$yget rounded to the nearest integer, which has the effect of treating each point$nas a square of side 1. squares within squares, we love a fractal moment ๐ฆ($n_lo, $n_hi) = $path->rect_to_n_range ($x1,$y1, $x2,$y2)โ the returned range is exact, meaning$n_loand$n_hiare genuinely the smallest and biggest values in the rectangle. no approximations, we don't do that here โจ
๐ FORMULAS ๐
๐ธ N to X,Y ๐ธ
to break N into X,Y it's convenient to take two diagonals at a time, since the length then changes by 1 each pair, which makes a quadratic. starting at each X=0,Y=odd just after a perfect square N lets you get away with just a sqrt ๐
Nstart = d*d+1
where d numbers diagonal pairs, eg. d=3 for X=0,Y=5 going down. and this reverses super easily as:
d = floor sqrt(N-1)
the code reckons the start of the diagonal as 0.5 further back, so that N=9.5 sits at X=-.5,Y=5.5. to do that, d gets formed as:
d = floor sqrt(N-0.5)
= int( sqrt(int(4*$n)-2)/2 )
taking the /2 out of the sqrt helps with "Math::BigInt" which circa Perl 5.14 doesn't inter-operate with flonums very well. it's giving compatibility struggles ๐ญ
in any case N-Nstart is an offset into two diagonals โ the first one of length d many points, the second one d+1. for example d=3 starting Y=5 covers points N=10,11,12 followed by Y=6 N=13,14,15,16.
the formulas get simplified by calculating a remainder relative to the second diagonal, so it's negative for the first and positive for the second:
Nrem = N - (d*(d+1)+1)
d*(d+1)+1 is 1 past the pronic numbers when ending each first diagonal, as described above. anyway, for example d=3 is relative to N=13, making Nrem=-3,-2,-1 or Nrem=0,1,2,3.
to include that preceding 0.5 in the second diagonal, it simply means reckoning Nrem>=-0.5 as belonging to the second. in that base:
if Nrem >= -0.5
X = Nrem # direction="down"
Y = 2*d - Nrem
else
X = Nrem + d
Y = d - Nrem - 1
for example N=15 gives Nrem=1 which is the first case, so X=1, Y=2*3-1=5. or N=11 gives Nrem=-2 which is the second case, so X=-2+3=1, Y=3-(-2)-1=4. math checks out bestie ๐งฎ
for "up" direction the Nrem and d are the same, but the coordinate directions reverse:
if Nrem >= -0.5
X = d - Nrem # direction="up"
Y = d + Nrem
else
X = -Nrem - 1
Y = 2d + Nrem
another way is to reckon Nstart from the X=0,Y=even diagonals, which then gives two diagonals of the same length, and d gets formed by a sqrt inverting a pronic Nstart=d*(d+1). two ways to slay the same problem ๐
๐ Rectangle to N Range ๐
within each row, increasing X is increasing N. within each column, increasing Y is increasing N. and this holds true in both the "down" and "up" arrangements. on that basis, in a rectangle the lower left corner is the minimum N and the upper right is the maximum N โจ
if the rectangle is partly outside the covered octant then the corners have to be shifted to put them in range, ie. trim off any rows or columns entirely outside the rectangle. for the lower left this means:
| | /
| | /
+-------- if x1 < 0 then x1 = 0
x1 | / increase x1 to within octant
|/
+
| |/
| | if y1 < x1 then y1 = x1
| /| increase y1 to bottom-left within octant
|/ +----y1
+ x1
and for the top right:
| / x2
| ------+ y2 if x2 > y2 then x2 = y2
| / | decrease x2 so top-right within octant
| / | (the end of the y2 row)
|/
+
๐ฅ OEIS ๐ฅ
entries in Sloane's Online Encyclopedia of Integer Sequences related to this path include:
<http://oeis.org/A055087> (etc)
direction=down
A002620 N at end each run X=k,Y=k and X=k,Y=k+1
direction=down, n_start=0
A055087 X coord, runs 0 to k twice
A082375 Y-X, runs k to 0 or 1 stepping by 2
A005563 N on X=Y diagonal, X*(X+2)
direction=up
A002620 N on Y axis, end of each run, quarter squares
direction=up, n_start=0
A024206 N on Y axis (starting from n=1 is Y=0, so Y=n-1)
A014616 N in column X=1 (is Y axis N-1, from N=3)
A002378 N on X=Y diagonal, pronic X*(X+1)
either direction, n_start=0
A055086 X+Y, k repeating floor(k/2)+1 times
A004652 N start and end of each even-numbered diagonal
A274427 map to N of full Diagonals
permutations
A056536 N of PyramidRows in DiagonalsOctant order
A091995 with DiagonalsOctant direction=up
A091018 N-1, ie. starting from 0
A090894 N-1 and DiagonalsOctant direction=up
A056537 N of DiagonalsOctant at X,Y in PyramidRows order
inverse of A056536
sequence cataloguing is such a mood ๐
โญ SEE ALSO โญ
Math::PlanePath, Math::PlanePath::Diagonals, Math::PlanePath::DiagonalsAlternating, Math::PlanePath::PyramidRows
๐ HOME PAGE ๐
<http://user42.tuxfamily.org/math-planepath/index.html>
๐ LICENSE ๐
Copyright 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Kevin Ryde
This file is part of Math-PlanePath.
Math-PlanePath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Math-PlanePath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. see the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Math-PlanePath. If not, see <http://www.gnu.org/licenses/>.
legal bestie moment: that "no warranty" bit is real and it matters, so don't come for anyone if it breaks ๐
and that's a wrap!! this page was living its best life as perl v5.32.0, dated 2021-01-23, and it's the Math::...Octant(3pm) manual. go build some diagonal stripes, you absolute icon ๐ซถโจ๐
๐ฆ where this page comes from
- debian bookworm: libmath-planepath-perl 129-1 ยท GPL-3.0-or-later
- debian trixie: libmath-planepath-perl 129-1 ยท GPL-3.0-or-later
- ubuntu jammy: libmath-planepath-perl 129-1 ยท GPL-3.0-or-later
- ubuntu noble: libmath-planepath-perl 129-1 ยท GPL-3.0-or-later
- ubuntu resolute: libmath-planepath-perl 129-1 ยท GPL-3.0-or-later
- ubuntu stonking: libmath-planepath-perl 129-1 ยท GPL-3.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms