FAUST compiler  0.9.9.6b8
doc_Text.cpp
Go to the documentation of this file.
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 }