run:R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
21.8 KB
2026-03-11 16:18:52
R W Run
14.17 KB
2026-03-11 16:18:52
R W Run
129.86 KB
2026-03-11 16:18:52
R W Run
15.37 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
6.78 KB
2026-03-11 16:18:52
R W Run
24 KB
2026-03-11 16:18:52
R W Run
30.44 KB
2026-03-11 16:18:52
R W Run
1.55 KB
2026-03-11 16:18:52
R W Run
11.24 KB
2026-03-11 16:18:52
R W Run
6.46 KB
2026-03-11 16:18:52
R W Run
209 By
2026-03-11 16:18:52
R W Run
10.78 KB
2026-03-11 16:18:52
R W Run
2.4 KB
2026-03-11 16:18:52
R W Run
1.35 KB
2026-03-11 16:18:52
R W Run
error_log
📄Int32.php
1<?php
2
3/**
4 * Class ParagonIE_Sodium_Core32_Int32
5 *
6 * Encapsulates a 32-bit integer.
7 *
8 * These are immutable. It always returns a new instance.
9 */
10class ParagonIE_Sodium_Core32_Int32
11{
12 /**
13 * @var array<int, int> - two 16-bit integers
14 *
15 * 0 is the higher 16 bits
16 * 1 is the lower 16 bits
17 */
18 public $limbs = array(0, 0);
19
20 /**
21 * @var int
22 */
23 public $overflow = 0;
24
25 /**
26 * @var bool
27 */
28 public $unsignedInt = false;
29
30 /**
31 * ParagonIE_Sodium_Core32_Int32 constructor.
32 * @param array $array
33 * @param bool $unsignedInt
34 */
35 public function __construct($array = array(0, 0), $unsignedInt = false)
36 {
37 $this->limbs = array(
38 (int) $array[0],
39 (int) $array[1]
40 );
41 $this->overflow = 0;
42 $this->unsignedInt = $unsignedInt;
43 }
44
45 /**
46 * Adds two int32 objects
47 *
48 * @param ParagonIE_Sodium_Core32_Int32 $addend
49 * @return ParagonIE_Sodium_Core32_Int32
50 */
51 public function addInt32(ParagonIE_Sodium_Core32_Int32 $addend)
52 {
53 $i0 = $this->limbs[0];
54 $i1 = $this->limbs[1];
55 $j0 = $addend->limbs[0];
56 $j1 = $addend->limbs[1];
57
58 $r1 = $i1 + ($j1 & 0xffff);
59 $carry = $r1 >> 16;
60
61 $r0 = $i0 + ($j0 & 0xffff) + $carry;
62 $carry = $r0 >> 16;
63
64 $r0 &= 0xffff;
65 $r1 &= 0xffff;
66
67 $return = new ParagonIE_Sodium_Core32_Int32(
68 array($r0, $r1)
69 );
70 $return->overflow = $carry;
71 $return->unsignedInt = $this->unsignedInt;
72 return $return;
73 }
74
75 /**
76 * Adds a normal integer to an int32 object
77 *
78 * @param int $int
79 * @return ParagonIE_Sodium_Core32_Int32
80 * @throws SodiumException
81 * @throws TypeError
82 */
83 public function addInt($int)
84 {
85 ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
86 /** @var int $int */
87 $int = (int) $int;
88
89 $int = (int) $int;
90
91 $i0 = $this->limbs[0];
92 $i1 = $this->limbs[1];
93
94 $r1 = $i1 + ($int & 0xffff);
95 $carry = $r1 >> 16;
96
97 $r0 = $i0 + (($int >> 16) & 0xffff) + $carry;
98 $carry = $r0 >> 16;
99 $r0 &= 0xffff;
100 $r1 &= 0xffff;
101 $return = new ParagonIE_Sodium_Core32_Int32(
102 array($r0, $r1)
103 );
104 $return->overflow = $carry;
105 $return->unsignedInt = $this->unsignedInt;
106 return $return;
107 }
108
109 /**
110 * @param int $b
111 * @return int
112 */
113 public function compareInt($b = 0)
114 {
115 $gt = 0;
116 $eq = 1;
117
118 $i = 2;
119 $j = 0;
120 while ($i > 0) {
121 --$i;
122 /** @var int $x1 */
123 $x1 = $this->limbs[$i];
124 /** @var int $x2 */
125 $x2 = ($b >> ($j << 4)) & 0xffff;
126 /** @var int $gt */
127 $gt |= (($x2 - $x1) >> 8) & $eq;
128 /** @var int $eq */
129 $eq &= (($x2 ^ $x1) - 1) >> 8;
130 }
131 return ($gt + $gt - $eq) + 1;
132 }
133
134 /**
135 * @param int $m
136 * @return ParagonIE_Sodium_Core32_Int32
137 */
138 public function mask($m = 0)
139 {
140 /** @var int $hi */
141 $hi = ((int) $m >> 16);
142 $hi &= 0xffff;
143 /** @var int $lo */
144 $lo = ((int) $m) & 0xffff;
145 return new ParagonIE_Sodium_Core32_Int32(
146 array(
147 (int) ($this->limbs[0] & $hi),
148 (int) ($this->limbs[1] & $lo)
149 ),
150 $this->unsignedInt
151 );
152 }
153
154 /**
155 * @param array<int, int> $a
156 * @param array<int, int> $b
157 * @param int $baseLog2
158 * @return array<int, int>
159 */
160 public function multiplyLong(array $a, array $b, $baseLog2 = 16)
161 {
162 $a_l = count($a);
163 $b_l = count($b);
164 /** @var array<int, int> $r */
165 $r = array_fill(0, $a_l + $b_l + 1, 0);
166 $base = 1 << $baseLog2;
167 for ($i = 0; $i < $a_l; ++$i) {
168 $a_i = $a[$i];
169 for ($j = 0; $j < $a_l; ++$j) {
170 $b_j = $b[$j];
171 $product = ($a_i * $b_j) + $r[$i + $j];
172 $carry = ((int) $product >> $baseLog2 & 0xffff);
173 $r[$i + $j] = ((int) $product - (int) ($carry * $base)) & 0xffff;
174 $r[$i + $j + 1] += $carry;
175 }
176 }
177 return array_slice($r, 0, 5);
178 }
179
180 /**
181 * @param int $int
182 * @return ParagonIE_Sodium_Core32_Int32
183 */
184 public function mulIntFast($int)
185 {
186 // Handle negative numbers
187 $aNeg = ($this->limbs[0] >> 15) & 1;
188 $bNeg = ($int >> 31) & 1;
189 $a = array_reverse($this->limbs);
190 $b = array(
191 $int & 0xffff,
192 ($int >> 16) & 0xffff
193 );
194 if ($aNeg) {
195 for ($i = 0; $i < 2; ++$i) {
196 $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
197 }
198 ++$a[0];
199 }
200 if ($bNeg) {
201 for ($i = 0; $i < 2; ++$i) {
202 $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
203 }
204 ++$b[0];
205 }
206 // Multiply
207 $res = $this->multiplyLong($a, $b);
208
209 // Re-apply negation to results
210 if ($aNeg !== $bNeg) {
211 for ($i = 0; $i < 2; ++$i) {
212 $res[$i] = (0xffff ^ $res[$i]) & 0xffff;
213 }
214 // Handle integer overflow
215 $c = 1;
216 for ($i = 0; $i < 2; ++$i) {
217 $res[$i] += $c;
218 $c = $res[$i] >> 16;
219 $res[$i] &= 0xffff;
220 }
221 }
222
223 // Return our values
224 $return = new ParagonIE_Sodium_Core32_Int32();
225 $return->limbs = array(
226 $res[1] & 0xffff,
227 $res[0] & 0xffff
228 );
229 if (count($res) > 2) {
230 $return->overflow = $res[2] & 0xffff;
231 }
232 $return->unsignedInt = $this->unsignedInt;
233 return $return;
234 }
235
236 /**
237 * @param ParagonIE_Sodium_Core32_Int32 $right
238 * @return ParagonIE_Sodium_Core32_Int32
239 */
240 public function mulInt32Fast(ParagonIE_Sodium_Core32_Int32 $right)
241 {
242 $aNeg = ($this->limbs[0] >> 15) & 1;
243 $bNeg = ($right->limbs[0] >> 15) & 1;
244
245 $a = array_reverse($this->limbs);
246 $b = array_reverse($right->limbs);
247 if ($aNeg) {
248 for ($i = 0; $i < 2; ++$i) {
249 $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
250 }
251 ++$a[0];
252 }
253 if ($bNeg) {
254 for ($i = 0; $i < 2; ++$i) {
255 $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
256 }
257 ++$b[0];
258 }
259 $res = $this->multiplyLong($a, $b);
260 if ($aNeg !== $bNeg) {
261 if ($aNeg !== $bNeg) {
262 for ($i = 0; $i < 2; ++$i) {
263 $res[$i] = ($res[$i] ^ 0xffff) & 0xffff;
264 }
265 $c = 1;
266 for ($i = 0; $i < 2; ++$i) {
267 $res[$i] += $c;
268 $c = $res[$i] >> 16;
269 $res[$i] &= 0xffff;
270 }
271 }
272 }
273 $return = new ParagonIE_Sodium_Core32_Int32();
274 $return->limbs = array(
275 $res[1] & 0xffff,
276 $res[0] & 0xffff
277 );
278 if (count($res) > 2) {
279 $return->overflow = $res[2];
280 }
281 return $return;
282 }
283
284 /**
285 * @param int $int
286 * @param int $size
287 * @return ParagonIE_Sodium_Core32_Int32
288 * @throws SodiumException
289 * @throws TypeError
290 */
291 public function mulInt($int = 0, $size = 0)
292 {
293 ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
294 ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
295 if (ParagonIE_Sodium_Compat::$fastMult) {
296 return $this->mulIntFast((int) $int);
297 }
298 /** @var int $int */
299 $int = (int) $int;
300 /** @var int $size */
301 $size = (int) $size;
302
303 if (!$size) {
304 $size = 31;
305 }
306 /** @var int $size */
307
308 $a = clone $this;
309 $return = new ParagonIE_Sodium_Core32_Int32();
310 $return->unsignedInt = $this->unsignedInt;
311
312 // Initialize:
313 $ret0 = 0;
314 $ret1 = 0;
315 $a0 = $a->limbs[0];
316 $a1 = $a->limbs[1];
317
318 /** @var int $size */
319 /** @var int $i */
320 for ($i = $size; $i >= 0; --$i) {
321 $m = (int) (-($int & 1));
322 $x0 = $a0 & $m;
323 $x1 = $a1 & $m;
324
325 $ret1 += $x1;
326 $c = $ret1 >> 16;
327
328 $ret0 += $x0 + $c;
329
330 $ret0 &= 0xffff;
331 $ret1 &= 0xffff;
332
333 $a1 = ($a1 << 1);
334 $x1 = $a1 >> 16;
335 $a0 = ($a0 << 1) | $x1;
336 $a0 &= 0xffff;
337 $a1 &= 0xffff;
338 $int >>= 1;
339 }
340 $return->limbs[0] = $ret0;
341 $return->limbs[1] = $ret1;
342 return $return;
343 }
344
345 /**
346 * @param ParagonIE_Sodium_Core32_Int32 $int
347 * @param int $size
348 * @return ParagonIE_Sodium_Core32_Int32
349 * @throws SodiumException
350 * @throws TypeError
351 */
352 public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0)
353 {
354 ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
355 if (ParagonIE_Sodium_Compat::$fastMult) {
356 return $this->mulInt32Fast($int);
357 }
358 if (!$size) {
359 $size = 31;
360 }
361 /** @var int $size */
362
363 $a = clone $this;
364 $b = clone $int;
365 $return = new ParagonIE_Sodium_Core32_Int32();
366 $return->unsignedInt = $this->unsignedInt;
367
368 // Initialize:
369 $ret0 = 0;
370 $ret1 = 0;
371 $a0 = $a->limbs[0];
372 $a1 = $a->limbs[1];
373 $b0 = $b->limbs[0];
374 $b1 = $b->limbs[1];
375
376 /** @var int $size */
377 /** @var int $i */
378 for ($i = $size; $i >= 0; --$i) {
379 $m = (int) (-($b1 & 1));
380 $x0 = $a0 & $m;
381 $x1 = $a1 & $m;
382
383 $ret1 += $x1;
384 $c = $ret1 >> 16;
385
386 $ret0 += $x0 + $c;
387
388 $ret0 &= 0xffff;
389 $ret1 &= 0xffff;
390
391 $a1 = ($a1 << 1);
392 $x1 = $a1 >> 16;
393 $a0 = ($a0 << 1) | $x1;
394 $a0 &= 0xffff;
395 $a1 &= 0xffff;
396
397 $x0 = ($b0 & 1) << 16;
398 $b0 = ($b0 >> 1);
399 $b1 = (($b1 | $x0) >> 1);
400
401 $b0 &= 0xffff;
402 $b1 &= 0xffff;
403
404 }
405 $return->limbs[0] = $ret0;
406 $return->limbs[1] = $ret1;
407
408 return $return;
409 }
410
411 /**
412 * OR this 32-bit integer with another.
413 *
414 * @param ParagonIE_Sodium_Core32_Int32 $b
415 * @return ParagonIE_Sodium_Core32_Int32
416 */
417 public function orInt32(ParagonIE_Sodium_Core32_Int32 $b)
418 {
419 $return = new ParagonIE_Sodium_Core32_Int32();
420 $return->unsignedInt = $this->unsignedInt;
421 $return->limbs = array(
422 (int) ($this->limbs[0] | $b->limbs[0]),
423 (int) ($this->limbs[1] | $b->limbs[1])
424 );
425 /** @var int overflow */
426 $return->overflow = $this->overflow | $b->overflow;
427 return $return;
428 }
429
430 /**
431 * @param int $b
432 * @return bool
433 */
434 public function isGreaterThan($b = 0)
435 {
436 return $this->compareInt($b) > 0;
437 }
438
439 /**
440 * @param int $b
441 * @return bool
442 */
443 public function isLessThanInt($b = 0)
444 {
445 return $this->compareInt($b) < 0;
446 }
447
448 /**
449 * @param int $c
450 * @return ParagonIE_Sodium_Core32_Int32
451 * @throws SodiumException
452 * @throws TypeError
453 * @psalm-suppress MixedArrayAccess
454 */
455 public function rotateLeft($c = 0)
456 {
457 ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
458 /** @var int $c */
459 $c = (int) $c;
460
461 $return = new ParagonIE_Sodium_Core32_Int32();
462 $return->unsignedInt = $this->unsignedInt;
463 $c &= 31;
464 if ($c === 0) {
465 // NOP, but we want a copy.
466 $return->limbs = $this->limbs;
467 } else {
468 /** @var int $c */
469
470 /** @var int $idx_shift */
471 $idx_shift = ($c >> 4) & 1;
472
473 /** @var int $sub_shift */
474 $sub_shift = $c & 15;
475
476 /** @var array<int, int> $limbs */
477 $limbs =& $return->limbs;
478
479 /** @var array<int, int> $myLimbs */
480 $myLimbs =& $this->limbs;
481
482 for ($i = 1; $i >= 0; --$i) {
483 /** @var int $j */
484 $j = ($i + $idx_shift) & 1;
485 /** @var int $k */
486 $k = ($i + $idx_shift + 1) & 1;
487 $limbs[$i] = (int) (
488 (
489 ((int) ($myLimbs[$j]) << $sub_shift)
490 |
491 ((int) ($myLimbs[$k]) >> (16 - $sub_shift))
492 ) & 0xffff
493 );
494 }
495 }
496 return $return;
497 }
498
499 /**
500 * Rotate to the right
501 *
502 * @param int $c
503 * @return ParagonIE_Sodium_Core32_Int32
504 * @throws SodiumException
505 * @throws TypeError
506 * @psalm-suppress MixedArrayAccess
507 */
508 public function rotateRight($c = 0)
509 {
510 ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
511 /** @var int $c */
512 $c = (int) $c;
513
514 $return = new ParagonIE_Sodium_Core32_Int32();
515 $return->unsignedInt = $this->unsignedInt;
516 $c &= 31;
517 /** @var int $c */
518 if ($c === 0) {
519 // NOP, but we want a copy.
520 $return->limbs = $this->limbs;
521 } else {
522 /** @var int $c */
523
524 /** @var int $idx_shift */
525 $idx_shift = ($c >> 4) & 1;
526
527 /** @var int $sub_shift */
528 $sub_shift = $c & 15;
529
530 /** @var array<int, int> $limbs */
531 $limbs =& $return->limbs;
532
533 /** @var array<int, int> $myLimbs */
534 $myLimbs =& $this->limbs;
535
536 for ($i = 1; $i >= 0; --$i) {
537 /** @var int $j */
538 $j = ($i - $idx_shift) & 1;
539 /** @var int $k */
540 $k = ($i - $idx_shift - 1) & 1;
541 $limbs[$i] = (int) (
542 (
543 ((int) ($myLimbs[$j]) >> (int) ($sub_shift))
544 |
545 ((int) ($myLimbs[$k]) << (16 - (int) ($sub_shift)))
546 ) & 0xffff
547 );
548 }
549 }
550 return $return;
551 }
552
553 /**
554 * @param bool $bool
555 * @return self
556 */
557 public function setUnsignedInt($bool = false)
558 {
559 $this->unsignedInt = !empty($bool);
560 return $this;
561 }
562
563 /**
564 * @param int $c
565 * @return ParagonIE_Sodium_Core32_Int32
566 * @throws SodiumException
567 * @throws TypeError
568 */
569 public function shiftLeft($c = 0)
570 {
571 ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
572 /** @var int $c */
573 $c = (int) $c;
574
575 $return = new ParagonIE_Sodium_Core32_Int32();
576 $return->unsignedInt = $this->unsignedInt;
577 $c &= 63;
578 /** @var int $c */
579 if ($c === 0) {
580 $return->limbs = $this->limbs;
581 } elseif ($c < 0) {
582 /** @var int $c */
583 return $this->shiftRight(-$c);
584 } else {
585 /** @var int $c */
586 /** @var int $tmp */
587 $tmp = $this->limbs[1] << $c;
588 $return->limbs[1] = (int)($tmp & 0xffff);
589 /** @var int $carry */
590 $carry = $tmp >> 16;
591
592 /** @var int $tmp */
593 $tmp = ($this->limbs[0] << $c) | ($carry & 0xffff);
594 $return->limbs[0] = (int) ($tmp & 0xffff);
595 }
596 return $return;
597 }
598
599 /**
600 * @param int $c
601 * @return ParagonIE_Sodium_Core32_Int32
602 * @throws SodiumException
603 * @throws TypeError
604 * @psalm-suppress MixedAssignment
605 * @psalm-suppress MixedOperand
606 */
607 public function shiftRight($c = 0)
608 {
609 ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
610 /** @var int $c */
611 $c = (int) $c;
612
613 $return = new ParagonIE_Sodium_Core32_Int32();
614 $return->unsignedInt = $this->unsignedInt;
615 $c &= 63;
616 /** @var int $c */
617 if ($c >= 16) {
618 $return->limbs = array(
619 (int) ($this->overflow & 0xffff),
620 (int) ($this->limbs[0])
621 );
622 $return->overflow = $this->overflow >> 16;
623 return $return->shiftRight($c & 15);
624 }
625 if ($c === 0) {
626 $return->limbs = $this->limbs;
627 } elseif ($c < 0) {
628 /** @var int $c */
629 return $this->shiftLeft(-$c);
630 } else {
631 if (!is_int($c)) {
632 throw new TypeError();
633 }
634 /** @var int $c */
635 // $return->limbs[0] = (int) (($this->limbs[0] >> $c) & 0xffff);
636 $carryLeft = (int) ($this->overflow & ((1 << ($c + 1)) - 1));
637 $return->limbs[0] = (int) ((($this->limbs[0] >> $c) | ($carryLeft << (16 - $c))) & 0xffff);
638 $carryRight = (int) ($this->limbs[0] & ((1 << ($c + 1)) - 1));
639 $return->limbs[1] = (int) ((($this->limbs[1] >> $c) | ($carryRight << (16 - $c))) & 0xffff);
640 $return->overflow >>= $c;
641 }
642 return $return;
643 }
644
645 /**
646 * Subtract a normal integer from an int32 object.
647 *
648 * @param int $int
649 * @return ParagonIE_Sodium_Core32_Int32
650 * @throws SodiumException
651 * @throws TypeError
652 */
653 public function subInt($int)
654 {
655 ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
656 /** @var int $int */
657 $int = (int) $int;
658
659 $return = new ParagonIE_Sodium_Core32_Int32();
660 $return->unsignedInt = $this->unsignedInt;
661
662 /** @var int $tmp */
663 $tmp = $this->limbs[1] - ($int & 0xffff);
664 /** @var int $carry */
665 $carry = $tmp >> 16;
666 $return->limbs[1] = (int) ($tmp & 0xffff);
667
668 /** @var int $tmp */
669 $tmp = $this->limbs[0] - (($int >> 16) & 0xffff) + $carry;
670 $return->limbs[0] = (int) ($tmp & 0xffff);
671 return $return;
672 }
673
674 /**
675 * Subtract two int32 objects from each other
676 *
677 * @param ParagonIE_Sodium_Core32_Int32 $b
678 * @return ParagonIE_Sodium_Core32_Int32
679 */
680 public function subInt32(ParagonIE_Sodium_Core32_Int32 $b)
681 {
682 $return = new ParagonIE_Sodium_Core32_Int32();
683 $return->unsignedInt = $this->unsignedInt;
684
685 /** @var int $tmp */
686 $tmp = $this->limbs[1] - ($b->limbs[1] & 0xffff);
687 /** @var int $carry */
688 $carry = $tmp >> 16;
689 $return->limbs[1] = (int) ($tmp & 0xffff);
690
691 /** @var int $tmp */
692 $tmp = $this->limbs[0] - ($b->limbs[0] & 0xffff) + $carry;
693 $return->limbs[0] = (int) ($tmp & 0xffff);
694 return $return;
695 }
696
697 /**
698 * XOR this 32-bit integer with another.
699 *
700 * @param ParagonIE_Sodium_Core32_Int32 $b
701 * @return ParagonIE_Sodium_Core32_Int32
702 */
703 public function xorInt32(ParagonIE_Sodium_Core32_Int32 $b)
704 {
705 $return = new ParagonIE_Sodium_Core32_Int32();
706 $return->unsignedInt = $this->unsignedInt;
707 $return->limbs = array(
708 (int) ($this->limbs[0] ^ $b->limbs[0]),
709 (int) ($this->limbs[1] ^ $b->limbs[1])
710 );
711 return $return;
712 }
713
714 /**
715 * @param int $signed
716 * @return self
717 * @throws SodiumException
718 * @throws TypeError
719 */
720 public static function fromInt($signed)
721 {
722 ParagonIE_Sodium_Core32_Util::declareScalarType($signed, 'int', 1);;
723 /** @var int $signed */
724 $signed = (int) $signed;
725
726 return new ParagonIE_Sodium_Core32_Int32(
727 array(
728 (int) (($signed >> 16) & 0xffff),
729 (int) ($signed & 0xffff)
730 )
731 );
732 }
733
734 /**
735 * @param string $string
736 * @return self
737 * @throws SodiumException
738 * @throws TypeError
739 */
740 public static function fromString($string)
741 {
742 ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
743 $string = (string) $string;
744 if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) {
745 throw new RangeException(
746 'String must be 4 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
747 );
748 }
749 $return = new ParagonIE_Sodium_Core32_Int32();
750
751 $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8);
752 $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff);
753 $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8);
754 $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff);
755 return $return;
756 }
757
758 /**
759 * @param string $string
760 * @return self
761 * @throws SodiumException
762 * @throws TypeError
763 */
764 public static function fromReverseString($string)
765 {
766 ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
767 $string = (string) $string;
768 if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) {
769 throw new RangeException(
770 'String must be 4 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
771 );
772 }
773 $return = new ParagonIE_Sodium_Core32_Int32();
774
775 $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8);
776 $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff);
777 $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8);
778 $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff);
779 return $return;
780 }
781
782 /**
783 * @return array<int, int>
784 */
785 public function toArray()
786 {
787 return array((int) ($this->limbs[0] << 16 | $this->limbs[1]));
788 }
789
790 /**
791 * @return string
792 * @throws TypeError
793 */
794 public function toString()
795 {
796 return
797 ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff) .
798 ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
799 ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
800 ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff);
801 }
802
803 /**
804 * @return int
805 */
806 public function toInt()
807 {
808 return (int) (
809 (($this->limbs[0] & 0xffff) << 16)
810 |
811 ($this->limbs[1] & 0xffff)
812 );
813 }
814
815 /**
816 * @return ParagonIE_Sodium_Core32_Int32
817 */
818 public function toInt32()
819 {
820 $return = new ParagonIE_Sodium_Core32_Int32();
821 $return->limbs[0] = (int) ($this->limbs[0] & 0xffff);
822 $return->limbs[1] = (int) ($this->limbs[1] & 0xffff);
823 $return->unsignedInt = $this->unsignedInt;
824 $return->overflow = (int) ($this->overflow & 0x7fffffff);
825 return $return;
826 }
827
828 /**
829 * @return ParagonIE_Sodium_Core32_Int64
830 */
831 public function toInt64()
832 {
833 $return = new ParagonIE_Sodium_Core32_Int64();
834 $return->unsignedInt = $this->unsignedInt;
835 if ($this->unsignedInt) {
836 $return->limbs[0] += (($this->overflow >> 16) & 0xffff);
837 $return->limbs[1] += (($this->overflow) & 0xffff);
838 } else {
839 $neg = -(($this->limbs[0] >> 15) & 1);
840 $return->limbs[0] = (int)($neg & 0xffff);
841 $return->limbs[1] = (int)($neg & 0xffff);
842 }
843 $return->limbs[2] = (int) ($this->limbs[0] & 0xffff);
844 $return->limbs[3] = (int) ($this->limbs[1] & 0xffff);
845 return $return;
846 }
847
848 /**
849 * @return string
850 * @throws TypeError
851 */
852 public function toReverseString()
853 {
854 return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
855 ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
856 ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
857 ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff);
858 }
859
860 /**
861 * @return string
862 */
863 public function __toString()
864 {
865 try {
866 return $this->toString();
867 } catch (TypeError $ex) {
868 // PHP engine can't handle exceptions from __toString()
869 return '';
870 }
871 }
872}
873