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 Erf
10
{
11
    use ArrayEnabled;
12
 
13
    private const TWO_SQRT_PI = 1.128379167095512574;
14
 
15
    /**
16
     * ERF.
17
     *
18
     * Returns the error function integrated between the lower and upper bound arguments.
19
     *
20
     *    Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments,
21
     *            the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
22
     *            improved, so that it can now calculate the function for both positive and negative ranges.
23
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts negative arguments.
24
     *
25
     *    Excel Function:
26
     *        ERF(lower[,upper])
27
     *
28
     * @param mixed $lower Lower bound float for integrating ERF
29
     *                      Or can be an array of values
30
     * @param mixed $upper Upper bound float for integrating ERF.
31
     *                           If omitted, ERF integrates between zero and lower_limit
32
     *                      Or can be an array of values
33
     *
34
     * @return array|float|string If an array of numbers is passed as an argument, then the returned result will also be an array
35
     *            with the same dimensions
36
     */
37
    public static function ERF(mixed $lower, mixed $upper = null): array|float|string
38
    {
39
        if (is_array($lower) || is_array($upper)) {
40
            return self::evaluateArrayArguments([self::class, __FUNCTION__], $lower, $upper);
41
        }
42
 
43
        if (is_numeric($lower)) {
44
            if ($upper === null) {
45
                return self::erfValue($lower);
46
            }
47
            if (is_numeric($upper)) {
48
                return self::erfValue($upper) - self::erfValue($lower);
49
            }
50
        }
51
 
52
        return ExcelError::VALUE();
53
    }
54
 
55
    /**
56
     * ERFPRECISE.
57
     *
58
     * Returns the error function integrated between the lower and upper bound arguments.
59
     *
60
     *    Excel Function:
61
     *        ERF.PRECISE(limit)
62
     *
63
     * @param mixed $limit Float bound for integrating ERF, other bound is zero
64
     *                      Or can be an array of values
65
     *
66
     * @return array|float|string If an array of numbers is passed as an argument, then the returned result will also be an array
67
     *            with the same dimensions
68
     */
69
    public static function ERFPRECISE(mixed $limit)
70
    {
71
        if (is_array($limit)) {
72
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $limit);
73
        }
74
 
75
        return self::ERF($limit);
76
    }
77
 
78
    private static function makeFloat(mixed $value): float
79
    {
80
        return is_numeric($value) ? ((float) $value) : 0.0;
81
    }
82
 
83
    /**
84
     * Method to calculate the erf value.
85
     */
86
    public static function erfValue(float|int|string $value): float
87
    {
88
        $value = (float) $value;
89
        if (abs($value) > 2.2) {
90
            return 1 - self::makeFloat(ErfC::ERFC($value));
91
        }
92
        $sum = $term = $value;
93
        $xsqr = ($value * $value);
94
        $j = 1;
95
        do {
96
            $term *= $xsqr / $j;
97
            $sum -= $term / (2 * $j + 1);
98
            ++$j;
99
            $term *= $xsqr / $j;
100
            $sum += $term / (2 * $j + 1);
101
            ++$j;
102
            if ($sum == 0.0) {
103
                break;
104
            }
105
        } while (abs($term / $sum) > Functions::PRECISION);
106
 
107
        return self::TWO_SQRT_PI * $sum;
108
    }
109
}