<?php
/**
 * @license MIT
 *
 * Modified using Strauss.
 * @see https://github.com/BrianHenryIE/strauss
 */

declare(strict_types=1);

namespace iThemesSecurity\Strauss\ZxcvbnPhp\Math\Impl;

class BinomialProviderFloat64 extends AbstractBinomialProvider
{
    protected function calculate(int $n, int $k): float
    {
        $c = 1.0;

        for ($i = 1; $i <= $k; $i++, $n--) {
            // We're aiming for $c * $n / $i, but the $c * $n part could cause us to lose precision, so use $c / $i * $n instead. The caveat
            // here is that in order to get a precise answer, we need to minimize the chances of going above ~2^52.  This is mitigated
            // somewhat by dealing with whole part and the remainder separately, but it's not perfect and could overflow in practice, which
            // would result in a loss of precision.
            $c = floor($c / $i) * $n + floor(fmod($c, $i) * $n / $i);
        }

        return $c;
    }
}