File Coverage

blib/lib/Convert/Number/Greek.pm
Criterion Covered Total %
statement 42 42 100.0
branch 18 18 100.0
condition 11 14 78.5
subroutine 8 8 100.0
pod 2 2 100.0
total 81 84 96.4


line stmt bran cond sub pod time code
1             package Convert::Number::Greek;
2              
3             require 5.008;
4 2     2   2990 use strict; # :-(
  2         5  
  2         81  
5 2     2   11 use warnings; # :-(
  2         4  
  2         70  
6 2     2   7684 use POSIX 'floor';
  2         15299  
  2         15  
7 2     2   2325 use utf8;
  2         4  
  2         14  
8             require Exporter;
9              
10              
11             =head1 NAME
12              
13             Convert::Number::Greek - Convert between Arabic and Greek numerals
14              
15             =cut
16              
17              
18 2         1246 use vars qw[
19             @ISA
20             @EXPORT_OK
21             $VERSION
22             @greek_digits
23             @greek_digits_uc
24 2     2   73 ];
  2         4  
25              
26             $VERSION = '0.02';
27             @ISA = 'Exporter';
28             @EXPORT_OK = qw'num2greek greek2num';
29              
30              
31             =head1 VERSION
32              
33             Version 0.02
34              
35             =head1 SYNOPSIS
36              
37             use Convert::Number::Greek qw'num2greek greek2num';
38            
39             $greek_number = num2greek 1996;
40             # $greek_number now contains
41             # "\x{375}\x{3b1}\x{3e1}\x{3df}\x{3db}\x{374}"
42              
43             $number = greek2num "\x{3b5}\x{3c3}\x{3c4}\x{3b6}'";
44             # $number now contains 567
45            
46             =head1 DESCRIPTION
47              
48             This module provides subroutines for converting between Arabic and
49             Greek numbers.
50              
51              
52             =head1 FUNCTIONS
53              
54             =over 4
55              
56             =item num2greek ( NUMBER, { OPTIONS } )
57              
58             num2greek converts an Arabic numeral to a Greek numeral in the form of
59             a Unicode string the syntax is as follows:
60              
61             NUMBER is the number to convert. It should be a string of digits,
62             nothing more (see L, below). OPTIONS (optional) is a reference
63             to a hash of boolean options. The options available are as follows:
64            
65             Option Name Default Value Description
66             upper 0 Use uppercase Greek letters
67             uc 0 " " " "
68             stigma 1 Use the stigma for 6 as opposed to
69             sigma followed by tau
70             arch_koppa 0 Use the archaic koppa instead of
71             the modern one
72             numbersign 1 Append a Greek number sign (U+0374)
73             to the resulting string
74            
75             When you specify options, C is treated as false, so
76            
77             num2greek $some_number, { uc => 1, stigma }
78              
79             actually means
80              
81             num2greek $some_number, { uc => 1, stigma => 0 }
82              
83             =cut
84            
85              
86              
87             @greek_digits = (
88             ['', qw[α β γ δ ε ϛ ζ η θ]],
89             ['', qw[ι κ λ μ ν ξ ο π ϟ]],
90             ['', qw[ρ σ τ υ φ χ ψ ω ϡ]],
91             );
92             @greek_digits_uc = (
93             ['', qw[Α Β Γ Δ Ε Ϛ Ζ Η Θ]],
94             ['', qw[Ι Κ Λ Μ Ν Ξ Ο Π Ϟ]],
95             ['', qw[Ρ Σ Τ Υ Φ Χ Ψ Ω Ϡ]],
96             );
97              
98             sub num2greek ($;$) {
99 16     16 1 551 my ($n, $options) = @_;
100 16         22 my $ret;
101              
102 16   100     47 $options ||= {};
103              
104 16 100 100     88 my @digits = $$options{uc} || $$options{upper} ? @greek_digits_uc : @greek_digits;
105            
106 16 100 66     66 exists $$options{stigma} and !$$options{stigma} and
    100          
107             local $digits[0][6] = $digits[0][6] eq 'ϛ' ? 'στ' : 'ΣΤ';
108 16 100       43 $$options{arch_koppa} and
    100          
109             local $digits[1][9] = $digits[1][9] eq 'ϟ' ? 'ϙ' : 'Ϙ';
110            
111 16         48 for my $place ( reverse 0 .. length($n) - 1 ) {
112 62         112 my $digit = substr $n, length($n) - $place - 1, 1;
113            
114 62         299 $ret .= '͵' x floor($place / 3) . # thousands indicator
115             $digits[$place % 3][$digit];
116            
117             }
118 16 100 66     59 $ret .= 'ʹ' unless exists $$options{numbersign} and !$$options{numbersign};
119 16         89 $ret;
120             }
121              
122             =item greek2num ( STRING )
123              
124             =for comment
125             later it will be =item greek2num ( STRING, { OPTIONS } )
126              
127             The C function parses a Greek numbers and returns the
128             Arabic equivalent.
129              
130             STRING is a string consisting of a Greek number. Anything following
131             the number will be ignored, but will raise a warning if
132             S> is on (unless it's just whitespace).
133              
134             Currently no options are available.
135              
136             =for comment OPTIONS is a
137             reference to a hash of booleans. The only option available at present
138             is C, which requires the digits to be in standard
139             order; id est, most significant digits first.
140              
141             =cut
142              
143             our %greek_digit_2_num = qw(
144             α 1
145             β 2
146             γ 3
147             δ 4
148             ε 5
149             ϛ 6
150             ζ 7
151             η 8
152             θ 9
153             ι 10
154             κ 20
155             λ 30
156             μ 40
157             ν 50
158             ξ 60
159             ο 70
160             π 80
161             ϟ 90
162             ρ 100
163             σ 200
164             τ 300
165             υ 400
166             φ 500
167             χ 600
168             ψ 700
169             ω 800
170             ϡ 900
171             Α 1
172             Β 2
173             Γ 3
174             Δ 4
175             Ε 5
176             Ϛ 6
177             Ζ 7
178             Η 8
179             Θ 9
180             Ι 10
181             Κ 20
182             Λ 30
183             Μ 40
184             Ν 50
185             Ξ 60
186             Ο 70
187             Π 80
188             Ϟ 90
189             Ρ 100
190             Σ 200
191             Τ 300
192             Υ 400
193             Φ 500
194             Χ 600
195             Ψ 700
196             Ω 800
197             Ϡ 900
198             ϙ 90
199             Ϙ 90
200             ᾳ 1000
201             ῃ 8000
202             ῳ 800000
203             ᾼ 1000
204             ῌ 8000
205             ῼ 800000
206             );
207              
208             sub greek2num ($;$) {
209 41     41 1 23498 my($n,$ret,$thousands,$digit) = $_[0];
210              
211 41         225 $n =~ s/^\s+//;
212              
213 41         149 while (length $n) {
214 109   66     503 $thousands = $n =~ s/^([͵,]+)// && length $1;
215 2 100   2   13 if($n =~ s/^στ//i) {
  2 100       3  
  2         29  
  109         1104  
216 2         4 $digit = 6;
217             }
218             elsif(exists $greek_digit_2_num{substr $n,0,1}) {
219 98         353 $digit = $greek_digit_2_num{substr $n,0,1,''};
220             }
221             else {
222 9         40 $n =~ s/^['’ʹ´΄]?\s*//; # straight quote, smart
223 9 100       31 length $n or last; # quote, number sign,
224 3         750 warnings::warnif( # oxia, tonos
225             numeric =>
226             qq/Argument "$_[0]" isn't numeric in greek2num/
227             );
228 3         17 last;
229             }
230 100         342 $ret += $digit * 1000**$thousands;
231             }
232 41         163 $ret;
233             }
234              
235             =back
236              
237             =head1 EXPORTS
238              
239             None by default, but you get C and C if you ask
240             for them (politely).
241              
242             =head1 DIAGNOSTICS
243              
244             The greek2num function will trigger a "non-numeric" warning if you
245             S>.
246              
247             =head1 COMPATIBILITY
248              
249             This module requires perl 5.8.0 or later, though the earliest version
250             I have tested it with is 5.8.1.
251              
252             =head1 BUGS
253              
254             The C function does not yet have any error-checking
255             mechanism in place. The input should be a string of Arabic digits, or
256             at least a value that stringifies to such. Using an argument that does
257             not fit this description may produce nonsensical results.
258              
259             =head1 AUTHOR
260              
261             Father Chrysostomos
262              
263             =cut
264              
265              
266              
267