Class NumberPairing
java.lang.Object
com.github.yellowstonegames.grid.NumberPairing
Utility functions for pairing (and tripling) functions, which take two (or three) numbers, typically
The classic example of a pairing function is the Cantor pairing function, which assigns increasing results to pairs of ints, with the "shell" based on the sum of the two inputs. Another, lesser-known example is the Rosenberg-Strong pairing function, which has its "shell" based on the greater of the two inputs. The Cantor pairing function forms right-triangle shapes for its shells, whereas the Rosenberg-Strong pairing function forms squares.
ints,
and return an int with magnitude dependent on the input number with maximum magnitude. The results can be organized
into "shells" (also called "gnomons") based on the scale of the inputs; if any input is very large, the shell will
be very far from the origin, but if all inputs are small, the shell will be closer to the origin. All pairing
functions map each unique pair of valid inputs to one valid output, where valid inputs must be in a particular range.
This also permits an inverse to exist for any pairing function, which takes one number and produces two results.
Here, the inverses mutate a Point2Int or Point3Int to avoid allocating a new object every time.
The classic example of a pairing function is the Cantor pairing function, which assigns increasing results to pairs of ints, with the "shell" based on the sum of the two inputs. Another, lesser-known example is the Rosenberg-Strong pairing function, which has its "shell" based on the greater of the two inputs. The Cantor pairing function forms right-triangle shapes for its shells, whereas the Rosenberg-Strong pairing function forms squares.
-
Method Summary
Modifier and TypeMethodDescriptionstatic intcantor(int x, int y) static Point2IntcantorInverse(Point2Int p, int d) Inverse of the 2D Cantor pairing function.static intpers(int x, int y, int z) 3D Pigeon-Ettinger-Rosenberg-Strong Triple (PERS) function.static Point3IntpersInverse(Point3Int p, int d) Inverse of the 3D Pigeon-Ettinger-Rosenberg-Strong (PERS) Triple function.static introsenbergStrong(int x, int y) 2D Rosenberg-Strong pairing function.static Point2IntrosenbergStrongInverse(Point2Int p, int d) Inverse of the 2D Rosenberg-Strong pairing function.static intszudzik(int x, int y) 2D Szudzik Elegant pairing function.static Point2IntszudzikInverse(Point2Int p, int d) Inverse of the 2D Szudzik Elegant pairing function.static intwindingRosenbergStrong(int x, int y) 2D Boustrophedonic ("ox-turning", or "sidewinding") Rosenberg-Strong pairing function.static Point2IntwindingRosenbergStrongInverse(Point2Int p, int d) Inverse of the 2D Boustrophedonic ("ox-turning", or "sidewinding") Rosenberg-Strong pairing function.
-
Method Details
-
cantor
public static int cantor(int x, int y) 2D Cantor pairing function. This is a way of getting a unique int result for small enough x and y values, where "small enough" can safely be considered "between 0 and 32766." This can overflow if the sum of x and y is greater than 65533, so it can't reasonably deal with all int inputs. This is permitted to have adjacent results "jump" from non-adjacent inputs, but only when the shell changes. The shell is defined as the sum of x and y. Adjacency here permits diagonal movement.- Parameters:
x- non-negative horizontal input, between 0 and 32766, inclusivey- non-negative vertical input, between 0 and 32766, inclusive- Returns:
- pair of x and y as one int via the Cantor pairing function
-
cantorInverse
Inverse of the 2D Cantor pairing function.- Parameters:
p- a point that will have its contents overwritten with the decoded x and y of the given distanced- pair of x and y via the Cantor function, from the origin, between 0 and 2147385344, inclusive- Returns:
p, after modifications
-
rosenbergStrong
public static int rosenbergStrong(int x, int y) 2D Rosenberg-Strong pairing function. See Steven Pigeon's blog. This is permitted to have adjacent results "jump" from non-adjacent inputs, but only when the shell changes. The shell is defined as the greater of x and y. Adjacency here does not permit diagonal movement.- Parameters:
x- non-negative horizontal input, between 0 and 46339, inclusivey- non-negative vertical input, between 0 and 46339, inclusive- Returns:
- pair of x and y as one int via the Rosenberg-Strong function
-
rosenbergStrongInverse
Inverse of the 2D Rosenberg-Strong pairing function. See Steven Pigeon's blog.- Parameters:
p- a point that will have its contents overwritten with the decoded x and y of the given distanced- pair of x and y via the Rosenberg-Strong function, from the origin, between 0 and 2147395599, inclusive- Returns:
p, after modifications
-
windingRosenbergStrong
public static int windingRosenbergStrong(int x, int y) 2D Boustrophedonic ("ox-turning", or "sidewinding") Rosenberg-Strong pairing function. See Steven Pigeon's blog. All adjacent results will come from adjacent inputs, even when the shell changes. The shell is defined as the greater of x and y. Adjacency here does not permit diagonal movement.- Parameters:
x- non-negative horizontal input, between 0 and 46339, inclusivey- non-negative vertical input, between 0 and 46339, inclusive- Returns:
- distance on the Boustrophedonic Rosenberg-Strong curve, from the origin
-
windingRosenbergStrongInverse
Inverse of the 2D Boustrophedonic ("ox-turning", or "sidewinding") Rosenberg-Strong pairing function. See Steven Pigeon's blog.- Parameters:
p- a point that will have its contents overwritten with the decoded x and y of the given distanced- the distance on the Boustrophedonic Rosenberg-Strong curve, from the origin, between 0 and 2147395599, inclusive- Returns:
p, after modifications
-
szudzik
public static int szudzik(int x, int y) 2D Szudzik Elegant pairing function. See Wikipedia. This pairing function does not guarantee that results in the same shell will be adjacent for adjacent inputs; that is, it is permitted to "jump" even within a shell.- Parameters:
x- non-negative horizontal input, between 0 and 46339, inclusivey- non-negative vertical input, between 0 and 46339, inclusive- Returns:
- pair of x and y as one int via the Szudzik Elegant function
-
szudzikInverse
Inverse of the 2D Szudzik Elegant pairing function. See Wikipedia.- Parameters:
p- a point that will have its contents overwritten with the decoded x and y of the given distanced- pair of x and y via the Szudzik Elegant function, from the origin, between 0 and 2147395599, inclusive- Returns:
p, after modifications
-
pers
public static int pers(int x, int y, int z) 3D Pigeon-Ettinger-Rosenberg-Strong Triple (PERS) function. This gets a single integer that encodes three non-negative ints (between 0 and 1289, inclusive) into one distance along a space-filling curve starting at (0,0,0). The curve is organized into cube-shaped "shells" or "gnomons," each shell being completely returned before an outer shell can be returned. That is, the distance to a point inside a cube will always be less than the distance to a point that is outside that cube (if both have inputs that are in range). Two different shells will connect at one of two edges, either y=0,z=0 for an even shell connecting to a larger odd shell, or z=0,y=0 for an odd shell connecting to a larger even shell.
Notably, the distance will always be less thanMath.pow(Math.max(x, Math.max(y, z)) + 1, 3)for inputs that are in range. All adjacent results will come from adjacent inputs, even when the shell changes. The shell is defined as the greater of x, y, and z. Adjacency here does not permit diagonal movement.
This is based on a boustrophedonic Rosenberg-Strong pairing function (see Steven Pigeon's blog for more), but extended to three dimensions. The blog post suggests using the pair of x with the pair of y and z as a triple function, but that doesn't act like the 2D pairing function regarding shells.
"We could, of course, devise some complicated function for 3..." -- Steven Pigeon
"Yes! It works!" -- Tommy Ettinger- Parameters:
x- 3D coordinate, between 0 and 1289, inclusivey- 3D coordinate, between 0 and 1289, inclusivez- 3D coordinate, between 0 and 1289, inclusive- Returns:
- the distance along a space-filling curve from the origin to the given point.
-
persInverse
Inverse of the 3D Pigeon-Ettinger-Rosenberg-Strong (PERS) Triple function. This takes a single doubledfor distance and aPoint3Intpthat will be modified in-place, and sets p to hold the coordinates of the point at distanceMath.floor(d)along the Pigeon-Ettinger-Rosenberg-Strong space-filling curve, starting at the origin (0,0,0). The curve is organized into cube-shaped "shells" or "gnomons," each shell being completely returned before an outer shell can be returned. That is, the distance to a point inside a cube will always be less than the distance to a point that is outside that cube (if both have inputs that are in range). Two different shells will connect at one of two edges, either y=0,z=0 for an even shell connecting to a larger odd shell, or z=0,y=0 for an odd shell connecting to a larger even shell.
Notably, the distance will always be less thanMath.pow(Math.max(x, Math.max(y, z)) + 1, 3)for inputs that are between 0 and 2146688999, inclusive.
This is based on a boustrophedonic Rosenberg-Strong pairing function (see Steven Pigeon's blog for more), but extended to three dimensions. The blog post suggests using the pair of x with the pair of y and z as a triple function, but that doesn't act like the 2D pairing function regarding shells.
"We could, of course, devise some complicated function for 3..." -- Steven Pigeon
"Yes! It works!" -- Tommy Ettinger- Parameters:
p- a non-null Point3Int that will be modified in-placed- the distance along the space-filling curve from the origin, between 0 and 2146688999, inclusive- Returns:
p, containing the point at distancedalong the curve
-