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

Generated on Sun Dec 9 21:56:24 2007 for onPHP by  doxygen 1.5.4