| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649 | 
							- <?php
 
- namespace PhpOffice\PhpSpreadsheet\Calculation;
 
- use Matrix\Exception as MatrixException;
 
- use Matrix\Matrix;
 
- class MathTrig
 
- {
 
-     //
 
-     //    Private method to return an array of the factors of the input value
 
-     //
 
-     private static function factors($value)
 
-     {
 
-         $startVal = floor(sqrt($value));
 
-         $factorArray = [];
 
-         for ($i = $startVal; $i > 1; --$i) {
 
-             if (($value % $i) == 0) {
 
-                 $factorArray = array_merge($factorArray, self::factors($value / $i));
 
-                 $factorArray = array_merge($factorArray, self::factors($i));
 
-                 if ($i <= sqrt($value)) {
 
-                     break;
 
-                 }
 
-             }
 
-         }
 
-         if (!empty($factorArray)) {
 
-             rsort($factorArray);
 
-             return $factorArray;
 
-         }
 
-         return [(int) $value];
 
-     }
 
-     private static function romanCut($num, $n)
 
-     {
 
-         return ($num - ($num % $n)) / $n;
 
-     }
 
-     /**
 
-      * ATAN2.
 
-      *
 
-      * This function calculates the arc tangent of the two variables x and y. It is similar to
 
-      *        calculating the arc tangent of y ÷ x, except that the signs of both arguments are used
 
-      *        to determine the quadrant of the result.
 
-      * The arctangent is the angle from the x-axis to a line containing the origin (0, 0) and a
 
-      *        point with coordinates (xCoordinate, yCoordinate). The angle is given in radians between
 
-      *        -pi and pi, excluding -pi.
 
-      *
 
-      * Note that the Excel ATAN2() function accepts its arguments in the reverse order to the standard
 
-      *        PHP atan2() function, so we need to reverse them here before calling the PHP atan() function.
 
-      *
 
-      * Excel Function:
 
-      *        ATAN2(xCoordinate,yCoordinate)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $xCoordinate the x-coordinate of the point
 
-      * @param float $yCoordinate the y-coordinate of the point
 
-      *
 
-      * @return float the inverse tangent of the specified x- and y-coordinates
 
-      */
 
-     public static function ATAN2($xCoordinate = null, $yCoordinate = null)
 
-     {
 
-         $xCoordinate = Functions::flattenSingleValue($xCoordinate);
 
-         $yCoordinate = Functions::flattenSingleValue($yCoordinate);
 
-         $xCoordinate = ($xCoordinate !== null) ? $xCoordinate : 0.0;
 
-         $yCoordinate = ($yCoordinate !== null) ? $yCoordinate : 0.0;
 
-         if (((is_numeric($xCoordinate)) || (is_bool($xCoordinate))) &&
 
-             ((is_numeric($yCoordinate))) || (is_bool($yCoordinate))) {
 
-             $xCoordinate = (float) $xCoordinate;
 
-             $yCoordinate = (float) $yCoordinate;
 
-             if (($xCoordinate == 0) && ($yCoordinate == 0)) {
 
-                 return Functions::DIV0();
 
-             }
 
-             return atan2($yCoordinate, $xCoordinate);
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * CEILING.
 
-      *
 
-      * Returns number rounded up, away from zero, to the nearest multiple of significance.
 
-      *        For example, if you want to avoid using pennies in your prices and your product is
 
-      *        priced at $4.42, use the formula =CEILING(4.42,0.05) to round prices up to the
 
-      *        nearest nickel.
 
-      *
 
-      * Excel Function:
 
-      *        CEILING(number[,significance])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $number the number you want to round
 
-      * @param float $significance the multiple to which you want to round
 
-      *
 
-      * @return float Rounded Number
 
-      */
 
-     public static function CEILING($number, $significance = null)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         $significance = Functions::flattenSingleValue($significance);
 
-         if (($significance === null) &&
 
-             (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) {
 
-             $significance = $number / abs($number);
 
-         }
 
-         if ((is_numeric($number)) && (is_numeric($significance))) {
 
-             if (($number == 0.0) || ($significance == 0.0)) {
 
-                 return 0.0;
 
-             } elseif (self::SIGN($number) == self::SIGN($significance)) {
 
-                 return ceil($number / $significance) * $significance;
 
-             }
 
-             return Functions::NAN();
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * COMBIN.
 
-      *
 
-      * Returns the number of combinations for a given number of items. Use COMBIN to
 
-      *        determine the total possible number of groups for a given number of items.
 
-      *
 
-      * Excel Function:
 
-      *        COMBIN(numObjs,numInSet)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param int $numObjs Number of different objects
 
-      * @param int $numInSet Number of objects in each combination
 
-      *
 
-      * @return int Number of combinations
 
-      */
 
-     public static function COMBIN($numObjs, $numInSet)
 
-     {
 
-         $numObjs = Functions::flattenSingleValue($numObjs);
 
-         $numInSet = Functions::flattenSingleValue($numInSet);
 
-         if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
 
-             if ($numObjs < $numInSet) {
 
-                 return Functions::NAN();
 
-             } elseif ($numInSet < 0) {
 
-                 return Functions::NAN();
 
-             }
 
-             return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet);
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * EVEN.
 
-      *
 
-      * Returns number rounded up to the nearest even integer.
 
-      * You can use this function for processing items that come in twos. For example,
 
-      *        a packing crate accepts rows of one or two items. The crate is full when
 
-      *        the number of items, rounded up to the nearest two, matches the crate's
 
-      *        capacity.
 
-      *
 
-      * Excel Function:
 
-      *        EVEN(number)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $number Number to round
 
-      *
 
-      * @return int Rounded Number
 
-      */
 
-     public static function EVEN($number)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         if ($number === null) {
 
-             return 0;
 
-         } elseif (is_bool($number)) {
 
-             $number = (int) $number;
 
-         }
 
-         if (is_numeric($number)) {
 
-             $significance = 2 * self::SIGN($number);
 
-             return (int) self::CEILING($number, $significance);
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * FACT.
 
-      *
 
-      * Returns the factorial of a number.
 
-      * The factorial of a number is equal to 1*2*3*...* number.
 
-      *
 
-      * Excel Function:
 
-      *        FACT(factVal)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $factVal Factorial Value
 
-      *
 
-      * @return int Factorial
 
-      */
 
-     public static function FACT($factVal)
 
-     {
 
-         $factVal = Functions::flattenSingleValue($factVal);
 
-         if (is_numeric($factVal)) {
 
-             if ($factVal < 0) {
 
-                 return Functions::NAN();
 
-             }
 
-             $factLoop = floor($factVal);
 
-             if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
 
-                 if ($factVal > $factLoop) {
 
-                     return Functions::NAN();
 
-                 }
 
-             }
 
-             $factorial = 1;
 
-             while ($factLoop > 1) {
 
-                 $factorial *= $factLoop--;
 
-             }
 
-             return $factorial;
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * FACTDOUBLE.
 
-      *
 
-      * Returns the double factorial of a number.
 
-      *
 
-      * Excel Function:
 
-      *        FACTDOUBLE(factVal)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $factVal Factorial Value
 
-      *
 
-      * @return int Double Factorial
 
-      */
 
-     public static function FACTDOUBLE($factVal)
 
-     {
 
-         $factLoop = Functions::flattenSingleValue($factVal);
 
-         if (is_numeric($factLoop)) {
 
-             $factLoop = floor($factLoop);
 
-             if ($factVal < 0) {
 
-                 return Functions::NAN();
 
-             }
 
-             $factorial = 1;
 
-             while ($factLoop > 1) {
 
-                 $factorial *= $factLoop--;
 
-                 --$factLoop;
 
-             }
 
-             return $factorial;
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * FLOOR.
 
-      *
 
-      * Rounds number down, toward zero, to the nearest multiple of significance.
 
-      *
 
-      * Excel Function:
 
-      *        FLOOR(number[,significance])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $number Number to round
 
-      * @param float $significance Significance
 
-      *
 
-      * @return float Rounded Number
 
-      */
 
-     public static function FLOOR($number, $significance = null)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         $significance = Functions::flattenSingleValue($significance);
 
-         if (($significance === null) &&
 
-             (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) {
 
-             $significance = $number / abs($number);
 
-         }
 
-         if ((is_numeric($number)) && (is_numeric($significance))) {
 
-             if ($significance == 0.0) {
 
-                 return Functions::DIV0();
 
-             } elseif ($number == 0.0) {
 
-                 return 0.0;
 
-             } elseif (self::SIGN($number) == self::SIGN($significance)) {
 
-                 return floor($number / $significance) * $significance;
 
-             }
 
-             return Functions::NAN();
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     private static function evaluateGCD($a, $b)
 
-     {
 
-         return $b ? self::evaluateGCD($b, $a % $b) : $a;
 
-     }
 
-     /**
 
-      * GCD.
 
-      *
 
-      * Returns the greatest common divisor of a series of numbers.
 
-      * The greatest common divisor is the largest integer that divides both
 
-      *        number1 and number2 without a remainder.
 
-      *
 
-      * Excel Function:
 
-      *        GCD(number1[,number2[, ...]])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed ...$args Data values
 
-      *
 
-      * @return int Greatest Common Divisor
 
-      */
 
-     public static function GCD(...$args)
 
-     {
 
-         $args = Functions::flattenArray($args);
 
-         // Loop through arguments
 
-         foreach (Functions::flattenArray($args) as $value) {
 
-             if (!is_numeric($value)) {
 
-                 return Functions::VALUE();
 
-             } elseif ($value < 0) {
 
-                 return Functions::NAN();
 
-             }
 
-         }
 
-         $gcd = (int) array_pop($args);
 
-         do {
 
-             $gcd = self::evaluateGCD($gcd, (int) array_pop($args));
 
-         } while (!empty($args));
 
-         return $gcd;
 
-     }
 
-     /**
 
-      * INT.
 
-      *
 
-      * Casts a floating point value to an integer
 
-      *
 
-      * Excel Function:
 
-      *        INT(number)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $number Number to cast to an integer
 
-      *
 
-      * @return int Integer value
 
-      */
 
-     public static function INT($number)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         if ($number === null) {
 
-             return 0;
 
-         } elseif (is_bool($number)) {
 
-             return (int) $number;
 
-         }
 
-         if (is_numeric($number)) {
 
-             return (int) floor($number);
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * LCM.
 
-      *
 
-      * Returns the lowest common multiplier of a series of numbers
 
-      * The least common multiple is the smallest positive integer that is a multiple
 
-      * of all integer arguments number1, number2, and so on. Use LCM to add fractions
 
-      * with different denominators.
 
-      *
 
-      * Excel Function:
 
-      *        LCM(number1[,number2[, ...]])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed ...$args Data values
 
-      *
 
-      * @return int Lowest Common Multiplier
 
-      */
 
-     public static function LCM(...$args)
 
-     {
 
-         $returnValue = 1;
 
-         $allPoweredFactors = [];
 
-         // Loop through arguments
 
-         foreach (Functions::flattenArray($args) as $value) {
 
-             if (!is_numeric($value)) {
 
-                 return Functions::VALUE();
 
-             }
 
-             if ($value == 0) {
 
-                 return 0;
 
-             } elseif ($value < 0) {
 
-                 return Functions::NAN();
 
-             }
 
-             $myFactors = self::factors(floor($value));
 
-             $myCountedFactors = array_count_values($myFactors);
 
-             $myPoweredFactors = [];
 
-             foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
 
-                 $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor, $myCountedPower);
 
-             }
 
-             foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
 
-                 if (isset($allPoweredFactors[$myPoweredValue])) {
 
-                     if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
 
-                         $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
 
-                     }
 
-                 } else {
 
-                     $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
 
-                 }
 
-             }
 
-         }
 
-         foreach ($allPoweredFactors as $allPoweredFactor) {
 
-             $returnValue *= (int) $allPoweredFactor;
 
-         }
 
-         return $returnValue;
 
-     }
 
-     /**
 
-      * LOG_BASE.
 
-      *
 
-      * Returns the logarithm of a number to a specified base. The default base is 10.
 
-      *
 
-      * Excel Function:
 
-      *        LOG(number[,base])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param float $number The positive real number for which you want the logarithm
 
-      * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10.
 
-      *
 
-      * @return float
 
-      */
 
-     public static function logBase($number = null, $base = 10)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         $base = ($base === null) ? 10 : (float) Functions::flattenSingleValue($base);
 
-         if ((!is_numeric($base)) || (!is_numeric($number))) {
 
-             return Functions::VALUE();
 
-         }
 
-         if (($base <= 0) || ($number <= 0)) {
 
-             return Functions::NAN();
 
-         }
 
-         return log($number, $base);
 
-     }
 
-     /**
 
-      * MDETERM.
 
-      *
 
-      * Returns the matrix determinant of an array.
 
-      *
 
-      * Excel Function:
 
-      *        MDETERM(array)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param array $matrixValues A matrix of values
 
-      *
 
-      * @return float
 
-      */
 
-     public static function MDETERM($matrixValues)
 
-     {
 
-         $matrixData = [];
 
-         if (!is_array($matrixValues)) {
 
-             $matrixValues = [[$matrixValues]];
 
-         }
 
-         $row = $maxColumn = 0;
 
-         foreach ($matrixValues as $matrixRow) {
 
-             if (!is_array($matrixRow)) {
 
-                 $matrixRow = [$matrixRow];
 
-             }
 
-             $column = 0;
 
-             foreach ($matrixRow as $matrixCell) {
 
-                 if ((is_string($matrixCell)) || ($matrixCell === null)) {
 
-                     return Functions::VALUE();
 
-                 }
 
-                 $matrixData[$row][$column] = $matrixCell;
 
-                 ++$column;
 
-             }
 
-             if ($column > $maxColumn) {
 
-                 $maxColumn = $column;
 
-             }
 
-             ++$row;
 
-         }
 
-         $matrix = new Matrix($matrixData);
 
-         if (!$matrix->isSquare()) {
 
-             return Functions::VALUE();
 
-         }
 
-         try {
 
-             return $matrix->determinant();
 
-         } catch (MatrixException $ex) {
 
-             return Functions::VALUE();
 
-         }
 
-     }
 
-     /**
 
-      * MINVERSE.
 
-      *
 
-      * Returns the inverse matrix for the matrix stored in an array.
 
-      *
 
-      * Excel Function:
 
-      *        MINVERSE(array)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param array $matrixValues A matrix of values
 
-      *
 
-      * @return array
 
-      */
 
-     public static function MINVERSE($matrixValues)
 
-     {
 
-         $matrixData = [];
 
-         if (!is_array($matrixValues)) {
 
-             $matrixValues = [[$matrixValues]];
 
-         }
 
-         $row = $maxColumn = 0;
 
-         foreach ($matrixValues as $matrixRow) {
 
-             if (!is_array($matrixRow)) {
 
-                 $matrixRow = [$matrixRow];
 
-             }
 
-             $column = 0;
 
-             foreach ($matrixRow as $matrixCell) {
 
-                 if ((is_string($matrixCell)) || ($matrixCell === null)) {
 
-                     return Functions::VALUE();
 
-                 }
 
-                 $matrixData[$row][$column] = $matrixCell;
 
-                 ++$column;
 
-             }
 
-             if ($column > $maxColumn) {
 
-                 $maxColumn = $column;
 
-             }
 
-             ++$row;
 
-         }
 
-         $matrix = new Matrix($matrixData);
 
-         if (!$matrix->isSquare()) {
 
-             return Functions::VALUE();
 
-         }
 
-         if ($matrix->determinant() == 0.0) {
 
-             return Functions::NAN();
 
-         }
 
-         try {
 
-             return $matrix->inverse()->toArray();
 
-         } catch (MatrixException $ex) {
 
-             return Functions::VALUE();
 
-         }
 
-     }
 
-     /**
 
-      * MMULT.
 
-      *
 
-      * @param array $matrixData1 A matrix of values
 
-      * @param array $matrixData2 A matrix of values
 
-      *
 
-      * @return array
 
-      */
 
-     public static function MMULT($matrixData1, $matrixData2)
 
-     {
 
-         $matrixAData = $matrixBData = [];
 
-         if (!is_array($matrixData1)) {
 
-             $matrixData1 = [[$matrixData1]];
 
-         }
 
-         if (!is_array($matrixData2)) {
 
-             $matrixData2 = [[$matrixData2]];
 
-         }
 
-         try {
 
-             $rowA = 0;
 
-             foreach ($matrixData1 as $matrixRow) {
 
-                 if (!is_array($matrixRow)) {
 
-                     $matrixRow = [$matrixRow];
 
-                 }
 
-                 $columnA = 0;
 
-                 foreach ($matrixRow as $matrixCell) {
 
-                     if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
 
-                         return Functions::VALUE();
 
-                     }
 
-                     $matrixAData[$rowA][$columnA] = $matrixCell;
 
-                     ++$columnA;
 
-                 }
 
-                 ++$rowA;
 
-             }
 
-             $matrixA = new Matrix($matrixAData);
 
-             $rowB = 0;
 
-             foreach ($matrixData2 as $matrixRow) {
 
-                 if (!is_array($matrixRow)) {
 
-                     $matrixRow = [$matrixRow];
 
-                 }
 
-                 $columnB = 0;
 
-                 foreach ($matrixRow as $matrixCell) {
 
-                     if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
 
-                         return Functions::VALUE();
 
-                     }
 
-                     $matrixBData[$rowB][$columnB] = $matrixCell;
 
-                     ++$columnB;
 
-                 }
 
-                 ++$rowB;
 
-             }
 
-             $matrixB = new Matrix($matrixBData);
 
-             if ($columnA != $rowB) {
 
-                 return Functions::VALUE();
 
-             }
 
-             return $matrixA->multiply($matrixB)->toArray();
 
-         } catch (MatrixException $ex) {
 
-             return Functions::VALUE();
 
-         }
 
-     }
 
-     /**
 
-      * MOD.
 
-      *
 
-      * @param int $a Dividend
 
-      * @param int $b Divisor
 
-      *
 
-      * @return int Remainder
 
-      */
 
-     public static function MOD($a = 1, $b = 1)
 
-     {
 
-         $a = (float) Functions::flattenSingleValue($a);
 
-         $b = (float) Functions::flattenSingleValue($b);
 
-         if ($b == 0.0) {
 
-             return Functions::DIV0();
 
-         } elseif (($a < 0.0) && ($b > 0.0)) {
 
-             return $b - fmod(abs($a), $b);
 
-         } elseif (($a > 0.0) && ($b < 0.0)) {
 
-             return $b + fmod($a, abs($b));
 
-         }
 
-         return fmod($a, $b);
 
-     }
 
-     /**
 
-      * MROUND.
 
-      *
 
-      * Rounds a number to the nearest multiple of a specified value
 
-      *
 
-      * @param float $number Number to round
 
-      * @param int $multiple Multiple to which you want to round $number
 
-      *
 
-      * @return float Rounded Number
 
-      */
 
-     public static function MROUND($number, $multiple)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         $multiple = Functions::flattenSingleValue($multiple);
 
-         if ((is_numeric($number)) && (is_numeric($multiple))) {
 
-             if ($multiple == 0) {
 
-                 return 0;
 
-             }
 
-             if ((self::SIGN($number)) == (self::SIGN($multiple))) {
 
-                 $multiplier = 1 / $multiple;
 
-                 return round($number * $multiplier) / $multiplier;
 
-             }
 
-             return Functions::NAN();
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * MULTINOMIAL.
 
-      *
 
-      * Returns the ratio of the factorial of a sum of values to the product of factorials.
 
-      *
 
-      * @param array of mixed Data Series
 
-      *
 
-      * @return float
 
-      */
 
-     public static function MULTINOMIAL(...$args)
 
-     {
 
-         $summer = 0;
 
-         $divisor = 1;
 
-         // Loop through arguments
 
-         foreach (Functions::flattenArray($args) as $arg) {
 
-             // Is it a numeric value?
 
-             if (is_numeric($arg)) {
 
-                 if ($arg < 1) {
 
-                     return Functions::NAN();
 
-                 }
 
-                 $summer += floor($arg);
 
-                 $divisor *= self::FACT($arg);
 
-             } else {
 
-                 return Functions::VALUE();
 
-             }
 
-         }
 
-         // Return
 
-         if ($summer > 0) {
 
-             $summer = self::FACT($summer);
 
-             return $summer / $divisor;
 
-         }
 
-         return 0;
 
-     }
 
-     /**
 
-      * ODD.
 
-      *
 
-      * Returns number rounded up to the nearest odd integer.
 
-      *
 
-      * @param float $number Number to round
 
-      *
 
-      * @return int Rounded Number
 
-      */
 
-     public static function ODD($number)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         if ($number === null) {
 
-             return 1;
 
-         } elseif (is_bool($number)) {
 
-             return 1;
 
-         } elseif (is_numeric($number)) {
 
-             $significance = self::SIGN($number);
 
-             if ($significance == 0) {
 
-                 return 1;
 
-             }
 
-             $result = self::CEILING($number, $significance);
 
-             if ($result == self::EVEN($result)) {
 
-                 $result += $significance;
 
-             }
 
-             return (int) $result;
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * POWER.
 
-      *
 
-      * Computes x raised to the power y.
 
-      *
 
-      * @param float $x
 
-      * @param float $y
 
-      *
 
-      * @return float
 
-      */
 
-     public static function POWER($x = 0, $y = 2)
 
-     {
 
-         $x = Functions::flattenSingleValue($x);
 
-         $y = Functions::flattenSingleValue($y);
 
-         // Validate parameters
 
-         if ($x == 0.0 && $y == 0.0) {
 
-             return Functions::NAN();
 
-         } elseif ($x == 0.0 && $y < 0.0) {
 
-             return Functions::DIV0();
 
-         }
 
-         // Return
 
-         $result = pow($x, $y);
 
-         return (!is_nan($result) && !is_infinite($result)) ? $result : Functions::NAN();
 
-     }
 
-     /**
 
-      * PRODUCT.
 
-      *
 
-      * PRODUCT returns the product of all the values and cells referenced in the argument list.
 
-      *
 
-      * Excel Function:
 
-      *        PRODUCT(value1[,value2[, ...]])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed ...$args Data values
 
-      *
 
-      * @return float
 
-      */
 
-     public static function PRODUCT(...$args)
 
-     {
 
-         // Return value
 
-         $returnValue = null;
 
-         // Loop through arguments
 
-         foreach (Functions::flattenArray($args) as $arg) {
 
-             // Is it a numeric value?
 
-             if ((is_numeric($arg)) && (!is_string($arg))) {
 
-                 if ($returnValue === null) {
 
-                     $returnValue = $arg;
 
-                 } else {
 
-                     $returnValue *= $arg;
 
-                 }
 
-             }
 
-         }
 
-         // Return
 
-         if ($returnValue === null) {
 
-             return 0;
 
-         }
 
-         return $returnValue;
 
-     }
 
-     /**
 
-      * QUOTIENT.
 
-      *
 
-      * QUOTIENT function returns the integer portion of a division. Numerator is the divided number
 
-      *        and denominator is the divisor.
 
-      *
 
-      * Excel Function:
 
-      *        QUOTIENT(value1[,value2[, ...]])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed ...$args Data values
 
-      *
 
-      * @return float
 
-      */
 
-     public static function QUOTIENT(...$args)
 
-     {
 
-         // Return value
 
-         $returnValue = null;
 
-         // Loop through arguments
 
-         foreach (Functions::flattenArray($args) as $arg) {
 
-             // Is it a numeric value?
 
-             if ((is_numeric($arg)) && (!is_string($arg))) {
 
-                 if ($returnValue === null) {
 
-                     $returnValue = ($arg == 0) ? 0 : $arg;
 
-                 } else {
 
-                     if (($returnValue == 0) || ($arg == 0)) {
 
-                         $returnValue = 0;
 
-                     } else {
 
-                         $returnValue /= $arg;
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         // Return
 
-         return (int) $returnValue;
 
-     }
 
-     /**
 
-      * RAND.
 
-      *
 
-      * @param int $min Minimal value
 
-      * @param int $max Maximal value
 
-      *
 
-      * @return int Random number
 
-      */
 
-     public static function RAND($min = 0, $max = 0)
 
-     {
 
-         $min = Functions::flattenSingleValue($min);
 
-         $max = Functions::flattenSingleValue($max);
 
-         if ($min == 0 && $max == 0) {
 
-             return (mt_rand(0, 10000000)) / 10000000;
 
-         }
 
-         return mt_rand($min, $max);
 
-     }
 
-     public static function ROMAN($aValue, $style = 0)
 
-     {
 
-         $aValue = Functions::flattenSingleValue($aValue);
 
-         $style = ($style === null) ? 0 : (int) Functions::flattenSingleValue($style);
 
-         if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $aValue = (int) $aValue;
 
-         if ($aValue == 0) {
 
-             return '';
 
-         }
 
-         $mill = ['', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM'];
 
-         $cent = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'];
 
-         $tens = ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'];
 
-         $ones = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'];
 
-         $roman = '';
 
-         while ($aValue > 5999) {
 
-             $roman .= 'M';
 
-             $aValue -= 1000;
 
-         }
 
-         $m = self::romanCut($aValue, 1000);
 
-         $aValue %= 1000;
 
-         $c = self::romanCut($aValue, 100);
 
-         $aValue %= 100;
 
-         $t = self::romanCut($aValue, 10);
 
-         $aValue %= 10;
 
-         return $roman . $mill[$m] . $cent[$c] . $tens[$t] . $ones[$aValue];
 
-     }
 
-     /**
 
-      * ROUNDUP.
 
-      *
 
-      * Rounds a number up to a specified number of decimal places
 
-      *
 
-      * @param float $number Number to round
 
-      * @param int $digits Number of digits to which you want to round $number
 
-      *
 
-      * @return float Rounded Number
 
-      */
 
-     public static function ROUNDUP($number, $digits)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         $digits = Functions::flattenSingleValue($digits);
 
-         if ((is_numeric($number)) && (is_numeric($digits))) {
 
-             $significance = pow(10, (int) $digits);
 
-             if ($number < 0.0) {
 
-                 return floor($number * $significance) / $significance;
 
-             }
 
-             return ceil($number * $significance) / $significance;
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * ROUNDDOWN.
 
-      *
 
-      * Rounds a number down to a specified number of decimal places
 
-      *
 
-      * @param float $number Number to round
 
-      * @param int $digits Number of digits to which you want to round $number
 
-      *
 
-      * @return float Rounded Number
 
-      */
 
-     public static function ROUNDDOWN($number, $digits)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         $digits = Functions::flattenSingleValue($digits);
 
-         if ((is_numeric($number)) && (is_numeric($digits))) {
 
-             $significance = pow(10, (int) $digits);
 
-             if ($number < 0.0) {
 
-                 return ceil($number * $significance) / $significance;
 
-             }
 
-             return floor($number * $significance) / $significance;
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * SERIESSUM.
 
-      *
 
-      * Returns the sum of a power series
 
-      *
 
-      * @param float $x Input value to the power series
 
-      * @param float $n Initial power to which you want to raise $x
 
-      * @param float $m Step by which to increase $n for each term in the series
 
-      * @param array of mixed Data Series
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SERIESSUM(...$args)
 
-     {
 
-         $returnValue = 0;
 
-         // Loop through arguments
 
-         $aArgs = Functions::flattenArray($args);
 
-         $x = array_shift($aArgs);
 
-         $n = array_shift($aArgs);
 
-         $m = array_shift($aArgs);
 
-         if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) {
 
-             // Calculate
 
-             $i = 0;
 
-             foreach ($aArgs as $arg) {
 
-                 // Is it a numeric value?
 
-                 if ((is_numeric($arg)) && (!is_string($arg))) {
 
-                     $returnValue += $arg * pow($x, $n + ($m * $i++));
 
-                 } else {
 
-                     return Functions::VALUE();
 
-                 }
 
-             }
 
-             return $returnValue;
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * SIGN.
 
-      *
 
-      * Determines the sign of a number. Returns 1 if the number is positive, zero (0)
 
-      *        if the number is 0, and -1 if the number is negative.
 
-      *
 
-      * @param float $number Number to round
 
-      *
 
-      * @return int sign value
 
-      */
 
-     public static function SIGN($number)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         if (is_bool($number)) {
 
-             return (int) $number;
 
-         }
 
-         if (is_numeric($number)) {
 
-             if ($number == 0.0) {
 
-                 return 0;
 
-             }
 
-             return $number / abs($number);
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * SQRTPI.
 
-      *
 
-      * Returns the square root of (number * pi).
 
-      *
 
-      * @param float $number Number
 
-      *
 
-      * @return float Square Root of Number * Pi
 
-      */
 
-     public static function SQRTPI($number)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         if (is_numeric($number)) {
 
-             if ($number < 0) {
 
-                 return Functions::NAN();
 
-             }
 
-             return sqrt($number * M_PI);
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     protected static function filterHiddenArgs($cellReference, $args)
 
-     {
 
-         return array_filter(
 
-             $args,
 
-             function ($index) use ($cellReference) {
 
-                 list(, $row, $column) = explode('.', $index);
 
-                 return $cellReference->getWorksheet()->getRowDimension($row)->getVisible() &&
 
-                     $cellReference->getWorksheet()->getColumnDimension($column)->getVisible();
 
-             },
 
-             ARRAY_FILTER_USE_KEY
 
-         );
 
-     }
 
-     protected static function filterFormulaArgs($cellReference, $args)
 
-     {
 
-         return array_filter(
 
-             $args,
 
-             function ($index) use ($cellReference) {
 
-                 list(, $row, $column) = explode('.', $index);
 
-                 if ($cellReference->getWorksheet()->cellExists($column . $row)) {
 
-                     //take this cell out if it contains the SUBTOTAL or AGGREGATE functions in a formula
 
-                     $isFormula = $cellReference->getWorksheet()->getCell($column . $row)->isFormula();
 
-                     $cellFormula = !preg_match('/^=.*\b(SUBTOTAL|AGGREGATE)\s*\(/i', $cellReference->getWorksheet()->getCell($column . $row)->getValue());
 
-                     return !$isFormula || $cellFormula;
 
-                 }
 
-                 return true;
 
-             },
 
-             ARRAY_FILTER_USE_KEY
 
-         );
 
-     }
 
-     /**
 
-      * SUBTOTAL.
 
-      *
 
-      * Returns a subtotal in a list or database.
 
-      *
 
-      * @param int the number 1 to 11 that specifies which function to
 
-      *                    use in calculating subtotals within a range
 
-      *                    list
 
-      *            Numbers 101 to 111 shadow the functions of 1 to 11
 
-      *                    but ignore any values in the range that are
 
-      *                    in hidden rows or columns
 
-      * @param array of mixed Data Series
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUBTOTAL(...$args)
 
-     {
 
-         $cellReference = array_pop($args);
 
-         $aArgs = Functions::flattenArrayIndexed($args);
 
-         $subtotal = array_shift($aArgs);
 
-         // Calculate
 
-         if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
 
-             if ($subtotal > 100) {
 
-                 $aArgs = self::filterHiddenArgs($cellReference, $aArgs);
 
-                 $subtotal -= 100;
 
-             }
 
-             $aArgs = self::filterFormulaArgs($cellReference, $aArgs);
 
-             switch ($subtotal) {
 
-                 case 1:
 
-                     return Statistical::AVERAGE($aArgs);
 
-                 case 2:
 
-                     return Statistical::COUNT($aArgs);
 
-                 case 3:
 
-                     return Statistical::COUNTA($aArgs);
 
-                 case 4:
 
-                     return Statistical::MAX($aArgs);
 
-                 case 5:
 
-                     return Statistical::MIN($aArgs);
 
-                 case 6:
 
-                     return self::PRODUCT($aArgs);
 
-                 case 7:
 
-                     return Statistical::STDEV($aArgs);
 
-                 case 8:
 
-                     return Statistical::STDEVP($aArgs);
 
-                 case 9:
 
-                     return self::SUM($aArgs);
 
-                 case 10:
 
-                     return Statistical::VARFunc($aArgs);
 
-                 case 11:
 
-                     return Statistical::VARP($aArgs);
 
-             }
 
-         }
 
-         return Functions::VALUE();
 
-     }
 
-     /**
 
-      * SUM.
 
-      *
 
-      * SUM computes the sum of all the values and cells referenced in the argument list.
 
-      *
 
-      * Excel Function:
 
-      *        SUM(value1[,value2[, ...]])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed ...$args Data values
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUM(...$args)
 
-     {
 
-         $returnValue = 0;
 
-         // Loop through the arguments
 
-         foreach (Functions::flattenArray($args) as $arg) {
 
-             // Is it a numeric value?
 
-             if ((is_numeric($arg)) && (!is_string($arg))) {
 
-                 $returnValue += $arg;
 
-             }
 
-         }
 
-         return $returnValue;
 
-     }
 
-     /**
 
-      * SUMIF.
 
-      *
 
-      * Counts the number of cells that contain numbers within the list of arguments
 
-      *
 
-      * Excel Function:
 
-      *        SUMIF(value1[,value2[, ...]],condition)
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed $aArgs Data values
 
-      * @param string $condition the criteria that defines which cells will be summed
 
-      * @param mixed $sumArgs
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUMIF($aArgs, $condition, $sumArgs = [])
 
-     {
 
-         $returnValue = 0;
 
-         $aArgs = Functions::flattenArray($aArgs);
 
-         $sumArgs = Functions::flattenArray($sumArgs);
 
-         if (empty($sumArgs)) {
 
-             $sumArgs = $aArgs;
 
-         }
 
-         $condition = Functions::ifCondition($condition);
 
-         // Loop through arguments
 
-         foreach ($aArgs as $key => $arg) {
 
-             if (!is_numeric($arg)) {
 
-                 $arg = str_replace('"', '""', $arg);
 
-                 $arg = Calculation::wrapResult(strtoupper($arg));
 
-             }
 
-             $testCondition = '=' . $arg . $condition;
 
-             if (is_numeric($sumArgs[$key]) &&
 
-                 Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
 
-                 // Is it a value within our criteria and only numeric can be added to the result
 
-                 $returnValue += $sumArgs[$key];
 
-             }
 
-         }
 
-         return $returnValue;
 
-     }
 
-     /**
 
-      * SUMIFS.
 
-      *
 
-      *    Counts the number of cells that contain numbers within the list of arguments
 
-      *
 
-      *    Excel Function:
 
-      *        SUMIFS(value1[,value2[, ...]],condition)
 
-      *
 
-      *    @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed $args Data values
 
-      * @param string $condition the criteria that defines which cells will be summed
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUMIFS(...$args)
 
-     {
 
-         $arrayList = $args;
 
-         // Return value
 
-         $returnValue = 0;
 
-         $sumArgs = Functions::flattenArray(array_shift($arrayList));
 
-         $aArgsArray = [];
 
-         $conditions = [];
 
-         while (count($arrayList) > 0) {
 
-             $aArgsArray[] = Functions::flattenArray(array_shift($arrayList));
 
-             $conditions[] = Functions::ifCondition(array_shift($arrayList));
 
-         }
 
-         // Loop through each sum and see if arguments and conditions are true
 
-         foreach ($sumArgs as $index => $value) {
 
-             $valid = true;
 
-             foreach ($conditions as $cidx => $condition) {
 
-                 $arg = $aArgsArray[$cidx][$index];
 
-                 // Loop through arguments
 
-                 if (!is_numeric($arg)) {
 
-                     $arg = Calculation::wrapResult(strtoupper($arg));
 
-                 }
 
-                 $testCondition = '=' . $arg . $condition;
 
-                 if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
 
-                     // Is not a value within our criteria
 
-                     $valid = false;
 
-                     break; // if false found, don't need to check other conditions
 
-                 }
 
-             }
 
-             if ($valid) {
 
-                 $returnValue += $value;
 
-             }
 
-         }
 
-         // Return
 
-         return $returnValue;
 
-     }
 
-     /**
 
-      * SUMPRODUCT.
 
-      *
 
-      * Excel Function:
 
-      *        SUMPRODUCT(value1[,value2[, ...]])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed ...$args Data values
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUMPRODUCT(...$args)
 
-     {
 
-         $arrayList = $args;
 
-         $wrkArray = Functions::flattenArray(array_shift($arrayList));
 
-         $wrkCellCount = count($wrkArray);
 
-         for ($i = 0; $i < $wrkCellCount; ++$i) {
 
-             if ((!is_numeric($wrkArray[$i])) || (is_string($wrkArray[$i]))) {
 
-                 $wrkArray[$i] = 0;
 
-             }
 
-         }
 
-         foreach ($arrayList as $matrixData) {
 
-             $array2 = Functions::flattenArray($matrixData);
 
-             $count = count($array2);
 
-             if ($wrkCellCount != $count) {
 
-                 return Functions::VALUE();
 
-             }
 
-             foreach ($array2 as $i => $val) {
 
-                 if ((!is_numeric($val)) || (is_string($val))) {
 
-                     $val = 0;
 
-                 }
 
-                 $wrkArray[$i] *= $val;
 
-             }
 
-         }
 
-         return array_sum($wrkArray);
 
-     }
 
-     /**
 
-      * SUMSQ.
 
-      *
 
-      * SUMSQ returns the sum of the squares of the arguments
 
-      *
 
-      * Excel Function:
 
-      *        SUMSQ(value1[,value2[, ...]])
 
-      *
 
-      * @category Mathematical and Trigonometric Functions
 
-      *
 
-      * @param mixed ...$args Data values
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUMSQ(...$args)
 
-     {
 
-         $returnValue = 0;
 
-         // Loop through arguments
 
-         foreach (Functions::flattenArray($args) as $arg) {
 
-             // Is it a numeric value?
 
-             if ((is_numeric($arg)) && (!is_string($arg))) {
 
-                 $returnValue += ($arg * $arg);
 
-             }
 
-         }
 
-         return $returnValue;
 
-     }
 
-     /**
 
-      * SUMX2MY2.
 
-      *
 
-      * @param mixed[] $matrixData1 Matrix #1
 
-      * @param mixed[] $matrixData2 Matrix #2
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUMX2MY2($matrixData1, $matrixData2)
 
-     {
 
-         $array1 = Functions::flattenArray($matrixData1);
 
-         $array2 = Functions::flattenArray($matrixData2);
 
-         $count = min(count($array1), count($array2));
 
-         $result = 0;
 
-         for ($i = 0; $i < $count; ++$i) {
 
-             if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
 
-                 ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
 
-                 $result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]);
 
-             }
 
-         }
 
-         return $result;
 
-     }
 
-     /**
 
-      * SUMX2PY2.
 
-      *
 
-      * @param mixed[] $matrixData1 Matrix #1
 
-      * @param mixed[] $matrixData2 Matrix #2
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUMX2PY2($matrixData1, $matrixData2)
 
-     {
 
-         $array1 = Functions::flattenArray($matrixData1);
 
-         $array2 = Functions::flattenArray($matrixData2);
 
-         $count = min(count($array1), count($array2));
 
-         $result = 0;
 
-         for ($i = 0; $i < $count; ++$i) {
 
-             if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
 
-                 ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
 
-                 $result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]);
 
-             }
 
-         }
 
-         return $result;
 
-     }
 
-     /**
 
-      * SUMXMY2.
 
-      *
 
-      * @param mixed[] $matrixData1 Matrix #1
 
-      * @param mixed[] $matrixData2 Matrix #2
 
-      *
 
-      * @return float
 
-      */
 
-     public static function SUMXMY2($matrixData1, $matrixData2)
 
-     {
 
-         $array1 = Functions::flattenArray($matrixData1);
 
-         $array2 = Functions::flattenArray($matrixData2);
 
-         $count = min(count($array1), count($array2));
 
-         $result = 0;
 
-         for ($i = 0; $i < $count; ++$i) {
 
-             if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
 
-                 ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
 
-                 $result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]);
 
-             }
 
-         }
 
-         return $result;
 
-     }
 
-     /**
 
-      * TRUNC.
 
-      *
 
-      * Truncates value to the number of fractional digits by number_digits.
 
-      *
 
-      * @param float $value
 
-      * @param int $digits
 
-      *
 
-      * @return float Truncated value
 
-      */
 
-     public static function TRUNC($value = 0, $digits = 0)
 
-     {
 
-         $value = Functions::flattenSingleValue($value);
 
-         $digits = Functions::flattenSingleValue($digits);
 
-         // Validate parameters
 
-         if ((!is_numeric($value)) || (!is_numeric($digits))) {
 
-             return Functions::VALUE();
 
-         }
 
-         $digits = floor($digits);
 
-         // Truncate
 
-         $adjust = pow(10, $digits);
 
-         if (($digits > 0) && (rtrim((int) ((abs($value) - abs((int) $value)) * $adjust), '0') < $adjust / 10)) {
 
-             return $value;
 
-         }
 
-         return ((int) ($value * $adjust)) / $adjust;
 
-     }
 
-     /**
 
-      * SEC.
 
-      *
 
-      * Returns the secant of an angle.
 
-      *
 
-      * @param float $angle Number
 
-      *
 
-      * @return float|string The secant of the angle
 
-      */
 
-     public static function SEC($angle)
 
-     {
 
-         $angle = Functions::flattenSingleValue($angle);
 
-         if (!is_numeric($angle)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $result = cos($angle);
 
-         return ($result == 0.0) ? Functions::DIV0() : 1 / $result;
 
-     }
 
-     /**
 
-      * SECH.
 
-      *
 
-      * Returns the hyperbolic secant of an angle.
 
-      *
 
-      * @param float $angle Number
 
-      *
 
-      * @return float|string The hyperbolic secant of the angle
 
-      */
 
-     public static function SECH($angle)
 
-     {
 
-         $angle = Functions::flattenSingleValue($angle);
 
-         if (!is_numeric($angle)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $result = cosh($angle);
 
-         return ($result == 0.0) ? Functions::DIV0() : 1 / $result;
 
-     }
 
-     /**
 
-      * CSC.
 
-      *
 
-      * Returns the cosecant of an angle.
 
-      *
 
-      * @param float $angle Number
 
-      *
 
-      * @return float|string The cosecant of the angle
 
-      */
 
-     public static function CSC($angle)
 
-     {
 
-         $angle = Functions::flattenSingleValue($angle);
 
-         if (!is_numeric($angle)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $result = sin($angle);
 
-         return ($result == 0.0) ? Functions::DIV0() : 1 / $result;
 
-     }
 
-     /**
 
-      * CSCH.
 
-      *
 
-      * Returns the hyperbolic cosecant of an angle.
 
-      *
 
-      * @param float $angle Number
 
-      *
 
-      * @return float|string The hyperbolic cosecant of the angle
 
-      */
 
-     public static function CSCH($angle)
 
-     {
 
-         $angle = Functions::flattenSingleValue($angle);
 
-         if (!is_numeric($angle)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $result = sinh($angle);
 
-         return ($result == 0.0) ? Functions::DIV0() : 1 / $result;
 
-     }
 
-     /**
 
-      * COT.
 
-      *
 
-      * Returns the cotangent of an angle.
 
-      *
 
-      * @param float $angle Number
 
-      *
 
-      * @return float|string The cotangent of the angle
 
-      */
 
-     public static function COT($angle)
 
-     {
 
-         $angle = Functions::flattenSingleValue($angle);
 
-         if (!is_numeric($angle)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $result = tan($angle);
 
-         return ($result == 0.0) ? Functions::DIV0() : 1 / $result;
 
-     }
 
-     /**
 
-      * COTH.
 
-      *
 
-      * Returns the hyperbolic cotangent of an angle.
 
-      *
 
-      * @param float $angle Number
 
-      *
 
-      * @return float|string The hyperbolic cotangent of the angle
 
-      */
 
-     public static function COTH($angle)
 
-     {
 
-         $angle = Functions::flattenSingleValue($angle);
 
-         if (!is_numeric($angle)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $result = tanh($angle);
 
-         return ($result == 0.0) ? Functions::DIV0() : 1 / $result;
 
-     }
 
-     /**
 
-      * ACOT.
 
-      *
 
-      * Returns the arccotangent of a number.
 
-      *
 
-      * @param float $number Number
 
-      *
 
-      * @return float|string The arccotangent of the number
 
-      */
 
-     public static function ACOT($number)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         if (!is_numeric($number)) {
 
-             return Functions::VALUE();
 
-         }
 
-         return (M_PI / 2) - atan($number);
 
-     }
 
-     /**
 
-      * ACOTH.
 
-      *
 
-      * Returns the hyperbolic arccotangent of a number.
 
-      *
 
-      * @param float $number Number
 
-      *
 
-      * @return float|string The hyperbolic arccotangent of the number
 
-      */
 
-     public static function ACOTH($number)
 
-     {
 
-         $number = Functions::flattenSingleValue($number);
 
-         if (!is_numeric($number)) {
 
-             return Functions::VALUE();
 
-         }
 
-         $result = log(($number + 1) / ($number - 1)) / 2;
 
-         return is_nan($result) ? Functions::NAN() : $result;
 
-     }
 
- }
 
 
  |