# GmpBigInteger.class.php

Go to the documentation of this file.

    00001 <?php
    00002 /***************************************************************************
    00003  *   Copyright (C) 2007 by Anton E. Lebedevich                             *
    00004  *                                                                         *
    00005  *   This program is free software; you can redistribute it and/or modify  *
    00006  *   it under the terms of the GNU Lesser General Public License as        *
    00007  *   published by the Free Software Foundation; either version 3 of the    *
    00008  *   License, or (at your option) any later version.                       *
    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 { // is_float($floatValue)
    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 ?>