Go to the documentation of this file.00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00015 final class GmpBigInteger implements BigInteger
00016 {
00017 private $resource = null;
00018
00022 public static function make($number, $base = 10)
00023 {
00024 Assert::isTrue(is_numeric($number));
00025
00026 $result = new self;
00027 $result->resource = gmp_init($number, $base);
00028
00029 return $result;
00030 }
00031
00035 public static function getFactory()
00036 {
00037 return GmpBigIntegerFactory::me();
00038 }
00039
00043 public static function makeFromBinary($binary)
00044 {
00045 if ($binary === null || $binary === '')
00046 throw new WrongArgumentException(
00047 'can\'t make number from emptyness'
00048 );
00049
00050 if (ord($binary) > 127)
00051 throw new WrongArgumentException('only positive numbers allowed');
00052
00053 $number = self::make(0);
00054
00055 $length = strlen($binary);
00056 for ($i = 0; $i < $length; ++$i) {
00057 $number = $number->
00058 mul(self::make(256))->
00059 add(self::make(ord($binary)));
00060
00061 $binary = substr($binary, 1);
00062 }
00063
00064 return $number;
00065 }
00066
00070 public function add(BigInteger $x)
00071 {
00072 $result = new self;
00073 $result->resource = gmp_add($this->resource, $x->resource);
00074 return $result;
00075 }
00076
00077 public function compareTo(BigInteger $x)
00078 {
00079 $out = gmp_cmp($this->resource, $x->resource);
00080
00081 if ($out == 0)
00082 return 0;
00083 elseif ($out > 0)
00084 return 1;
00085 else
00086 return -1;
00087 }
00088
00092 public function mod(BigInteger $mod)
00093 {
00094 $result = new self;
00095 $result->resource = gmp_mod($this->resource, $mod->resource);
00096 return $result;
00097 }
00098
00102 public function pow(BigInteger $exp)
00103 {
00104 $result = new self;
00105 $result->resource = gmp_pow($this->resource, $exp->intValue());
00106 return $result;
00107 }
00108
00112 public function modPow(BigInteger $exp, BigInteger $mod)
00113 {
00114 $result = new self;
00115 $result->resource = gmp_powm(
00116 $this->resource,
00117 $exp->resource,
00118 $mod->resource
00119 );
00120 return $result;
00121 }
00122
00126 public function subtract(BigInteger $x)
00127 {
00128 $result = new self;
00129 $result->resource = gmp_sub($this->resource, $x->resource);
00130 return $result;
00131 }
00132
00136 public function mul(BigInteger $x)
00137 {
00138 $result = new self;
00139 $result->resource = gmp_mul($this->resource, $x->resource);
00140 return $result;
00141 }
00142
00146 public function div(BigInteger $x)
00147 {
00148 $result = new self;
00149 $result->resource = gmp_div($this->resource, $x->resource);
00150 return $result;
00151 }
00152
00153 public function toString()
00154 {
00155 return gmp_strval($this->resource);
00156 }
00157
00158 public function toBinary()
00159 {
00160 $withZero = gmp_cmp($this->resource, 0);
00161
00162 if ($withZero < 0)
00163 throw new WrongArgumentException('only positive integers allowed');
00164 elseif ($withZero === 0)
00165 return "\x00";
00166
00167 $bytes = array();
00168
00169 $dividend = $this->resource;
00170 while (gmp_cmp($dividend, 0) > 0) {
00171 list ($dividend, $reminder) = gmp_div_qr($dividend, 256);
00172 array_unshift($bytes, gmp_intval($reminder));
00173 }
00174
00175 if ($bytes[0] > 127) {
00176 array_unshift($bytes, 0);
00177 }
00178
00179 $binary = null;
00180 foreach ($bytes as $byte) {
00181 $binary .= pack('C', $byte);
00182 }
00183
00184 return $binary;
00185 }
00186
00187 public function intValue()
00188 {
00189 $intValue = gmp_intval($this->resource);
00190
00191 if ((string) $intValue !== gmp_strval($this->resource))
00192 throw new WrongArgumentException(
00193 'can\'t represent itself by integer'
00194 );
00195
00196 return $intValue;
00197 }
00198
00199 public function floatValue()
00200 {
00201 $stringValue = gmp_strval($this->resource);
00202 $floatValue = floatval($stringValue);
00203
00204 if (
00205 is_int($floatValue)
00206 && (string)$floatValue !== $stringValue
00207 || ! is_float($floatValue)
00208 ) {
00209 throw new WrongArgumentException('can\'t convert to float');
00210
00211 } else {
00212
00213 $absValue = abs($floatValue);
00214 $exponent = floor($absValue == 0 ? 0 : log10($absValue));
00215 $mantiss = (int) floor($floatValue * pow(10, -$exponent));
00216
00217 if (
00218 gmp_cmp(
00219 gmp_abs($this->resource),
00220 gmp_abs(
00221 gmp_sub(
00222 gmp_abs($this->resource),
00223 gmp_mul($mantiss, gmp_pow(10, $exponent))
00224 )
00225 )
00226 ) < 0
00227 )
00228 throw new WrongArgumentException('can\'t convert to float');
00229 }
00230
00231 return $floatValue;
00232 }
00233 }
00234 ?>