File Coverage

blib/lib/Lingua/TLH/Numbers.pm
Criterion Covered Total %
statement 39 39 100.0
branch 14 16 87.5
condition 9 9 100.0
subroutine 8 8 100.0
pod 2 2 100.0
total 72 74 97.3


line stmt bran cond sub pod time code
1             package Lingua::TLH::Numbers;
2              
3 2     2   23852 use 5.008_001;
  2         7  
  2         98  
4 2     2   10 use strict;
  2         5  
  2         70  
5 2     2   10 use warnings;
  2         4  
  2         50  
6 2     2   1017 use Readonly;
  2         3546  
  2         128  
7 2     2   1111 use Regexp::Common qw( number );
  2         5903  
  2         14  
8              
9 2     2   3589 use base qw( Exporter );
  2         4  
  2         1205  
10             our @EXPORT_OK = qw( num2tlh num2tlh_ordinal );
11             our %EXPORT_TAGS = ( all => \@EXPORT_OK );
12              
13             our $VERSION = '0.01';
14              
15             # up to 9 million supported
16             Readonly my $MAX_INT_DIGITS => 7;
17              
18             Readonly my $EMPTY_STR => q{};
19             Readonly my $SPACE => q{ };
20             Readonly my $MINUS => q{-};
21              
22             Readonly my $POINT => q{vI'};
23             Readonly my $ORDINAL_SUFFIX => q{DIch};
24              
25             Readonly my @NAMES1 => qw< pagh wa' cha' wej loS vagh jav Soch chorgh Hut >;
26             Readonly my @NAMES2 => $EMPTY_STR, qw< maH vatlh SaD netlh bIp 'uy' >;
27              
28             # convert number to words
29             sub num2tlh {
30 84     84 1 36806 my ($number) = @_;
31 84         101 my $digit_count = 0;
32 84         110 my @names;
33              
34 84 100       189 return unless defined $number;
35              
36             # NaN and inf not supported
37 83 100 100     537 return if $number eq 'NaN' || $number =~ m{^ [-+]? inf $}ix;
38              
39 79 100       418 return if $number !~ m{^ $RE{num}{real}{-keep} $}x;
40 73         12433 my ($sign, $int, $frac) = ($2, $4, $6);
41              
42             # negatives not supported
43 73 100       245 return if $sign eq $MINUS;
44              
45 66 50       474 return if length $int > $MAX_INT_DIGITS;
46              
47             # integer
48             DIGIT:
49 66         438 for my $digit (reverse split $EMPTY_STR, $int) {
50             # skip zero unless it is the only digit
51 198 100 100     993 next DIGIT if $digit == 0 && $int != 0;
52              
53 92         329 unshift @names, $NAMES1[$digit] . $NAMES2[$digit_count];
54             }
55             continue {
56 198         1147 $digit_count++;
57             }
58              
59             # fraction
60 66 100 100     224 if (defined $frac && $frac ne $EMPTY_STR) {
61 12         93 push @names, $POINT, map { $NAMES1[$_] } split $EMPTY_STR, $frac;
  18         133  
62             }
63              
64 66         276 return join $SPACE, @names;
65             }
66              
67             # convert number to ordinal words
68             sub num2tlh_ordinal {
69 23     23 1 12020 my ($number) = @_;
70 23         48 my $name = num2tlh($number);
71              
72 23 50       195 return unless defined $name;
73 23         60 return $name . $ORDINAL_SUFFIX;
74             }
75              
76             1;
77              
78             __END__