Skip to content

Commit eeb5d06

Browse files
authored
Merge pull request #29 from memory-agape/0.0.4.5
Support double/float calculation
2 parents 1271f21 + 4c5c68f commit eeb5d06

File tree

10 files changed

+47
-93
lines changed

10 files changed

+47
-93
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ Sorry, I do not have enough time (T_T)
2323

2424
- Implements
2525
- Event
26-
- double/float calculation.
2726
- Many built-in libraries (ex. java.lang.xxx, java.io.xxx and so on)
2827
- etc...
2928

@@ -290,11 +289,11 @@ public static void main(java.lang.String[])
290289
- **LOCAL STORAGE** is showing stacked items on a method.
291290

292291
## PHP problems
293-
- The PHP is cannot calculating big numbers because of PHP is different to the Java.
292+
- **Problem 1:** The PHP is cannot calculating big numbers because of PHP is different to the Java.
294293
But the PHPJava use `bcmath` functions and `gmp` functions to a certain extent to cover to calculate.
295294
The PHPJava return valued is mixed why therefore We recommend to cast to `string` on the PHPJava.
296295

297-
- The PHPJava cannot cover to Java's types completely because of PHP is different to the Java.
296+
- **Problem 2:** The PHPJava cannot cover to Java's types completely because of PHP is different to the Java.
298297
The Java and the PHPJava comparison table is below.
299298

300299
|Java |PHPJava |
@@ -309,6 +308,9 @@ public static void main(java.lang.String[])
309308
|float |\PHPJava\Kernel\Types\\_Float (including `__toString`), string, float |
310309
|double |\PHPJava\Kernel\Types\\_Char (including `__toString`), string, float |
311310

311+
- **Problem 3:** The PHPJava cannot calculate big numbered `double` and `float` values because of `gmp_pow` cannot calculate negative exponents.
312+
So the PHPJava use built-in functions which is `pow`.
313+
312314
## Run unit tests
313315

314316
- PHPUnit test is below.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "JVM emulator by PHP",
44
"type": "library",
55
"license": "MIT",
6-
"version": "0.0.4.2-dev",
6+
"version": "0.0.4.5-dev",
77
"authors": [
88
{
99
"name": "memory"

src/Kernel/Mnemonics/_dadd.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ public function execute(): void
1414
$value1 = $this->getStack();
1515
$value2 = $this->getStack();
1616

17-
$this->pushStack(BinaryTool::add($value1, $value2, 8));
17+
$this->pushStack(BinaryTool::add($value1, $value2));
1818
}
1919
}

src/Kernel/Mnemonics/_iadd.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ public function execute(): void
1414
$leftValue = $this->getStack();
1515
$rightValue = $this->getStack();
1616

17-
$this->pushStack(BinaryTool::add($leftValue, $rightValue, 4));
17+
$this->pushStack(BinaryTool::add($leftValue, $rightValue));
1818
}
1919
}

src/Kernel/Mnemonics/_ishl.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ public function execute(): void
1414
$value1 = $this->getStack();
1515
$value2 = $this->getStack();
1616

17-
$this->pushStack(BinaryTool::shiftLeft($value1, $value2, 4));
17+
$this->pushStack(BinaryTool::shiftLeft($value1, $value2));
1818
}
1919
}

src/Kernel/Mnemonics/_ladd.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ public function execute(): void
1414
$value1 = $this->getStack();
1515
$value2 = $this->getStack();
1616

17-
$this->pushStack(BinaryTool::add($value1, $value2, 8));
17+
$this->pushStack(BinaryTool::add($value1, $value2));
1818
}
1919
}

src/Kernel/Mnemonics/_lshl.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ public function execute(): void
1414
$value1 = $this->getStack();
1515
$value2 = $this->getStack();
1616

17-
$this->pushStack(BinaryTool::shiftLeft($value1, $value2, 8));
17+
$this->pushStack(BinaryTool::shiftLeft($value1, $value2));
1818
}
1919
}

src/Kernel/Structures/_Double.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ public function execute(): void
1616
$this->highBytes = $this->readUnsignedInt();
1717
$this->lowBytes = $this->readUnsignedInt();
1818
}
19+
1920
public function getBytes()
2021
{
21-
return ($this->highBytes << 32) + $this->lowBytes;
22+
return BinaryTool::convertDoubleToIEEE754(
23+
($this->highBytes << 32) + $this->lowBytes
24+
);
2225
}
2326
}

src/Kernel/Structures/_Float.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ public function execute(): void
1616
}
1717
public function getBytes()
1818
{
19-
return $this->bytes;
19+
return BinaryTool::convertFloatToIEEE754($this->bytes);
2020
}
2121
}

src/Utilities/BinaryTool.php

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ final public static function toHex($data)
88
if (is_int($data)) {
99
return sprintf('%X', $data);
1010
}
11-
1211
return strtoupper(base_convert($data, 10, 16));
1312
}
1413

@@ -18,11 +17,7 @@ final public static function reverseBits($bits)
1817

1918
// reverse
2019
for ($i = 0; $i < $bitSize; $i++) {
21-
if ($bits[$i] === '0') {
22-
$bits[$i] = '1';
23-
} else {
24-
$bits[$i] = '0';
25-
}
20+
$bits[$i] = $bits[$i] === '0' ? '1' : '0';
2621
}
2722

2823
return $bits;
@@ -36,17 +31,11 @@ final public static function addOneBit($bits)
3631
// nop
3732
}
3833

39-
if ($index === -1) {
40-
throw new BinaryToolsException('Passed parameter was overflow');
41-
}
42-
4334
$bits[$index] = '1';
44-
4535
for ($i = $index + 1; $i < $bitSize; $i++) {
4636
$bits[$i] = '0';
4737
}
4838

49-
5039
return $bits;
5140
}
5241

@@ -74,14 +63,7 @@ final public static function negate($value, $bytes)
7463
}
7564

7665
$convert = self::addOneBit(self::reverseBits($value));
77-
78-
if ($convert[0] === '1') {
79-
$convert = '-' . base_convert($convert, 2, 10);
80-
} else {
81-
$convert = base_convert($convert, 2, 10);
82-
}
83-
84-
return $convert;
66+
return ($convert[0] === '1' ? '-' : '') . base_convert($convert, 2, 10);
8567
}
8668

8769
final public static function multiply($value1, $value2, $bytes)
@@ -91,16 +73,13 @@ final public static function multiply($value1, $value2, $bytes)
9173
if (function_exists('gmp_mul')) {
9274
$a = gmp_init($value1);
9375
$b = gmp_init($value2);
94-
9576
return gmp_strval(gmp_mul($a, $b));
96-
} elseif (function_exists('bcmul')) {
97-
return bcmul($value1, $value2);
98-
} else {
99-
throw new BinaryToolsException('Cannot multiply values.');
10077
}
78+
79+
return $value1 * $value2;
10180
}
10281

103-
final public static function add($value1, $value2, $bytes)
82+
final public static function add($value1, $value2)
10483
{
10584
$value1 = (int) $value1;
10685
$value2 = (int) $value2;
@@ -109,11 +88,8 @@ final public static function add($value1, $value2, $bytes)
10988
$b = gmp_init($value2);
11089

11190
return gmp_strval(gmp_add($a, $b));
112-
} elseif (function_exists('bcadd')) {
113-
return bcadd($value1, $value2);
114-
} else {
115-
throw new BinaryToolsException('Cannot add values.');
11691
}
92+
return $value1 + $value2;
11793
}
11894

11995
final public static function sub($value1, $value2, $bytes)
@@ -125,11 +101,8 @@ final public static function sub($value1, $value2, $bytes)
125101
$b = gmp_init($value2);
126102

127103
return gmp_strval(gmp_sub($a, $b));
128-
} elseif (function_exists('bcsub')) {
129-
return bcsub($value1, $value2);
130-
} else {
131-
throw new BinaryToolsException('Cannot sub values.');
132104
}
105+
return $value1 - $value2;
133106
}
134107

135108
final public static function div($value1, $value2, $bytes)
@@ -141,22 +114,21 @@ final public static function div($value1, $value2, $bytes)
141114
$b = gmp_init($value2);
142115

143116
return gmp_strval(gmp_div($a, $b));
144-
} elseif (function_exists('bcdiv')) {
145-
return bcdiv($value1, $value2);
146-
} else {
147-
throw new BinaryToolsException('Cannot div values.');
148117
}
118+
119+
return $value1 / $value2;
149120
}
150121

151-
final public static function shiftLeft($value1, $value2, $bytes)
122+
final public static function shiftLeft($value1, $value2)
152123
{
153124
$value1 = (int) $value1;
154125
$value2 = (int) $value2;
155-
$bits = base_convert($value1, 10, 2);
156126

157-
$bits = sprintf('%0' . ($bytes * 8) . 's', $bits . str_repeat('0', $value2));
127+
if (function_exists('gmp_mul')) {
128+
return gmp_strval(gmp_mul($value1, gmp_pow(2, $value2)));
129+
}
158130

159-
return base_convert($bits, 2, 10);
131+
return $value1 << $value2;
160132
}
161133

162134
final public static function unsignedShiftRight($value1, $value2, $bytes)
@@ -188,11 +160,7 @@ final public static function orBits($value1, $value2, $bytes)
188160

189161
$build = '';
190162
for ($i = 0; $i < $bytes * 8; $i++) {
191-
if ($value1[$i] === '1' || $value2[$i] == '1') {
192-
$build .= '1';
193-
} else {
194-
$build .= '0';
195-
}
163+
$build .= ($value1[$i] === '1' || $value2[$i] == '1') ? '1' : '0';
196164
}
197165

198166
return base_convert($build, 2, 10);
@@ -207,12 +175,7 @@ final public static function xorBits($value1, $value2, $bytes)
207175

208176
$build = '';
209177
for ($i = 0; $i < $bytes * 8; $i++) {
210-
if (($value1[$i] === '1' && $value2[$i] === '0') ||
211-
($value1[$i] === '0' && $value2[$i] === '1')) {
212-
$build .= '1';
213-
} else {
214-
$build .= '0';
215-
}
178+
$build .= (($value1[$i] === '1' && $value2[$i] === '0') || ($value1[$i] === '0' && $value2[$i] === '1')) ? '1' : 0;
216179
}
217180

218181
return base_convert($build, 2, 10);
@@ -227,41 +190,27 @@ final public static function andBits($value1, $value2, $bytes)
227190

228191
$build = '';
229192
for ($i = 0; $i < $bytes * 8; $i++) {
230-
if ($value1[$i] === '1' && $value2[$i] === '1') {
231-
$build .= '1';
232-
} else {
233-
$build .= '0';
234-
}
193+
$build .= $value1[$i] === '1' && $value2[$i] === '1' ? '1' : '0';
235194
}
236195

237196
return base_convert($build, 2, 10);
238197
}
239198

240-
final public static function convertDoubleToIEEE754($doubleValue, $rounded = 8)
199+
final public static function convertDoubleToIEEE754($doubleValue)
241200
{
242-
$doubleValue = sprintf('%063s', base_convert($doubleValue, 10, 2));
243-
244-
$sign = $doubleValue[0];
245-
$exponent = substr($doubleValue, 1, 10);
246-
$fraction = substr($doubleValue, 11);
247-
248-
// double scale
249-
$scale = 52;
250-
251-
$fractionData = 0;
252-
for ($i = 0; $i < 52; $i++) {
253-
$fractionData = bcadd($fractionData, bcmul($fraction[$i], bcpow(2, -1 * ($i + 1), $scale), $scale), $scale);
254-
}
255-
256-
// calc sign
257-
$operand1 = -1 * $sign;
258-
259-
// calc fraction
260-
$operand2 = bcadd(1, $fractionData, $scale);
261-
262-
// calc exponent and bias(?)
263-
$operand3 = bcpow(2, bindec($exponent), $scale);
201+
$bits = $doubleValue;
202+
$s = ($bits >> 63) == 0 ? 1 : -1;
203+
$e = ($bits >> 52) & 0x7ff;
204+
$m = ($e == 0) ? (($bits & 0xfffffffffffff) << 1) : ($bits & 0xfffffffffffff) | 0x10000000000000;
205+
return $s * $m * pow(2, $e - 1075);
206+
}
264207

265-
return bcmul(-2, bcmul(bcmul($operand1, $operand2, $scale), $operand3, $scale), $rounded);
208+
final public static function convertFloatToIEEE754($floatValue)
209+
{
210+
$bits = $floatValue;
211+
$s = ($bits >> 31) == 0 ? 1 : -1;
212+
$e = ($bits >> 23) & 0xff;
213+
$m = ($e == 0) ? (($bits & 0x7fffff) << 1) : ($bits & 0x7fffff) | 0x800000;
214+
return $s * $m * pow(2, $e - 150);
266215
}
267216
}

0 commit comments

Comments
 (0)