--- /dev/null
+/************************************************************************
+ ************************************************************************
+ FAUST compiler
+ Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
+ ---------------------------------------------------------------------
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ************************************************************************
+ ************************************************************************/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include "doc_Text.hh"
+#include "compatibility.hh"
+#include <string>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <assert.h>
+#include <cmath>
+#include <stdlib.h>
+
+#include "floats.hh"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#endif
+
+#ifndef M_PI_4
+#define M_PI_4 0.785398163397448309616
+#endif
+
+#ifndef M_E
+#define M_E 2.71828182845904523536
+#endif
+
+extern bool gInternDoubleSwitch;
+const string symbolicNumber (double n);
+
+
+
+#if 0
+/**
+ * Suppress trailing zero in a string representating a floating point number.
+ * example : 1.00000 -> 1.0
+ * example : 1.00000f -> 1.0f
+ */
+
+static void zdel(char* c)
+{
+ int l = strlen(c) - 1;
+ bool f = (c[l] == 'f');
+
+ if (f) c[l--] = 0; // remove trailing if any f
+ while ( l>1 && c[l-1] != '.' && c[l] == '0') c[l--] = 0;
+ if (f) c[++l] = 'f'; // restaure trailing f if needed
+}
+#endif
+
+string docT (char* c) { return string(c); }
+string docT (int n) { char c[64]; snprintf(c, 63, "%d",n); return string(c); }
+string docT (long n) { char c[64]; snprintf(c, 63, "%ld",n); return string(c); }
+string docT (double n) { return symbolicNumber(n); }
+
+
+//
+//*****************************SYMBOLIC NUMBER REPRESENTATION*******************
+//
+
+/**
+ * Compute the smallest float representable
+ * difference epsilon such that 1 != 1+epsilon
+ */
+float fltEpsilon()
+{
+ float machEps = 1.0f;
+ do {
+ machEps /= 2.0f;
+ } while ((float)(1.0 + (machEps/2.0)) != 1.0);
+ return machEps;
+}
+
+
+/**
+ * Compute the smallest double representable
+ * difference epsilon such that 1 != 1+epsilon
+ */
+double dblEpsilon()
+{
+ double machEps = 1.0f;
+ do {
+ machEps /= 2.0f;
+ } while ((1.0 + (machEps/2.0)) != 1.0);
+ return machEps;
+}
+
+
+/**
+ * Check if two floating point numbers are (almost) equal
+ * Abs(x-y) < epsilon
+ */
+static bool AlmostEqual(double A, double B)
+{
+ double maxRelativeError = 2*dblEpsilon();
+ double maxAbsoluteError = maxRelativeError;
+
+
+ if (fabs(A - B) < maxAbsoluteError)
+ return true;
+ double relativeError;
+ if (fabs(B) > fabs(A))
+ relativeError = fabs((A - B) / B);
+ else
+ relativeError = fabs((A - B) / A);
+ if (relativeError <= maxRelativeError)
+ return true;
+ return false;
+}
+
+
+/**
+ * Return true if n>0 is equal to PI^k for some small integer k.
+ * k = log(n)/log(pi) is integer => n = exp(int(k)*log(pi))
+ * The latex representation \pi^{k} is returned in string s
+ */
+bool isPiPower (double n, string& s)
+{
+ assert(n>0);
+ stringstream ss (stringstream::out|stringstream::in);
+ int k = floor(log(n)/log(M_PI));
+ if ( AlmostEqual(n, exp(k * log(M_PI))) && (k!=0) && (abs(k)<5.0) ) {
+ ss << "\\pi";
+ if (k!=1) ss << "^{"<< k <<"}";
+ s = ss.str();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/**
+ * Return true if n>0 is equal to e^k for some small integer k.
+ * The latex representation e^{k} is returned in string s
+ */
+bool isExpPower (double n, string& s)
+{
+ assert(n>0);
+ stringstream ss (stringstream::out|stringstream::in);
+ int k = floor(log(n));
+ if ( AlmostEqual(n, exp(k)) && (k!=0) && (abs(k)<5.0) ) {
+ ss << "e";
+ if (k!=1) ss << "^{"<< k <<"}";
+ s = ss.str();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/**
+ * Return true if n>0 is equal to e^k or PI^k for some integer k
+ * The symbolic latex representation is returned in string s
+ */
+bool isSymbolicPower (double n, string& s)
+{
+ assert(n>0);
+ if (isPiPower(n,s)) {
+ return true;
+ } else if (isExpPower(n,s)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/**
+ * Return exp or num.exp, or exp/denom, or num/denom.exp
+ */
+const string addFraction (int num, int denom, const string& exp)
+{
+ stringstream ss (stringstream::out|stringstream::in);
+
+ if ((num==1) & (denom==1)) {
+ ss << exp;
+ } else if ((num==1) & (denom!=1)) {
+ ss << "\\frac{"<< exp << "}{" << denom << "}";
+ } else if ((num!=1) & (denom==1)) {
+ ss << num << "*" << exp;
+ } else {
+ ss << "\\frac{"<< num << "}{" << denom << "}*" << exp;
+ }
+ return ss.str();
+}
+
+
+/**
+ * Return symbolic or numerical representation of n>0
+ */
+const string positiveSymbolicNumber (double n)
+{
+ string s;
+ assert(n>0);
+
+ // Try to find a symbolic representation
+
+ for (int i=1;i<10;i++) {
+ for(int j=1;j<10;j++) {
+ if (isSymbolicPower(i*n/j,s)) {
+ return addFraction(j,i,s);
+ }
+ }
+ }
+
+ // No symbolic representation,
+ // Then numerical representation x.10^k
+
+ char tmp[64];
+ string entree = " * 10^{";
+ char sortie = '}';
+ string::size_type ps;
+
+ snprintf(tmp, 63, "%.15g", n); // Warning: over 15 decimals, results are wrong !!
+ s = tmp;
+ ps = s.find('e');
+
+ if (ps != string::npos) {
+ s.replace(ps, 1, "");
+ s.insert(ps, entree);
+ s += sortie;
+ }
+
+ return s;
+
+}
+
+
+/**
+ * Return symbolic or numerical representation of n
+ */
+const string symbolicNumber (double n)
+{
+ if (n>0.0) {
+ return positiveSymbolicNumber(n);
+ } else if (n<0.0) {
+ return string("-") + positiveSymbolicNumber(-n);
+ } else {
+ return "0";
+ }
+}