diff --git a/README.md b/README.md index de091d06..87f92f89 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ Sorry, I do not have enough time (T_T) - Implements - Event -- double/float calculation. - Many built-in libraries (ex. java.lang.xxx, java.io.xxx and so on) - etc... @@ -290,11 +289,11 @@ public static void main(java.lang.String[]) - **LOCAL STORAGE** is showing stacked items on a method. ## PHP problems -- The PHP is cannot calculating big numbers because of PHP is different to the Java. +- **Problem 1:** The PHP is cannot calculating big numbers because of PHP is different to the Java. But the PHPJava use `bcmath` functions and `gmp` functions to a certain extent to cover to calculate. The PHPJava return valued is mixed why therefore We recommend to cast to `string` on the PHPJava. -- The PHPJava cannot cover to Java's types completely because of PHP is different to the Java. +- **Problem 2:** The PHPJava cannot cover to Java's types completely because of PHP is different to the Java. The Java and the PHPJava comparison table is below. |Java |PHPJava | @@ -309,6 +308,9 @@ public static void main(java.lang.String[]) |float |\PHPJava\Kernel\Types\\_Float (including `__toString`), string, float | |double |\PHPJava\Kernel\Types\\_Char (including `__toString`), string, float | +- **Problem 3:** The PHPJava cannot calculate big numbered `double` and `float` values because of `gmp_pow` cannot calculate negative exponents. + So the PHPJava use built-in functions which is `pow`. + ## Run unit tests - PHPUnit test is below. diff --git a/composer.json b/composer.json index 42a2a89c..ab971c8c 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "JVM emulator by PHP", "type": "library", "license": "MIT", - "version": "0.0.4.2-dev", + "version": "0.0.4.5-dev", "authors": [ { "name": "memory" diff --git a/src/Kernel/Mnemonics/_dadd.php b/src/Kernel/Mnemonics/_dadd.php index 6ee80da9..ba9437e6 100644 --- a/src/Kernel/Mnemonics/_dadd.php +++ b/src/Kernel/Mnemonics/_dadd.php @@ -14,6 +14,6 @@ public function execute(): void $value1 = $this->getStack(); $value2 = $this->getStack(); - $this->pushStack(BinaryTool::add($value1, $value2, 8)); + $this->pushStack(BinaryTool::add($value1, $value2)); } } diff --git a/src/Kernel/Mnemonics/_iadd.php b/src/Kernel/Mnemonics/_iadd.php index d67734ea..08789c60 100644 --- a/src/Kernel/Mnemonics/_iadd.php +++ b/src/Kernel/Mnemonics/_iadd.php @@ -14,6 +14,6 @@ public function execute(): void $leftValue = $this->getStack(); $rightValue = $this->getStack(); - $this->pushStack(BinaryTool::add($leftValue, $rightValue, 4)); + $this->pushStack(BinaryTool::add($leftValue, $rightValue)); } } diff --git a/src/Kernel/Mnemonics/_ishl.php b/src/Kernel/Mnemonics/_ishl.php index ab080c37..a344c67c 100644 --- a/src/Kernel/Mnemonics/_ishl.php +++ b/src/Kernel/Mnemonics/_ishl.php @@ -14,6 +14,6 @@ public function execute(): void $value1 = $this->getStack(); $value2 = $this->getStack(); - $this->pushStack(BinaryTool::shiftLeft($value1, $value2, 4)); + $this->pushStack(BinaryTool::shiftLeft($value1, $value2)); } } diff --git a/src/Kernel/Mnemonics/_ladd.php b/src/Kernel/Mnemonics/_ladd.php index d9a30a33..9e33cf16 100644 --- a/src/Kernel/Mnemonics/_ladd.php +++ b/src/Kernel/Mnemonics/_ladd.php @@ -14,6 +14,6 @@ public function execute(): void $value1 = $this->getStack(); $value2 = $this->getStack(); - $this->pushStack(BinaryTool::add($value1, $value2, 8)); + $this->pushStack(BinaryTool::add($value1, $value2)); } } diff --git a/src/Kernel/Mnemonics/_lshl.php b/src/Kernel/Mnemonics/_lshl.php index 52a868ff..54ed1257 100644 --- a/src/Kernel/Mnemonics/_lshl.php +++ b/src/Kernel/Mnemonics/_lshl.php @@ -14,6 +14,6 @@ public function execute(): void $value1 = $this->getStack(); $value2 = $this->getStack(); - $this->pushStack(BinaryTool::shiftLeft($value1, $value2, 8)); + $this->pushStack(BinaryTool::shiftLeft($value1, $value2)); } } diff --git a/src/Kernel/Structures/_Double.php b/src/Kernel/Structures/_Double.php index e06a17f8..8f18e70f 100644 --- a/src/Kernel/Structures/_Double.php +++ b/src/Kernel/Structures/_Double.php @@ -16,8 +16,11 @@ public function execute(): void $this->highBytes = $this->readUnsignedInt(); $this->lowBytes = $this->readUnsignedInt(); } + public function getBytes() { - return ($this->highBytes << 32) + $this->lowBytes; + return BinaryTool::convertDoubleToIEEE754( + ($this->highBytes << 32) + $this->lowBytes + ); } } diff --git a/src/Kernel/Structures/_Float.php b/src/Kernel/Structures/_Float.php index a12364f5..05bc7f43 100644 --- a/src/Kernel/Structures/_Float.php +++ b/src/Kernel/Structures/_Float.php @@ -16,6 +16,6 @@ public function execute(): void } public function getBytes() { - return $this->bytes; + return BinaryTool::convertFloatToIEEE754($this->bytes); } } diff --git a/src/Utilities/BinaryTool.php b/src/Utilities/BinaryTool.php index 54d1221e..6d2df9b6 100644 --- a/src/Utilities/BinaryTool.php +++ b/src/Utilities/BinaryTool.php @@ -8,7 +8,6 @@ final public static function toHex($data) if (is_int($data)) { return sprintf('%X', $data); } - return strtoupper(base_convert($data, 10, 16)); } @@ -18,11 +17,7 @@ final public static function reverseBits($bits) // reverse for ($i = 0; $i < $bitSize; $i++) { - if ($bits[$i] === '0') { - $bits[$i] = '1'; - } else { - $bits[$i] = '0'; - } + $bits[$i] = $bits[$i] === '0' ? '1' : '0'; } return $bits; @@ -36,17 +31,11 @@ final public static function addOneBit($bits) // nop } - if ($index === -1) { - throw new BinaryToolsException('Passed parameter was overflow'); - } - $bits[$index] = '1'; - for ($i = $index + 1; $i < $bitSize; $i++) { $bits[$i] = '0'; } - return $bits; } @@ -74,14 +63,7 @@ final public static function negate($value, $bytes) } $convert = self::addOneBit(self::reverseBits($value)); - - if ($convert[0] === '1') { - $convert = '-' . base_convert($convert, 2, 10); - } else { - $convert = base_convert($convert, 2, 10); - } - - return $convert; + return ($convert[0] === '1' ? '-' : '') . base_convert($convert, 2, 10); } final public static function multiply($value1, $value2, $bytes) @@ -91,16 +73,13 @@ final public static function multiply($value1, $value2, $bytes) if (function_exists('gmp_mul')) { $a = gmp_init($value1); $b = gmp_init($value2); - return gmp_strval(gmp_mul($a, $b)); - } elseif (function_exists('bcmul')) { - return bcmul($value1, $value2); - } else { - throw new BinaryToolsException('Cannot multiply values.'); } + + return $value1 * $value2; } - final public static function add($value1, $value2, $bytes) + final public static function add($value1, $value2) { $value1 = (int) $value1; $value2 = (int) $value2; @@ -109,11 +88,8 @@ final public static function add($value1, $value2, $bytes) $b = gmp_init($value2); return gmp_strval(gmp_add($a, $b)); - } elseif (function_exists('bcadd')) { - return bcadd($value1, $value2); - } else { - throw new BinaryToolsException('Cannot add values.'); } + return $value1 + $value2; } final public static function sub($value1, $value2, $bytes) @@ -125,11 +101,8 @@ final public static function sub($value1, $value2, $bytes) $b = gmp_init($value2); return gmp_strval(gmp_sub($a, $b)); - } elseif (function_exists('bcsub')) { - return bcsub($value1, $value2); - } else { - throw new BinaryToolsException('Cannot sub values.'); } + return $value1 - $value2; } final public static function div($value1, $value2, $bytes) @@ -141,22 +114,21 @@ final public static function div($value1, $value2, $bytes) $b = gmp_init($value2); return gmp_strval(gmp_div($a, $b)); - } elseif (function_exists('bcdiv')) { - return bcdiv($value1, $value2); - } else { - throw new BinaryToolsException('Cannot div values.'); } + + return $value1 / $value2; } - final public static function shiftLeft($value1, $value2, $bytes) + final public static function shiftLeft($value1, $value2) { $value1 = (int) $value1; $value2 = (int) $value2; - $bits = base_convert($value1, 10, 2); - $bits = sprintf('%0' . ($bytes * 8) . 's', $bits . str_repeat('0', $value2)); + if (function_exists('gmp_mul')) { + return gmp_strval(gmp_mul($value1, gmp_pow(2, $value2))); + } - return base_convert($bits, 2, 10); + return $value1 << $value2; } final public static function unsignedShiftRight($value1, $value2, $bytes) @@ -188,11 +160,7 @@ final public static function orBits($value1, $value2, $bytes) $build = ''; for ($i = 0; $i < $bytes * 8; $i++) { - if ($value1[$i] === '1' || $value2[$i] == '1') { - $build .= '1'; - } else { - $build .= '0'; - } + $build .= ($value1[$i] === '1' || $value2[$i] == '1') ? '1' : '0'; } return base_convert($build, 2, 10); @@ -207,12 +175,7 @@ final public static function xorBits($value1, $value2, $bytes) $build = ''; for ($i = 0; $i < $bytes * 8; $i++) { - if (($value1[$i] === '1' && $value2[$i] === '0') || - ($value1[$i] === '0' && $value2[$i] === '1')) { - $build .= '1'; - } else { - $build .= '0'; - } + $build .= (($value1[$i] === '1' && $value2[$i] === '0') || ($value1[$i] === '0' && $value2[$i] === '1')) ? '1' : 0; } return base_convert($build, 2, 10); @@ -227,41 +190,27 @@ final public static function andBits($value1, $value2, $bytes) $build = ''; for ($i = 0; $i < $bytes * 8; $i++) { - if ($value1[$i] === '1' && $value2[$i] === '1') { - $build .= '1'; - } else { - $build .= '0'; - } + $build .= $value1[$i] === '1' && $value2[$i] === '1' ? '1' : '0'; } return base_convert($build, 2, 10); } - final public static function convertDoubleToIEEE754($doubleValue, $rounded = 8) + final public static function convertDoubleToIEEE754($doubleValue) { - $doubleValue = sprintf('%063s', base_convert($doubleValue, 10, 2)); - - $sign = $doubleValue[0]; - $exponent = substr($doubleValue, 1, 10); - $fraction = substr($doubleValue, 11); - - // double scale - $scale = 52; - - $fractionData = 0; - for ($i = 0; $i < 52; $i++) { - $fractionData = bcadd($fractionData, bcmul($fraction[$i], bcpow(2, -1 * ($i + 1), $scale), $scale), $scale); - } - - // calc sign - $operand1 = -1 * $sign; - - // calc fraction - $operand2 = bcadd(1, $fractionData, $scale); - - // calc exponent and bias(?) - $operand3 = bcpow(2, bindec($exponent), $scale); + $bits = $doubleValue; + $s = ($bits >> 63) == 0 ? 1 : -1; + $e = ($bits >> 52) & 0x7ff; + $m = ($e == 0) ? (($bits & 0xfffffffffffff) << 1) : ($bits & 0xfffffffffffff) | 0x10000000000000; + return $s * $m * pow(2, $e - 1075); + } - return bcmul(-2, bcmul(bcmul($operand1, $operand2, $scale), $operand3, $scale), $rounded); + final public static function convertFloatToIEEE754($floatValue) + { + $bits = $floatValue; + $s = ($bits >> 31) == 0 ? 1 : -1; + $e = ($bits >> 23) & 0xff; + $m = ($e == 0) ? (($bits & 0x7fffff) << 1) : ($bits & 0x7fffff) | 0x800000; + return $s * $m * pow(2, $e - 150); } }