private function normalize(int $w, int $n, int $d): array
    {
        if ($d == 0) {
            throw new Exception\BadDataException('Denominator cannot be zero');
        }
        // Make sure $d is positive
        if ($d < 0) {
            $n *= -1;
            $d *= -1;
        }

        // Reduce the fraction
        if (abs($n) >= $d) {
            $w += intdiv($n, $d);
            $n = $n % $d;
        }
        $gcd = 0;
        while ($gcd != 1 && $n !== 0) {
            $gcd = abs(Algebra::gcd($n, $d));
            $n /= $gcd;
            $d /= $gcd;
        }

        // Make the signs of $n and $w match
        if (Special::sgn($w) !== Special::sgn($n) && $w !== 0 && $n !== 0) {
            $w = $w - Special::sgn($w);
            $n = ($d - abs($n)) * Special::sgn($w);
        }

        if ($n == 0) {
            $d = 1;
        }
        return [$w, $n, $d];
    }