basix_doc 0.1
|
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