00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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
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
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
00164
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 }