Math_BigInteger
[ class tree: Math_BigInteger ] [ index: Math_BigInteger ] [ all elements ]

Source for file Math_BigInteger.php

Documentation is available at Math_BigInteger.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3.  
  4. /**
  5.  * Pure-PHP arbitrary precision integer arithmetic library.
  6.  *
  7.  * Supports base-2, base-10, base-16, and base-256 numbers.  Uses the GMP or BCMath extensions, if available,
  8.  * and an internal implementation, otherwise.
  9.  *
  10.  * PHP versions 4 and 5
  11.  *
  12.  * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
  13.  * {@link MATH_BIGINTEGER_MODE_INTERNAL MATH_BIGINTEGER_MODE_INTERNAL} mode)
  14.  *
  15.  * Math_BigInteger uses base-2**26 to perform operations such as multiplication and division and
  16.  * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction.  Because the largest possible
  17.  * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating
  18.  * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are
  19.  * used.  As a consequence, bitwise operators such as >> and << cannot be used, nor can the modulo operator %,
  20.  * which only supports integers.  Although this fact will slow this library down, the fact that such a high
  21.  * base is being used should more than compensate.
  22.  *
  23.  * When PHP version 6 is officially released, we'll be able to use 64-bit integers.  This should, once again,
  24.  * allow bitwise operators, and will increase the maximum possible base to 2**31 (or 2**62 for addition /
  25.  * subtraction).
  26.  *
  27.  * Useful resources are as follows:
  28.  *
  29.  *  - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)}
  30.  *  - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)}
  31.  *  - Java's BigInteger classes.  See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip
  32.  *
  33.  * One idea for optimization is to use the comba method to reduce the number of operations performed.
  34.  * MPM uses this quite extensively.  The following URL elaborates:
  35.  *
  36.  * {@link http://www.everything2.com/index.pl?node_id=1736418}}}
  37.  *
  38.  * Here's a quick 'n dirty example of how to use this library:
  39.  * <code>
  40.  * <?php
  41.  *    include('Math_BigInteger.php');
  42.  *
  43.  *    $a = new Math_BigInteger(2);
  44.  *    $b = new Math_BigInteger(3);
  45.  *
  46.  *    $c = $a->add($b);
  47.  *
  48.  *    echo $c->toString(); // outputs 5
  49.  * ?>
  50.  * </code>
  51.  *
  52.  * LICENSE: This library is free software; you can redistribute it and/or
  53.  * modify it under the terms of the GNU Lesser General Public
  54.  * License as published by the Free Software Foundation; either
  55.  * version 2.1 of the License, or (at your option) any later version.
  56.  *
  57.  * This library is distributed in the hope that it will be useful,
  58.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  59.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  60.  * Lesser General Public License for more details.
  61.  *
  62.  * You should have received a copy of the GNU Lesser General Public
  63.  * License along with this library; if not, write to the Free Software
  64.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  65.  * MA  02111-1307  USA
  66.  *
  67.  * @category   Math
  68.  * @package    Math_BigInteger
  69.  * @author     Jim Wigginton <terrafrost@php.net>
  70.  * @copyright  MMVI Jim Wigginton
  71.  * @license    http://www.gnu.org/licenses/lgpl.txt
  72.  * @version    CVS: $Id: Math_BigInteger.php,v 1.6 2006/11/16 15:42:08 terrafrost Exp $
  73.  * @link       http://pear.php.net/package/Math_BigInteger
  74.  */
  75.  
  76. /**
  77.  * Include PHP_Compat module bcpowmod since that function does not exist in PHP4:
  78.  * {@link http://pear.php.net/package/PHP_Compat/}
  79.  * {@link http://php.net/function.bcpowmod}
  80.  */
  81. require_once 'PHP/Compat/Function/bcpowmod.php';
  82. // array_fill requires PHP 4.2.0+, per http://php.net/function.array_fill
  83. // see http://www.frostjedi.com/terra/scripts/pear/array_fill.phps
  84. // require_once 'PHP/Compat/Function/array_fill.php';
  85.  
  86.  
  87.  
  88. /**#@+
  89.  * @access private
  90.  * @see Math_BigInteger::_slidingWindow()
  91.  */
  92. /**
  93.  * @see Math_BigInteger::_montgomery()
  94.  * @see Math_BigInteger::_undoMontgomery()
  95.  */
  96. define('MATH_BIGINTEGER_MONTGOMERY'0);
  97. /**
  98.  * @see Math_BigInteger::_barrett()
  99.  */
  100. define('MATH_BIGINTEGER_BARRETT'1);
  101. /**
  102.  * @see Math_BigInteger::_mod2()
  103.  */
  104. define('MATH_BIGINTEGER_POWEROF2'2);
  105. /**
  106.  * @see Math_BigInteger::_remainder()
  107.  */
  108. define('MATH_BIGINTEGER_CLASSIC'3);
  109. /**
  110.  * @see Math_BigInteger::_copy()
  111.  */
  112. define('MATH_BIGINTEGER_NONE'4);
  113. /**#@-*/
  114.  
  115.  * @access private
  116.  * @see Math_BigInteger::_montgomery()
  117.  * @see Math_BigInteger::_barrett()
  118.  */
  119. /**
  120.  * $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid.
  121.  */
  122. define('MATH_BIGINTEGER_VARIABLE'0);
  123. /**
  124.  * $cache[MATH_BIGINTEGER_DATA] contains the cached data.
  125.  */
  126. define('MATH_BIGINTEGER_DATA'1);
  127. /**#@-*/
  128.  
  129.  * @access private
  130.  * @see Math_BigInteger::Math_BigInteger()
  131.  */
  132. /**
  133.  * To use the pure-PHP implementation
  134.  */
  135. define('MATH_BIGINTEGER_MODE_INTERNAL',1);
  136. /**
  137.  * To use the BCMath library
  138.  *
  139.  * (if enabled; otherwise, the internal implementation will be used)
  140.  */
  141. define('MATH_BIGINTEGER_MODE_BCMATH',2);
  142. /**
  143.  * To use the GMP library
  144.  *
  145.  * (if present; otherwise, either the BCMath or the internal implementation will be used)
  146.  */
  147. define('MATH_BIGINTEGER_MODE_GMP',3);
  148. /**#@-*/
  149.  
  150.  * Pure-PHP arbitrary precission integer arithmetic library. Supports base-2, base-10, base-16, and base-256
  151.  * numbers.  Negative numbers are supported in all publically accessable functions save for modPow
  152.  * and modInverse.
  153.  *
  154.  * @author  Jim Wigginton <terrafrost@php.net>
  155.  * @version 1.0.0RC2
  156.  * @access  public
  157.  * @package Math_BigInteger
  158.  */
  159. class Math_BigInteger {
  160.     /**
  161.      * Holds the BigInteger's value.
  162.      *
  163.      * @var Array 
  164.      * @access private
  165.      */
  166.     var $value;
  167.  
  168.     /**
  169.      * Holds the BigInteger's magnitude.
  170.      *
  171.      * @var Boolean 
  172.      * @access private
  173.      */
  174.     var $is_negative = false;
  175.  
  176.     /**
  177.      * Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers.
  178.      *
  179.      * Here's a quick 'n dirty example:
  180.      * <code>
  181.      * <?php
  182.      *    include('Math_BigInteger.php');
  183.      *
  184.      *    $a = new Math_BigInteger('0x32', 16); // 50 in base-16
  185.      *
  186.      *    echo $a->toString(); // outputs 50
  187.      * ?>
  188.      * </code>
  189.      *
  190.      * @param optional $x base-10 number or base-$base number if $base set.
  191.      * @param optional integer $base
  192.      * @return Math_BigInteger 
  193.      * @access public
  194.      */
  195.     function Math_BigInteger($x = 0$base = 10)
  196.     {
  197.         if !defined('MATH_BIGINTEGER_MODE') ) {
  198.             switch (true{
  199.                 case extension_loaded('gmp'):
  200.                     define('MATH_BIGINTEGER_MODE'MATH_BIGINTEGER_MODE_GMP);
  201.                     break;
  202.                 case extension_loaded('bcmath'):
  203.                     define('MATH_BIGINTEGER_MODE'MATH_BIGINTEGER_MODE_BCMATH);
  204.                     break;
  205.                 default:
  206.                     $this->value = array();
  207.                     define('MATH_BIGINTEGER_MODE'MATH_BIGINTEGER_MODE_INTERNAL);
  208.             }
  209.         }
  210.  
  211.         switch (MATH_BIGINTEGER_MODE{
  212.             case MATH_BIGINTEGER_MODE_GMP:
  213.                 $this->value = gmp_init(0);
  214.                 break;
  215.             case MATH_BIGINTEGER_MODE_BCMATH:
  216.                 $this->value '0';
  217.                 break;
  218.             default:
  219.                 $this->value = array();
  220.         }
  221.  
  222.         if ($x === 0{
  223.             return;
  224.         }
  225.  
  226.         switch ($base{
  227.             case 256:
  228.                 switch (MATH_BIGINTEGER_MODE{
  229.                     case MATH_BIGINTEGER_MODE_GMP:
  230.                         $temp unpack('H*hex'$x);
  231.                         $this->value = gmp_init('0x' $temp['hex']);
  232.                         break;
  233.                     case MATH_BIGINTEGER_MODE_BCMATH:
  234.                         $len strlen($x);
  235.                         $len+= (3 * $len% 4; // rounds $len to the nearest 4.
  236.  
  237.                         $x str_pad($x$lenchr(0)STR_PAD_LEFT);
  238.  
  239.                         for ($i = 0; $i $len$i+= 4{
  240.                             $this->value = bcmul($this->value'4294967296')// 4294967296 == 2**32
  241.                             $this->value = bcadd($this->value0x1000000 * ord($x{$i}((ord($x{$i + 1}<< 16(ord($x{$i + 2}<< 8ord($x{$i + 3})));
  242.                         }
  243.  
  244.                         break;
  245.                     // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
  246.                     case MATH_BIGINTEGER_MODE_INTERNAL:
  247.                         while (strlen($x)) {
  248.                             $this->value[$this->_bytes2int($this->_base256_rshift($x26));
  249.                         }
  250.                 }
  251.                 break;
  252.             case 16:
  253.                 if ($x{0== '-'{
  254.                     $this->is_negative = true;
  255.                     $x substr($x1);
  256.                 }
  257.  
  258.                 $x preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#''$1'$x);
  259.  
  260.                 switch (MATH_BIGINTEGER_MODE{
  261.                     case MATH_BIGINTEGER_MODE_GMP:
  262.                         $temp $this->is_negative '-0x' $x '0x' $x;
  263.                         $this->value = gmp_init($temp);
  264.                         $this->is_negative = false;
  265.                         break;
  266.                     case MATH_BIGINTEGER_MODE_BCMATH:
  267.                         $x strlen($x'0' $x $x;
  268.                         $temp = new Math_BigInteger(pack('H*'$x)256);
  269.                         $this->value $this->is_negative '-' $temp->value : $temp->value;
  270.                         $this->is_negative = false;
  271.                         break;
  272.                     case MATH_BIGINTEGER_MODE_INTERNAL:
  273.                         $x strlen($x'0' $x $x;
  274.                         $temp = new Math_BigInteger(pack('H*'$x)256);
  275.                         $this->value $temp->value;
  276.                 }
  277.                 break;
  278.             case 10:
  279.                 $x preg_replace('#^(-?[0-9]*).*#','$1',$x);
  280.  
  281.                 switch (MATH_BIGINTEGER_MODE{
  282.                     case MATH_BIGINTEGER_MODE_GMP:
  283.                         $this->value = gmp_init($x);
  284.                         break;
  285.                     case MATH_BIGINTEGER_MODE_BCMATH:
  286.                         // explicitly casting $x to a string is necessary, here, since doing $x{0} on -1 yields different
  287.                         // results then doing it on '-1' does (modInverse does $x{0})
  288.                         $this->value = (string) $x;
  289.                         break;
  290.                     case MATH_BIGINTEGER_MODE_INTERNAL:
  291.                         $temp = new Math_BigInteger();
  292.  
  293.                         // array(10000000) is 10**7 in base-2**26.  10**7 is the closest to 2**26 we can get without passing it.
  294.                         $multiplier = new Math_BigInteger();
  295.                         $multiplier->value = array(10000000);
  296.  
  297.                         if ($x{0== '-'{
  298.                             $this->is_negative = true;
  299.                             $x substr($x1);
  300.                         }
  301.  
  302.                         $x str_pad($xstrlen($x(6 * strlen($x)) % 70STR_PAD_LEFT);
  303.  
  304.                         while (strlen($x)) {
  305.                             $temp $temp->multiply($multiplier);
  306.                             $temp $temp->add(new Math_BigInteger($this->_int2bytes(substr($x07))256));
  307.                             $x substr($x7);
  308.                         }
  309.  
  310.                         $this->value $temp->value;
  311.                 }
  312.                 break;
  313.             case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
  314.                 if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP{
  315.                     $this->value = gmp_init($x2);
  316.                     break;
  317.                 }
  318.  
  319.                 if ($x{0== '-'{
  320.                     $this->is_negative = true;
  321.                     $x substr($x1);
  322.                 }
  323.  
  324.                 $x preg_replace('#^([01]*).*#''$1'$x);
  325.                 $x str_pad($xstrlen($x(3 * strlen($x)) % 40STR_PAD_LEFT);
  326.  
  327.                 $str '0x';
  328.                 while (strlen($x)) {
  329.                    $part substr($x04);
  330.                    $str.= dechex(bindec($part));
  331.                    $x substr($x4);
  332.                 }
  333.  
  334.                 $temp = new Math_BigInteger($str16);
  335.                 $this->value $temp->value;
  336.  
  337.                 if (MATH_BINGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH && $this->is_negative{
  338.                     $this->value '-' $this->value;
  339.                     $this->is_negative = false;
  340.                 }
  341.  
  342.                 break;
  343.             default:
  344.                 // base not supported, so we'll let $this == 0
  345.         }
  346.     }
  347.  
  348.     /**
  349.      * Converts a BigInteger to a byte string (eg. base-256).
  350.      *
  351.      * Here's a quick 'n dirty example:
  352.      * <code>
  353.      * <?php
  354.      *    include('Math_BigInteger.php');
  355.      *
  356.      *    $a = new Math_BigInteger('65');
  357.      *
  358.      *    echo $a->toBytes(); // outputs chr(65)
  359.      * ?>
  360.      * </code>
  361.      *
  362.      * @return String 
  363.      * @access public
  364.      * @internal Converts a base-2**26 number to base-2**8
  365.      */
  366.     function toBytes()
  367.     {
  368.         switch MATH_BIGINTEGER_MODE {
  369.             case MATH_BIGINTEGER_MODE_GMP:
  370.                 if (gmp_cmp($this->valuegmp_init(0)) == 0{
  371.                     return '';
  372.                 }
  373.  
  374.                 $temp = gmp_strval(gmp_abs($this->value)16);
  375.                 $temp strlen($temp'0' $temp $temp;
  376.  
  377.                 return ltrim(pack('H*'$temp)chr(0));
  378.             case MATH_BIGINTEGER_MODE_BCMATH:
  379.                 if ($this->value === '0'{
  380.                     return '';
  381.                 }
  382.  
  383.                 $value '';
  384.                 $current $this->value;                 
  385.  
  386.                 // we don't do four bytes at a time because then numbers larger than 1<<31 would be negative
  387.                 // two's complimented numbers, which would break chr.
  388.                 while (bccomp($current'0'> 0{
  389.                     $temp = bcmod($current0x1000000);
  390.                     $value chr($temp >> 16chr($temp >> 8chr($temp$value;
  391.                     $current = bcdiv($current0x1000000);
  392.                 }
  393.  
  394.                 return ltrim($valuechr(0));
  395.         }
  396.  
  397.         if (!count($this->value)) {
  398.             return '';
  399.         }
  400.  
  401.         $result $this->_int2bytes($this->value[count($this->value- 1]);
  402.  
  403.         $temp $this->_copy();
  404.  
  405.         for ($i count($temp->value- 2; $i >= 0; $i--{
  406.             $temp->_base256_lshift($result26);
  407.             $result $result str_pad($temp->_int2bytes($temp->value[$i])strlen($result)chr(0)STR_PAD_LEFT);
  408.         }
  409.  
  410.         return $result;
  411.     }
  412.  
  413.     /**
  414.      * Converts a BigInteger to a base-10 number.
  415.      *
  416.      * Here's a quick 'n dirty example:
  417.      * <code>
  418.      * <?php
  419.      *    include('Math_BigInteger.php');
  420.      *
  421.      *    $a = new Math_BigInteger('50');
  422.      *
  423.      *    echo $a->toString(); // outputs 50
  424.      * ?>
  425.      * </code>
  426.      *
  427.      * @return String 
  428.      * @access public
  429.      * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
  430.      */
  431.     function toString()
  432.     {
  433.         switch MATH_BIGINTEGER_MODE {
  434.             case MATH_BIGINTEGER_MODE_GMP:
  435.                 return gmp_strval($this->value);
  436.             case MATH_BIGINTEGER_MODE_BCMATH:
  437.                 if ($this->value === '0'{
  438.                     return '0';
  439.                 }
  440.  
  441.                 return ltrim($this->value'0');
  442.         }
  443.  
  444.         if (!count($this->value)) {
  445.             return '0';
  446.         }
  447.  
  448.         $result ($this->is_negative'-' '';
  449.  
  450.         $temp $this->_copy();
  451.  
  452.         $divisor = new Math_BigInteger();
  453.         $divisor->value = array(10000000)// eg. 10**7
  454.  
  455.         while (count($temp->value)) {
  456.             list($temp$mod$temp->divide($divisor);
  457.             $result str_pad($this->_bytes2int($mod->toBytes())7'0'STR_PAD_LEFT$result;
  458.         }
  459.  
  460.         return ltrim($result'0');
  461.     }
  462.  
  463.     /**
  464.      * Adds two BigIntegers.
  465.      *
  466.      * Here's a quick 'n dirty example:
  467.      * <code>
  468.      * <?php
  469.      *    include('Math_BigInteger.php');
  470.      *
  471.      *    $a = new Math_BigInteger('10');
  472.      *    $b = new Math_BigInteger('20');
  473.      *
  474.      *    $c = $a->add($b);
  475.      *
  476.      *    echo $c->toString(); // outputs 30
  477.      * ?>
  478.      * </code>
  479.      *
  480.      * @param Math_BigInteger $y 
  481.      * @return Math_BigInteger 
  482.      * @access public
  483.      * @internal Performs base-2**52 addition
  484.      */
  485.     function add($y)
  486.     {
  487.         switch MATH_BIGINTEGER_MODE {
  488.             case MATH_BIGINTEGER_MODE_GMP:
  489.                 $temp = new Math_BigInteger();
  490.                 $temp->value = gmp_add($this->value$y->value);
  491.  
  492.                 return $temp;
  493.             case MATH_BIGINTEGER_MODE_BCMATH:
  494.                 $temp = new Math_BigInteger();
  495.                 $temp->value = bcadd($this->value$y->value);
  496.  
  497.                 return $temp;
  498.         }
  499.  
  500.         // subtract, if appropriate
  501.         if $this->is_negative != $y->is_negative {
  502.             // is $y the negative number?
  503.             $y_negative $this->compare($y> 0;
  504.  
  505.             $temp $this->_copy();
  506.             $y $y->_copy();
  507.             $temp->is_negative = $y->is_negative = false;
  508.  
  509.             $diff $temp->compare($y);
  510.             if !$diff {
  511.                 return new Math_BigInteger();
  512.             }
  513.  
  514.             $temp $temp->subtract($y);
  515.  
  516.             $temp->is_negative = ($diff > 0!$y_negative $y_negative;
  517.  
  518.             return $temp;
  519.         }
  520.  
  521.         $result = new Math_BigInteger();
  522.         $carry = 0;
  523.  
  524.         $size max(count($this->value)count($y->value));
  525.         $size+= $size % 2; // rounds $size to the nearest 2.
  526.  
  527.         $x array_pad($this->value$size,0);
  528.         $y array_pad($y->value$size0);
  529.  
  530.         for ($i = 0; $i $size - 1; $i+=2{
  531.             $sum $x[$i + 1* 0x4000000 + $x[$i$y[$i + 1* 0x4000000 + $y[$i$carry;
  532.             $carry $sum >= 4503599627370496; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
  533.             $sum $carry $sum - 4503599627370496 : $sum;
  534.  
  535.             $temp floor($sum / 0x4000000);
  536.  
  537.             $result->value[$sum - 0x4000000 * $temp// eg. a faster alternative to fmod($sum,0x4000000)
  538.             $result->value[$temp;
  539.         }
  540.  
  541.         if ($carry{
  542.             $result->value[$carry;
  543.         }
  544.  
  545.         $result->is_negative = $this->is_negative;
  546.  
  547.         return $result->_normalize();
  548.     }
  549.  
  550.     /**
  551.      * Subtracts two BigIntegers.
  552.      *
  553.      * Here's a quick 'n dirty example:
  554.      * <code>
  555.      * <?php
  556.      *    include('Math_BigInteger.php');
  557.      *
  558.      *    $a = new Math_BigInteger('10');
  559.      *    $b = new Math_BigInteger('20');
  560.      *
  561.      *    $c = $a->subtract($b);
  562.      *
  563.      *    echo $c->toString(); // outputs -10
  564.      * ?>
  565.      * </code>
  566.      *
  567.      * @param Math_BigInteger $y 
  568.      * @return Math_BigInteger 
  569.      * @access public
  570.      * @internal Performs base-2**52 subtraction
  571.      */
  572.     function subtract($y)
  573.     {
  574.         switch MATH_BIGINTEGER_MODE {
  575.             case MATH_BIGINTEGER_MODE_GMP:
  576.                 $temp = new Math_BigInteger();
  577.                 $temp->value = gmp_sub($this->value$y->value);
  578.  
  579.                 return $temp;
  580.             case MATH_BIGINTEGER_MODE_BCMATH:
  581.                 $temp = new Math_BigInteger();
  582.                 $temp->value = bcsub($this->value$y->value);
  583.  
  584.                 return $temp;
  585.         }
  586.  
  587.         // add, if appropriate
  588.         if $this->is_negative != $y->is_negative {
  589.             $is_negative $y->compare($this> 0;
  590.  
  591.             $temp $this->_copy();
  592.             $y $y->_copy();
  593.             $temp->is_negative = $y->is_negative = false;
  594.  
  595.             $temp $temp->add($y);
  596.  
  597.             $temp->is_negative = $is_negative;
  598.  
  599.             return $temp;
  600.         }
  601.  
  602.         $diff $this->compare($y);
  603.  
  604.         if !$diff {
  605.             return new Math_BigInteger();
  606.         }
  607.  
  608.         // switch $this and $y around, if appropriate.
  609.         if ( (!$this->is_negative && $diff < 0|| ($this->is_negative && $diff > 0) ) {
  610.             $is_negative $y->is_negative;
  611.  
  612.             $temp $this->_copy();
  613.             $y $y->_copy();
  614.             $temp->is_negative = $y->is_negative = false;
  615.  
  616.             $temp $y->subtract($temp);
  617.             $temp->is_negative = !$is_negative;
  618.  
  619.             return $temp;
  620.         }
  621.  
  622.         $result = new Math_BigInteger();
  623.         $carry = 0;
  624.  
  625.         $size max(count($this->value)count($y->value));
  626.         $size+= $size % 2;
  627.  
  628.         $x array_pad($this->value$size0);
  629.         $y array_pad($y->value$size0);
  630.  
  631.         for ($i = 0; $i $size - 1;$i+=2{
  632.