File Coverage

blib/lib/Lingua/HIN/Num2Word.pm
Criterion Covered Total %
statement 53 59 89.8
branch 24 28 85.7
condition 7 9 77.7
subroutine 10 11 90.9
pod 2 2 100.0
total 96 109 88.0


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; eval: (folding-mode 1); coding:utf-8 -*-
2             package Lingua::HIN::Num2Word;
3             # ABSTRACT: Number to word conversion in Hindi
4              
5 1     1   103541 use 5.16.0;
  1         4  
6 1     1   8 use utf8;
  1         3  
  1         37  
7 1     1   41 use warnings;
  1         2  
  1         74  
8              
9             # {{{ use block
10              
11 1     1   8 use Carp;
  1         4  
  1         115  
12 1     1   847 use Export::Attrs;
  1         13575  
  1         7  
13 1     1   656 use Readonly;
  1         3413  
  1         498  
14              
15             # }}}
16             # {{{ variable declarations
17              
18             my Readonly::Scalar $COPY = 'Copyright (c) PetaMem, s.r.o. 2004-present';
19             our $VERSION = '0.2603300';
20              
21             # }}}
22             # {{{ lookup tables
23              
24             my @ONES = qw(
25             शून्य एक दो तीन चार
26             पाँच छह सात आठ नौ
27             );
28              
29             # Complete irregular forms 10-99 — Hindi requires full enumeration
30             my @FULL = (
31             undef, undef, undef, undef, undef, # 0- 4 (use @ONES)
32             undef, undef, undef, undef, undef, # 5- 9 (use @ONES)
33             'दस', 'ग्यारह', 'बारह', 'तेरह', 'चौदह', # 10-14
34             'पंद्रह', 'सोलह', 'सत्रह', 'अट्ठारह', 'उन्नीस', # 15-19
35             'बीस', 'इक्कीस', 'बाईस', 'तेईस', 'चौबिस', # 20-24
36             'पच्चीस', 'छब्बीस', 'सत्ताईस', 'अट्ठाईस', 'उनतीस', # 25-29
37             'तीस', 'इकतीस', 'बत्तीस', 'तैंतीस', 'चौंतीस', # 30-34
38             'पैंतीस', 'छत्तीस', 'सैंतीस', 'अड़तीस', 'उनतालीस', # 35-39
39             'चालीस', 'इकतालीस', 'बयालीस', 'तैंतालीस', 'चौंतालीस', # 40-44
40             'पैंतालीस', 'छयालीस', 'सैंतालीस', 'अड़तालीस', 'उनचास', # 45-49
41             'पचास', 'इक्यावन', 'बावन', 'तिरेपन', 'चौवन', # 50-54
42             'पचपन', 'छप्पन', 'सत्तावन', 'अट्ठावन', 'उनसठ', # 55-59
43             'साठ', 'इकसठ', 'बासठ', 'तिरेसठ', 'चौंसठ', # 60-64
44             'पैंसठ', 'छयासठ', 'सरसठ', 'अड़सठ', 'उनहत्तर', # 65-69
45             'सत्तर', 'इकहत्तर', 'बहत्तर', 'तिहत्तर', 'चौहत्तर', # 70-74
46             'पचहत्तर', 'छिहत्तर', 'सतहत्तर', 'अठहत्तर', 'उन्यासी', # 75-79
47             'अस्सी', 'इक्यासी', 'बयासी', 'तिरासी', 'चौरासी', # 80-84
48             'पचासी', 'छियासी', 'सत्तासी', 'अठासी', 'नवासी', # 85-89
49             'नब्बे', 'इक्यानवे', 'बानवे', 'तिरानवे', 'चौरानवे', # 90-94
50             'पचानवे', 'छियानवे', 'सत्तानवे', 'अट्ठानवे', 'निन्यानवे', # 95-99
51             );
52              
53             # }}}
54              
55             # {{{ _cardinal_below_100 internal: 0-99
56              
57             sub _cardinal_below_100 {
58 20     20   30 my $n = shift;
59 20 100       66 return $ONES[$n] if $n < 10;
60 9         26 return $FULL[$n];
61             }
62              
63             # }}}
64             # {{{ num2hin_cardinal convert number to text
65              
66             sub num2hin_cardinal :Export {
67 14     14 1 235533 my $positive = shift;
68              
69 14 100 66     195 croak 'You should specify a number from interval [0, 99_99_99_999]'
      66        
      100        
70             if !defined $positive
71             || $positive !~ m{\A\d+\z}xms
72             || $positive < 0
73             || $positive > 99_99_99_999;
74              
75             # 0-99: direct lookup
76 12 100       36 return _cardinal_below_100($positive) if $positive < 100;
77              
78 8         17 my $out = '';
79 8         18 my $remain = $positive;
80              
81             # करोड़ (crore = 10^7)
82 8 100       18 if ($remain >= 1_00_00_000) {
83 2         9 my $crore = int($remain / 1_00_00_000);
84 2         4 $remain = $remain % 1_00_00_000;
85 2         6 $out .= _build_chunk($crore) . ' करोड़';
86             }
87              
88             # लाख (lakh = 10^5)
89 8 100       18 if ($remain >= 1_00_000) {
90 3         9 my $lakh = int($remain / 1_00_000);
91 3         6 $remain = $remain % 1_00_000;
92 3 100       8 $out .= ' ' if length $out;
93 3         8 $out .= _build_chunk($lakh) . ' लाख';
94             }
95              
96             # हज़ार (hazaar = 10^3)
97 8 100       20 if ($remain >= 1_000) {
98 4         10 my $hazaar = int($remain / 1_000);
99 4         8 $remain = $remain % 1_000;
100 4 100       12 $out .= ' ' if length $out;
101 4         10 $out .= _build_chunk($hazaar) . ' हज़ार';
102             }
103              
104             # सौ (sau = 10^2)
105 8 100       18 if ($remain >= 100) {
106 4         11 my $sau = int($remain / 100);
107 4         26 $remain = $remain % 100;
108 4 100       51 $out .= ' ' if length $out;
109 4         9 $out .= _cardinal_below_100($sau) . ' सौ';
110             }
111              
112             # remainder 1-99
113 8 100       18 if ($remain > 0) {
114 3 50       16 $out .= ' ' if length $out;
115 3         5 $out .= _cardinal_below_100($remain);
116             }
117              
118 8         22 return $out;
119 1     1   8 }
  1         2  
  1         8  
120              
121             # }}}
122             # {{{ _build_chunk internal: render a sub-100 chunk (for multipliers)
123              
124             sub _build_chunk {
125 9     9   16 my $n = shift;
126 9 50       28 return _cardinal_below_100($n) if $n < 100;
127              
128             # Multiplier can itself be up to 99 (e.g. 99 करोड़), so always < 100
129             # But for safety, handle hundreds within multipliers
130 0           my $h = int($n / 100);
131 0           my $r = $n % 100;
132 0           my $out = _cardinal_below_100($h) . ' सौ';
133 0 0         $out .= ' ' . _cardinal_below_100($r) if $r > 0;
134 0           return $out;
135             }
136              
137             # }}}
138             # {{{ capabilities declare supported features
139              
140             sub capabilities {
141             return {
142 0     0 1   cardinal => 1,
143             ordinal => 0,
144             };
145             }
146              
147             # }}}
148              
149             1;
150              
151             __END__