Files
medicalalert-web-reloaded/wp/wp-content/ip-geo-api/ip2location/bcmath.php
Tony Volpe be83910651 Merged in feature/280-dev-dev01 (pull request #21)
auto-patch  280-dev-dev01-2024-01-19T16_41_58

* auto-patch  280-dev-dev01-2024-01-19T16_41_58
2024-01-19 16:44:43 +00:00

216 lines
7.4 KiB
PHP

<?php
/**
* Alternative library for BCMath extension
*
*/
if ( extension_loaded('gmp') ):
if ( ! function_exists('bcadd') ):
function bcadd( $Num1 = '0', $Num2 = '0', $Scale = null ) {
return gmp_strval( gmp_add( $Num1, $Num2 ), 10 );
}
endif;
if ( ! function_exists('bcsub') ):
function bcsub( $Num1 = '0', $Num2 = '0', $Scale = null ) {
return gmp_strval( gmp_sub( $Num1, $Num2 ), 10 );
}
endif;
if ( ! function_exists('bcmul') ):
function bcmul( $Num1 = '0', $Num2 = '0' ) {
return gmp_strval( gmp_mul( $Num1, $Num2 ), 10 );
}
endif;
if ( ! function_exists('bcpow') ):
function bcpow( $num, $power ) {
return gmp_strval( gmp_pow( $num, $power ), 10 );
}
endif;
else: // extension_loaded('gmp')
if ( ! function_exists('bcadd') ):
/**
* bcadd - Add two arbitrary precision numbers.
* @link https://php.net/manual/en/function.bcadd.php
*/
function bcadd($Num1='0',$Num2='0',$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=array();
// 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);
return( $Output ? $Output : '0' );
}
endif; // ! function_exists('bcadd')
if ( ! function_exists('bcsub') ):
/**
* bcsub - Subtract one arbitrary precision number from another.
* @link https://php.net/manual/en/function.bcsub.php
*/
function bcsub($Num1='0',$Num2='0',$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=array();
// 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);
return( $Output ? $Output : '0' );
}
endif; // ! function_exists('bcsub')
if ( ! function_exists('bcmul') ):
/**
* bcmul - Multiply two arbitrary precision numbers.
* @link https://php.net/manual/en/function.bcmul.php
*/
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=array();
// 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);
}
endif; // ! function_exists('bcmul')
if ( ! function_exists('bcpow') ):
/**
* bcpow - Raise an arbitrary precision number to another.
* @link https://php.net/manual/en/function.bcmul.php
*/
function bcpow($num, $power) {
$awnser = "1";
while ($power) {
$awnser = bcmul($awnser, $num, 100);
$power = bcsub($power, "1");
}
return rtrim($awnser, '0.');
}
endif; // ! function_exists('bcpow')
endif; // extension_loaded('gmp')
?>