Passed
Push — master ( e16571...85a9a3 )
by
unknown
23:21 queued 15:50
created

Lcm::testNonNulls()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
6
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
7
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
8
9
class Lcm
10
{
11
    /**
12
     *  Private method to return an array of the factors of the input value.
13
     *
14
     * @return int[]
15
     */
16 11
    private static function factors(float $value): array
17
    {
18 11
        $startVal = floor(sqrt($value));
19
20 11
        $factorArray = [];
21 11
        for ($i = $startVal; $i > 1; --$i) {
22 11
            if (($value % $i) == 0) {
23 8
                $factorArray = array_merge($factorArray, self::factors($value / $i));
24 8
                $factorArray = array_merge($factorArray, self::factors($i));
25 8
                if ($i <= sqrt($value)) {
26 8
                    break;
27
                }
28
            }
29
        }
30 11
        if (!empty($factorArray)) {
31 8
            rsort($factorArray);
32
            /** @var int[] $factorArray */
33
34 8
            return $factorArray;
35
        }
36
37 11
        return [(int) $value];
38
    }
39
40
    /**
41
     * LCM.
42
     *
43
     * Returns the lowest common multiplier of a series of numbers
44
     * The least common multiple is the smallest positive integer that is a multiple
45
     * of all integer arguments number1, number2, and so on. Use LCM to add fractions
46
     * with different denominators.
47
     *
48
     * Excel Function:
49
     *        LCM(number1[,number2[, ...]])
50
     *
51
     * @param mixed ...$args Data values
52
     *
53
     * @return int|string Lowest Common Multiplier, or a string containing an error
54
     */
55 19
    public static function evaluate(mixed ...$args): int|string
56
    {
57
        try {
58 19
            $arrayArgs = [];
59 19
            $anyZeros = 0;
60 19
            $anyNonNulls = 0;
61 19
            foreach (Functions::flattenArray($args) as $value1) {
62 19
                $anyNonNulls += (int) ($value1 !== null);
63 19
                $value = Helpers::validateNumericNullSubstitution($value1, 1);
64 19
                Helpers::validateNotNegative($value);
65 19
                $arrayArgs[] = (int) $value;
66 19
                $anyZeros += (int) !((bool) $value);
67
            }
68 14
            self::testNonNulls($anyNonNulls);
69 12
            if ($anyZeros) {
70 12
                return 0;
71
            }
72 7
        } catch (Exception $e) {
73 7
            return $e->getMessage();
74
        }
75
76 11
        $returnValue = 1;
77 11
        $allPoweredFactors = [];
78
        // Loop through arguments
79 11
        foreach ($arrayArgs as $value) {
80 11
            $myFactors = self::factors(floor($value));
81 11
            $myCountedFactors = array_count_values($myFactors);
82 11
            $myPoweredFactors = [];
83 11
            foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
84 11
                $myPoweredFactors[$myCountedFactor] = $myCountedFactor ** $myCountedPower;
85
            }
86 11
            self::processPoweredFactors($allPoweredFactors, $myPoweredFactors);
87
        }
88 11
        foreach ($allPoweredFactors as $allPoweredFactor) {
89
            /** @var scalar $allPoweredFactor */
90 11
            $returnValue *= (int) $allPoweredFactor;
91
        }
92
93 11
        return $returnValue;
94
    }
95
96
    /**
97
     * @param mixed[] $allPoweredFactors
98
     * @param mixed[] $myPoweredFactors
99
     */
100 11
    private static function processPoweredFactors(array &$allPoweredFactors, array &$myPoweredFactors): void
101
    {
102 11
        foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
103 11
            if (isset($allPoweredFactors[$myPoweredValue])) {
104 8
                if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
105 5
                    $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
106
                }
107
            } else {
108 11
                $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
109
            }
110
        }
111
    }
112
113 14
    private static function testNonNulls(int $anyNonNulls): void
114
    {
115 14
        if (!$anyNonNulls) {
116 2
            throw new Exception(ExcelError::VALUE());
117
        }
118
    }
119
}
120