#pragma once // Ported from de.varylab.discreteconformal.util.DiscreteEllipticUtility (Java). // Only the pure-math subset (no HDS required). #include #include namespace conformallab { // Move tau into the fundamental domain of the modular group SL(2,Z): // |Re(tau)| <= 0.5, Im(tau) >= 0, Re(tau) >= 0, |tau| >= 1 // // Algorithm: iteratively apply // 1. T-shift: Re > 0.5 or Re < 0 → Re -= sign(Re) // 2. Im-flip: Im < 0 → Im = -Im // 3. Re-flip: Re < 0 → Re = -Re // 4. S-invert: |tau| < 1 → tau = 1/tau // // Corresponds to Java DiscreteEllipticUtility.normalizeModulus(Complex). inline std::complex normalizeModulus(std::complex tau) { int maxIter = 100; while (--maxIter > 0) { double re = tau.real(); double im = tau.imag(); // exit when all conditions satisfied if (std::abs(re) <= 0.5 && im >= 0.0 && re >= 0.0 && std::abs(tau) >= 1.0) break; if (std::abs(re) > 0.5) re -= (re > 0.0 ? 1.0 : -1.0); // signum shift if (im < 0.0) im = -im; if (re < 0.0) re = -re; tau = std::complex(re, im); if (std::abs(tau) < 1.0) tau = 1.0 / tau; // S-transformation: invert } return tau; } } // namespace conformallab