Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / compiler / documentator / doc_Text.cpp
1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
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.
10
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.
15
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 ************************************************************************/
21
22
23
24 #include <stdio.h>
25 #include <string.h>
26 #include "doc_Text.hh"
27 #include "compatibility.hh"
28 #include <string>
29 #include <vector>
30 #include <iostream>
31 #include <sstream>
32 #include <assert.h>
33 #include <cmath>
34 #include <stdlib.h>
35
36 #include "floats.hh"
37
38 #ifndef M_PI
39 #define M_PI 3.14159265358979323846
40 #endif
41
42 #ifndef M_PI_2
43 #define M_PI_2 1.57079632679489661923
44 #endif
45
46 #ifndef M_PI_4
47 #define M_PI_4 0.785398163397448309616
48 #endif
49
50 #ifndef M_E
51 #define M_E 2.71828182845904523536
52 #endif
53
54 extern bool gInternDoubleSwitch;
55 const string symbolicNumber (double n);
56
57
58
59 #if 0
60 /**
61 * Suppress trailing zero in a string representating a floating point number.
62 * example : 1.00000 -> 1.0
63 * example : 1.00000f -> 1.0f
64 */
65
66 static void zdel(char* c)
67 {
68 int l = strlen(c) - 1;
69 bool f = (c[l] == 'f');
70
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
74 }
75 #endif
76
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); }
81
82
83 //
84 //*****************************SYMBOLIC NUMBER REPRESENTATION*******************
85 //
86
87 /**
88 * Compute the smallest float representable
89 * difference epsilon such that 1 != 1+epsilon
90 */
91 float fltEpsilon()
92 {
93 float machEps = 1.0f;
94 do {
95 machEps /= 2.0f;
96 } while ((float)(1.0 + (machEps/2.0)) != 1.0);
97 return machEps;
98 }
99
100
101 /**
102 * Compute the smallest double representable
103 * difference epsilon such that 1 != 1+epsilon
104 */
105 double dblEpsilon()
106 {
107 double machEps = 1.0f;
108 do {
109 machEps /= 2.0f;
110 } while ((1.0 + (machEps/2.0)) != 1.0);
111 return machEps;
112 }
113
114
115 /**
116 * Check if two floating point numbers are (almost) equal
117 * Abs(x-y) < epsilon
118 */
119 static bool AlmostEqual(double A, double B)
120 {
121 double maxRelativeError = 2*dblEpsilon();
122 double maxAbsoluteError = maxRelativeError;
123
124
125 if (fabs(A - B) < maxAbsoluteError)
126 return true;
127 double relativeError;
128 if (fabs(B) > fabs(A))
129 relativeError = fabs((A - B) / B);
130 else
131 relativeError = fabs((A - B) / A);
132 if (relativeError <= maxRelativeError)
133 return true;
134 return false;
135 }
136
137
138 /**
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
142 */
143 bool isPiPower (double n, string& s)
144 {
145 assert(n>0);
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) ) {
149 ss << "\\pi";
150 if (k!=1) ss << "^{"<< k <<"}";
151 s = ss.str();
152 return true;
153 } else {
154 return false;
155 }
156 }
157
158
159 /**
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
162 */
163 bool isExpPower (double n, string& s)
164 {
165 assert(n>0);
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) ) {
169 ss << "e";
170 if (k!=1) ss << "^{"<< k <<"}";
171 s = ss.str();
172 return true;
173 } else {
174 return false;
175 }
176 }
177
178
179 /**
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
182 */
183 bool isSymbolicPower (double n, string& s)
184 {
185 assert(n>0);
186 if (isPiPower(n,s)) {
187 return true;
188 } else if (isExpPower(n,s)) {
189 return true;
190 } else {
191 return false;
192 }
193 }
194
195
196 /**
197 * Return exp or num.exp, or exp/denom, or num/denom.exp
198 */
199 const string addFraction (int num, int denom, const string& exp)
200 {
201 stringstream ss (stringstream::out|stringstream::in);
202
203 if ((num==1) & (denom==1)) {
204 ss << exp;
205 } else if ((num==1) & (denom!=1)) {
206 ss << "\\frac{"<< exp << "}{" << denom << "}";
207 } else if ((num!=1) & (denom==1)) {
208 ss << num << "*" << exp;
209 } else {
210 ss << "\\frac{"<< num << "}{" << denom << "}*" << exp;
211 }
212 return ss.str();
213 }
214
215
216 /**
217 * Return symbolic or numerical representation of n>0
218 */
219 const string positiveSymbolicNumber (double n)
220 {
221 string s;
222 assert(n>0);
223
224 // Try to find a symbolic representation
225
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);
230 }
231 }
232 }
233
234 // No symbolic representation,
235 // Then numerical representation x.10^k
236
237 char tmp[64];
238 string entree = " * 10^{";
239 char sortie = '}';
240 string::size_type ps;
241
242 snprintf(tmp, 63, "%.15g", n); // Warning: over 15 decimals, results are wrong !!
243 s = tmp;
244 ps = s.find('e');
245
246 if (ps != string::npos) {
247 s.replace(ps, 1, "");
248 s.insert(ps, entree);
249 s += sortie;
250 }
251
252 return s;
253
254 }
255
256
257 /**
258 * Return symbolic or numerical representation of n
259 */
260 const string symbolicNumber (double n)
261 {
262 if (n>0.0) {
263 return positiveSymbolicNumber(n);
264 } else if (n<0.0) {
265 return string("-") + positiveSymbolicNumber(-n);
266 } else {
267 return "0";
268 }
269 }