File Coverage

blib/lib/Number/WithError/LaTeX.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Number::WithError::LaTeX;
2              
3 6     6   104007 use 5.008;
  6         19  
  6         221  
4 6     6   31 use strict;
  6         11  
  6         201  
5 6     6   30 use warnings;
  6         7  
  6         303  
6              
7             our $VERSION = '0.06';
8              
9 6     6   27 use base 'Number::WithError';
  6         8  
  6         6205  
10              
11 6     6   92061 use base 'Exporter';
  6         15  
  6         366  
12             our %EXPORT_TAGS = %Number::WithError::EXPORT_TAGS;
13             our @EXPORT_OK = @Number::WithError::EXPORT_OK;
14              
15 6     6   9359 use TeX::Encode;
  0            
  0            
16             use Encode ();
17             use Carp qw/croak/;
18              
19             sub witherror { Number::WithError::LaTeX->new(@_) }
20             sub witherror_big { Number::WithError::LaTeX->new_big(@_) }
21              
22             use Params::Util qw/_ARRAY0/;
23              
24              
25             =head1 NAME
26              
27             Number::WithError::LaTeX - LaTeX output for Number::WithError
28              
29             =head1 SYNOPSIS
30              
31             use Number::WithError::LaTeX;
32            
33             my $num = Number::WithError::LaTeX->new(5.647, 0.31);
34             print $num . "\n";
35             # prints '5.65e+00 +/- 3.1e-01'
36             # (I.e. it automatically does scientific rounding)
37            
38             print $num->latex() . "\n";
39             # prints '5.65 \cdot 10^{0} \pm 3.1 \cdot 10^{-1}'
40            
41             print $num->latex(radix => ',', enclose => '$') . "\n";
42             # prints '$5,\!65 \cdot 10^{0} \pm 3,\!1 \cdot 10^{-1}$'
43            
44             print $num->encode("This will encode an e-acute (".chr(0xe9).") as \\'e") . "\n";
45             # Delegated to TeX::Encode::encode().
46             # prints 'This is a German umlaut: \"a'
47              
48             =head1 DESCRIPTION
49              
50             This class is a subclass of L. It provides the same
51             interface and the same exports.
52              
53             It adds several methods to every object. The main functionality is provided by
54             C, which dumps the object
55             as valid LaTeX code. Also, C is a convenient way to encode
56             any UTF-8 string into TeX. It is just a convenience thing since it is delegated
57             to L.
58              
59             Unlike C, this module requires perl version 5.8 or later.
60             (That is the rationale for creating a separate distribution, too.)
61              
62             =head1 EXPORT
63              
64             This module exports the following subroutines on demand. It supports
65             the C<:all> Exporter tag to export all of them. The subroutines are
66             documented in L.
67              
68             =head2 witherror
69              
70             =head2 witherror_big
71              
72             =cut
73              
74             =head1 METHODS
75              
76             This is a list of public methods.
77              
78             =head2 latex
79              
80             This method stringifies the object as valid LaTeX code. The returned
81             string is valid in a LaTeX math mode. That means, you will have to
82             enclose it in dollars or in an C environment by default.
83              
84             The method takes named parameters. All parameters are optional.
85              
86             The C parameter can set a string to enclose the produced
87             latex code in. This can be either a simple string like C<$> or an
88             array reference containing two strings. Those two strings will be
89             used for the start and end respectively. (For environments.)
90              
91             Example: (let C<$obj> be '5.6e-01 +/- 2.3e-02')
92              
93             $obj->latex(enclose => '$');
94             # returns '$5.6 \cdot 10^{-1} \pm 2.3 \cdot 10^{-2}$'
95              
96             The asymmetric environment-like C can be used as follows:
97              
98             $obj->latex(enclose => ['\begin{equation}', '\end{equation}']);
99             # returns'\begin{equation}5.6 \cdot 10^{-1} \pm 2.3 \cdot 10^{-2}\end{equation}'
100              
101             There are two convenience methods C and C which do
102             exactly what the above examples demonstrated.
103              
104             The C parameter can set the radix (I) used. The default is
105             a dot (C<.>). If you use a comma, LaTeX will generally typeset it in a way that
106             results in a space after the comma. Since that is not desireable, using a C<,>
107             as the radix results in the radix being set as C<,\!>. An example can be found
108             in the synopsis.
109              
110             =cut
111              
112             our $CFloatCapture = qr/([+-]?)(?=\d|\.\d)(\d*(?:\.\d*)?)((?:[Ee][+-]?\d+)?)/;
113              
114             sub latex {
115             my $self = shift;
116             croak("Uneven number of arguments to ".__PACKAGE__."->latex().") if @_ % 2;
117             my %opt = @_;
118             my $radix = $opt{radix};
119             if (not defined $radix) {
120             $radix = '.';
121             }
122             elsif ($radix eq '.') {
123             #fine
124             }
125             else {
126             $radix .= '\!';
127             }
128              
129             my $enclose = $opt{enclose};
130             $enclose = '' if not defined $enclose;
131             $enclose = '' if _ARRAY0($enclose) and @$enclose != 2;
132            
133             my $str = "".$self->round();
134              
135             my $result;
136             pos($str) = 0;
137             my $p = -1;
138             my $number = 1;
139             while (defined pos($str) and pos($str) < length($str)) {
140             die "Failed to advance string parser at position $p in '$str'." if pos($str) == $p;
141             $p = pos($str);
142            
143             # number
144             if ($number) {
145             $str =~ /\G\s*$CFloatCapture\s*/cgo or die "Expected number starting at position $p in '$str'.";
146             my $sgn = $1;
147             my $num = $2;
148             my $exp = $3;
149              
150             unless ($exp =~ s/^[eE]([+-]?)(\d+)$/" \\cdot 10^{".($1eq'-'?'-':'').(0+$2)."}"/e) {
151             $exp = ' \cdot 10^{0}';
152             }
153            
154             $num =~ s/\./$radix/;
155            
156             $result .= "$sgn$num$exp";
157             $number = 0;
158             }
159             # +/-, +, -
160             else {
161             $str =~ /\G\s*(\+\/\-|\+|\-)\s*/cgo or die "Expected operator (+/-, +, -) starting at position $p in '$str'.";
162             my $op = $1;
163             if ($op eq '+/-') {
164             $op = '\pm';
165             }
166              
167             $result .= " $op ";
168             $number = 1;
169             }
170            
171             }
172            
173             if (_ARRAY0($enclose)) {
174             return $enclose->[0].$result.$enclose->[1];
175             }
176             else {
177             return $enclose.$result.$enclose;
178             }
179             }
180              
181             =head2 latex_math
182              
183             Works exactly like C except that the C string defaults to C<$>.
184              
185             =cut
186              
187             sub latex_math {
188             shift()->latex(enclose => '$', @_)
189             }
190              
191             =head2 latex_equation
192              
193             Works exactly like C except that the C string defaults to the
194             environment C<\begin{equation}\n> and C<\n\end{equation}>.
195              
196             =cut
197              
198             sub latex_equation {
199             shift()->latex(enclose => ["\\begin{equation}\n", "\n\\end{equation}"], @_)
200             }
201              
202             =head2 encode
203              
204             This method encodes an arbitrary UTF-8 string as TeX. Syntax:
205              
206             my $encoded = $obj->encode($string);
207              
208             For detailed documentation, please refer to L.
209              
210             =cut
211              
212             sub encode {
213             my $self = shift;
214             return Encode::encode('latex', shift);
215             }
216              
217              
218             1;
219              
220             __END__