* $int1 = new GTBigInteger(4);
* $int2 = new GTBigInteger("-12312321351878937123123098123");
* $int3 = new GTBigInteger(array(1, 226, 64));
*
*
* @throws GTException
* @param string|int|array $value value as string or integer or byte array
*/
public function __construct($value) {
if ($value === null || $value === '') {
throw new GTException("parameter value is required");
}
if (is_array($value)) {
$bytes = $value;
$value = '0';
$sign = '';
$length = count($bytes);
if ($length <= 0) {
throw new GTException("Invalid length: {$length}");
}
if ($bytes[0] >> 7 == 1) {
$sign = '-';
for ($i = 0; $i < $length; $i++) {
$bytes[$i] = ~$bytes[$i] & 0xFF;
}
}
for ($i = 0; $i < $length; $i++) {
$value = bcadd($value, bcmul($bytes[$i], bcpow(256, $length - $i - 1, 0), 0), 0);
}
if ($sign == '-') {
$value = bcadd($value, 1);
}
$value = $sign . $value;
} else if ($value instanceof GTBigInteger) {
$value = $value->getValue();
}
$value = (string) $value;
$chars = array(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-'
);
foreach (GTUtil::toArray($value) as $c) {
if (!in_array($c, $chars, true)) {
throw new GTException("parameter value contains invalid character: {$c}");
}
}
$this->value = $value;
}
/**
* Gets the integer value as string.
*
* @return string integer value as string
*/
public function getValue() {
return $this->value;
}
/**
* Compares this GTBigInteger to another GTBigInteger.
*
* @param GTBigInteger $integer the other GTBigInteger
* @return int 0 if both integers are equal, 1 if current integer is larger than the other, -1 otherwise
*/
public function comp(GTBigInteger $integer) {
return bccomp($this->value, $integer->value, 0);
}
/**
* Adds this GTBigInteger and another GTBigInteger.
*
* @param GTBigInteger $integer the other GTBigInteger
* @return GTBigInteger the sum of the two integers
*/
public function add(GTBigInteger $integer) {
return new GTBigInteger(bcadd($this->value, $integer->value, 0));
}
/**
* Subtracts another GTBigInteger from this integer.
*
* @param GTBigInteger $integer the GTBigInteger to subtract from this one
* @return GTBigInteger the result of the subtraction
*/
public function sub(GTBigInteger $integer) {
return new GTBigInteger(bcsub($this->value, $integer->value, 0));
}
/**
* Multiplies another GTBigInteger with this GTBigInteger.
*
* @param GTBigInteger $integer the GTBigInteger to multiply with
* @return GTBigInteger the result of the multiplication
*/
public function mul(GTBigInteger $integer) {
return new GTBigInteger(bcmul($this->value, $integer->value, 0));
}
/**
* Divides this GTBigInteger with another GTBigInteger.
*
* @param GTBigInteger $integer the GTBigInteger to divide by
* @return GTBigInteger the result of the division
*/
public function div(GTBigInteger $integer) {
return new GTBigInteger(bcdiv($this->value, $integer->value, 0));
}
/**
* Gets the modulus of this GTBigInteger using another GTBigInteger as modulus.
*
* @param int $integer modulus
* @return GTBigInteger the modulus
*/
public function mod($modulus) {
return new GTBigInteger(bcmod($this->value, $modulus));
}
/**
* Raises this GTBigInteger to the power of another GTBigInteger.
*
* @param GTBigInteger $integer power
* @return GTBigInteger result of raising this GTBigInteger to the power of another GTBigInteger
*/
public function pow(GTBigInteger $integer) {
return new GTBigInteger(bcpow($this->value, $integer->value, 0));
}
/**
* Returns a GTBigInteger whose value is (this << $step).
*
* @param int $step shift distance
* @return GTBigInteger this << $step
*/
public function shiftLeft($step) {
return new GTBigInteger(bcmul($this->value, bcpow(2, $step)));
}
/**
* Returns a GTBigInteger whose value is (this >> $step).
*
* @param int $step shift distance
* @return GTBigInteger this >> $step
*/
public function shiftRight($step) {
return new GTBigInteger(bcdiv($this->value, bcpow(2, $step)));
}
/**
* Returns a GTBitInteger whose value is ($this | $integer).
*
* @param GTBigInteger $integer value to be OR'ed with this GTBigInteger
* @return GTBigInteger $this | $integer
*/
public function bitOr(GTBigInteger $integer) {
$bytes1 = $this->toBytes();
$bytes2 = $integer->toBytes();
$length = max(count($bytes1), count($bytes2));
GTUtil::lpad($bytes1, $length, 0x0);
GTUtil::lpad($bytes2, $length, 0x0);
$result = array();
for ($i = 0; $i < $length; $i++) {
$result[$i] = $bytes1[$i] | $bytes2[$i];
}
return new GTBigInteger($result);
}
/**
* Returns a GTBigInteger whose value is ($this ^ $integer).
*
* @param GTBigInteger $integer value to be XOR'ed with this GTBigInteger
* @return GTBigInteger $this | $integer
*/
public function bitXor(GTBigInteger $integer) {
$bytes1 = $this->toBytes();
$bytes2 = $integer->toBytes();
$length = max(count($bytes1), count($bytes2));
GTUtil::lpad($bytes1, $length, 0x0);
GTUtil::lpad($bytes2, $length, 0x0);
$result = array();
for ($i = 0; $i < $length; $i++) {
$result[$i] = $bytes1[$i] ^ $bytes2[$i];
}
return new GTBigInteger($result);
}
/**
* Returns a GTBigInteger whose value is ($this & $integer).
*
* @param GTBigInteger $integer value to be AND'ed with this GTBigInteger
* @return GTBigInteger $this & $integer
*/
public function bitAnd(GTBigInteger $integer) {
$bytes1 = $this->toBytes();
$bytes2 = $integer->toBytes();
$length = max(count($bytes1), count($bytes2));
GTUtil::lpad($bytes1, $length, 0x0);
GTUtil::lpad($bytes2, $length, 0x0);
$result = array();
for ($i = 0; $i < $length; $i++) {
$result[$i] = $bytes1[$i] & $bytes2[$i];
}
return new GTBigInteger($result);
}
/**
* Returns a GTBigInteger whose value is (~$this).
*
*
* @return GTBigInteger ~$this
*/
public function bitNot() {
$result = array();
foreach ($this->toBytes() as $byte) {
array_push($result, ~$byte & 0xFF);
}
return new GTBigInteger($result);
}
/**
* Returns an array of bytes that contains this integers two's complement representation.
*
* Example:
*
*
* $int = new GTBigInteger(123456);
*
* print_r($int->toBytes());
*
* // Array
* // (
* // [0] => 1
* // [1] => 226
* // [2] => 64
* // )
*
*
* @return array byte array that contains two's complement representation of this integer
*/
public function toBytes() {
$result = '';
$buff = $this->value;
$sign = '';
if ($buff{0} == '-') {
$sign = '-';
$buff = substr($buff, 1);
}
while (bccomp($buff, 255, 0) == 1) {
$rest = bcmod($buff, 256);
$buff = bcdiv($buff, 256, 0);
$result = chr($rest) . $result;
}
$result = chr($buff) . $result;
$bytes = GTUtil::toByteArray($result);
if ($sign == '-') {
for ($i = 0; $i < count($bytes); $i++) {
$bytes[$i] = ~$bytes[$i] & 0xFF;
}
array_unshift($bytes, 0x0);
$int = new GTBigInteger($bytes);
$int = $int->add(new GTBigInteger(1));
$bytes = $int->toBytes();
// strip leading 0 bytes
while (count($bytes) > 0 && $bytes[0] == 0x0) {
array_shift($bytes);
}
return $bytes;
} else {
// add leading 0x0 so the integer isn't considered negative
if (count($bytes) > 0 && $bytes[0] >> 7 == 1) {
array_unshift($bytes, 0x0);
}
return $bytes;
}
}
/**
* Returns a bit string that contains the bits of this integer.
*
* Example:
*
*
* $int = new GTBigInteger(4);
* echo $int->toBits();
*
* // 00000100
*
*
* @return string bit string containing the bits of this integer
*/
public function toBits() {
$result = '';
foreach ($this->toBytes() as $byte) {
$byte = decbin($byte);
while (strlen($byte) % 8 != 0) {
$byte = '0' . $byte;
}
$result .= $byte;
}
return $result;
}
}
?>