Background
Complex floor is a domain extension of the mathematical floor function for complex numbers. This is used in some APL languages to implement floor ⌊
, ceiling ⌈
, residue |
, GCD ∨
, and LCM ∧
on complex numbers.
For the rest of this challenge, an integer refers to a Gaussian integer, i.e. a complex number whose real and imaginary parts are integers.
Eugene McDonnell defined seven requirements of a complex floor function (copied from the wiki page, with APL code fragments translated into plain math notation):
- Existence. Every number has a floor.
- Uniqueness. Every number has only one floor.
- Fractionality. The magnitude of the difference of a number and its floor shall be less than one. This property must be satisfied to guarantee that remainders are less in magnitude than divisors. It may be called the fundamental property of the floor function.
- Integrity. The floor of a number is an integer.
- Convexity. If \$g\$ is the floor of the numbers \$z\$ and \$w\$, then it is also the floor of all numbers on the line segment between \$z\$ and \$w\$.
- Integer Translation. For \$c\$ a complex integer, \$c+ \lfloor z \rfloor = \lfloor c+z \rfloor\$.
- Compatibility. The complex floor function is compatible with the real floor function. Furthermore, its action on purely imaginary numbers is similar to the action of the real floor function on real numbers. In particular, \$\operatorname{re}(\lfloor z \rfloor) ≤ \operatorname{re}(\lceil z \rceil)\$ and \$\operatorname{im}(\lfloor z \rfloor) ≤ \operatorname{im}(\lceil z \rceil)\$. (Ceiling for complex numbers is defined as \$\lceil z \rceil = -\lfloor -z \rfloor \$.)
One shape that satisfies these conditions is a rectangle \$\sqrt{1\over2}\$ units high and \$\sqrt2\$ units wide, rotated 45 degrees, as in the following image.
One interesting consequence of fractionality is that the magnitude of the residue is always smaller than that of the divisor, and the Euclidean algorithm always terminates on arbitrary complex number inputs.
Task
Define your own complex floor that satisfies the requirements listed above, and implement it. It is OK if you simply use McDonnell's function. If you use a different function, please include an explanation of how it satisfies the requirements.
Please note that simply flooring the two components is NOT a valid answer since it violates Fractionality: when \$z = 3.9 + 2.9i\$,
$$ \lfloor z \rfloor = 3 + 2i \\ z-\lfloor z \rfloor = 0.9 + 0.9i \\ |z-\lfloor z \rfloor| = |0.9 + 0.9i| = 0.9 \sqrt2 > 1 $$
You may represent a complex number as a built-in complex number or a pair of real numbers. You don't need to care too much about boundary conditions, since floating-point imprecision will impact its correctness anyway.
It is known to be implemented in Dyalog APL, J, and NARS2000. You are not allowed to use floor/ceiling/residue/GCD/LCM functions with non-real complex arguments for these languages.
Standard code-golf rules apply. Shortest code in bytes wins.
3.9+2.9i
is3+2i
; the difference is0.9+0.9i
; magnitude of0.9+0.9i
is greater than one which is not allowed). \$\endgroup\$