Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert JavaScript function to PHP

Tags:

javascript

php

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;
}
like image 726
szmegma Avatar asked Nov 25 '21 20:11

szmegma


People also ask

Can you convert JavaScript to PHP?

The JS to PHP Converter was created for online converting JavaScript into PHP code. This can come in handy for print JS code via PHP print functions or variable, used in most PHP frameworks and CMS, such as WordPress, Yii, Laravel, etc. For example in Yii2 - $this->registerJs('alert("transform js to php")'); .

Can you mix PHP and JavaScript?

PHP is executed on the server, javascript on the client. You can't 'mix' them. When you call a PHP page the server parses the entire thing and executes anything inside PHP tags. The resulting text is then passed to the user's browser where any client side code is executed.

Can I convert Python code to PHP?

I created a python-to-php converter called py2php. It can auto-translate the basic logic and then you will need to tweak library calls, etc. Still experimental. Here is auto-generated PHP from the python provided by the OP.

What is the JS to PHP converter?

The JS to PHP Converter was created for online converting JavaScript into PHP code. This can come in handy for print JS code via PHP print functions or variable, used in most PHP frameworks and CMS, such as WordPress, Yii, Laravel, etc. For example in Yii2 - $this->registerJs ('alert ("transform js to php")');.

How to pass JavaScript variables to PHP?

The way to pass a JavaScript variable to PHP is through a request. Method 1: This example uses form element and GET/POST method to pass JavaScript variables to PHP. The form of contents can be accessed through the GET and POST actions in PHP. When the form is submitted, the client sends the form data in the form of a URL such as:

What is JavaScript function in PHP?

Summing up, the javascript function is used to execute or trigger a function from a javascript code block (i.e written between <script> and </sccript>) by any event in HTML block. PHP considers every HTML element as strings inside the echo command.

Can you convert Lisp code to JavaScript?

You can convert to JavaScript, VBScript, LotusScript, ASP, PHP, JSP, Ruby, Rebol, Lisp, C#, Perl, and Python. Lisp and Rebol may not render script and style tags so you may need to remove any out of your code. Convert to Javascript.


Video Answer


4 Answers

If what you are doing with x = x.concat() is attempting to ensure that the original passed array is not being modified by your function, you do not have to do anything to ensure that in your PHP version of this function because by default arguments will be copied rather than passed by reference. To force an array to be passed by reference in PHP, you must preceded the argument name with an ampersand (&). This can be demonstrated with the following program where we have defined two functions that each modify the first element of the passed array. In the first function, test1, the array argument is copied so the original passed array remains unmodified. But in the second function, test2, the array argument is passed by reference and when the function returns, the original passed array will have been modified. The only difference between the two functions is that in test1 the arguments is defined as $x and in test2 as &$x:

<?php

// $x is passed by value:
function test1($x)
{
    $x[0] = 9;
    print_r($x);
}

// $x is passed by reference:
function test2(&$x)
{
    $x[0] = 9;
    print_r($x);
}

$my_array = [0, 1, 2];
echo "Pass by value:\n";
test1($my_array); //$my_array remains unmodified
print_r($my_array);

echo "\n\nPass by reference:\n";
test2($my_array); //$my_array is modified
print_r($my_array);

Prints:

Pass by value:
Array
(
    [0] => 9
    [1] => 1
    [2] => 2
)
Array
(
    [0] => 0
    [1] => 1
    [2] => 2
)


Pass by reference:
Array
(
    [0] => 9
    [1] => 1
    [2] => 2
)
Array
(
    [0] => 9
    [1] => 1
    [2] => 2
)

Update

You have several issues. First, you describe toppart returning different values in the JavaScript and PHP versions and you ask us to explain the discrepeancy but you never specify what the actual start, len and bx2 value inputs were to the functions and leave us to figure that out for ourselves. And did you post the PHP version of toppart because I don't see it.

Second, let me elaborate on my previous response. I should have said that arrays will by default be copied rather than passed by reference (class objects will be passed by reference, but that is not applicable here). But that is not just for passing arguments to functions. Consider the following:

$a = [0, 1, 2];
$b = $a; // copy-on-write
$b[0] = 9; // $b is [9, 1, 2]
echo $a; // $a is still [0, 1, 2]

So if you have a JavaScript array a and the assignment b = a, which is a reference copy such that if you modify b you are modifying the array referenced by b you are also modifying the array referenced by a, the semantic equivalent in PHP is $b = @$a;. This ensures that $b and $a not only refer to the same array but if you modify the array referenced by $b, you will be modifying the same array referenced by $a.

So if you have a JavaScript function defined as follows:

function bdiv(x, y)
{
etc.

where $x and $y are arrays, theoretically bdiv could modify the actual arrays being passed and aliased as x and y and therefore the semantic equivalent in PHP would be to define this function as follows:

function bdiv(@$x, @$y)
{
etc.

But here is the problem. Later on in the JavaScript code we have:

x=x.concat()

In JavaScript you have no choice but to pass array arguments by reference. Ealrly on in the JavaScript code there is:

        for(;;) {
            xx=bsub(x,y)
            if(xx.length==0) break
            x=xx; q++
        }

The assignment to x is conditionally executed but would certainly modify the passed x argument. So later on when the code x=x.concat() is executed to assign a copy of the current value of x to x, this would certainly prevent further subsequent modification of the passed array, but what else does it accomplish? Prior to the copy of x there are assignments such as arr['mod'] = x and after the copy of x is made we have assignments to x[0]. Without the copy of x being made that assignment to x[0] would also be updating the array stored at arr['mod']. So the array copy is being done to prevent that.

There are several PHP idioms for making a copy of an array, as already pointed out, for example, $x = array_merge([], $x). But even if you execute this statement in PHP, once you have defined the argument to bdiv as @$x, i.e. pass by reference, you would still be subsequently modifying the passed array as you make assignments to the array referenced by x. So there can be no exact PHP equivalent of the JavaScript result as far as what the passed JavaScript x array will end being when the function returns. The following PHP program demonstrated that even after a copy of x is assigned to x and then an assignment is made to the new array referenced by x, it updates the passed array:

<?php

function test(&$x)
{
    $x = array_merge(array(), $x);
    $x[0] = 9;
    print_r($x);
}

$arr = [0, 1, 2];
test($arr);
print_r($arr);

Prints:

Array
(
    [0] => 9
    [1] => 1
    [2] => 2
)
Array
(
    [0] => 9
    [1] => 1
    [2] => 2
)

So this array copying will not have the other effect of preventing further modifications to the passed array. As far as I can tell the original JavaScript program actually leaves the original passed array in an undefined state. You might as well leave the PHP function defined as bdiv($x, $y) so that the original arrays are left unmodified.

But the above discussion suggests that you may have a problem elsewhere. Where you have a JavaScript assignment of the form a = b where b is an array and there is a subsequent modification to a, for example a[i] = some_value, the equivalent PHP code must be $a = @$b; etc,, that is, a reference assignment.

And as mentioned in a comment by @AKX, you should look into the BC Math functions if you are having issues with toppart.

like image 136
Booboo Avatar answered Oct 21 '22 00:10

Booboo


I am confused why your JavaScript code even has:

x=x.concat()
y=y.concat()

They don't serve any purpose other than assigning a new copy of same array to itself. If it was intended to avoid modification on the original array, then you can simply replace those two lines of code with:

$x = array_merge(array(), $x);
$y = array_merge(array(), $y);

They both serve exact same purpose.

At this point, I am not sure about rest of the php code that you wrote so far, but if it helps you in anyway, that is fine.

like image 41
Kiran Shakya Avatar answered Oct 21 '22 01:10

Kiran Shakya


replace array_push with array_merge.

This will return the merged array then store the result in $x;

array_merge is meant for arrays. it will take the values from one array and append it to the other. just like concat does in JS.

... splits the array ($x) into several values, this is not the correct input. it is the equivalent of array_merge(1,2,3) (i.e arrays are not being inputted)

$x = array(1,2,3);
$x = array_merge($x,$x);
var_dump($x); //output: [1,2,3,1,2,3]

echo $x[4]; // output: 2

if i've misunderstood the question please let me know.

like image 1
Santa claus Avatar answered Oct 21 '22 01:10

Santa claus


Use array_merge instead of array_push i.e

  $x = array(1, 2, 3);
       print_r(array_merge($x,$x));
like image 1
Jyotikant Patil Avatar answered Oct 21 '22 01:10

Jyotikant Patil