|
FAUST compiler
0.9.9.6b8
|
00001 /************************************************************************ 00002 ************************************************************************ 00003 FAUST compiler 00004 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale 00005 --------------------------------------------------------------------- 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 ************************************************************************ 00020 ************************************************************************/ 00021 00022 00023 00024 #include <stdio.h> 00025 #include <string.h> 00026 #include "doc_Text.hh" 00027 #include "compatibility.hh" 00028 #include <string> 00029 #include <vector> 00030 #include <iostream> 00031 #include <sstream> 00032 #include <assert.h> 00033 #include <cmath> 00034 00035 #include "floats.hh" 00036 00037 #ifndef M_PI 00038 #define M_PI 3.14159265358979323846 00039 #endif 00040 00041 #ifndef M_PI_2 00042 #define M_PI_2 1.57079632679489661923 00043 #endif 00044 00045 #ifndef M_PI_4 00046 #define M_PI_4 0.785398163397448309616 00047 #endif 00048 00049 #ifndef M_E 00050 #define M_E 2.71828182845904523536 00051 #endif 00052 00053 extern bool gInternDoubleSwitch; 00054 const string symbolicNumber (double n); 00055 00056 00057 00058 #if 0 00059 00065 static void zdel(char* c) 00066 { 00067 int l = strlen(c) - 1; 00068 bool f = (c[l] == 'f'); 00069 00070 if (f) c[l--] = 0; // remove trailing if any f 00071 while ( l>1 && c[l-1] != '.' && c[l] == '0') c[l--] = 0; 00072 if (f) c[++l] = 'f'; // restaure trailing f if needed 00073 } 00074 #endif 00075 00076 string docT (char* c) { return string(c); } 00077 string docT (int n) { char c[64]; snprintf(c, 63, "%d",n); return string(c); } 00078 string docT (long n) { char c[64]; snprintf(c, 63, "%ld",n); return string(c); } 00079 string docT (double n) { return symbolicNumber(n); } 00080 00081 00082 // 00083 //*****************************SYMBOLIC NUMBER REPRESENTATION******************* 00084 // 00085 00090 float fltEpsilon() 00091 { 00092 float machEps = 1.0f; 00093 do { 00094 machEps /= 2.0f; 00095 } while ((float)(1.0 + (machEps/2.0)) != 1.0); 00096 return machEps; 00097 } 00098 00099 00104 double dblEpsilon() 00105 { 00106 double machEps = 1.0f; 00107 do { 00108 machEps /= 2.0f; 00109 } while ((1.0 + (machEps/2.0)) != 1.0); 00110 return machEps; 00111 } 00112 00113 00118 static bool AlmostEqual(double A, double B) 00119 { 00120 double maxRelativeError = 2*dblEpsilon(); 00121 double maxAbsoluteError = maxRelativeError; 00122 00123 00124 if (fabs(A - B) < maxAbsoluteError) 00125 return true; 00126 double relativeError; 00127 if (fabs(B) > fabs(A)) 00128 relativeError = fabs((A - B) / B); 00129 else 00130 relativeError = fabs((A - B) / A); 00131 if (relativeError <= maxRelativeError) 00132 return true; 00133 return false; 00134 } 00135 00136 00142 bool isPiPower (double n, string& s) 00143 { 00144 assert(n>0); 00145 stringstream ss (stringstream::out|stringstream::in); 00146 int k = floor(log(n)/log(M_PI)); 00147 if ( AlmostEqual(n, exp(k * log(M_PI))) && (k!=0) && (abs(k)<5.0) ) { 00148 ss << "\\pi"; 00149 if (k!=1) ss << "^{"<< k <<"}"; 00150 s = ss.str(); 00151 return true; 00152 } else { 00153 return false; 00154 } 00155 } 00156 00157 00162 bool isExpPower (double n, string& s) 00163 { 00164 assert(n>0); 00165 stringstream ss (stringstream::out|stringstream::in); 00166 int k = floor(log(n)); 00167 if ( AlmostEqual(n, exp(k)) && (k!=0) && (abs(k)<5.0) ) { 00168 ss << "e"; 00169 if (k!=1) ss << "^{"<< k <<"}"; 00170 s = ss.str(); 00171 return true; 00172 } else { 00173 return false; 00174 } 00175 } 00176 00177 00182 bool isSymbolicPower (double n, string& s) 00183 { 00184 assert(n>0); 00185 if (isPiPower(n,s)) { 00186 return true; 00187 } else if (isExpPower(n,s)) { 00188 return true; 00189 } else { 00190 return false; 00191 } 00192 } 00193 00194 00198 const string addFraction (int num, int denom, const string& exp) 00199 { 00200 stringstream ss (stringstream::out|stringstream::in); 00201 00202 if ((num==1) & (denom==1)) { 00203 ss << exp; 00204 } else if ((num==1) & (denom!=1)) { 00205 ss << "\\frac{"<< exp << "}{" << denom << "}"; 00206 } else if ((num!=1) & (denom==1)) { 00207 ss << num << "*" << exp; 00208 } else { 00209 ss << "\\frac{"<< num << "}{" << denom << "}*" << exp; 00210 } 00211 return ss.str(); 00212 } 00213 00214 00218 const string positiveSymbolicNumber (double n) 00219 { 00220 string s; 00221 assert(n>0); 00222 00223 // Try to find a symbolic representation 00224 00225 for (int i=1;i<10;i++) { 00226 for(int j=1;j<10;j++) { 00227 if (isSymbolicPower(i*n/j,s)) { 00228 return addFraction(j,i,s); 00229 } 00230 } 00231 } 00232 00233 // No symbolic representation, 00234 // Then numerical representation x.10^k 00235 00236 char tmp[64]; 00237 string entree = " * 10^{"; 00238 char sortie = '}'; 00239 string::size_type ps; 00240 00241 snprintf(tmp, 63, "%.15g", n); // Warning: over 15 decimals, results are wrong !! 00242 s = tmp; 00243 ps = s.find('e'); 00244 00245 if (ps != string::npos) { 00246 s.replace(ps, 1, ""); 00247 s.insert(ps, entree); 00248 s += sortie; 00249 } 00250 00251 return s; 00252 00253 } 00254 00255 00259 const string symbolicNumber (double n) 00260 { 00261 if (n>0.0) { 00262 return positiveSymbolicNumber(n); 00263 } else if (n<0.0) { 00264 return string("-") + positiveSymbolicNumber(-n); 00265 } else { 00266 return "0"; 00267 } 00268 }
1.8.0