Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;
4
 
5
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
7
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
8
 
9
class ErfC
10
{
11
    use ArrayEnabled;
12
 
13
    /**
14
     * ERFC.
15
     *
16
     *    Returns the complementary ERF function integrated between x and infinity
17
     *
18
     *    Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument,
19
     *        the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
20
     *        improved, so that it can now calculate the function for both positive and negative x values.
21
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
22
     *
23
     *    Excel Function:
24
     *        ERFC(x)
25
     *
26
     * @param mixed $value The float lower bound for integrating ERFC
27
     *                      Or can be an array of values
28
     *
29
     * @return array|float|string If an array of numbers is passed as an argument, then the returned result will also be an array
30
     *            with the same dimensions
31
     */
32
    public static function ERFC(mixed $value)
33
    {
34
        if (is_array($value)) {
35
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
36
        }
37
 
38
        if (is_numeric($value)) {
39
            return self::erfcValue($value);
40
        }
41
 
42
        return ExcelError::VALUE();
43
    }
44
 
45
    private const ONE_SQRT_PI = 0.564189583547756287;
46
 
47
    /**
48
     * Method to calculate the erfc value.
49
     */
50
    private static function erfcValue(float|int|string $value): float|int
51
    {
52
        $value = (float) $value;
53
        if (abs($value) < 2.2) {
54
            return 1 - Erf::erfValue($value);
55
        }
56
        if ($value < 0) {
57
            return 2 - self::erfcValue(-$value);
58
        }
59
        $a = $n = 1;
60
        $b = $c = $value;
61
        $d = ($value * $value) + 0.5;
62
        $q2 = $b / $d;
63
        do {
64
            $t = $a * $n + $b * $value;
65
            $a = $b;
66
            $b = $t;
67
            $t = $c * $n + $d * $value;
68
            $c = $d;
69
            $d = $t;
70
            $n += 0.5;
71
            $q1 = $q2;
72
            $q2 = $b / $d;
73
        } while ((abs($q1 - $q2) / $q2) > Functions::PRECISION);
74
 
75
        return self::ONE_SQRT_PI * exp(-$value * $value) * $q2;
76
    }
77
}