basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/src/generic_utils.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : generic_utils.cpp
00004 * DESCRIPTION: Utility functions for generic expressions
00005 * COPYRIGHT  : (C) 2005  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #include <basix/evaluator.hpp>
00014 #include <basix/memoize.hpp>
00015 #include <basix/literal.hpp>
00016 #include <basix/compound.hpp>
00017 namespace mmx {
00018 
00019 /******************************************************************************
00020 * List compatability routines
00021 ******************************************************************************/
00022 
00023 generic
00024 range (const generic& g, nat start, nat end) {
00025   return vector_to_compound (range (compound_to_vector (g), start, end));
00026 }
00027 
00028 generic
00029 append (const generic& g1, const generic& g2) {
00030   return vector_to_compound (append (compound_to_vector (g1),
00031                                      compound_to_vector (g2)));
00032 }
00033 
00034 generic
00035 cons (const generic& g1, const generic& g2) {
00036   return vector_to_compound (cons (g1, compound_to_vector (g2)));
00037 }
00038 
00039 generic
00040 cons (const generic& g1, const generic& g2, const generic& g3) {
00041   return vector_to_compound (append (vec<generic> (g1, g2),
00042                                      compound_to_vector (g3)));
00043 }
00044 
00045 generic
00046 car (const generic& g) {
00047   return g[0];
00048 }
00049 
00050 generic
00051 cdr (const generic& g) {
00052   return vector_to_compound (range (compound_to_vector (g), 1, N(g)));
00053 }
00054 
00055 /******************************************************************************
00056 * Useful predicates
00057 ******************************************************************************/
00058 
00059 bool
00060 is_func (const generic& g, const char* f) {
00061   return is<compound> (g) && exact_eq (g[0], generic (f));
00062 }
00063 
00064 bool
00065 is_func (const generic& g, const char* f, nat n) {
00066   return is<compound> (g) && N (g) == (n+1) && exact_eq (g[0], generic (f));
00067 }
00068 
00069 bool
00070 is_func (const generic& g, const generic& f) {
00071   return is<compound> (g) && exact_eq (g[0], f);
00072 }
00073 
00074 bool
00075 is_func (const generic& g, const generic& f, nat n) {
00076   return is<compound> (g) && N (g) == (n+1) && exact_eq (g[0], f);
00077 }
00078 
00079 /******************************************************************************
00080 * Size function
00081 ******************************************************************************/
00082 
00083 generic
00084 var_flatten (const generic& g) {
00085   return as_generic (flatten (g));
00086 }
00087 
00088 nat
00089 size (const generic& g) {
00090   if (is<literal> (g)) return 1;
00091   if (is<compound> (g)) {
00092     nat i, n= N (g), sum= 1;
00093     for (i=0; i<n; i++)
00094       sum += size (g[i]);
00095     return sum;
00096   }
00097   return size (var_flatten (g));
00098 }
00099 
00100 /******************************************************************************
00101 * Comparison
00102 ******************************************************************************/
00103 
00104 bool
00105 is_numeric (const string& s) {
00106   return
00107     (N(s) > 0 && s[0] >= '0' && s[0] <= '9') ||
00108     (N(s) > 1 && s[0] == '-' && s[1] >= '0' && s[1] <= '9');
00109 }
00110 
00111 static int
00112 compare_numeric (const string& s1, const string& s2) {
00113   if (s1[0] == '-' && s2[0] != '-') return -1;
00114   if (s1[0] != '-' && s2[0] == '-') return 1;
00115   if (s1[0] == '-' && s2[0] == '-')
00116     return -compare_numeric (s1 (1, N (s1)), s2 (1, N(s2)));
00117   if (N(s1) < N(s2)) return -1;
00118   if (N(s1) > N(s2)) return 1;
00119   if (s1 < s2) return -1;
00120   if (s1 > s2) return 1;
00121   return 0;
00122 }
00123 
00124 static int compare (const generic& g1, const generic& g2, const int& dir);
00125 
00126 static int
00127 compare_sub (const generic& g1, const generic& g2, const int& direction) {
00128   nat s1= size (g1), s2= size (g2);
00129   if (s1 < s2) return -direction;
00130   if (s1 > s2) return direction;
00131   if (is<literal> (g1) && is<literal> (g2)) {
00132     string l1= literal_to_string (g1), l2= literal_to_string (g2);
00133     if (is_numeric (l1) && !is_numeric (l2)) return -direction;
00134     if (is_numeric (l2) && !is_numeric (l1)) return direction;
00135     if (is_numeric (l1) && is_numeric (l2))
00136       return direction * compare_numeric (l1, l2);
00137     if (l1 < l2) return -1;
00138     if (l1 > l2) return 1;
00139     return 0;
00140   }
00141   if (is<literal> (g1) && is<compound> (g2)) return -direction;
00142   if (is<compound> (g1) && is<literal> (g2)) return direction;
00143   if (is<compound> (g1) && is<compound> (g2)) {
00144     nat i, n1= N (g1), n2= N (g2);
00145     if (n1 < n2) return -direction;
00146     if (n1 > n2) return direction;
00147     for (i=0; i<n1; i++) {
00148       int c= compare (g1[i], g2[i], direction);
00149       if (c != 0) return c;
00150     }
00151     return 0;
00152   }
00153   return compare (var_flatten (g1), var_flatten (g2), direction);
00154 }
00155 
00156 int compare_N (const generic& g1, const generic& g2) {
00157   return compare_sub (g1, g2, -1); }
00158 int compare_P (const generic& g1, const generic& g2) {
00159   return compare_sub (g1, g2, 1); }
00160 
00161 static int
00162 compare (const generic& g1, const generic& g2, const int& dir) {
00163   // NOTE: the splitting into two cases should not be necessary.
00164   // We do it in order to avoid an internal compiler error...
00165   if (dir < 0) {
00166     MEMOIZE_BINARY (std_memoizer,int,generic,generic,compare_N,g1,g2,
00167                    compare_N (g1, g2));
00168   }
00169   else {
00170     MEMOIZE_BINARY (std_memoizer,int,generic,generic,compare_P,g1,g2,
00171                    compare_P (g1, g2));
00172   }
00173 }
00174 
00175 int
00176 big_small_compare (const generic& g1, const generic& g2) {
00177   return compare (g1, g2, -1);
00178 }
00179 
00180 int
00181 small_big_compare (const generic& g1, const generic& g2) {
00182   return compare (g1, g2, 1);
00183 }
00184 
00185 } // namespace mmx
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines