00001 #ifndef VIENNAMATH_MANIPULATION_EXPAND_HPP
00002 #define VIENNAMATH_MANIPULATION_EXPAND_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "viennamath/forwards.h"
00021 #include "viennamath/runtime/unary_expr.hpp"
00022 #include "viennamath/compiletime/unary_op_tags.hpp"
00023 #include "viennamath/runtime/interval.hpp"
00024 #include "viennamath/runtime/symbolic_interval.hpp"
00025 #include "viennamath/runtime/integral.hpp"
00026
00031 namespace viennamath
00032 {
00034
00035 namespace result_of
00036 {
00043 template <typename T>
00044 struct expand {};
00045
00046
00047 namespace detail
00048 {
00049
00050 template <typename T>
00051 struct has_plus_or_minus
00052 {
00053 enum { value = 0 };
00054 };
00055
00056 template <typename LHS, typename NumericT, typename RHS>
00057 struct has_plus_or_minus< ct_binary_expr<LHS, op_plus<NumericT>, RHS> >
00058 {
00059 enum { value = 1 };
00060 };
00061
00062 template <typename LHS, typename NumericT, typename RHS>
00063 struct has_plus_or_minus< ct_binary_expr<LHS, op_minus<NumericT>, RHS> >
00064 {
00065 enum { value = 1 };
00066 };
00067
00068 template <typename LHS, typename NumericT, typename RHS>
00069 struct has_plus_or_minus< ct_binary_expr<LHS, op_mult<NumericT>, RHS> >
00070 {
00071 enum { value = has_plus_or_minus<LHS>::value + has_plus_or_minus<RHS>::value };
00072 };
00073
00074 template <typename LHS, typename NumericT, typename RHS>
00075 struct has_plus_or_minus< ct_binary_expr<LHS, op_div<NumericT>, RHS> >
00076 {
00077 enum { value = has_plus_or_minus<LHS>::value};
00078 };
00079
00080
00081
00082 template <typename ExpressionType,
00083 typename FactorType,
00084 bool needs_expansion = (has_plus_or_minus<ExpressionType>::value != 0) >
00085 struct expand_with_factor
00086 {
00087 typedef ct_binary_expr< ExpressionType,
00088 op_mult<default_numeric_type>,
00089 FactorType
00090 > type;
00091 };
00092
00093 template <typename LHS, typename NumericT, typename RHS,
00094 typename FactorType>
00095 struct expand_with_factor < ct_binary_expr<LHS, op_plus<NumericT>, RHS>,
00096 FactorType,
00097 true>
00098 {
00099 typedef ct_binary_expr< typename expand_with_factor<LHS, FactorType>::type,
00100 op_plus<NumericT>,
00101 typename expand_with_factor<RHS, FactorType>::type
00102 > type;
00103 };
00104
00105
00106 template <typename LHS, typename NumericT, typename RHS,
00107 typename FactorType>
00108 struct expand_with_factor < ct_binary_expr<LHS, op_minus<NumericT>, RHS>,
00109 FactorType,
00110 true>
00111 {
00112 typedef ct_binary_expr< typename expand_with_factor<LHS, FactorType>::type,
00113 op_minus<NumericT>,
00114 typename expand_with_factor<RHS, FactorType>::type
00115 > type;
00116 };
00117
00118 template <typename LHS, typename NumericT, typename RHS,
00119 typename FactorType>
00120 struct expand_with_factor < ct_binary_expr<LHS, op_mult<NumericT>, RHS>,
00121 FactorType,
00122 true>
00123 {
00124 typedef typename viennamath::result_of::expand< ct_binary_expr<LHS, op_mult<NumericT>, RHS> >::type expanded_type;
00125 typedef typename expand_with_factor< expanded_type, FactorType >::type type;
00126 };
00127
00128 template <typename LHS, typename NumericT, typename RHS,
00129 typename FactorType>
00130 struct expand_with_factor < ct_binary_expr<LHS, op_div<NumericT>, RHS>,
00131 FactorType,
00132 true>
00133 {
00134 typedef ct_binary_expr< typename expand_with_factor<LHS, FactorType>::type,
00135 op_div<NumericT>,
00136 RHS
00137 > type;
00138 };
00139
00141
00142 template <typename LHS,
00143 typename RHS,
00144 bool lhs_expandable = (has_plus_or_minus<LHS>::value != 0),
00145 bool rhs_expandable = (has_plus_or_minus<RHS>::value != 0)>
00146 struct expand_product
00147 {
00148
00149 typedef ct_binary_expr<LHS,
00150 op_mult<default_numeric_type>,
00151 RHS > type;
00152 };
00153
00154 template <typename LHS,
00155 typename RHS>
00156 struct expand_product <LHS, RHS, true, false>
00157 {
00158 typedef typename expand_with_factor<LHS, RHS>::type type;
00159 };
00160
00161 template <typename LHS,
00162 typename RHS>
00163 struct expand_product <LHS, RHS, false, true>
00164 {
00165 typedef typename expand_with_factor<RHS, LHS>::type type;
00166 };
00167
00168 template <typename LHS,
00169 typename RHS>
00170 struct expand_product <LHS, RHS, true, true>
00171 {
00172
00173 typedef typename expand_with_factor<LHS, RHS>::type intermediate_type;
00174
00175 typedef typename viennamath::result_of::expand<intermediate_type>::type type;
00176 };
00177
00178 }
00179
00180
00182 template <typename LHS, typename NumericT, typename RHS>
00183 struct expand< ct_binary_expr<LHS, op_plus<NumericT>, RHS> >
00184 {
00185 typedef ct_binary_expr<typename expand<LHS>::type,
00186 op_plus<NumericT>,
00187 typename expand<RHS>::type > type;
00188 };
00189
00191 template <typename LHS, typename NumericT, typename RHS>
00192 struct expand< ct_binary_expr<LHS, op_minus<NumericT>, RHS> >
00193 {
00194 typedef ct_binary_expr<typename expand<LHS>::type,
00195 op_minus<NumericT>,
00196 typename expand<RHS>::type > type;
00197 };
00198
00200 template <typename LHS, typename NumericT, typename RHS>
00201 struct expand< ct_binary_expr<LHS, op_mult<NumericT>, RHS> >
00202 {
00203 typedef typename detail::expand_product<LHS, RHS>::type type;
00204 };
00205
00207 template <typename LHS, typename NumericT, typename RHS>
00208 struct expand< ct_binary_expr<LHS, op_div<NumericT>, RHS> >
00209 {
00210 typedef ct_binary_expr<typename expand<LHS>::type,
00211 op_div<NumericT>,
00212 typename expand<RHS>::type > type;
00213 };
00214
00216 template <typename LHS, typename OP>
00217 struct expand< ct_unary_expr<LHS, OP> >
00218 {
00219 typedef ct_unary_expr<LHS, OP> type;
00220 };
00221
00223 template <typename TAG>
00224 struct expand< ct_function_symbol<TAG> >
00225 {
00226 typedef ct_function_symbol<TAG> type;
00227 };
00228
00230 template <long value>
00231 struct expand< ct_constant<value> >
00232 {
00233 typedef ct_constant<value> type;
00234 };
00235
00237 template <id_type id>
00238 struct expand< ct_variable<id> >
00239 {
00240 typedef ct_variable<id> type;
00241 };
00242
00243
00244 }
00245
00246
00251 template <typename ExpressionType>
00252 typename result_of::expand<ExpressionType>::type
00253 expand(ExpressionType const & type)
00254 {
00255 return typename result_of::expand<ExpressionType>::type();
00256 }
00257
00258
00260
00261
00262 }
00263
00264 #endif