public function roundHalfEven(DecimalNumber $number, $precision)
    {
        $precision = $this->sanitizePrecision($precision);

        if ($number->getPrecision() <= $precision) {
            return $number;
        }

        /**
         * The principle for roundHalfEven is the following:
         *
         * let X = number to round
         *     P = number of decimal digits that we want
         *     D = digit from the fractional part at index P
         *     E = digit to the left of D
         *
         * if D != 5, roundHalfEven(X, P) = roundHalfUp(X, P)
         * if D = 5 and E is even, roundHalfEven(X, P) = truncate(X, P)
         * if D = 5 and E is odd and X is positive, roundHalfUp(X, P) = ceil(X, P)
         * if D = 5 and E is odd and X is negative, roundHalfUp(X, P) = floor(X, P)
         */

        $fractionalPart = $number->getFractionalPart();

        $digit = (int) $fractionalPart[$precision];

        if ($digit !== 5) {
            return $this->roundHalfUp($number, $precision);
        }

        // retrieve the digit to the left of it
        if ($precision === 0) {
            $referenceDigit = (int) substr($number->getIntegerPart(), -1);
        } else {
            $referenceDigit = (int) $fractionalPart[$precision - 1];
        }

        // truncate if even
        $isEven = $referenceDigit % 2 === 0;
        if ($isEven) {
            return $this->truncate($number, $precision);
        }

        // round away from zero
        $method = ($number->isPositive()) ? self::ROUND_CEIL : self::ROUND_FLOOR;
        return $this->compute($number, $precision, $method);
    }