1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
26 #include "doc_Text.hh"
27 #include "compatibility.hh"
39 #define M_PI 3.14159265358979323846
43 #define M_PI_2 1.57079632679489661923
47 #define M_PI_4 0.785398163397448309616
51 #define M_E 2.71828182845904523536
54 extern bool gInternDoubleSwitch
;
55 const string
symbolicNumber (double n
);
61 * Suppress trailing zero in a string representating a floating point number.
62 * example : 1.00000 -> 1.0
63 * example : 1.00000f -> 1.0f
66 static void zdel(char* c
)
68 int l
= strlen(c
) - 1;
69 bool f
= (c
[l
] == 'f');
71 if (f
) c
[l
--] = 0; // remove trailing if any f
72 while ( l
>1 && c
[l
-1] != '.' && c
[l
] == '0') c
[l
--] = 0;
73 if (f
) c
[++l
] = 'f'; // restaure trailing f if needed
77 string
docT (char* c
) { return string(c
); }
78 string
docT (int n
) { char c
[64]; snprintf(c
, 63, "%d",n
); return string(c
); }
79 string
docT (long n
) { char c
[64]; snprintf(c
, 63, "%ld",n
); return string(c
); }
80 string
docT (double n
) { return symbolicNumber(n
); }
84 //*****************************SYMBOLIC NUMBER REPRESENTATION*******************
88 * Compute the smallest float representable
89 * difference epsilon such that 1 != 1+epsilon
96 } while ((float)(1.0 + (machEps
/2.0)) != 1.0);
102 * Compute the smallest double representable
103 * difference epsilon such that 1 != 1+epsilon
107 double machEps
= 1.0f
;
110 } while ((1.0 + (machEps
/2.0)) != 1.0);
116 * Check if two floating point numbers are (almost) equal
119 static bool AlmostEqual(double A
, double B
)
121 double maxRelativeError
= 2*dblEpsilon();
122 double maxAbsoluteError
= maxRelativeError
;
125 if (fabs(A
- B
) < maxAbsoluteError
)
127 double relativeError
;
128 if (fabs(B
) > fabs(A
))
129 relativeError
= fabs((A
- B
) / B
);
131 relativeError
= fabs((A
- B
) / A
);
132 if (relativeError
<= maxRelativeError
)
139 * Return true if n>0 is equal to PI^k for some small integer k.
140 * k = log(n)/log(pi) is integer => n = exp(int(k)*log(pi))
141 * The latex representation \pi^{k} is returned in string s
143 bool isPiPower (double n
, string
& s
)
146 stringstream
ss (stringstream::out
|stringstream::in
);
147 int k
= floor(log(n
)/log(M_PI
));
148 if ( AlmostEqual(n
, exp(k
* log(M_PI
))) && (k
!=0) && (abs(k
)<5.0) ) {
150 if (k
!=1) ss
<< "^{"<< k
<<"}";
160 * Return true if n>0 is equal to e^k for some small integer k.
161 * The latex representation e^{k} is returned in string s
163 bool isExpPower (double n
, string
& s
)
166 stringstream
ss (stringstream::out
|stringstream::in
);
167 int k
= floor(log(n
));
168 if ( AlmostEqual(n
, exp(k
)) && (k
!=0) && (abs(k
)<5.0) ) {
170 if (k
!=1) ss
<< "^{"<< k
<<"}";
180 * Return true if n>0 is equal to e^k or PI^k for some integer k
181 * The symbolic latex representation is returned in string s
183 bool isSymbolicPower (double n
, string
& s
)
186 if (isPiPower(n
,s
)) {
188 } else if (isExpPower(n
,s
)) {
197 * Return exp or num.exp, or exp/denom, or num/denom.exp
199 const string
addFraction (int num
, int denom
, const string
& exp
)
201 stringstream
ss (stringstream::out
|stringstream::in
);
203 if ((num
==1) & (denom
==1)) {
205 } else if ((num
==1) & (denom
!=1)) {
206 ss
<< "\\frac{"<< exp
<< "}{" << denom
<< "}";
207 } else if ((num
!=1) & (denom
==1)) {
208 ss
<< num
<< "*" << exp
;
210 ss
<< "\\frac{"<< num
<< "}{" << denom
<< "}*" << exp
;
217 * Return symbolic or numerical representation of n>0
219 const string
positiveSymbolicNumber (double n
)
224 // Try to find a symbolic representation
226 for (int i
=1;i
<10;i
++) {
227 for(int j
=1;j
<10;j
++) {
228 if (isSymbolicPower(i
*n
/j
,s
)) {
229 return addFraction(j
,i
,s
);
234 // No symbolic representation,
235 // Then numerical representation x.10^k
238 string entree
= " * 10^{";
240 string::size_type ps
;
242 snprintf(tmp
, 63, "%.15g", n
); // Warning: over 15 decimals, results are wrong !!
246 if (ps
!= string::npos
) {
247 s
.replace(ps
, 1, "");
248 s
.insert(ps
, entree
);
258 * Return symbolic or numerical representation of n
260 const string
symbolicNumber (double n
)
263 return positiveSymbolicNumber(n
);
265 return string("-") + positiveSymbolicNumber(-n
);