<?php
/**
 * @package   Essentials YOOtheme Pro 2.4.12 build 1202.1125
 * @author    ZOOlanders https://www.zoolanders.com
 * @copyright Copyright (C) Joolanders, SL
 * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
 */

if (!function_exists('bcadd')) {
    function bcadd($Num1, $Num2, $Scale = null)
    {
        // check if they're valid positive numbers, extract the whole numbers and decimals
        if (!preg_match("/^\+?(\d+)(\.\d+)?$/", $Num1, $Tmp1) || !preg_match("/^\+?(\d+)(\.\d+)?$/", $Num2, $Tmp2)) {
            return '0';
        }

        // this is where the result is stored
        $Output = [];

        // remove ending zeroes from decimals and remove point
        $Dec1 = isset($Tmp1[2]) ? rtrim(substr($Tmp1[2], 1), '0') : '';
        $Dec2 = isset($Tmp2[2]) ? rtrim(substr($Tmp2[2], 1), '0') : '';

        // calculate the longest length of decimals
        $DLen = max(strlen($Dec1), strlen($Dec2));

        // if $Scale is null, automatically set it to the amount of decimal places for accuracy
        if ($Scale == null) {
            $Scale = $DLen;
        }

        // remove leading zeroes and reverse the whole numbers, then append padded decimals on the end
        $Num1 = strrev(ltrim($Tmp1[1], '0') . str_pad($Dec1, $DLen, '0'));
        $Num2 = strrev(ltrim($Tmp2[1], '0') . str_pad($Dec2, $DLen, '0'));

        // calculate the longest length we need to process
        $MLen = max(strlen($Num1), strlen($Num2));

        // pad the two numbers so they are of equal length (both equal to $MLen)
        $Num1 = str_pad($Num1, $MLen, '0');
        $Num2 = str_pad($Num2, $MLen, '0');

        // process each digit, keep the ones, carry the tens (remainders)
        for ($i = 0; $i < $MLen; $i++) {
            $Sum = (int) $Num1[$i] + (int) $Num2[$i];
            if (isset($Output[$i])) {
                $Sum += $Output[$i];
            }
            $Output[$i] = $Sum % 10;
            if ($Sum > 9) {
                $Output[$i + 1] = 1;
            }
        }

        // convert the array to string and reverse it
        $Output = strrev(implode('', $Output));

        // substring the decimal digits from the result, pad if necessary (if $Scale > amount of actual decimals)
        // next, since actual zero values can cause a problem with the substring values, if so, just simply give '0'
        // next, append the decimal value, if $Scale is defined, and return result
        $Decimal = str_pad(substr($Output, -$DLen, $Scale), $Scale, '0');
        $Output = $MLen - $DLen < 1 ? '0' : substr($Output, 0, -$DLen);
        $Output .= $Scale > 0 ? ".{$Decimal}" : '';

        return $Output;
    }
}

if (!function_exists('bcmul')) {
    function bcmul($Num1 = '0', $Num2 = '0')
    {
        // check if they're both plain numbers
        if (!preg_match("/^\d+$/", $Num1) || !preg_match("/^\d+$/", $Num2)) {
            return 0;
        }

        // remove zeroes from beginning of numbers
        for ($i = 0; $i < strlen($Num1); $i++) {
            if (@$Num1[$i] != '0') {
                $Num1 = substr($Num1, $i);

                break;
            }
        }
        for ($i = 0; $i < strlen($Num2); $i++) {
            if (@$Num2[$i] != '0') {
                $Num2 = substr($Num2, $i);

                break;
            }
        }

        // get both number lengths
        $Len1 = strlen($Num1);
        $Len2 = strlen($Num2);

        // $Rema is for storing the calculated numbers and $Rema2 is for carrying the remainders
        $Rema = $Rema2 = [];

        // we start by making a $Len1 by $Len2 table (array)
        for ($y = $i = 0; $y < $Len1; $y++) {
            for ($x = 0; $x < $Len2; $x++) {
                // we use the classic lattice method for calculating the multiplication..
                // this will multiply each number in $Num1 with each number in $Num2 and store it accordingly
                @$Rema[$i++ % $Len2] .= sprintf('%02d', (int) $Num1[$y] * (int) $Num2[$x]);
            }
        }

        // cycle through each stored number
        for ($y = 0; $y < $Len2; $y++) {
            for ($x = 0; $x < $Len1 * 2; $x++) {
                // add up the numbers in the diagonal fashion the lattice method uses
                @$Rema2[Floor(($x - 1) / 2) + 1 + $y] += (int) $Rema[$y][$x];
            }
        }

        // reverse the results around
        $Rema2 = array_reverse($Rema2);

        // cycle through all the results again
        for ($i = 0; $i < count($Rema2); $i++) {
            // reverse this item, split, keep the first digit, spread the other digits down the array
            $Rema3 = str_split(strrev($Rema2[$i]));
            for ($o = 0; $o < count($Rema3); $o++) {
                if ($o == 0) {
                    @$Rema2[$i + $o] = $Rema3[$o];
                } else {
                    @$Rema2[$i + $o] += $Rema3[$o];
                }
            }
        }
        // implode $Rema2 so it's a string and reverse it, this is the result!
        $Rema2 = strrev(implode('', $Rema2));

        // just to make sure, we delete the zeros from the beginning of the result and return
        while (strlen($Rema2) > 1 && $Rema2[0] == '0') {
            $Rema2 = substr($Rema2, 1);
        }

        return $Rema2;
    }
}

if (!function_exists('bcpow')) {
    function bcpow($num, $power)
    {
        $answer = '1';

        while ($power) {
            $answer = bcmul($answer, $num, 100);
            $power--;
        }

        return rtrim($answer, '0.');
    }
}
