File Coverage

blib/lib/RPerl/DataType/GMPInteger.pm
Criterion Covered Total %
statement 52 99 52.5
branch 0 10 0.0
condition n/a
subroutine 18 26 69.2
pod 0 12 0.0
total 70 147 47.6


line stmt bran cond sub pod time code
1             # [[[ HEADER ]]]
2             package RPerl::DataType::GMPInteger;
3 1     1   7 use strict;
  1         2  
  1         23  
4 1     1   4 use warnings;
  1         2  
  1         21  
5 1     1   4 use RPerl::AfterSubclass;
  1         2  
  1         130  
6             our $VERSION = 0.003_100;
7              
8             # [[[ OO INHERITANCE ]]]
9             #use parent qw(Math::BigInt RPerl::DataType::Scalar); # NEED UPGRADE, CORRELATION #rp023: Inline::CPP support for multiple inheritance
10 1     1   7 use parent qw(Math::BigInt);
  1         3  
  1         10  
11 1     1   21806 use Math::BigInt lib => 'GMP'; # we still actually use GMP in PERLOPS_PERLTYPES mode, albeit indirectly via Math::BigInt::GMP
  1         3  
  1         6  
12 1     1   20649 use RPerl::DataType::Scalar;
  1         4  
  1         49  
13              
14             # [[[ CRITICS ]]]
15             ## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls) # USER DEFAULT 1: allow numeric values & print operator
16             ## no critic qw(RequireInterpolationOfMetachars) # USER DEFAULT 2: allow single-quoted control characters & sigils
17             ## no critic qw(Capitalization ProhibitMultiplePackages ProhibitReusedNames) # SYSTEM DEFAULT 3: allow multiple & lower case package names
18              
19             # [[[ SUB-TYPES ]]]
20             # a gmp_integer is multi-precision integer using the GMP library
21             package # hide from PAUSE indexing
22             gmp_integer;
23 1     1   6 use strict;
  1         2  
  1         22  
24 1     1   6 use warnings;
  1         3  
  1         45  
25 1     1   6 use parent qw(RPerl::DataType::GMPInteger);
  1         2  
  1         14  
26              
27             # [[[ PRE-DECLARED TYPES ]]]
28             package # hide from PAUSE indexing
29             boolean;
30             package # hide from PAUSE indexing
31             unsigned_integer;
32             package # hide from PAUSE indexing
33             integer;
34             package # hide from PAUSE indexing
35             number;
36             package # hide from PAUSE indexing
37             character;
38             package # hide from PAUSE indexing
39             string;
40              
41             # [[[ SWITCH CONTEXT BACK TO PRIMARY PACKAGE ]]]
42             package RPerl::DataType::GMPInteger;
43 1     1   99 use strict;
  1         2  
  1         18  
44 1     1   5 use warnings;
  1         3  
  1         25  
45              
46             # [[[ INCLUDES ]]]
47             # for type-checking via RPerl_SvHROKp(); inside INIT to delay until after 'use MyConfig';
48             # NEED ADDRESS: INIT disabled due to warning "too late to run INIT block", do we need it any more?
49             #INIT {
50 1     1   6 use RPerl::HelperFunctions_cpp;
  1         4  
  1         42  
51             RPerl::HelperFunctions_cpp::cpp_load();
52              
53             #}
54 1     1   702 use RPerl::Operation::Expression::Operator::GMPFunctions;
  1         3  
  1         150  
55              
56             # [[[ EXPORTS ]]]
57 1     1   9 use Exporter 'import';
  1         2  
  1         1255  
58             our @EXPORT = qw(
59             gmp_integer_to_boolean gmp_integer_to_unsigned_integer gmp_integer_to_integer gmp_integer_to_number gmp_integer_to_character gmp_integer_to_string
60             boolean_to_gmp_integer integer_to_gmp_integer unsigned_integer_to_gmp_integer number_to_gmp_integer character_to_gmp_integer string_to_gmp_integer
61             );
62              
63             # DEV NOTE: never call Math::BigInt->new() without arg, to avoid 'Use of uninitialized value in new' introduced in M::BI v1.999712
64             our gmp_integer $new = sub {
65             ( my string $class, my number $input ) = @_;
66             if ( defined $input ) { return Math::BigInt::new( 'gmp_integer', $input ); }
67             else { return Math::BigInt::new( 'gmp_integer', 0 ); }
68             };
69              
70             # [[[ TYPE-CHECKING ]]]
71             our void $gmp_integer_CHECK = sub {
72             ( my $possible_gmp_integer ) = @_;
73              
74             # RPerl::diag("in PERLOPS_PERLTYPES gmp_integer(), top of subroutine\n");
75             if ( not( defined $possible_gmp_integer ) ) {
76             croak(
77             "\nERROR EMV00, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but undefined/null value found,\ncroaking"
78             );
79             }
80             if ( not( main::RPerl_SvHROKp($possible_gmp_integer) ) ) {
81             croak("\nERROR EMV01, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-hashref value found,\ncroaking");
82             }
83             my string $classname = main::class($possible_gmp_integer);
84             if ( not defined $classname ) {
85             croak(
86             "\nERROR EMV02, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-object (blessed hashref) value found,\ncroaking"
87             );
88             }
89             if ( not( UNIVERSAL::isa( $possible_gmp_integer, 'Math::BigInt' ) ) ) {
90             croak(
91             "\nERROR EMV03, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-Math::BigInt-derived object value found,\ncroaking"
92             );
93             }
94             if ( $classname ne 'gmp_integer' ) {
95             croak(
96             "\nERROR EMV04, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-gmp_integer object value found,\ncroaking"
97             );
98             }
99             if ( not exists $possible_gmp_integer->{value} ) {
100             croak(
101             "\nERROR EMV05, MISSING HASH ENTRY, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped object in hash entry expected at key 'value' but no hash entry exists,\ncroaking"
102             );
103             }
104             if ( not defined $possible_gmp_integer->{value} ) {
105             croak(
106             "\nERROR EMV06, MISSING HASH ENTRY, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped object in hash entry expected at key 'value' but no hash entry defined;\nOR\nERROR EMV07, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped value expected but undefined/null value found,\ncroaking"
107             );
108             }
109             if ( not defined main::class( $possible_gmp_integer->{value} ) ) {
110             croak(
111             "\nERROR EMV08, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped value expected but non-object (blessed hashref) value found,\ncroaking"
112             );
113             }
114             if ( not( UNIVERSAL::isa( $possible_gmp_integer->{value}, 'Math::BigInt::GMP' ) ) ) {
115             croak(
116             "\nERROR EMV09, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped value expected but non-Math::BigInt::GMP object value found,\ncroaking"
117             );
118             }
119              
120             # RPerl::diag("in PERLOPS_PERLTYPES gmp_integer(), bottom of subroutine\n");
121             };
122              
123             our void $gmp_integer_CHECKTRACE = sub {
124             ( my $possible_gmp_integer, my $variable_name, my $subroutine_name ) = @_;
125              
126             # RPerl::diag("in PERLOPS_PERLTYPES gmp_integer_CHECKTRACE(), top of subroutine\n");
127             if ( not( defined $possible_gmp_integer ) ) {
128             croak(
129             "\nERROR EMV00, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but undefined/null value found,\nin variable "
130             . $variable_name
131             . " from subroutine "
132             . $subroutine_name
133             . ",\ncroaking" );
134             }
135             if ( not( main::RPerl_SvHROKp($possible_gmp_integer) ) ) {
136             croak(
137             "\nERROR EMV01, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-hashref value found,\nin variable "
138             . $variable_name
139             . " from subroutine "
140             . $subroutine_name
141             . ",\ncroaking" );
142             }
143             my string $classname = main::class($possible_gmp_integer);
144             if ( not defined $classname ) {
145             croak(
146             "\nERROR EMV02, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-object (blessed hashref) value found,\nin variable "
147             . $variable_name
148             . " from subroutine "
149             . $subroutine_name
150             . ",\ncroaking" );
151             }
152             if ( not( UNIVERSAL::isa( $possible_gmp_integer, 'Math::BigInt' ) ) ) {
153             croak(
154             "\nERROR EMV03, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-Math::BigInt-derived object value found,\nin variable "
155             . $variable_name
156             . " from subroutine "
157             . $subroutine_name
158             . ",\ncroaking" );
159             }
160             if ( $classname ne 'gmp_integer' ) {
161             croak(
162             "\nERROR EMV04, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer external wrapper value expected but non-gmp_integer object value found,\nin variable "
163             . $variable_name
164             . " from subroutine "
165             . $subroutine_name
166             . ",\ncroaking" );
167             }
168             if ( not exists $possible_gmp_integer->{value} ) {
169             croak(
170             "\nERROR EMV05, MISSING HASH ENTRY, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped object in hash entry expected at key 'value' but no hash entry exists,\nin variable "
171             . $variable_name
172             . " from subroutine "
173             . $subroutine_name
174             . ",\ncroaking" );
175             }
176             if ( not defined $possible_gmp_integer->{value} ) {
177             croak(
178             "\nERROR EMV06, MISSING HASH ENTRY, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped object in hash entry expected at key 'value' but no hash entry defined;\nOR\nERROR EMV07, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped value expected but undefined/null value found,\nin variable "
179             . $variable_name
180             . " from subroutine "
181             . $subroutine_name
182             . ",\ncroaking" );
183             }
184             if ( not defined main::class( $possible_gmp_integer->{value} ) ) {
185             croak(
186             "\nERROR EMV08, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped value expected but non-object (blessed hashref) value found,\nin variable "
187             . $variable_name
188             . " from subroutine "
189             . $subroutine_name
190             . ",\ncroaking" );
191             }
192             if ( not( UNIVERSAL::isa( $possible_gmp_integer->{value}, 'Math::BigInt::GMP' ) ) ) {
193             croak(
194             "\nERROR EMV09, TYPE-CHECKING MISMATCH, PERLOPS_PERLTYPES:\ngmp_integer internal wrapped value expected but non-Math::BigInt::GMP object value found,\nin variable "
195             . $variable_name
196             . " from subroutine "
197             . $subroutine_name
198             . ",\ncroaking" );
199             }
200              
201             # RPerl::diag("in PERLOPS_PERLTYPES gmp_integer_CHECKTRACE(), bottom of subroutine\n");
202             };
203              
204             # [[[ BOOLEANIFY ]]]
205             #our boolean $gmp_integer_to_boolean = sub {
206             sub gmp_integer_to_boolean {
207 46     46 0 10395942 ( my gmp_integer $input_gmp_integer ) = @_;
208              
209             # gmp_integer_CHECK($input_gmp_integer);
210 46         1291 gmp_integer_CHECKTRACE( $input_gmp_integer, '$input_gmp_integer', 'gmp_integer_to_boolean()' );
211 0 0       0 if ( gmp_get_signed_integer($input_gmp_integer) == 0 ) { return 0; } # DEV NOTE: this one matches the C++ code more closely
  0         0  
212              
213             # if ( $input_gmp_integer->is_zero() ) { return 0; } # but this one may be faster?
214 0         0 else { return 1; }
215             }
216              
217             # [[[ UNSIGNED INTEGERIFY ]]]
218             #our unsigned_integer $gmp_integer_to_unsigned_integer = sub {
219             sub gmp_integer_to_unsigned_integer {
220 6     6 0 724 ( my gmp_integer $input_gmp_integer ) = @_;
221              
222             # gmp_integer_CHECK($input_gmp_integer);
223 6         137 gmp_integer_CHECKTRACE( $input_gmp_integer, '$input_gmp_integer', 'gmp_integer_to_unsigned_integer()' );
224 0         0 return abs $input_gmp_integer->numify();
225             }
226              
227             # [[[ INTEGERIFY ]]]
228             #our integer $gmp_integer_to_integer = sub {
229             sub gmp_integer_to_integer {
230 8     8 0 1091 ( my gmp_integer $input_gmp_integer ) = @_;
231              
232             # gmp_integer_CHECK($input_gmp_integer);
233 8         189 gmp_integer_CHECKTRACE( $input_gmp_integer, '$input_gmp_integer', 'gmp_integer_to_integer()' );
234 0         0 return $input_gmp_integer->numify();
235             }
236              
237             # [[[ NUMBERIFY ]]]
238             #our number $gmp_integer_to_number = sub {
239             sub gmp_integer_to_number {
240 0     0 0 0 ( my gmp_integer $input_gmp_integer ) = @_;
241              
242             # gmp_integer_CHECK($input_gmp_integer);
243 0         0 gmp_integer_CHECKTRACE( $input_gmp_integer, '$input_gmp_integer', 'gmp_integer_to_number()' );
244 0         0 return $input_gmp_integer->numify() * 1.0;
245             }
246              
247             # [[[ CHARACTERIFY ]]]
248             #our character $gmp_integer_to_character = sub {
249             sub gmp_integer_to_character {
250 0     0 0 0 ( my gmp_integer $input_gmp_integer ) = @_;
251              
252             # gmp_integer_CHECK($input_gmp_integer);
253 0         0 gmp_integer_CHECKTRACE( $input_gmp_integer, '$input_gmp_integer', 'gmp_integer_to_character()' );
254 0         0 my string $tmp_string = gmp_integer_to_string($input_gmp_integer);
255 0 0       0 if ( $tmp_string eq q{} ) { return q{}; }
  0         0  
256 0         0 else { return substr $tmp_string, 0, 1; }
257             }
258              
259             # [[[ STRINGIFY ]]]
260             #our string $gmp_integer_to_string = sub {
261             sub gmp_integer_to_string {
262 0     0 0 0 ( my gmp_integer $input_gmp_integer ) = @_;
263              
264             # gmp_integer_CHECK($input_gmp_integer);
265 0         0 gmp_integer_CHECKTRACE( $input_gmp_integer, '$input_gmp_integer', 'gmp_integer_to_string()' );
266              
267             # RPerl::diag("in PERLOPS_PERLTYPES gmp_integer_to_string(), received \$input_gmp_integer = $input_gmp_integer\n");
268              
269 0         0 my integer $is_negative = $input_gmp_integer->is_neg();
270 0         0 my string $retval = reverse $input_gmp_integer->bstr();
271 0 0       0 if ($is_negative) { chop $retval; } # remove negative sign
  0         0  
272 0         0 $retval =~ s/(\d{3})/$1_/gxms;
273 0 0       0 if ( ( substr $retval, -1, 1 ) eq '_' ) { chop $retval; }
  0         0  
274 0         0 $retval = reverse $retval;
275              
276 0 0       0 if ($is_negative) { $retval = q{-} . $retval; }
  0         0  
277              
278             # RPerl::diag('in PERLOPS_PERLTYPES gmp_integer_to_string(), have $retval = ' . q{'} . $retval . q{'} . "\n");
279 0         0 return $retval;
280             }
281              
282             # [[[ GMP INTEGERIFY ]]]
283             # DEV NOTE: keep all these *_to_gmp_integer() conversion subroutines here instead of spread throughout the other RPerl/DataType/*.pm files,
284             # so that loading will all be controlled by the 'use rperlgmp;' directive
285              
286             #our gmp_integer $boolean_to_gmp_integer = sub {
287             sub boolean_to_gmp_integer {
288 0     0 0 0 ( my boolean $input_boolean ) = @_;
289              
290             # ::boolean_CHECK($input_boolean);
291 0         0 ::boolean_CHECKTRACE( $input_boolean, '$input_boolean', 'boolean_to_gmp_integer()' );
292 0         0 my gmp_integer $output_gmp_integer = gmp_integer->new($input_boolean);
293 0         0 return $output_gmp_integer;
294             }
295              
296             #our gmp_integer $integer_to_gmp_integer = sub {
297             sub integer_to_gmp_integer {
298 4     4 0 7306 ( my integer $input_integer ) = @_;
299              
300             # ::integer_CHECK($input_integer);
301 4         28 ::integer_CHECKTRACE( $input_integer, '$input_integer', 'integer_to_gmp_integer()' );
302 4         150 my gmp_integer $output_gmp_integer = gmp_integer->new($input_integer);
303 4         190 return $output_gmp_integer;
304             }
305              
306             #our gmp_integer $unsigned_integer_to_gmp_integer = sub {
307             sub unsigned_integer_to_gmp_integer {
308 0     0 0   ( my unsigned_integer $input_unsigned_integer ) = @_;
309              
310             # ::unsigned_integer_CHECK($input_unsigned_integer);
311 0           ::unsigned_integer_CHECKTRACE( $input_unsigned_integer, '$input_unsigned_integer', 'unsigned_integer_to_gmp_integer()' );
312 0           my gmp_integer $output_gmp_integer = gmp_integer->new($input_unsigned_integer);
313 0           return $output_gmp_integer;
314             }
315              
316             #our gmp_integer $number_to_gmp_integer = sub {
317             sub number_to_gmp_integer {
318 0     0 0   ( my number $input_number ) = @_;
319              
320             # ::number_CHECK($input_number);
321 0           ::number_CHECKTRACE( $input_number, '$input_number', 'number_to_gmp_integer()' );
322 0           my gmp_integer $output_gmp_integer = gmp_integer->new( number_to_integer($input_number) );
323 0           return $output_gmp_integer;
324             }
325              
326             #our gmp_integer $character_to_gmp_integer = sub {
327             sub character_to_gmp_integer {
328 0     0 0   ( my character $input_character ) = @_;
329              
330             # ::character_CHECK($input_character);
331 0           ::character_CHECKTRACE( $input_character, '$input_character', 'character_to_gmp_integer()' );
332 0           my gmp_integer $output_gmp_integer = gmp_integer->new( character_to_integer($input_character) );
333 0           return $output_gmp_integer;
334             }
335              
336             #our gmp_integer $string_to_gmp_integer = sub {
337             sub string_to_gmp_integer {
338 0     0 0   ( my string $input_string ) = @_;
339              
340             # ::string_CHECK($input_string);
341 0           ::string_CHECKTRACE( $input_string, '$input_string', 'string_to_gmp_integer()' );
342 0           my gmp_integer $output_gmp_integer = gmp_integer->new( string_to_integer($input_string) );
343 0           return $output_gmp_integer;
344             }
345              
346             # [[[ TYPE TESTING ]]]
347             our gmp_integer $gmp_integer__typetest0 = sub {
348             my gmp_integer $retval = ( 21 / 7 ) + main::RPerl__DataType__Integer__MODE_ID(); # return gmp_integer (not number) value, don't do (22 / 7) etc.
349              
350             # RPerl::diag("in PERLOPS_PERLTYPES gmp_integer__typetest0(), have \$retval = $retval\n");
351             return ($retval);
352             };
353             our gmp_integer $gmp_integer__typetest1 = sub {
354             ( my gmp_integer $lucky_gmp_integer ) = @_;
355              
356             # ::gmp_integer_CHECK($lucky_gmp_integer);
357             ::gmp_integer_CHECKTRACE( $lucky_gmp_integer, '$lucky_gmp_integer', 'gmp_integer__typetest1()' );
358              
359             # RPerl::diag('in PERLOPS_PERLTYPES gmp_integer__typetest1(), received $lucky_gmp_integer = ' . gmp_integer_to_string($lucky_gmp_integer) . "\n");
360             return ( ( $lucky_gmp_integer * 2 ) + main::RPerl__DataType__Integer__MODE_ID() );
361             };
362              
363             1; # end of class