I have a JS function, with array inputs.
For example:
x=[ 239709880, 250229420, 109667654, 196414465, 13098 ]
y=[ 78135241, 54642792, 249 ]
OR:
x=[ 0, 0, 0, 0, 0, 0, 1 ]
y=[ 78135241, 54642792, 249 ]
OR:
x=[ 49 ]
y=[ 33 ]
function bdiv(x,y) {
var n=x.length-1, t=y.length-1, nmt=n-t, arr = []
if(n < t || n==t && (x[n]<y[n] || n>0 && x[n]==y[n] && x[n-1]<y[n-1])) {
arr['q']=[0]
arr['mod']=x
return arr
}
if(n==t && toppart(x,t,2)/toppart(y,t,2) <4) {
var q=0, xx
for(;;) {
xx=bsub(x,y)
if(xx.length==0) break
x=xx; q++
}
arr['q']=[q]
arr['mod']=x
return arr
}
var shift, shift2
shift2=Math.floor(Math.log(y[t])/log2)+1
shift=bs-shift2
if(shift) {
x=x.concat()
y=y.concat()
for(i=t; i>0; i--) y[i]=((y[i]<<shift) & bm) | (y[i-1] >> shift2); y[0]=(y[0]<<shift) & bm
if(x[n] & ((bm <<shift2) & bm)) { x[++n]=0; nmt++; }
for(i=n; i>0; i--) x[i]=((x[i]<<shift) & bm) | (x[i-1] >> shift2); x[0]=(x[0]<<shift) & bm
}
var i, j, x2, y2,q=zeros(nmt+1)
y2=zeros(nmt).concat(y)
for(;;) {
x2=bsub(x,y2)
if(x2.length==0) break
q[nmt]++
x=x2
}
var yt=y[t], top=toppart(y,t,2)
for(i=n; i>t; i--) {
m=i-t-1
if(i >= x.length)
q[m]=1
else if(x[i] == yt)
q[m]=bm
else
q[m]=Math.floor(toppart(x,i,2)/yt)
topx=toppart(x,i,3)
while(q[m] * top > topx)
q[m]--
y2=y2.slice(1)
x2=bsub(x,bmul([q[m]],y2))
if(x2.length==0) {
q[m]--
x2=bsub(x,bmul([q[m]],y2))
}
x=x2
}
if(shift){
for(i=0; i<x.length-1; i++)
x[i]=(x[i]>>shift) | ((x[i+1] << shift2) & bm);
x[x.length-1]>>=shift
}
while(q.length > 1 && q[q.length-1]==0)
q=q.slice(0,q.length-1)
while(x.length > 1 && x[x.length-1]==0)
x=x.slice(0,x.length-1)
arr['q']=q
arr['mod']=x
return arr;
}
What I have done under 5 days so far in PHP:
function bdiv($x,$y){
global $bs, $bm, $bx2, $bx, $bd, $bdm, $log2;
$arr=[];
$n=count($x)-1;
$t=count($y)-1;
$nmt=$n-$t;
if($n < $t || $n==$t && ($x[$n]<$y[$n] || $n>0 && $x[$n]==$y[$n] && $x[$n-1]<$y[$n-1]))
return ['q'=>[0], 'mod'=>$x];
if($n==$t && toppart($x,$t,2)/toppart($y,$t,2) <4){
$q=0;
for(;;){
$xx=bsub($x,$y);
if(count($xx)==0)
break;
$x=$xx;
$q++;
}
return ['q'=>[$q], 'mod'=>$x];
}
$shift2=floor(log($y[$t])/$log2)+1;
$shift=$bs-$shift2;
if($shift){
/////////////////////////////////////////////// Booboo
//$x = array_merge(array(),$x);
//$y = array_merge(array(),$y);
for($i=$t; $i>0; $i--)
$y[$i]=(($y[$i] << $shift) & $bm) | ($y[$i-1] >> $shift2);
$y[0]=($y[0] << $shift) & $bm;
if($x[$n] & (($bm << $shift2) & $bm)){
$x[++$n]=0;
$nmt++;
}
for($i=$n; $i > 0; $i--)
$x[$i]=(($x[$i] << $shift) & $bm) | ($x[$i-1] >> $shift2);
$x[0]=($x[0] << $shift) & $bm;
}
$q=zeros($nmt+1);
//array_push($arr, zeros($nmt));
//array_push($arr, $y);
//$y2=array_merge(...$arr);
//////////////////////////////////// use array_merge straight away
$y2=array_merge(zeros($nmt),$y);
for(;;){
$x2=bsub($x,$y2);
if(count($x2)==0)
break;
$q[$nmt]++;
$x=$x2;
}
$yt=$y[$t];
$top=toppart($y,$t,2);
for($i=$n; $i>$t; $i--){
$m=$i-$t-1;
if($i >= count($x))
$q[$m]=1;
else if($x[$i] == $yt)
$q[$m]=$bm;
else
$q[$m]=floor(toppart($x,$i,2)/$yt);
$topx=toppart($x,$i,3);
while($q[$m] * $top > $topx)
$q[$m]--;
$y2=array_slice($y2,1);
$x2=bsub($x,bmul([$q[$m]],$y2));
if(count($x2)==0){
$q[$m]--;
$x2=bsub($x,bmul([$q[$m]],$y2));
}
$x=$x2;
}
if($shift){
for($i=0; $i<count($x)-1; $i++)
$x[$i]=($x[$i] >> $shift) | (($x[$i+1] << $shift2) & $bm);
$x[count($x)-1] >>= $shift;
}
while(count($q) > 1 && $q[count($q)-1]==0)
$q=array_slice($q, 0, count($q)-1);
while(count($x) > 1 && $x[count($x)-1]==0)
$x=array_slice($x, 0, count($x)-1);
return ['q'=>$q, 'mod'=>$x];
}
So as I marked in the PHP code I have a problem with the array_push($x,$x), seems like this is not the equivalent of x=x.concat(). Array_push add the whole current $x values as a new element to the existing $x array:
$x=[ 1, 2, 3 ];
array_push($x,$x);
then $x will be [ 1, 2, 3, [ 1, 2, 3 ] ]
If I try to flatten the array ($x=array_merge(...$x);) then a new PHP error shows up: array_merge(): Argument #1 is not an array
I would really appreciate it if anyone have any idea, how to convert properly this JS function to a PHP version. Thanks in advance.
==========================> UPDATE I
@Kiran Shakya idea to replace x=x.concat() with $x=array_merge(array(),$x); is actually working or at least I don't get any PHP error or warning on that, but start an infinite loop, which I have to shut manually. The script calling the toppart function, which operating with arbitrary precision numbers (multiply and add):
function toppart(x,start,len) {
var n=0
while(start >= 0 && len > 0){
n=n*bx2+x[start--]
len--
}
return n
}
The interesting part is, the JS returned for an example 70144566321522750 but the PHP returned 70144566321522751. In the later loop the differences are much bigger.
I have checked all numbers in both versions and all the same inputs: x,start,len,bx2. This can be a bug or one of them cannot handle big integers or what can be the reason?
==========================> UPDATE II
I applied Booboo solution, I just completely skipped the concat() parts
So the inputs are:
$x=[ 210763776, 109357119, 261308872];
$start=2;
$len=2;
$bx2=268435456;
...and returns 70144566321522751 in PHP and 70144566321522750 in JS. I use bcadd() and bcmul() but the result is same if I'm using math operator signs.
function toppart($x,$start,$len){
global $bs, $bm, $bx2, $bx, $bd, $bdm, $log2;
$n=0;
while($start >= 0 && $len > 0){
$n= bcadd(bcmul($n, $bx2),$x[$start--]);
$len--;
}
return $n;
}