File Coverage

blib/lib/Data/Integer.pm
Criterion Covered Total %
statement 624 625 99.8
branch 180 194 92.7
condition 33 42 78.5
subroutine 188 188 100.0
pod 74 74 100.0
total 1099 1123 97.8


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Data::Integer - details of the native integer data type
4              
5             =head1 SYNOPSIS
6              
7             use Data::Integer qw(natint_bits);
8              
9             $n = natint_bits;
10              
11             # and other constants; see text
12              
13             use Data::Integer qw(nint sint uint nint_is_sint nint_is_uint);
14              
15             $ni = nint($ni);
16             $si = sint($si);
17             $ui = uint($ui);
18             if(nint_is_sint($ni)) { ...
19             if(nint_is_uint($ni)) { ...
20              
21             use Data::Integer qw(
22             nint_sgn sint_sgn uint_sgn
23             nint_abs sint_abs uint_abs
24             nint_cmp sint_cmp uint_cmp
25             nint_min sint_min uint_min
26             nint_max sint_max uint_max
27             nint_neg sint_neg uint_neg
28             nint_add sint_add uint_add
29             nint_sub sint_sub uint_sub);
30              
31             $sn = nint_sgn($ni);
32             $sn = sint_sgn($si);
33             $sn = uint_sgn($ui);
34             $ni = nint_abs($ni);
35             $si = sint_abs($si);
36             $ui = uint_abs($ui);
37             @sorted_nints = sort { nint_cmp($a, $b) } @nints;
38             @sorted_sints = sort { sint_cmp($a, $b) } @sints;
39             @sorted_uints = sort { uint_cmp($a, $b) } @uints;
40             $ni = nint_min($na, $nb);
41             $si = sint_min($sa, $sb);
42             $ui = uint_min($ua, $ub);
43             $ni = nint_max($na, $nb);
44             $si = sint_max($sa, $sb);
45             $ui = uint_max($ua, $ub);
46             $ni = nint_neg($ni);
47             $si = sint_neg($si);
48             $ui = uint_neg($ui);
49             $ni = nint_add($na, $nb);
50             $si = sint_add($sa, $sb);
51             $ui = uint_add($ua, $ub);
52             $ni = nint_sub($na, $nb);
53             $si = sint_sub($sa, $sb);
54             $ui = uint_sub($ua, $ub);
55              
56             use Data::Integer qw(
57             sint_shl uint_shl
58             sint_shr uint_shr
59             sint_rol uint_rol
60             sint_ror uint_ror);
61              
62             $si = sint_shl($si, $dist);
63             $ui = uint_shl($ui, $dist);
64             $si = sint_shr($si, $dist);
65             $ui = uint_shr($ui, $dist);
66             $si = sint_rol($si, $dist);
67             $ui = uint_rol($ui, $dist);
68             $si = sint_ror($si, $dist);
69             $ui = uint_ror($ui, $dist);
70              
71             use Data::Integer qw(
72             nint_bits_as_sint nint_bits_as_uint
73             sint_bits_as_uint uint_bits_as_sint);
74              
75             $si = nint_bits_as_sint($ni);
76             $ui = nint_bits_as_uint($ni);
77             $ui = sint_bits_as_uint($si);
78             $si = uint_bits_as_sint($ui);
79              
80             use Data::Integer qw(
81             sint_not uint_not
82             sint_and uint_and
83             sint_nand uint_nand
84             sint_andn uint_andn
85             sint_or uint_or
86             sint_nor uint_nor
87             sint_orn uint_orn
88             sint_xor uint_xor
89             sint_nxor uint_nxor
90             sint_mux uint_mux);
91              
92             $si = sint_not($si);
93             $ui = uint_not($ui);
94             $si = sint_and($sa, $sb);
95             $ui = uint_and($ua, $ub);
96             $si = sint_nand($sa, $sb);
97             $ui = uint_nand($ua, $ub);
98             $si = sint_andn($sa, $sb);
99             $ui = uint_andn($ua, $ub);
100             $si = sint_or($sa, $sb);
101             $ui = uint_or($ua, $ub);
102             $si = sint_nor($sa, $sb);
103             $ui = uint_nor($ua, $ub);
104             $si = sint_orn($sa, $sb);
105             $ui = uint_orn($ua, $ub);
106             $si = sint_xor($sa, $sb);
107             $ui = uint_xor($ua, $ub);
108             $si = sint_nxor($sa, $sb);
109             $ui = uint_nxor($ua, $ub);
110             $si = sint_mux($sa, $sb, $sc);
111             $ui = uint_mux($ua, $ub, $uc);
112              
113             use Data::Integer qw(
114             sint_madd uint_madd
115             sint_msub uint_msub
116             sint_cadd uint_cadd
117             sint_csub uint_csub
118             sint_sadd uint_sadd
119             sint_ssub uint_ssub);
120              
121             $si = sint_madd($sa, $sb);
122             $ui = uint_madd($ua, $ub);
123             $si = sint_msub($sa, $sb);
124             $ui = uint_msub($ua, $ub);
125             ($carry, $si) = sint_cadd($sa, $sb, $carry);
126             ($carry, $ui) = uint_cadd($ua, $ub, $carry);
127             ($carry, $si) = sint_csub($sa, $sb, $carry);
128             ($carry, $ui) = uint_csub($ua, $ub, $carry);
129             $si = sint_sadd($sa, $sb);
130             $ui = uint_sadd($ua, $ub);
131             $si = sint_ssub($sa, $sb);
132             $ui = uint_ssub($ua, $ub);
133              
134             use Data::Integer qw(natint_hex hex_natint);
135              
136             print natint_hex($value);
137             $value = hex_natint($string);
138              
139             =head1 DESCRIPTION
140              
141             This module is about the native integer numerical data type. A native
142             integer is one of the types of datum that can appear in the numeric part
143             of a Perl scalar. This module supplies constants describing the native
144             integer type.
145              
146             There are actually two native integer representations: signed and
147             unsigned. Both are handled by this module.
148              
149             =head1 NATIVE INTEGERS
150              
151             Each native integer format represents a value using binary place
152             value, with some fixed number of bits. The number of bits is the
153             same for both signed and unsigned representations. In each case
154             the least-significant bit has the value 1, the next 2, the next 4,
155             and so on. In the unsigned representation, this pattern continues up
156             to and including the most-significant bit, which for a 32-bit machine
157             therefore has the value 2^31 (2147483648). The unsigned format cannot
158             represent any negative numbers.
159              
160             In the signed format, the most-significant bit is exceptional, having
161             the negation of the value that it does in the unsigned format. Thus on
162             a 32-bit machine this has the value -2^31 (-2147483648). Values with
163             this bit set are negative, and those with it clear are non-negative;
164             this bit is also known as the "sign bit".
165              
166             It is usual in machine arithmetic to use one of these formats at a
167             time, for example to add two signed numbers yielding a signed result.
168             However, Perl has a trick: a scalar with a native integer value contains
169             an additional flag bit which indicates whether the signed or unsigned
170             format is being used. It is therefore possible to mix signed and unsigned
171             numbers in arithmetic, at some extra expense.
172              
173             =cut
174              
175             package Data::Integer;
176              
177 8     8   461923 { use 5.006; }
  8         30  
178 8     8   41 use warnings;
  8         15  
  8         252  
179 8     8   46 use strict;
  8         19  
  8         230  
180              
181 8     8   42 use Carp qw(croak);
  8         13  
  8         484  
182              
183             our $VERSION = "0.006";
184              
185 8     8   2234 use parent "Exporter";
  8         2192  
  8         38  
186             our @EXPORT_OK = qw(
187             natint_bits
188             min_nint max_nint min_natint max_natint
189             min_sint max_sint min_signed_natint max_signed_natint
190             min_uint max_uint min_unsigned_natint max_unsigned_natint
191             nint sint uint
192             nint_is_sint nint_is_uint
193             nint_sgn sint_sgn uint_sgn
194             nint_abs sint_abs uint_abs
195             nint_cmp sint_cmp uint_cmp
196             nint_min sint_min uint_min
197             nint_max sint_max uint_max
198             nint_neg sint_neg uint_neg
199             nint_add sint_add uint_add
200             nint_sub sint_sub uint_sub
201             sint_shl uint_shl
202             sint_shr uint_shr
203             sint_rol uint_rol
204             sint_ror uint_ror
205             nint_bits_as_sint nint_bits_as_uint
206             sint_bits_as_uint uint_bits_as_sint
207             sint_not uint_not
208             sint_and uint_and
209             sint_nand uint_nand
210             sint_andn uint_andn
211             sint_or uint_or
212             sint_nor uint_nor
213             sint_orn uint_orn
214             sint_xor uint_xor
215             sint_nxor uint_nxor
216             sint_mux uint_mux
217             sint_madd uint_madd
218             sint_msub uint_msub
219             sint_cadd uint_cadd
220             sint_csub uint_csub
221             sint_sadd uint_sadd
222             sint_ssub uint_ssub
223             natint_hex hex_natint
224             );
225              
226             =head1 CONSTANTS
227              
228             Each of the extreme-value constants has two names, a short one and a
229             long one. The short names are more convenient to use, but the long
230             names are clearer in a context where other similar constants exist.
231              
232             Due to the risks of Perl changing the behaviour of a native integer value
233             that has been involved in floating point arithmetic (see L),
234             the extreme-value constants are actually non-constant functions that
235             always return a fresh copy of the appropriate value. The returned value
236             is always a pure native integer value, unsullied by floating point or
237             string operations.
238              
239             =over
240              
241             =item natint_bits
242              
243             The width, in bits, of the native integer data types.
244              
245             =cut
246              
247             # Count the number of bits in native integers by repeatedly shifting a bit
248             # left until it turns into the sign bit. "use integer" forces the use of a
249             # signed integer representation.
250             BEGIN {
251 8     8   3482 use integer;
  8         107  
  8         38  
252 8     8   554 my $bit_count = 1;
253 8         14 my $test_bit = 1;
254 8         36 while($test_bit > 0) {
255 504         541 $bit_count += 1;
256 504         687 $test_bit <<= 1;
257             }
258 8         14 my $natint_bits = $bit_count;
259 8         303 *natint_bits = sub () { $natint_bits };
  0         0  
260             }
261              
262             =item min_nint
263              
264             =item min_natint
265              
266             The minimum representable value in either representation. This is
267             -2^(natint_bits - 1).
268              
269             =cut
270              
271             BEGIN {
272 8     8   49 my $min_nint = do { use integer; 1 << (natint_bits - 1) };
  8     8   18  
  8         75  
  8         425  
  8         18  
273 8     13117   382 *min_natint = *min_nint = sub() { my $ret = $min_nint };
  13117         51453  
274             }
275              
276             =item max_nint
277              
278             =item max_natint
279              
280             The maximum representable value in either representation. This is
281             2^natint_bits - 1.
282              
283             =cut
284              
285             BEGIN {
286 8     8   22 my $max_nint = ~0;
287 8     9167   229 *max_natint = *max_nint = sub() { my $ret = $max_nint };
  9167         23458  
288             }
289              
290             =item min_sint
291              
292             =item min_signed_natint
293              
294             The minimum representable value in the signed representation. This is
295             -2^(natint_bits - 1).
296              
297             =cut
298              
299 8     8   569 BEGIN { *min_signed_natint = *min_sint = \&min_nint; }
300              
301             =item max_sint
302              
303             =item max_signed_natint
304              
305             The maximum representable value in the signed representation. This is
306             2^(natint_bits - 1) - 1.
307              
308             =cut
309              
310             BEGIN {
311 8     8   30 my $max_sint = ~min_sint;
312 8     4427   334 *max_signed_natint = *max_sint = sub() { my $ret = $max_sint };
  4427         12880  
313             }
314              
315             =item min_uint
316              
317             =item min_unsigned_natint
318              
319             The minimum representable value in the unsigned representation.
320             This is zero.
321              
322             =cut
323              
324             BEGIN {
325 8     8   20 my $min_uint = 0;
326 8     4136   217 *min_unsigned_natint = *min_uint = sub() { my $ret = $min_uint };
  4136         12597  
327             }
328              
329             =item max_uint
330              
331             =item max_unsigned_natint
332              
333             The maximum representable value in the unsigned representation. This is
334             2^natint_bits - 1.
335              
336             =cut
337              
338 8     8   548 BEGIN { *max_unsigned_natint = *max_uint = \&max_nint; }
339              
340             =back
341              
342             =head1 FUNCTIONS
343              
344             Each "nint_", "sint_", or "uint_" function operates on one of the three
345             integer formats. "nint_" functions operate on Perl's union of signed
346             and unsigned; "sint_" functions operate on signed integers; and "uint_"
347             functions operate on unsigned integers. Except where indicated otherwise,
348             the function returns a value of its primary type.
349              
350             Parameters I, I, and I, where present, must be numbers of
351             the appropriate type: specifically, with a numerical value that can be
352             represented in that type. If there are multiple flavours of zero, due
353             to floating point funkiness, all zeroes are treated the same. Parameters
354             with other names have other requirements, explained with each function.
355              
356             The functions attempt to detect unsuitable arguments, and C if
357             an invalid argument is detected, but they can't notice some kinds of
358             incorrect argument. Generally, it is the caller's responsibility to
359             provide a sane numerical argument, and supplying an invalid argument will
360             cause mayhem. Only the numeric value of plain scalar arguments is used;
361             the string value is completely ignored, so dualvars are not a problem.
362              
363             =head2 Canonicalisation and classification
364              
365             These are basic glue functions.
366              
367             =over
368              
369             =item nint(A)
370              
371             =item sint(A)
372              
373             =item uint(A)
374              
375             These functions each take an argument in a specific integer format and
376             return its numerical value. This is the argument canonicalisation that is
377             performed by all of the functions in this module, presented in isolation.
378              
379             =cut
380              
381             sub nint($) {
382 4669     4669 1 10634 my $tval = $_[0];
383 4669 100 100     10629 croak "not a native integer"
      100        
384             unless int($tval) == $tval && $tval >= min_nint &&
385             $tval <= max_nint;
386 8 100   8   50 return ($tval = $_[0]) < 0 ? do { use integer; 0 | $_[0] } : 0 | $_[0];
  8         15  
  8         44  
  4666         10082  
  1587         3352  
387             }
388              
389             sub sint($) {
390 3930     3930 1 6672 my $tval = $_[0];
391 3930 100 100     8847 croak "not a signed native integer"
      100        
392             unless int($tval) == $tval && $tval >= min_sint &&
393             $tval <= max_sint;
394 8     8   761 my $val = do { use integer; 0 | $_[0] };
  8         12  
  8         21  
  3922         4983  
  3922         5450  
395             croak "not a signed native integer"
396 8 50 66 8   299 if $tval >= 0 && do { use integer; $val < 0 };
  8         13  
  8         26  
  3922         6418  
  2406         6120  
397 3922         8187 return $val;
398             }
399              
400             sub uint($) {
401 4135     4135 1 10017 my $tval = $_[0];
402 4135 100 100     9535 croak "not an unsigned native integer"
      100        
403             unless int($tval) == $tval && $tval >= min_uint &&
404             $tval <= max_uint;
405 4128         10023 return 0 | $_[0];
406             }
407              
408             =item nint_is_sint(A)
409              
410             Takes a native integer of either type. Returns a truth value indicating
411             whether this value can be exactly represented as a signed native integer.
412              
413             =cut
414              
415             sub nint_is_sint($) {
416 1314     1314 1 297978 my $val = nint($_[0]);
417             return (my $tval = $val) < 0 ||
418 8   66 8   884 do { use integer; ($val & min_sint) == 0 };
  8         12  
  8         23  
  1314         2868  
419             }
420              
421             =item nint_is_uint(A)
422              
423             Takes a native integer of either type. Returns a truth value indicating
424             whether this value can be exactly represented as an unsigned native
425             integer.
426              
427             =cut
428              
429 1099     1099 1 175123 sub nint_is_uint($) { nint($_[0]) >= 0 }
430              
431             =back
432              
433             =head2 Arithmetic
434              
435             These functions operate on numerical values rather than just bit patterns.
436             They will all C if the true numerical result doesn't fit into the
437             result format, rather than give a wrong answer.
438              
439             =over
440              
441             =item nint_sgn(A)
442              
443             =item sint_sgn(A)
444              
445             =item uint_sgn(A)
446              
447             Returns +1 if the argument is positive, 0 if the argument is zero,
448             or -1 if the argument is negative.
449              
450             =cut
451              
452 21     21 1 3816 sub nint_sgn($) { nint($_[0]) <=> 0 }
453              
454 8     8 1 755 sub sint_sgn($) { use integer; sint($_[0]) <=> 0 }
  8     8   18  
  8         27  
  8         32  
455              
456 8 100   8 1 348 sub uint_sgn($) { use integer; uint($_[0]) == 0 ? 0 : +1 }
  8     8   15  
  8         18  
  8         31  
457              
458             =item nint_abs(A)
459              
460             =item sint_abs(A)
461              
462             =item uint_abs(A)
463              
464             Absolute value (magnitude, discarding sign).
465              
466             =cut
467              
468             sub nint_abs($) {
469 21     21 1 46 my $a = nint($_[0]);
470 21 100       48 if((my $tval = $a) >= 0) {
    100          
471 14         38 return $a;
472 8     8   489 } elsif(do { use integer; $a == min_sint }) {
  8         14  
  8         18  
  7         16  
473 1         4 return 0 | min_sint;
474             } else {
475 8     8   240 use integer;
  8         15  
  8         26  
476 6         18 return -$a;
477             }
478             }
479              
480             sub sint_abs($) {
481 8     8 1 15 my $a = sint($_[0]);
482 8     8   437 use integer;
  8         15  
  8         16  
483 8 100       17 croak "integer overflow" if $a == min_sint;
484 7 100       30 return $a < 0 ? -$a : $a;
485             }
486              
487             *uint_abs = \&uint;
488              
489             =item nint_cmp(A, B)
490              
491             =item sint_cmp(A, B)
492              
493             =item uint_cmp(A, B)
494              
495             Arithmetic comparison. Returns -1, 0, or +1, indicating whether A is
496             less than, equal to, or greater than B.
497              
498             =cut
499              
500             sub nint_cmp($$) {
501 196     196 1 23218 my($a, $b) = (nint($_[0]), nint($_[1]));
502 196 100       341 if((my $ta = $a) < 0) {
503 70 100       122 if((my $tb = $b) < 0) {
504 8     8   734 use integer;
  8         14  
  8         32  
505 25         96 return $a <=> $b;
506             } else {
507 45         150 return -1;
508             }
509             } else {
510 126 100       220 if((my $tb = $b) < 0) {
511 45         153 return 1;
512             } else {
513 8     8   446 use integer;
  8         19  
  8         31  
514 81         114 return ($a ^ min_sint) <=> ($b ^ min_sint);
515             }
516             }
517             }
518              
519 8     8 1 454 sub sint_cmp($$) { use integer; sint($_[0]) <=> sint($_[1]) }
  8     121   15  
  8         19  
  121         460  
520              
521             sub uint_cmp($$) {
522 8     8   470 use integer;
  8         14  
  8         20  
523 81     81 1 325 return (uint($_[0]) ^ min_sint) <=> (uint($_[1]) ^ min_sint);
524             }
525              
526             =item nint_min(A, B)
527              
528             =item sint_min(A, B)
529              
530             =item uint_min(A, B)
531              
532             Arithmetic minimum. Returns the arithmetically lesser of the two
533             arguments.
534              
535             =cut
536              
537             sub nint_min($$) {
538 196     196 1 416 my($a, $b) = (nint($_[0]), nint($_[1]));
539 196 100       357 if((my $ta = $a) < 0) {
540 70 100       129 if((my $tb = $b) < 0) {
541 8     8   635 use integer;
  8         17  
  8         21  
542 25 100       73 return $a < $b ? $a : $b;
543             } else {
544 45         98 return $a;
545             }
546             } else {
547 126 100       214 if((my $tb = $b) < 0) {
548 45         91 return $b;
549             } else {
550 8     8   365 use integer;
  8         14  
  8         30  
551 81 100       128 return ($a ^ min_sint) < ($b ^ min_sint) ? $a : $b;
552             }
553             }
554             }
555              
556             sub sint_min($$) {
557 121     121 1 261 my($a, $b) = (sint($_[0]), sint($_[1]));
558 8     8   697 use integer;
  8         18  
  8         24  
559 121 100       304 return $a < $b ? $a : $b;
560             }
561              
562             sub uint_min($$) {
563 81     81 1 178 my($a, $b) = (uint($_[0]), uint($_[1]));
564 8     8   549 use integer;
  8         22  
  8         40  
565 81 100       135 return ($a ^ min_sint) < ($b ^ min_sint) ? $a : $b;
566             }
567              
568             =item nint_max(A, B)
569              
570             =item sint_max(A, B)
571              
572             =item uint_max(A, B)
573              
574             Arithmetic maximum. Returns the arithmetically greater of the two
575             arguments.
576              
577             =cut
578              
579             sub nint_max($$) {
580 196     196 1 52648 my($a, $b) = (nint($_[0]), nint($_[1]));
581 196 100       348 if((my $ta = $a) < 0) {
582 70 100       134 if((my $tb = $b) < 0) {
583 8     8   731 use integer;
  8         16  
  8         21  
584 25 100       80 return $a < $b ? $b : $a;
585             } else {
586 45         90 return $b;
587             }
588             } else {
589 126 100       223 if((my $tb = $b) < 0) {
590 45         100 return $a;
591             } else {
592 8     8   378 use integer;
  8         18  
  8         27  
593 81 100       118 return ($a ^ min_sint) < ($b ^ min_sint) ? $b : $a;
594             }
595             }
596             }
597              
598             sub sint_max($$) {
599 121     121 1 32933 my($a, $b) = (sint($_[0]), sint($_[1]));
600 8     8   621 use integer;
  8         15  
  8         21  
601 121 100       289 return $a < $b ? $b : $a;
602             }
603              
604             sub uint_max($$) {
605 81     81 1 21662 my($a, $b) = (uint($_[0]), uint($_[1]));
606 8     8   505 use integer;
  8         14  
  8         20  
607 81 100       137 return ($a ^ min_sint) < ($b ^ min_sint) ? $b : $a;
608             }
609              
610             =item nint_neg(A)
611              
612             =item sint_neg(A)
613              
614             =item uint_neg(A)
615              
616             Negation: returns -A.
617              
618             =cut
619              
620             sub nint_neg($) {
621 12     12 1 24 my $a = nint($_[0]);
622 12 100       24 if((my $ta = $a) <= 0) {
623 8     8   539 return 0 | do { use integer; -$a };
  8         17  
  8         26  
  5         8  
  5         12  
624             } else {
625 8     8   218 use integer;
  8         16  
  8         21  
626 7         15 my $neg = -$a;
627 7 100       295 croak "integer overflow" if $neg >= 0;
628 4         11 return $neg;
629             }
630             }
631              
632             sub sint_neg($) {
633 8     8 1 5676 my $a = sint($_[0]);
634 8     8   547 use integer;
  8         18  
  8         19  
635 8 100       14 croak "integer overflow" if $a == min_sint;
636 7         16 return -$a;
637             }
638              
639             sub uint_neg($) {
640 8     8   372 use integer;
  8         12  
  8         22  
641 8 100   8 1 18 croak "integer overflow" unless uint($_[0]) == 0;
642 1         3 return my $zero = 0;
643             }
644              
645             =item nint_add(A, B)
646              
647             =item sint_add(A, B)
648              
649             =item uint_add(A, B)
650              
651             Addition: returns A + B.
652              
653             =cut
654              
655             sub nint_add($$) {
656 252     252 1 129633 my($a, $b) = (nint($_[0]), nint($_[1]));
657 252 100       476 if((my $ta = $a) < 0) {
658 89 100       174 if((my $tb = $b) < 0) {
659 8     8   619 use integer;
  8         12  
  8         22  
660 34         56 my $r = $a + $b;
661 34 100       1394 croak "integer overflow" if $r > $a;
662 18         44 return $r;
663             } else {
664 8     8   339 use integer;
  8         15  
  8         23  
665 55         99 my $r = $a + $b;
666 8 100   8   219 $r = do { no integer; 0 | $r } if $r < $a;
  8         13  
  8         29  
  55         135  
  7         14  
667 55         137 return $r;
668             }
669             } else {
670 163 100       337 if((my $tb = $b) < 0) {
671 8     8   343 use integer;
  8         20  
  8         26  
672 55         109 my $r = $a + $b;
673 8 100   8   258 $r = do { no integer; 0 | $r } if $r < $b;
  8         19  
  8         24  
  55         119  
  7         13  
674 55         179 return $r;
675             } else {
676 8     8   346 use integer;
  8         17  
  8         22  
677 108         153 my $r = $a + $b;
678 108 100       154 croak "integer overflow"
679             if ($r ^ min_sint) < ($a ^ min_sint);
680 8     8   339 return do { no integer; 0 | $r };
  8         16  
  8         22  
  68         83  
  68         155  
681             }
682             }
683             }
684              
685             sub sint_add($$) {
686 148     148 1 48095 my($a, $b) = (sint($_[0]), sint($_[1]));
687 8     8   593 use integer;
  8         24  
  8         42  
688 148         246 my $r = $a + $b;
689 148 100       3600 croak "integer overflow" if $b < 0 ? $r > $a : $r < $a;
    100          
690 112         251 return $r;
691             }
692              
693             sub uint_add($$) {
694 108     108 1 31519 my($a, $b) = (uint($_[0]), uint($_[1]));
695 8     8   657 use integer;
  8         14  
  8         20  
696 108         166 my $r = $a + $b;
697 108 100       167 croak "integer overflow" if ($r ^ min_sint) < ($a ^ min_sint);
698 8     8   375 return do { no integer; 0 | $r };
  8         16  
  8         22  
  68         85  
  68         128  
699             }
700              
701             =item nint_sub(A, B)
702              
703             =item sint_sub(A, B)
704              
705             =item uint_sub(A, B)
706              
707             Subtraction: returns A - B.
708              
709             =cut
710              
711             sub nint_sub($$) {
712 234     234 1 52020 my($a, $b) = (nint($_[0]), nint($_[1]));
713 234 100       499 if((my $ta = $a) < 0) {
    100          
714 63 100       122 if((my $tb = $b) < 0) {
    100          
715 8     8   612 use integer;
  8         14  
  8         31  
716 31         87 return $a - $b;
717             } elsif(!($b & min_sint)) {
718 8     8   297 use integer;
  8         16  
  8         19  
719 22         47 my $r = $a - $b;
720 22 100       909 croak "integer overflow" if $r >= 0;
721 13         37 return $r;
722             } else {
723 10         844 croak "integer overflow";
724             }
725             } elsif(!($a & min_sint)) {
726 106 100       217 if((my $tb = $b) < 0) {
    100          
727 8     8   565 return 0 | do { use integer; $a - $b };
  8         13  
  8         22  
  35         55  
  35         131  
728             } elsif(!($b & min_sint)) {
729 8     8   285 use integer;
  8         13  
  8         22  
730 47         133 return $a - $b;
731             } else {
732 8     8   184 use integer;
  8         14  
  8         17  
733 24         37 my $r = $a - $b;
734 24 100       1041 croak "integer overflow" if $r >= 0;
735 14         33 return $r;
736             }
737             } else {
738 65 100       147 if((my $tb = $b) < 0) {
    100          
739 8     8   331 use integer;
  8         12  
  8         19  
740 16         29 my $r = $a - $b;
741 16 100       776 croak "integer overflow" if $r >= 0;
742 8     8   232 return do { no integer; 0 | $r };
  8         12  
  8         27  
  7         12  
  7         18  
743             } elsif(!($b & min_sint)) {
744 8     8   276 return 0 | do { use integer; $a - $b };
  8         15  
  8         20  
  31         44  
  31         84  
745             } else {
746 8     8   380 use integer;
  8         18  
  8         23  
747 18         53 return $a - $b;
748             }
749             }
750             }
751              
752             sub sint_sub($$) {
753 135     135 1 647 my($a, $b) = (sint($_[0]), sint($_[1]));
754 8     8   583 use integer;
  8         12  
  8         23  
755 135         210 my $r = $a - $b;
756 135 100       2411 croak "integer overflow" if $b > 0 ? $r > $a : $r < $a;
    100          
757 112         224 return $r;
758             }
759              
760             sub uint_sub($$) {
761 120     120 1 539 my($a, $b) = (uint($_[0]), uint($_[1]));
762 8     8   602 use integer;
  8         14  
  8         21  
763 120         177 my $r = $a - $b;
764 120 100       183 croak "integer overflow" if ($r ^ min_sint) > ($a ^ min_sint);
765 8     8   342 return do { no integer; 0 | $r };
  8         32  
  8         26  
  68         88  
  68         128  
766             }
767              
768             =back
769              
770             =head2 Bit shifting
771              
772             These functions all operate on the bit patterns representing integers,
773             mostly ignoring the numerical values represented. In most cases the
774             results for particular numerical arguments are influenced by the word
775             size, because that determines where a bit being left-shifted will drop
776             off the end of the word and where a bit will be shifted in during a
777             rightward shift.
778              
779             With the exception of rightward shifts (see below), each pair of
780             functions performs exactly the same operations on the bit sequences.
781             There inevitably can't be any functions here that operate on Perl's union
782             of signed and unsigned; you must choose, by which function you call,
783             which type the result is to be tagged as.
784              
785             =over
786              
787             =item sint_shl(A, DIST)
788              
789             =item uint_shl(A, DIST)
790              
791             Bitwise left shift (towards more-significant bits). I is the
792             distance to shift, in bits, and must be an integer in the range [0,
793             natint_bits). Zeroes are shifted in from the right.
794              
795             =cut
796              
797             sub sint_shl($$) {
798 21     21 1 69 my($val, $dist) = @_;
799 21         32 $dist = uint($dist);
800 21 50       41 croak "shift distance exceeds word size" if $dist >= natint_bits;
801 8     8   596 use integer;
  8         16  
  8         24  
802 21         39 return sint($val) << $dist;
803             }
804              
805             sub uint_shl($$) {
806 21     21 1 5267 my($val, $dist) = @_;
807 21         41 $dist = uint($dist);
808 21 50       44 croak "shift distance exceeds word size" if $dist >= natint_bits;
809 8     8   678 no integer;
  8         17  
  8         63  
810 21         31 return uint($val) << $dist;
811             }
812              
813             =item sint_shr(A, DIST)
814              
815             =item uint_shr(A, DIST)
816              
817             Bitwise right shift (towards less-significant bits). I is the
818             distance to shift, in bits, and must be an integer in the range [0,
819             natint_bits).
820              
821             When performing an unsigned right shift, zeroes are shifted in from the
822             left. A signed right shift is different: the sign bit gets duplicated,
823             so right-shifting a negative number always gives a negative result.
824              
825             =cut
826              
827             sub sint_shr($$) {
828 17     17 1 4008 my($val, $dist) = @_;
829 17         30 $dist = uint($dist);
830 17 50       28 croak "shift distance exceeds word size" if $dist >= natint_bits;
831 8     8   959 use integer;
  8         15  
  8         23  
832 17         24 return sint($val) >> $dist;
833             }
834              
835             sub uint_shr($$) {
836 17     17 1 4281 my($val, $dist) = @_;
837 17         34 $dist = uint($dist);
838 17 50       31 croak "shift distance exceeds word size" if $dist >= natint_bits;
839 8     8   645 no integer;
  8         16  
  8         29  
840 17         29 return uint($val) >> $dist;
841             }
842              
843             =item sint_rol(A, DIST)
844              
845             =item uint_rol(A, DIST)
846              
847             Bitwise left rotation (towards more-significant bits, with the
848             most-significant bit wrapping round to the least-significant bit).
849             I is the distance to rotate, in bits, and must be an integer in
850             the range [0, natint_bits).
851              
852             =cut
853              
854             sub sint_rol($$) {
855 21     21 1 63 my($val, $dist) = @_;
856 21         28 $dist = uint($dist);
857 21 50       38 croak "shift distance exceeds word size" if $dist >= natint_bits;
858 21         33 $val = sint($val);
859 21 100       40 return $val if $dist == 0;
860 17         33 my $low_val = $val >> (natint_bits - $dist);
861 8     8   706 use integer;
  8         15  
  8         26  
862 17         41 return $low_val | ($val << $dist);
863             }
864              
865             sub uint_rol($$) {
866 21     21 1 5172 my($val, $dist) = @_;
867 21         33 $dist = uint($dist);
868 21 50       42 croak "shift distance exceeds word size" if $dist >= natint_bits;
869 21         30 $val = uint($val);
870 21 100       37 return $val if $dist == 0;
871 17         39 return ($val >> (natint_bits - $dist)) | ($val << $dist);
872             }
873              
874             =item sint_ror(A, DIST)
875              
876             =item uint_ror(A, DIST)
877              
878             Bitwise right rotation (towards less-significant bits, with the
879             least-significant bit wrapping round to the most-significant bit).
880             I is the distance to rotate, in bits, and must be an integer in
881             the range [0, natint_bits).
882              
883             =cut
884              
885             sub sint_ror($$) {
886 21     21 1 38 my($val, $dist) = @_;
887 21         30 $dist = uint($dist);
888 21 50       32 croak "shift distance exceeds word size" if $dist >= natint_bits;
889 21         35 $val = sint($val);
890 21 100       51 return $val if $dist == 0;
891 17         24 my $low_val = $val >> $dist;
892 8     8   1259 use integer;
  8         16  
  8         28  
893 17         42 return $low_val | ($val << (natint_bits - $dist));
894             }
895              
896             sub uint_ror($$) {
897 21     21 1 38 my($val, $dist) = @_;
898 21         34 $dist = uint($dist);
899 21 50       38 croak "shift distance exceeds word size" if $dist >= natint_bits;
900 21         28 $val = uint($val);
901 21 100       34 return $val if $dist == 0;
902 17         43 return ($val >> $dist) | ($val << (natint_bits - $dist));
903             }
904              
905             =back
906              
907             =head2 Format conversion
908              
909             These functions convert between the various native integer formats
910             by reinterpreting the bit patterns used to represent the integers.
911             The bit pattern remains unchanged; its meaning changes, and so the
912             numerical value changes. Perl scalars preserve the numerical value,
913             rather than just the bit pattern, so from the Perl point of view these
914             are functions that change numbers into other numbers.
915              
916             =over
917              
918             =item nint_bits_as_sint(A)
919              
920             Converts a native integer of either type to a signed integer, by
921             reinterpreting the bits. The most-significant bit (whether a sign bit
922             or not) becomes a sign bit.
923              
924             =cut
925              
926 8     8 1 873 sub nint_bits_as_sint($) { use integer; nint($_[0]) | 0 }
  8     13   20  
  8         29  
  13         1734  
927              
928             =item nint_bits_as_uint(A)
929              
930             Converts a native integer of either type to an unsigned integer, by
931             reinterpreting the bits. The most-significant bit (whether a sign bit
932             or not) becomes an ordinary most-significant bit.
933              
934             =cut
935              
936 8     8 1 412 sub nint_bits_as_uint($) { no integer; nint($_[0]) | 0 }
  8     13   16  
  8         78  
  13         29  
937              
938             =item sint_bits_as_uint(A)
939              
940             Converts a signed integer to an unsigned integer, by reinterpreting
941             the bits. The sign bit becomes an ordinary most-significant bit.
942              
943             =cut
944              
945 8     8 1 484 sub sint_bits_as_uint($) { no integer; sint($_[0]) | 0 }
  8     9   17  
  8         31  
  9         23  
946              
947             =item uint_bits_as_sint(A)
948              
949             Converts an unsigned integer to a signed integer, by reinterpreting
950             the bits. The most-significant bit becomes a sign bit.
951              
952             =cut
953              
954 8     8 1 368 sub uint_bits_as_sint($) { use integer; uint($_[0]) | 0 }
  8     578   16  
  8         22  
  578         1639  
955              
956             =back
957              
958             =head2 Bitwise operations
959              
960             These functions all operate on the bit patterns representing integers,
961             completely ignoring the numerical values represented. They are mostly
962             not influenced by the word size, in the sense that they will produce
963             the same numerical result for the same numerical arguments regardless
964             of word size. However, a few are affected by the word size: those on
965             unsigned operands that return a non-zero result if given zero arguments.
966              
967             Each pair of functions performs exactly the same operations on the bit
968             sequences. There inevitably can't be any functions here that operate on
969             Perl's union of signed and unsigned; you must choose, by which function
970             you call, which type the result is to be tagged as.
971              
972             =over
973              
974             =item sint_not(A)
975              
976             =item uint_not(A)
977              
978             Bitwise complement (NOT).
979              
980             =cut
981              
982 8     8 1 344 sub sint_not($) { use integer; ~sint($_[0]) }
  8     8   16  
  8         25  
  8         19  
983              
984 8     8 1 349 sub uint_not($) { no integer; ~uint($_[0]) }
  8     8   17  
  8         23  
  8         827  
985              
986             =item sint_and(A, B)
987              
988             =item uint_and(A, B)
989              
990             Bitwise conjunction (AND).
991              
992             =cut
993              
994 8     8 1 351 sub sint_and($$) { use integer; sint($_[0]) & sint($_[1]) }
  8     16   20  
  8         179  
  16         47  
995              
996 8     8 1 435 sub uint_and($$) { no integer; uint($_[0]) & uint($_[1]) }
  8     16   16  
  8         28  
  16         1640  
997              
998             =item sint_nand(A, B)
999              
1000             =item uint_nand(A, B)
1001              
1002             Bitwise inverted conjunction (NAND).
1003              
1004             =cut
1005              
1006 8     8 1 481 sub sint_nand($$) { use integer; ~(sint($_[0]) & sint($_[1])) }
  8     16   19  
  8         24  
  16         57  
1007              
1008 8     8 1 458 sub uint_nand($$) { no integer; ~(uint($_[0]) & uint($_[1])) }
  8     16   14  
  8         26  
  16         1915  
1009              
1010             =item sint_andn(A, B)
1011              
1012             =item uint_andn(A, B)
1013              
1014             Bitwise conjunction with inverted argument (A AND (NOT B)).
1015              
1016             =cut
1017              
1018 8     8 1 417 sub sint_andn($$) { use integer; sint($_[0]) & ~sint($_[1]) }
  8     8   16  
  8         42  
  8         31  
1019              
1020 8     8 1 410 sub uint_andn($$) { no integer; uint($_[0]) & ~uint($_[1]) }
  8     8   18  
  8         23  
  8         1797  
1021              
1022             =item sint_or(A, B)
1023              
1024             =item uint_or(A, B)
1025              
1026             Bitwise disjunction (OR).
1027              
1028             =cut
1029              
1030 8     8 1 427 sub sint_or($$) { use integer; sint($_[0]) | sint($_[1]) }
  8     16   13  
  8         23  
  16         43  
1031              
1032 8     8 1 485 sub uint_or($$) { no integer; uint($_[0]) | uint($_[1]) }
  8     16   20  
  8         23  
  16         1966  
1033              
1034             =item sint_nor(A, B)
1035              
1036             =item uint_nor(A, B)
1037              
1038             Bitwise inverted disjunction (NOR).
1039              
1040             =cut
1041              
1042 8     8 1 536 sub sint_nor($$) { use integer; ~(sint($_[0]) | sint($_[1])) }
  8     16   17  
  8         26  
  16         59  
1043              
1044 8     8 1 516 sub uint_nor($$) { no integer; ~(uint($_[0]) | uint($_[1])) }
  8     16   18  
  8         26  
  16         2095  
1045              
1046             =item sint_orn(A, B)
1047              
1048             =item uint_orn(A, B)
1049              
1050             Bitwise disjunction with inverted argument (A OR (NOT B)).
1051              
1052             =cut
1053              
1054 8     8 1 672 sub sint_orn($$) { use integer; sint($_[0]) | ~sint($_[1]) }
  8     8   17  
  8         24  
  8         40  
1055              
1056 8     8 1 532 sub uint_orn($$) { no integer; uint($_[0]) | ~uint($_[1]) }
  8     8   17  
  8         31  
  8         2511  
1057              
1058             =item sint_xor(A, B)
1059              
1060             =item uint_xor(A, B)
1061              
1062             Bitwise symmetric difference (XOR).
1063              
1064             =cut
1065              
1066 8     8 1 555 sub sint_xor($$) { use integer; sint($_[0]) ^ sint($_[1]) }
  8     16   13  
  8         22  
  16         51  
1067              
1068 8     8 1 382 sub uint_xor($$) { no integer; uint($_[0]) ^ uint($_[1]) }
  8     16   14  
  8         21  
  16         2493  
1069              
1070             =item sint_nxor(A, B)
1071              
1072             =item uint_nxor(A, B)
1073              
1074             Bitwise symmetric similarity (NXOR).
1075              
1076             =cut
1077              
1078 8     8 1 447 sub sint_nxor($$) { use integer; ~(sint($_[0]) ^ sint($_[1])) }
  8     16   26  
  8         28  
  16         56  
1079              
1080 8     8 1 450 sub uint_nxor($$) { no integer; ~(uint($_[0]) ^ uint($_[1])) }
  8     16   16  
  8         24  
  16         1739  
1081              
1082             =item sint_mux(A, B, C)
1083              
1084             =item uint_mux(A, B, C)
1085              
1086             Bitwise multiplex. The output has a bit from B wherever A has a 1 bit,
1087             and a bit from C wherever A has a 0 bit. That is, the result is (A AND B)
1088             OR ((NOT A) AND C).
1089              
1090             =cut
1091              
1092             sub sint_mux($$$) {
1093 10     10 1 29 my $a = sint($_[0]);
1094 8     8   511 use integer;
  8         24  
  8         30  
1095 10         23 return ($a & sint($_[1])) | (~$a & sint($_[2]));
1096             }
1097              
1098             sub uint_mux($$$) {
1099 10     10 1 1100 my $a = uint($_[0]);
1100 8     8   724 no integer;
  8         27  
  8         26  
1101 10         18 return ($a & uint($_[1])) | (~$a & uint($_[2]));
1102             }
1103              
1104             =back
1105              
1106             =head2 Machine arithmetic
1107              
1108             These functions perform arithmetic operations that are inherently
1109             influenced by the word size. They always produce a well-defined output
1110             if given valid inputs. There inevitably can't be any functions here
1111             that operate on Perl's union of signed and unsigned; you must choose,
1112             by which function you call, which type the result is to be tagged as.
1113              
1114             =over
1115              
1116             =item sint_madd(A, B)
1117              
1118             =item uint_madd(A, B)
1119              
1120             Modular addition. The result for unsigned addition is (A + B)
1121             mod 2^natint_bits. The signed version behaves similarly, but with a
1122             different result range.
1123              
1124             =cut
1125              
1126 8     8 1 438 sub sint_madd($$) { use integer; sint($_[0]) + sint($_[1]) }
  8     172   13  
  8         19  
  172         499  
1127              
1128 8     8 1 489 sub uint_madd($$) { 0 | do { use integer; uint($_[0]) + uint($_[1]) } }
  8     172   35  
  8         28  
  172         22368  
  172         353  
1129              
1130             =item sint_msub(A, B)
1131              
1132             =item uint_msub(A, B)
1133              
1134             Modular subtraction. The result for unsigned subtraction is (A - B)
1135             mod 2^natint_bits. The signed version behaves similarly, but with a
1136             different result range.
1137              
1138             =cut
1139              
1140 8     8 1 436 sub sint_msub($$) { use integer; sint($_[0]) - sint($_[1]) }
  8     172   9  
  8         22  
  172         380  
1141              
1142 8     8 1 368 sub uint_msub($$) { 0 | do { use integer; uint($_[0]) - uint($_[1]) } }
  8     172   12  
  8         23  
  172         264  
  172         334  
1143              
1144             =item sint_cadd(A, B, CARRY_IN)
1145              
1146             =item uint_cadd(A, B, CARRY_IN)
1147              
1148             Addition with carry. Two word arguments (A and B) and an input carry
1149             bit (CARRY_IN, which must have the value 0 or 1) are all added together.
1150             Returns a list of two items: an output carry and an output word (of the
1151             same signedness as the inputs). Precisely, the output list (CARRY_OUT,
1152             R) is such that CARRY_OUT*2^natint_bits + R = A + B + CARRY_IN.
1153              
1154             =cut
1155              
1156             sub sint_cadd($$$) {
1157 196     196 1 104414 my($a, $b, $cin) = map { sint($_) } @_;
  588         963  
1158 8     8   601 use integer;
  8         15  
  8         20  
1159 196 50 66     574 croak "invalid carry" unless $cin == 0 || $cin == 1;
1160 196         351 my $r = $a + $b + $cin;
1161 196 100       511 my $cout = $b < 0 ? $r > $a ? -1 : 0 : $r < $a ? +1 : 0;
    100          
    100          
1162 196         466 return ($cout, $r);
1163             }
1164              
1165             sub uint_cadd($$$) {
1166 172     172 1 96360 my($a, $b, $cin) = map { uint($_) } @_;
  516         941  
1167 8     8   789 use integer;
  8         19  
  8         24  
1168 172 50 66     613 croak "invalid carry" unless $cin == 0 || $cin == 1;
1169 172         294 my $r = $a + $b;
1170 172 100       302 my $cout = ($r ^ min_sint) < ($a ^ min_sint) ? 1 : 0;
1171 172 100       379 if($cin) {
1172 86         163 $r += 1;
1173 86 100       235 $cout = 1 if $r == 0;
1174             }
1175 8     8   557 return ($cout, do { no integer; 0 | $r });
  8         20  
  8         24  
  172         237  
  172         467  
1176             }
1177              
1178             =item sint_csub(A, B, CARRY_IN)
1179              
1180             =item uint_csub(A, B, CARRY_IN)
1181              
1182             Subtraction with carry (borrow). The second word argument (B) and
1183             an input carry bit (CARRY_IN, which must have the value 0 or 1) are
1184             subtracted from the first word argument (A). Returns a list of two
1185             items: an output carry and an output word (of the same signedness as
1186             the inputs). Precisely, the output list (CARRY_OUT, R) is such that R -
1187             CARRY_OUT*2^natint_bits = A - B - CARRY_IN.
1188              
1189             =cut
1190              
1191             sub sint_csub($$$) {
1192 196     196 1 106246 my($a, $b, $cin) = map { sint($_) } @_;
  588         1027  
1193 8     8   607 use integer;
  8         16  
  8         25  
1194 196 50 66     596 croak "invalid carry" unless $cin == 0 || $cin == 1;
1195 196         351 my $r = $a - $b - $cin;
1196 196 100       575 my $cout = $b < 0 ? $r < $a ? -1 : 0 : $r > $a ? +1 : 0;
    100          
    100          
1197 196         460 return ($cout, $r);
1198             }
1199              
1200             sub uint_csub($$$) {
1201 172     172 1 95788 my($a, $b, $cin) = map { uint($_) } @_;
  516         936  
1202 8     8   763 use integer;
  8         16  
  8         28  
1203 172 50 66     653 croak "invalid carry" unless $cin == 0 || $cin == 1;
1204 172         299 my $r = $a - $b;
1205 172 100       321 my $cout = ($r ^ min_sint) > ($a ^ min_sint) ? 1 : 0;
1206 172 100       337 if($cin) {
1207 86 100       237 $cout = 1 if $r == 0;
1208 86         177 $r -= 1;
1209             }
1210 8     8   486 return ($cout, do { no integer; 0 | $r });
  8         14  
  8         27  
  172         230  
  172         491  
1211             }
1212              
1213             =item sint_sadd(A, B)
1214              
1215             =item uint_sadd(A, B)
1216              
1217             Saturating addition. The result is A + B if that will fit into the result
1218             format, otherwise the minimum or maximum value of the result format is
1219             returned depending on the direction in which the addition overflowed.
1220              
1221             =cut
1222              
1223             sub sint_sadd($$) {
1224 98     98 1 11428 my($a, $b) = map { sint($_) } @_;
  196         302  
1225 8     8   538 use integer;
  8         16  
  8         21  
1226 98         139 my $r = $a + $b;
1227 98 100       160 if($b < 0) {
1228 39 100       82 $r = min_sint if $r > $a;
1229             } else {
1230 59 100       107 $r = max_sint if $r < $a;
1231             }
1232 98         198 return $r;
1233             }
1234              
1235             sub uint_sadd($$) {
1236 86     86 1 9900 my($a, $b) = map { uint($_) } @_;
  172         268  
1237 8     8   711 use integer;
  8         16  
  8         26  
1238 86         118 my $r = $a + $b;
1239 86 100       144 $r = max_uint if ($r ^ min_sint) < ($a ^ min_sint);
1240 8     8   458 return do { no integer; 0 | $r };
  8         17  
  8         25  
  86         107  
  86         171  
1241             }
1242              
1243             =item sint_ssub(A, B)
1244              
1245             =item uint_ssub(A, B)
1246              
1247             Saturating subtraction. The result is A - B if that will fit into the
1248             result format, otherwise the minimum or maximum value of the result
1249             format is returned depending on the direction in which the subtraction
1250             overflowed.
1251              
1252             =cut
1253              
1254             sub sint_ssub($$) {
1255 92     92 1 22070 my($a, $b) = map { sint($_) } @_;
  184         288  
1256 8     8   573 use integer;
  8         15  
  8         21  
1257 92         134 my $r = $a - $b;
1258 92 100       150 if($b >= 0) {
1259 50 100       88 $r = min_sint if $r > $a;
1260             } else {
1261 42 100       73 $r = max_sint if $r < $a;
1262             }
1263 92         163 return $r;
1264             }
1265              
1266             sub uint_ssub($$) {
1267 89     89 1 20534 my($a, $b) = map { uint($_) } @_;
  178         268  
1268 8     8   694 use integer;
  8         18  
  8         25  
1269 89 100       152 my $r = ($a ^ min_sint) <= ($b ^ min_sint) ? 0 : $a - $b;
1270 8     8   306 return do { no integer; 0 | $r };
  8         16  
  8         20  
  89         114  
  89         287  
1271             }
1272              
1273             =back
1274              
1275             =head2 String conversion
1276              
1277             =over
1278              
1279             =item natint_hex(VALUE)
1280              
1281             VALUE must be a native integer value. The function encodes VALUE in
1282             hexadecimal, returning that representation as a string. Specifically,
1283             the output is of the form "IB<0x>I", where "I" is the sign
1284             and "I" is a sequence of hexadecimal digits.
1285              
1286             =cut
1287              
1288             sub natint_hex($) {
1289 9     9 1 116 my $val = nint($_[0]);
1290 9         20 my $sgn = nint_sgn($val);
1291 9         20 $val = nint_abs($val);
1292 9         14 my $digits = "";
1293 9         16 my $i = (natint_bits+3) >> 2;
1294 9         20 for(; $i >= 7; $i -= 7) {
1295 18         57 $digits = sprintf("%07x", $val & 0xfffffff).$digits;
1296 18         38 $val >>= 28;
1297             }
1298 9         17 for(; $i--; ) {
1299 18         32 $digits = sprintf("%01x", $val & 0xf).$digits;
1300 18         34 $val >>= 4;
1301             }
1302 9 100       73 return ($sgn == -1 ? "-" : "+")."0x".$digits;
1303             }
1304              
1305             =item hex_natint(STRING)
1306              
1307             Generates and returns a native integer value from a string encoding it in
1308             hexadecimal. Specifically, the input format is "[I][B<0x>]I",
1309             where "I" is the sign and "I" is a sequence of one or more
1310             hexadecimal digits. The input is interpreted case insensitively.
1311             If the value given in the string cannot be exactly represented in the
1312             native integer type, the function Cs.
1313              
1314             The core Perl function C (see L) does a similar job
1315             to this function, but differs in several ways. Principally, C
1316             doesn't handle negative values, and it gives the wrong answer for values
1317             that don't fit into the native integer type. In Perl 5.6 it also gives
1318             the wrong answer for values that don't fit into the native floating
1319             point type. It also doesn't enforce strict syntax on the input string.
1320              
1321             =cut
1322              
1323             my %hexdigit_value;
1324             {
1325 8     8   1222 use integer;
  8         20  
  8         32  
1326             $hexdigit_value{chr(ord("0") + $_)} = $_ foreach 0..9;
1327             $hexdigit_value{chr(ord("a") + $_)} = 10+$_ foreach 0..5;
1328             $hexdigit_value{chr(ord("A") + $_)} = 10+$_ foreach 0..5;
1329             }
1330              
1331             sub hex_natint($) {
1332 103     103 1 42166 my($str) = @_;
1333 103 50       639 $str =~ /\A([-+]?)(?:0x)?([0-9a-f]+)\z/i
1334             or croak "bad syntax for hexadecimal integer value";
1335 103         343 my($sign, $digits) = ($1, $2);
1336 8     8   1562 use integer;
  8         21  
  8         25  
1337 103         301 $digits =~ /\A0*/g;
1338 103 100       254 return my $zero = 0 if $digits =~ /\G\z/gc;
1339 100         198 $digits =~ /\G(.)/g;
1340 100         222 my $value = $hexdigit_value{$1};
1341 100         194 my $bits_to_go = (length($digits)-pos($digits)) << 2;
1342 100 100 33     6247 croak "integer value too large"
      66        
1343             if $bits_to_go >= natint_bits ||
1344             ($bits_to_go + 4 > natint_bits &&
1345             (max_uint >> $bits_to_go) < $value);
1346 31         87 while($digits =~ /\G(.)/g) {
1347 252         622 $value = ($value << 4) | $hexdigit_value{$1};
1348             }
1349 31 100       67 if($sign eq "-") {
1350 15         24 $value = -$value;
1351 15 100       837 croak "integer value too large" if $value >= 0;
1352 7         32 return $value;
1353             } else {
1354 8     8   1468 no integer;
  8         14  
  8         26  
1355 16         88 return 0 | $value;
1356             }
1357             }
1358              
1359             =back
1360              
1361             =head1 BUGS
1362              
1363             In Perl 5.6, when a native integer scalar is used in any arithmetic other
1364             than specifically integer arithmetic, it gets partially transformed into
1365             a floating point scalar. Even if its numerical value can be represented
1366             exactly in floating point, so that floating point arithmetic uses the
1367             correct numerical value, some operations are affected by the floatness.
1368             In particular, the stringification of the scalar doesn't necessarily
1369             represent its exact value if it is tagged as floating point.
1370              
1371             Because of this transforming behaviour, if you need to stringify a native
1372             integer it is best to ensure that it doesn't get used in any non-integer
1373             arithmetic first. If an integer scalar must be used in standard Perl
1374             arithmetic, it may be copied first and the copy operated upon to avoid
1375             causing side effects on the original. If an integer scalar might have
1376             already been transformed, it can be cleaned by passing it through the
1377             canonicalisation function C. The functions in this module all
1378             avoid modifying their arguments, and always return pristine integers.
1379              
1380             Perl 5.8+ still internally modifies integer scalars in the same
1381             circumstances, but seems to have corrected all the misbehaviour that
1382             resulted from it.
1383              
1384             Also in Perl 5.6, default Perl arithmetic doesn't necessarily work
1385             correctly on native integers. (This is part of the motivation for
1386             the myriad arithmetic functions in this module.) Default arithmetic
1387             here is strictly floating point, so if there are native integers that
1388             cannot be exactly represented in floating point then the arithmetic will
1389             approximate the values before operating on them. Perl 5.8+ attempts to
1390             use native integer operations where possible in its default arithmetic,
1391             but as of Perl 5.8.8 it doesn't always succeed. For reliable integer
1392             arithmetic, integer operations must still be requested explicitly.
1393              
1394             =head1 SEE ALSO
1395              
1396             L,
1397             L,
1398             L
1399              
1400             =head1 AUTHOR
1401              
1402             Andrew Main (Zefram)
1403              
1404             =head1 COPYRIGHT
1405              
1406             Copyright (C) 2007, 2010, 2015, 2017
1407             Andrew Main (Zefram)
1408              
1409             =head1 LICENSE
1410              
1411             This module is free software; you can redistribute it and/or modify it
1412             under the same terms as Perl itself.
1413              
1414             =cut
1415              
1416             1;