basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/include/basix/operators.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : operators.hpp
00004 * DESCRIPTION: Templates and default implementations of several operations
00005 * COPYRIGHT  : (C) 2003  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 #ifndef __MMX_OPERATORS_HPP
00014 #define __MMX_OPERATORS_HPP
00015 #include <basix/port.hpp>
00016 #include <basix/identifiers.hpp>
00017 
00019 
00020 namespace mmx {
00021 
00022 /******************************************************************************
00023 * Refer to standard C++ operators by another name
00024 ******************************************************************************/
00025 
00026 #define TMPL template<typename T>
00027 
00028 TMPL T neg_operator (const T& x) { return -x; }
00029 TMPL T add_operator (const T& x, const T& y) { return x+y; }
00030 TMPL T sub_operator (const T& x, const T& y) { return x-y; }
00031 TMPL T mul_operator (const T& x, const T& y) { return x*y; }
00032 TMPL T div_operator (const T& x, const T& y) { return x/y; }
00033 
00034 TMPL bool equal_operator (const T& x, const T& y) { return x==y; }
00035 TMPL bool unequal_operator (const T& x, const T& y) { return x!=y; }
00036 TMPL bool less_operator (const T& x, const T& y) { return x<y; }
00037 TMPL bool lesseq_operator (const T& x, const T& y) { return x<=y; }
00038 TMPL bool gtr_operator (const T& x, const T& y) { return x>y; }
00039 TMPL bool gtreq_operator (const T& x, const T& y) { return x>=y; }
00040 
00041 #undef TMPL
00042 
00043 /******************************************************************************
00044 * Default versions of in place operators
00045 ******************************************************************************/
00046 
00047 template<typename R> inline void
00048 neg (R& x) { x= -x; }
00049 template<typename R, typename C1> inline void
00050 neg (R& x, const C1& y1) { x= -y1; }
00051 template<typename R, typename C1, typename C2> inline void
00052 add (R& x, const C1& y1, const C2& y2) { x= y1 + y2; }
00053 template<typename R, typename C1, typename C2> inline void
00054 sub (R& x, const C1& y1, const C2& y2) { x= y1 - y2; }
00055 template<typename R, typename C1, typename C2> inline void
00056 mul (R& x, const C1& y1, const C2& y2) { x= y1 * y2; }
00057 template<typename R, typename C1, typename C2> inline void
00058 div (R& x, const C1& y1, const C2& y2) { x= y1 / y2; }
00059 template<typename R, typename C1, typename C2> inline void
00060 mul_add (R& x, const C1& y1, const C2& y2) { x += y1 * y2; }
00061 template<typename R, typename C1, typename C2> inline void
00062 mul_sub (R& x, const C1& y1, const C2& y2) { x -= y1 * y2; }
00063 
00064 /******************************************************************************
00065 * Consider arbitrary routines as operators
00066 ******************************************************************************/
00067 
00068 template<typename C, C (*fun) (const C&)>
00069 struct unary_op {
00070   static inline C
00071   op (const C& x) { return fun (x); }
00072 };
00073 
00074 template<typename C, C (*fun) (const C&, const C&)>
00075 struct binary_op {
00076   static inline C
00077   op (const C& x, const C& y) { return fun (x, y); }
00078 };
00079 
00080 /******************************************************************************
00081 * Specify the return type for operators which perform a cast
00082 ******************************************************************************/
00083 
00084 template<typename Op, typename R>
00085 struct replace_return_op {
00086   static inline R
00087   op () { return Op::template op<R> (); }
00088   template<typename X1> static inline R
00089   op (const X1& x1) { return Op::template op<R> (x1); }
00090   template<typename X1, typename X2> static inline R
00091   op (const X1& x1, const X2& x2) { return Op::template op<R> (x1, x2); }
00092   static inline void
00093   set_op (R& r) { Op::set_op (r); }
00094   template<typename X1> static inline void
00095   set_op (R& r, const X1& x1) { Op::set_op (r, x1); }
00096   template<typename X1, typename X2> static inline void
00097   set_op (R& r, const X1& x1, const X2& x2) { Op::set_op (r, x1, x2); }
00098 };
00099 
00100 template<typename Op, typename R>
00101 struct return_op_helper {
00102   typedef Op Rop;
00103 };
00104 
00105 #define REPLACEABLE_RETURN(Op)         \
00106 template<typename R>                   \
00107 struct return_op_helper<Op,R> {        \
00108   typedef replace_return_op<Op,R> Rop; \
00109 };
00110 
00111 #define Return_op(Op,R) \
00112   typename return_op_helper<Op,R>::Rop
00113 
00114 /******************************************************************************
00115 * Get the in-place variant of an operator
00116 ******************************************************************************/
00117 
00118 template<typename Op>
00119 struct in_place_op {
00120   template<typename R> static inline void
00121   op (R& r) { (void) Op::set_op (r); }
00122   template<typename R, typename S1> static inline void
00123   op (R& r, const S1& s1) { (void) Op::set_op (r, s1); }
00124   template<typename R, typename S1, typename S2> static inline void
00125   op (R& r, const S1& s1, const S2& s2) { (void) Op::set_op (r, s1, s2); }
00126   static inline syntactic
00127   op (const syntactic& s1) {
00128     return apply (Op::set_name (), s1); }
00129   static inline syntactic
00130   op (const syntactic& s1, const syntactic& s2) {
00131     return apply (Op::set_name (), s1, s2); }
00132   static inline syntactic
00133   op (const syntactic& s1, const syntactic& s2, const syntactic& s3) {
00134     return apply (Op::set_name (), s1, s2, s3); }  
00135 };
00136 
00137 /******************************************************************************
00138 * Constructors and copying
00139 ******************************************************************************/
00140 
00141 struct no_op {
00142   static generic set_name () { return GEN_NOOP; }
00143   template<typename C1> static inline void
00144   set_op (C1& x1) { (void) x1; }
00145   template<typename C1, typename C2> static inline void
00146   set_op (C1& x1, C2& x2) { (void) x1; (void) x2; }
00147   template<typename C1, typename C2, typename C3> static inline void
00148   set_op (C1& x1, C2& x2, C3& x3) { (void) x1; (void) x2; (void) x3; }
00149 };
00150 
00151 struct id_op {
00152   static generic name () { return GEN_IDENTITY; }
00153   static generic set_name () { return GEN_ASSIGN; }
00154   template<typename C> static inline C
00155   op (const C& x) { return x; }
00156   template<typename R, typename C> static inline void
00157   set_op (R& x, const C& y) { x= y; }
00158 };
00159 
00160 struct as_op {
00161   template<typename R, typename C> static inline R
00162   op (const C& x) { return as<R> (x); }
00163   template<typename R, typename C> static inline void
00164   set_op (R& x, const C& y) { set_as (x, y); }
00165 };
00166 
00167 REPLACEABLE_RETURN(as_op);
00168 
00169 struct copy_op {
00170   template<typename C> static inline C
00171   op (const C& x) { return copy (x); }
00172   template<typename R, typename C> static inline void
00173   set_op (R& x, const C& y) { x= copy (y); }
00174   static inline generic
00175   op (const generic& x) { return x; }
00176   static inline syntactic
00177   op (const syntactic& x) { return x; }
00178   template<typename R> static inline void
00179   set_op (R& x, const generic& y) { x= y; }
00180   template<typename R> static inline void
00181   set_op (R& x, const syntactic& y) { x= y; }
00182 };
00183 
00184 struct clear_op {
00185   template<typename C> static inline void
00186   set_op (C& x) { clear (x); }
00187 };
00188 
00189 struct duplicate_op {
00190   template<typename C> static inline C
00191   op (const C& x) { return duplicate (x); }
00192   template<typename R, typename C> static inline void
00193   set_op (R& x, const C& y) { x= duplicate (y); }
00194 };
00195 
00196 struct fast_op {
00197   static generic name () { return GEN_FAST; }
00198   template<typename C> static inline Fast_type(C)
00199   op (const C& x) { return fast (x); }
00200   template<typename R, typename C> static inline void
00201   set_op (R& x, const C& y) { x= fast (y); }
00202 };
00203 
00204 struct slow_op {
00205   static generic name () { return GEN_SLOW; }
00206   template<typename C> static inline C
00207   op (const Fast_type(C)& x) { return slow (x); }
00208   template<typename R, typename C> static inline void
00209   set_op (R& x, const C& y) { x= slow_as<R> (y); }
00210 };
00211 
00212 struct swap_op {
00213   template<typename C> static inline void
00214   set_op (C& x, C& y) { C aux= x; x= y; y= aux; }
00215 };
00216 
00217 struct flatten_op {
00218   template<typename C> static inline syntactic
00219   op (const C& x) { return flatten (x); }
00220   template<typename R, typename C> static inline void
00221   set_op (R& x, const C& y) { x= flatten (y); }
00222 };
00223 
00224 template<typename C>
00225 struct unary_return_type_helper<flatten_op,C> {
00226   typedef syntactic RET;
00227 };
00228 
00229 /******************************************************************************
00230 * Constants
00231 ******************************************************************************/
00232 
00233 struct log2_as_op {
00234   template<typename R> static inline R
00235   op () { return Log2 (R); }
00236   template<typename R> static inline void
00237   set_op (R& x) { set_log2 (x); }
00238 };
00239 
00240 struct pi_as_op {
00241   template<typename R> static inline R
00242   op () { return Pi (R); }
00243   template<typename R> static inline void
00244   set_op (R& x) { set_pi (x); }
00245 };
00246 
00247 struct euler_as_op {
00248   template<typename R> static inline R
00249   op () { return Euler (R); }
00250   template<typename R> static inline void
00251   set_op (R& x) { set_euler (x); }
00252 };
00253 
00254 struct catalan_as_op {
00255   template<typename R> static inline R
00256   op () { return Catalan (R); }
00257   template<typename R> static inline void
00258   set_op (R& x) { set_catalan (x); }
00259 };
00260 
00261 struct smallest_as_op {
00262   template<typename R> static inline R
00263   op () { return Smallest (R); }
00264   template<typename R> static inline void
00265   set_op (R& x) { set_smallest (x); }
00266 };
00267 
00268 struct largest_as_op {
00269   template<typename R> static inline R
00270   op () { return Largest (R); }
00271   template<typename R> static inline void
00272   set_op (R& x) { set_largest (x); }
00273 };
00274 
00275 struct accuracy_as_op {
00276   template<typename R> static inline R
00277   op () { return Accuracy (R); }
00278   template<typename R> static inline void
00279   set_op (R& x) { set_accuracy (x); }
00280 };
00281 
00282 struct imaginary_as_op {
00283   template<typename R> static inline R
00284   op () { return Imaginary (R); }
00285   template<typename R> static inline void
00286   set_op (R& x) { set_imaginary (x); }
00287 };
00288 
00289 struct nan_as_op {
00290   template<typename R> static inline R
00291   op () { return Nan (R); }
00292   template<typename R> static inline void
00293   set_op (R& x) { set_nan (x); }
00294 };
00295 
00296 struct infinity_as_op {
00297   template<typename R> static inline R
00298   op () { return Infinity (R); }
00299   template<typename R> static inline void
00300   set_op (R& x) { set_infinity (x); }
00301 };
00302 
00303 struct maximal_as_op {
00304   template<typename R> static inline R
00305   op () { return Maximal (R); }
00306   template<typename R> static inline void
00307   set_op (R& x) { set_maximal (x); }
00308 };
00309 
00310 struct minimal_as_op {
00311   template<typename R> static inline R
00312   op () { return Minimal (R); }
00313   template<typename R> static inline void
00314   set_op (R& x) { set_minimal (x); }
00315 };
00316 
00317 struct fuzz_as_op {
00318   template<typename R> static inline R
00319   op () { return Fuzz (R); }
00320   template<typename R> static inline void
00321   set_op (R& x) { set_fuzz (x); }
00322 };
00323 
00324 REPLACEABLE_RETURN(log2_as_op);
00325 REPLACEABLE_RETURN(pi_as_op);
00326 REPLACEABLE_RETURN(euler_as_op);
00327 REPLACEABLE_RETURN(catalan_as_op);
00328 REPLACEABLE_RETURN(smallest_as_op);
00329 REPLACEABLE_RETURN(largest_as_op);
00330 REPLACEABLE_RETURN(accuracy_as_op);
00331 REPLACEABLE_RETURN(imaginary_as_op);
00332 REPLACEABLE_RETURN(infinity_as_op);
00333 REPLACEABLE_RETURN(nan_as_op);
00334 REPLACEABLE_RETURN(maximal_as_op);
00335 REPLACEABLE_RETURN(minimal_as_op);
00336 REPLACEABLE_RETURN(fuzz_as_op);
00337 
00338 /******************************************************************************
00339 * Hashing
00340 ******************************************************************************/
00341 
00342 struct hash_op {
00343   static generic name () { return GEN_HASH; }
00344   template<typename C> static inline nat
00345   op (const C& x) { return hash (x); }
00346 };
00347 
00348 struct exact_hash_op {
00349   static generic name () { return GEN_EXACT_HASH; }
00350   template<typename C> static inline nat
00351   op (const C& x) { return exact_hash (x); }
00352 };
00353 
00354 struct hard_hash_op {
00355   static generic name () { return GEN_HARD_HASH; }
00356   template<typename C> static inline nat
00357   op (const C& x) { return hard_hash (x); }
00358 };
00359 
00360 /******************************************************************************
00361 * Arithmetic operators
00362 ******************************************************************************/
00363 
00364 struct zero_op {
00365   template<typename T> static inline T
00366   op (const T& x) { return T(0); }
00367 };
00368 
00369 struct neg_op {
00370   static generic name () { return GEN_MINUS; }
00371   template<typename C> static inline C
00372   op (const C& x) { return -x; }
00373   template<typename C> static inline void
00374   set_op (C& x) { neg (x); }
00375   template<typename R, typename C> static inline void
00376   set_op (R& x, const C& y) { neg (x, y); }
00377   template<typename C> static inline C
00378   diff_op (const C& me, const C& x) {
00379     (void) me; return -derive (x); }
00380 
00381   template<typename C, typename M> static inline C
00382   op_mod (const C& x, const M& p) {
00383     C y; neg_mod (y, x, p); return y; }
00384   template<typename C, typename M> static inline C
00385   op_mod (const C& x, const M& p, C& carry) {
00386     C y; neg_mod (y, x, p, carry); return y; }
00387   template<typename C, typename M> static inline void
00388   set_op_mod (C& x, const M& p) {
00389     neg_mod (x, p); }
00390   template<typename C, typename M> static inline void
00391   set_op_mod (C& x, const M& p, C& carry) {
00392     neg_mod (x, p, carry); }
00393   template<typename C, typename M> static inline void
00394   set_op_mod (C& x, const C& y, const M& p) {
00395     neg_mod (x, y, p); }
00396   template<typename C, typename M> static inline void
00397   set_op_mod (C& x, const C& y, const M& p, C& carry) {
00398     neg_mod (x, y, p, carry); }
00399 };
00400 
00401 struct add_op {
00402   typedef id_op lop;
00403   typedef id_op rop;
00404   static generic name () { return GEN_PLUS; }
00405   static generic set_name () { return GEN_PLUS_ASSIGN; }
00406   template<typename C> static inline C
00407   neutral () { return 0; }
00408   template<typename R> static inline void
00409   set_neutral (R& r) { set_zero (r); }
00410   template<typename C> static inline C
00411   op (const C& x, const C& y) { return x + y; }
00412   template<typename R, typename C> static inline void
00413   set_op (R& x, const C& y) { x += y; }
00414   template<typename R, typename C1, typename C2> static inline void
00415   set_op (R& x, const C1& y1, const C2& y2) { add (x, y1, y2); }
00416   template<typename C> static inline C
00417   diff_op (const C& me, const C& x, const C& y) {
00418     (void) me; return derive (x) + derive (y); }
00419   template<typename C, typename M> static inline C
00420   op_mod (const C& x, const C& y, const M& p) {
00421     C z; add_mod (z, x, y, p); return z; }
00422   template<typename C, typename M> static inline C
00423   op_mod (const C& x, const C& y, const M& p, C& carry) {
00424     C z; add_mod (z, x, y, p, carry); return z; }
00425   template<typename C, typename M> static inline void
00426   set_op_mod (C& x, const C& y, const M& p) {
00427     add_mod (x, y, p); }
00428   template<typename C, typename M> static inline void
00429   set_op_mod (C& x, const C& y, const M& p, C& carry) {
00430     add_mod (x, y, p, carry); }
00431   template<typename C, typename M> static inline void
00432   set_op_mod (C& x, const C& y1, const C& y2, const M& p) {
00433     add_mod (x, y1, y2, p); }
00434   template<typename C, typename M> static inline void
00435   set_op_mod (C& x, const C& y1, const C& y2, const M& p, C& carry) {
00436     add_mod (x, y1, y2, p, carry); }
00437 };
00438 
00439 struct radd_op {
00440   static generic name () { return GEN_PLUS; }
00441   template<typename C,typename S> static inline C
00442   op (const C& x, const S& y) { return x + y; }
00443   template<typename C,typename S> static inline void
00444   set_op (C& x, const S& y) { x += y; }
00445   template<typename R, typename C1, typename C2> static inline void
00446   set_op (R& x, const C1& y1, const C2& y2) { add (x, y1, y2); }
00447 };
00448 
00449 struct ladd_op {
00450   static generic name () { return GEN_PLUS; }
00451   template<typename C,typename S> static inline C
00452   op (const C& y, const S& x) { return x + y; }
00453   template<typename R, typename C1, typename C2> static inline void
00454   set_op (R& x, const C1& y2, const C2& y1) { add (x, y1, y2); }
00455 };
00456 
00457 struct sub_op {
00458   typedef id_op lop;
00459   typedef neg_op rop;
00460   static generic name () { return GEN_MINUS; }
00461   static generic set_name () { return GEN_MINUS_ASSIGN; }
00462   template<typename C> static inline C
00463   op (const C& x, const C& y) { return x - y; }
00464   template<typename R, typename C> static inline void
00465   set_op (R& x, const C& y) { x -= y; }
00466   template<typename R, typename C1, typename C2> static inline void
00467   set_op (R& x, const C1& y1, const C2& y2) { sub (x, y1, y2); }
00468   template<typename C> static inline C
00469   diff_op (const C& me, const C& x, const C& y) {
00470     (void) me; return derive (x) - derive (y); }
00471   template<typename C, typename M> static inline C
00472   op_mod (const C& x, const C& y, const M& p) {
00473     C z; sub_mod (z, x, y, p); return z; }
00474   template<typename C, typename M> static inline C
00475   op_mod (const C& x, const C& y, const M& p, C& carry) {
00476     C z; sub_mod (z, x, y, p, carry); return z; }
00477   template<typename C, typename M> static inline void
00478   set_op_mod (C& x, const C& y, const M& p) {
00479     sub_mod (x, y, p); }
00480   template<typename C, typename M> static inline void
00481   set_op_mod (C& x, const C& y, const M& p, C& carry) {
00482     sub_mod (x, y, p, carry); }
00483   template<typename C, typename M> static inline void
00484   set_op_mod (C& x, const C& y1, const C& y2, const M& p) {
00485     sub_mod (x, y1, y2, p); }
00486   template<typename C, typename M> static inline void
00487   set_op_mod (C& x, const C& y1, const C& y2, const M& p, C& carry) {
00488     sub_mod (x, y1, y2, p, carry); }
00489 };
00490 
00491 struct rsub_op {
00492   static generic name () { return GEN_MINUS; }
00493   template<typename C,typename S> static inline C
00494   op (const C& x, const S& y) { return x - y; }
00495   template<typename C,typename S> static inline void
00496   set_op (C& x, const S& y) { x -= y; }
00497   template<typename R, typename C1, typename C2> static inline void
00498   set_op (R& x, const C1& y1, const C2& y2) { sub (x, y1, y2); }
00499 };
00500 
00501 struct lsub_op {
00502   static generic name () { return GEN_MINUS; }
00503   template<typename C,typename S> static inline C
00504   op (const C& y, const S& x) { return x - y; }
00505   template<typename R, typename C1, typename C2> static inline void
00506   set_op (R& x, const C1& y2, const C2& y1) { sub (x, y1, y2); }
00507 };
00508 
00509 struct lmul_op;
00510 struct rmul_op;
00511 struct mul_add_op;
00512 
00513 struct mul_op {
00514   typedef lmul_op sc_left;
00515   typedef rmul_op sc_right;
00516   typedef id_op nomul_op;
00517   typedef clear_op clr_op;
00518   typedef mul_add_op acc_op;
00519   static generic name () { return GEN_TIMES; }
00520   static generic set_name () { return GEN_TIMES_ASSIGN; }
00521   template<typename C> static inline C
00522   neutral () { return 1; }
00523   template<typename R> static inline void
00524   set_neutral (R& r) { set_one (r); }
00525   template<typename C> static inline C
00526   op (const C& x, const C& y) { return x * y; }
00527   template<typename R, typename C> static inline void
00528   set_op (R& x, const C& y) { x *= y; }
00529   template<typename R, typename C1, typename C2> static inline void
00530   set_op (R& x, const C1& y1, const C2& y2) { mul (x, y1, y2); }
00531   template<typename C> static inline C
00532   diff_op (const C& me, const C& x, const C& y) {
00533     (void) me; return derive (x)*y + x*derive (y); }
00534   template<typename C,typename M> static inline C
00535   op_mod (const C& x, const C& y, const M& p) {
00536     C z; mul_mod (z, x, y, p); return z; }
00537   template<typename C,typename M> static inline C
00538   op_mod (const C& x, const C& y, const M& p, C& carry) {
00539     C z; mul_mod (z, x, y, p, carry); return z; }
00540   template<typename C,typename M> static inline void
00541   set_op_mod (C& x, const C& y, const M& p) {
00542     mul_mod (x, y, p); }
00543   template<typename C,typename M> static inline void
00544   set_op_mod (C& x, const C& y, const M& p, C& carry) {
00545     mul_mod (x, y, p, carry); }
00546   template<typename C, typename M> static inline void
00547   set_op (C& x, const C& y1, const C& y2, const M& p) {
00548     mul_mod (x, y1, y2, p); }
00549   template<typename C, typename M> static inline void
00550   set_op (C& x, const C& y1, const C& y2, const M& p, C& carry) {
00551     mul_mod (x, y1, y2, p, carry); }
00552 };
00553 
00554 struct rmul_op {
00555   static generic name () { return GEN_TIMES; }
00556   template<typename C,typename S> static inline C
00557   op (const C& x, const S& y) { return x * y; }
00558   template<typename C,typename S> static inline void
00559   set_op (C& x, const S& y) { x *= y; }
00560   template<typename R, typename C1, typename C2> static inline void
00561   set_op (R& x, const C1& y1, const C2& y2) { mul (x, y1, y2); }
00562   template<typename C,typename S> static inline C
00563   diff_op (const C& me, const C& x, const S& y) {
00564     (void) me; return derive (x) * y; }
00565   template<typename C,typename M> static inline C
00566   op_mod (const C& x, const C& y, const M& p) {
00567     C z; mul_mod (z, x, y, p); return z; }
00568   template<typename C,typename M> static inline C
00569   op_mod (const C& x, const C& y, const M& p, C& carry) {
00570     C z; mul_mod (z, x, y, p, carry); return z; }
00571 };
00572 
00573 struct lmul_op {
00574   static generic name () { return GEN_TIMES; }
00575   template<typename C,typename S> static inline C
00576   op (const C& y, const S& x) { return x * y; }
00577   template<typename R, typename C1, typename C2> static inline void
00578   set_op (R& x, const C1& y2, const C2& y1) { mul (x, y1, y2); }
00579   template<typename C,typename S> static inline C
00580   diff_op (const C& me, const C& y, const S& x) {
00581     (void) me; return x * derive (y); }
00582   template<typename C,typename M> static inline C
00583   op_mod (const C& y, const C& x, const M& p) {
00584     C z; mul_mod (z, x, y, p); return z; }
00585   template<typename C,typename M> static inline C
00586   op_mod (const C& y, const C& x, const M& p, C& carry) {
00587     C z; mul_mod (z, x, y, p, carry); return z; }
00588 };
00589 
00590 struct mul_add_op {
00591   typedef add_op nomul_op;
00592   typedef mul_op rhs_op;
00593   typedef no_op clr_op;
00594   typedef mul_add_op acc_op;
00595   static generic name () { return GEN_MUL_ADD; }
00596   template<typename C> static inline C
00597   neutral () { return 0; }
00598   template<typename R> static inline void
00599   set_neutral (R& r) { set_zero (r); }
00600   template<typename C> static inline C
00601   op (const C& x, const C& y, const C& z) { return x + y * z; }
00602   template<typename R, typename C1, typename C2> static inline void
00603   set_op (R& x, const C1& y, const C2& z) { mul_add (x, y, z); }
00604 };
00605 
00606 struct rmul_add_op {
00607   static generic name () { return GEN_MUL_ADD; }
00608   template<typename R, typename C,typename S> static inline void
00609   set_op (R& x, const C& y, const S& z) { mul_add (x, y, z); }
00610 };
00611 
00612 struct lmul_add_op {
00613   static generic name () { return GEN_MUL_ADD; }
00614   template<typename R, typename C,typename S> static inline void
00615   set_op (R& x, const C& z, const S& y) { mul_add (x, y, z); }
00616 };
00617 
00618 struct mul_sub_op {
00619   typedef sub_op nomul_op;
00620   typedef mul_op rhs_op;
00621   typedef no_op clr_op;
00622   typedef mul_sub_op acc_op;
00623   static generic name () { return GEN_MUL_SUB; }
00624   template<typename C> static inline C
00625   neutral () { return 0; }
00626   template<typename R> static inline void
00627   set_neutral (R& r) { set_zero (r); }
00628   template<typename C> static inline C
00629   op (const C& x, const C& y, const C& z) { return x - y * z; }
00630   template<typename R, typename C1, typename C2> static inline void
00631   set_op (R& x, const C1& y, const C2& z) { mul_sub (x, y, z); }
00632 };
00633 
00634 struct square_op {
00635   static generic name () { return GEN_SQUARE; }
00636   template<typename C> static inline C
00637   op (const C& x) { return square (x); }
00638   template<typename R> static inline void
00639   set_op (R& x) { x= square (x); }
00640   template<typename R, typename C> static inline void
00641   set_op (R& x, const C& y) { x= square (y); }
00642   template<typename C> static inline C
00643   diff_op (const C& me, const C& x) {
00644     (void) me; return 2*derive (x)*x; }
00645 };
00646 
00647 struct graeffe_op {
00648   static generic name () { return GEN_GRAEFFE; }
00649   template<typename C> static inline C
00650   op (const C& x) { return graeffe (x); }
00651   template<typename R> static inline void
00652   set_op (R& x) { x= graeffe (x); }
00653   template<typename R, typename C> static inline void
00654   set_op (R& x, const C& y) { x= graeffe (y); }
00655 };
00656 
00657 struct invert_op {
00658   static generic name () { return GEN_INVERT; }
00659   template<typename C> static inline C
00660   op (const C& x) { return invert (x); }
00661   template<typename C> static inline void
00662   set_op (C& x) { x= invert (x); }
00663   template<typename R, typename C> static inline void
00664   set_op (R& x, const C& y) { x= invert (y); }
00665   template<typename C> static inline C
00666   diff_op (const C& me, const C& x) {
00667     (void) me; return -derive (x) / square (x); }
00668   template<typename C> static inline C
00669   def (const C& me, const C& f) {
00670     return (C(1) - lshiftz (me * rshiftz (f))) / f[0]; }
00671 };
00672 
00673 struct ldiv_op;
00674 struct rdiv_op;
00675 
00676 struct div_op {
00677   typedef ldiv_op sc_left;
00678   typedef rdiv_op sc_right;
00679   static generic name () { return GEN_OVER; }
00680   static generic set_name () { return GEN_OVER_ASSIGN; }
00681   template<typename C> static inline C
00682   op (const C& x, const C& y) { return x / y; }
00683   template<typename R, typename C> static inline void
00684   set_op (R& x, const C& y) { x /= y; }
00685   template<typename R, typename C1, typename C2> static inline void
00686   set_op (R& x, const C1& y1, const C2& y2) { div (x, y1, y2); }
00687   template<typename C> static inline C
00688   diff_op (const C& me, const C& x, const C& y) {
00689     (void) me; return (derive (x)*y - x*derive (y)) / square (y); }
00690   static inline nat nr_init () { return 0; }
00691   template<typename C> static inline C
00692   def (const C& me, const C& f, const C& g) {
00693     if (g[0] == 0) {
00694       nat val;
00695       for (val=0; g[val]==0; val++)
00696         ASSERT (val != C::get_cancel_order (),
00697                 "valuation of denominator too high");
00698       return rshiftz (f, (int) val) / rshiftz (g, (int) val);
00699     }
00700     return (f - lshiftz (me * rshiftz (g))) / g[0]; }
00701 };
00702 
00703 struct rdiv_op {
00704   static generic name () { return GEN_OVER; }
00705   template<typename C,typename S> static inline C
00706   op (const C& x, const S& y) { return x / y; }
00707   template<typename C,typename S> static inline void
00708   set_op (C& x, const S& y) { x /= y; }
00709   template<typename R, typename C1, typename C2> static inline void
00710   set_op (R& x, const C1& y1, const C2& y2) { div (x, y1, y2); }
00711   template<typename C,typename S> static inline C
00712   diff_op (const C& me, const C& x, const S& y) {
00713     (void) me; return derive (x) / y; }
00714 };
00715 
00716 struct ldiv_op {
00717   static generic name () { return GEN_OVER; }
00718   template<typename C,typename S> static inline C
00719   op (const C& y, const S& x) { return x / y; }
00720   template<typename R, typename C1, typename C2> static inline void
00721   set_op (R& x, const C1& y2, const C2& y1) { div (x, y1, y2); }
00722   template<typename C,typename S> static inline C
00723   diff_op (const C& me, const C& y, const S& x) {
00724     (void) me; return -x * derive (y) / square (y); }
00725 };
00726 
00727 struct quo_op {
00728   static generic name () { return GEN_DIV; }
00729   template<typename C> static inline C
00730   op (const C& x, const C& y) { return quo (x, y); }
00731   template<typename R, typename C1, typename C2> static inline void
00732   set_op (R& x, const C1& y1, const C2& y2) { x= quo (y1, y2); }
00733   static inline nat nr_init () { return 0; }
00734   template<typename C> static inline C
00735   def (const C& me, const C& f, const C& g) {
00736     if (g[0] == 0) {
00737       nat val;
00738       for (val=0; g[val]==0; val++)
00739         if (val == C::get_cancel_order ()) return 0;
00740       return quo (rshiftz (f, (int) val), rshiftz (g, (int) val));
00741     }
00742     return quo (f - lshiftz (me * rshiftz (g)), g[0]); }
00743 };
00744 
00745 struct pquo_op {
00746   static generic name () { return "pquo"; }
00747   template<typename C> static inline C
00748   op (const C& x, const C& y) { return pquo (x, y); }
00749   template<typename R, typename C1, typename C2> static inline void
00750   set_op (R& x, const C1& y1, const C2& y2) { x= pquo (y1, y2); }
00751 };
00752 
00753 struct rquo_op {
00754   static generic name () { return GEN_DIV; }
00755   template<typename C,typename S> static inline C
00756   op (const C& x, const S& y) { return quo (x, y); }
00757   template<typename R, typename C1, typename C2> static inline void
00758   set_op (R& x, const C1& y1, const C2& y2) { x= quo (y1, y2); }
00759 };
00760 
00761 struct rem_op {
00762   static generic name () { return GEN_MOD; }
00763   template<typename C> static inline C
00764   op (const C& x, const C& y) { return rem (x, y); }
00765   template<typename R, typename C1, typename C2> static inline void
00766   set_op (R& x, const C1& y1, const C2& y2) { x= rem (y1, y2); }
00767   template<typename C> static inline C
00768   op (const C& x, const C& y, nat n) { return rem (x, y); }
00769 };
00770 
00771 struct prem_op {
00772   static generic name () { return "prem"; }
00773   template<typename C> static inline C
00774   op (const C& x, const C& y) { return prem (x, y); }
00775   template<typename R, typename C1, typename C2> static inline void
00776   set_op (R& x, const C1& y1, const C2& y2) { x= prem (y1, y2); }
00777   template<typename C> static inline C
00778   op (const C& x, const C& y, nat n) {
00779     if (x == 0 || y == 0) return x;
00780     nat m= deg (y);
00781     C z= m >= n ? C(1) : C(binpow (y[m], n - m));
00782     return  z * prem (x, y); }
00783 };
00784 
00785 struct rrem_op {
00786   static generic name () { return GEN_MOD; }
00787   template<typename C,typename S> static inline C
00788   op (const C& x, const S& y) { return rem (x, y); }
00789   template<typename R, typename C1, typename C2> static inline void
00790   set_op (R& x, const C1& y1, const C2& y2) { x= rem (y1, y2); }
00791 };
00792 
00793 struct lshift2_op {
00794   template<typename C,typename S> static inline C
00795   op (const C& x, const S& sh) { return lshift2 (x, sh); }
00796   template<typename C,typename S> static inline void
00797   set_op (C& x, const S& sh) { lshift2_assign (x, sh); }
00798   template<typename R, typename C1, typename C2> static inline void
00799   set_op (R& x, const C1& y1, const C2& y2) { lshift2 (x, y1, y2); }
00800 };
00801 
00802 struct rshift2_op {
00803   template<typename C,typename S> static inline C
00804   op (const C& x, const S& sh) { return rshift2 (x, sh); }
00805   template<typename C,typename S> static inline void
00806   set_op (C& x, const S& sh) { rshift2_assign (x, sh); }
00807   template<typename R, typename C1, typename C2> static inline void
00808   set_op (R& x, const C1& y1, const C2& y2) { rshift2 (x, y1, y2); }
00809 };
00810 
00811 struct lshiftz_op {
00812   template<typename C,typename S> static inline C
00813   op (const C& x, const S& sh) { return lshiftz (x, sh); }
00814   template<typename C,typename S> static inline void
00815   set_op (C& x, const S& sh) { lshiftz_assign (x, sh); }
00816   template<typename R, typename C1, typename C2> static inline void
00817   set_op (R& x, const C1& y1, const C2& y2) { lshiftz (x, y1, y2); }
00818 };
00819 
00820 struct rshiftz_op {
00821   template<typename C,typename S> static inline C
00822   op (const C& x, const S& sh) { return rshiftz (x, sh); }
00823   template<typename C,typename S> static inline void
00824   set_op (C& x, const S& sh) { rshiftz_assign (x, sh); }
00825   template<typename R, typename C1, typename C2> static inline void
00826   set_op (R& x, const C1& y1, const C2& y2) { rshiftz (x, y1, y2); }
00827 };
00828 
00829 struct incexp2_op {
00830   template<typename C,typename S> static inline C
00831   op (const C& x, const S& sh) { return incexp2 (x, sh); }
00832   template<typename C,typename S> static inline void
00833   set_op (C& x, const S& sh) { incexp2_assign (x, sh); }
00834   template<typename R, typename C1, typename C2> static inline void
00835   set_op (R& x, const C1& y1, const C2& y2) { incexp2 (x, y1, y2); }
00836 };
00837 
00838 struct decexp2_op {
00839   template<typename C,typename S> static inline C
00840   op (const C& x, const S& sh) { return decexp2 (x, sh); }
00841   template<typename C,typename S> static inline void
00842   set_op (C& x, const S& sh) { decexp2_assign (x, sh); }
00843   template<typename R, typename C1, typename C2> static inline void
00844   set_op (R& x, const C1& y1, const C2& y2) { decexp2 (x, y1, y2); }
00845 };
00846 
00847 struct or_op {
00848   template<typename C> static inline C
00849   neutral () { return false; }
00850   template<typename R> static inline void
00851   set_neutral (R& r) { set_false (r); }
00852   template<typename C> static inline C
00853   op (const C& x, const C& y) { return x | y; }
00854   template<typename R, typename C> static inline void
00855   set_op (R& x, const C& y) { x |= y; }
00856   template<typename R, typename C1, typename C2> static inline void
00857   set_op (R& x, const C1& y1, const C2& y2) { x= y1 | y2; }
00858 };
00859 
00860 struct and_op {
00861   template<typename C> static inline C
00862   neutral () { return true; }
00863   template<typename R> static inline void
00864   set_neutral (R& r) { set_true (r); }
00865   template<typename C> static inline C
00866   op (const C& x, const C& y) { return x & y; }
00867   template<typename R, typename C> static inline void
00868   set_op (R& x, const C& y) { x &= y; }
00869   template<typename R, typename C1, typename C2> static inline void
00870   set_op (R& x, const C1& y1, const C2& y2) { x= y1 & y2; }
00871 };
00872 
00873 /******************************************************************************
00874 * Extra arithmetic operators
00875 ******************************************************************************/
00876 
00877 struct gcd_op {
00878   static generic name () { return GEN_GCD; }
00879   template<typename C> static inline C
00880   neutral () { return C(0); }
00881   template<typename R> static inline void
00882   set_neutral (R& r) { set_zero (r); }
00883   template<typename C> static inline C
00884   op (const C& x, const C& y) { return gcd (x, y); }
00885   template<typename R, typename C> static inline void
00886   set_op (R& x, const C& y) { x= gcd (x, y); }
00887   template<typename R, typename C1, typename C2> static inline void
00888   set_op (R& x, const C1& y1, const C2& y2) { x= gcd (y1, y2); }
00889 };
00890 
00891 struct lcm_op {
00892   static generic name () { return GEN_LCM; }
00893   template<typename C> static inline C
00894   neutral () { return C(1); }
00895   template<typename R> static inline void
00896   set_neutral (R& r) { set_one (r); }
00897   template<typename C> static inline C
00898   op (const C& x, const C& y) { return lcm (x, y); }
00899   template<typename R, typename C> static inline void
00900   set_op (R& x, const C& y) { x= lcm (x, y); }
00901   template<typename R, typename C1, typename C2> static inline void
00902   set_op (R& x, const C1& y1, const C2& y2) { x= lcm (y1, y2); }
00903 };
00904 
00905 template<typename C> struct xgcd_matrix;
00906 
00907 struct xgcd_op {
00908   template<typename C> static inline xgcd_matrix<C>
00909   op (const C& x, const C& y) { return xgcd (x, y); }
00910   template<typename R, typename C1, typename C2> static inline void
00911   set_op (R& x, const C1& y1, const C2& y2) { x= xgcd (y1, y2); }
00912 };
00913 
00914 /******************************************************************************
00915 * Predicates
00916 ******************************************************************************/
00917 
00918 struct hard_eq_op { // hard equality in memory
00919   static generic name () { return GEN_HARD_EQ; }
00920   template<typename C> static inline bool
00921   op (const C& x, const C& y) { return hard_eq (x, y); }
00922   static inline syntactic
00923   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
00924   template<typename C> static inline bool
00925   not_op (const C& x, const C& y) { return hard_neq (x, y); }
00926   template<typename C> static inline nat
00927   hash_op (const C& x) { return hard_hash (x); }
00928 };
00929 
00930 struct hard_neq_op { // hard inequality in memory
00931   static generic name () { return GEN_HARD_NEQ; }
00932   template<typename C> static inline bool
00933   op (const C& x, const C& y) { return hard_neq (x, y); }
00934   static inline syntactic
00935   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
00936   template<typename C> static inline bool
00937   not_op (const C& x, const C& y) { return hard_eq (x, y); }
00938   template<typename C> static inline nat
00939   hash_op (const C& x) { return hard_hash (x); }
00940 };
00941 
00942 struct hard_less_op { // hard address comparaison
00943   static generic name () { return GEN_HARD_LESS; }
00944   template<typename C> static inline bool
00945   op (const C& x, const C& y) { return hard_less (x, y); }
00946 };
00947 
00948 struct hard_gtr_op { // hard address comparaison
00949   static generic name () { return GEN_HARD_GTR; }
00950   template<typename C> static inline bool
00951   op (const C& x, const C& y) { return hard_gtr (x, y); }
00952 };
00953 
00954 struct exact_eq_op { // syntactic equality
00955   static generic name () { return GEN_EXACT_EQ; }
00956   template<typename C> static inline bool
00957   op (const C& x, const C& y) { return exact_eq (x, y); }
00958   static inline syntactic
00959   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
00960   template<typename C> static inline bool
00961   not_op (const C& x, const C& y) { return exact_neq (x, y); }
00962   template<typename C> static inline nat
00963   hash_op (const C& x) { return exact_hash (x); }
00964 };
00965 
00966 struct exact_neq_op { // syntactic inequality
00967   static generic name () { return GEN_EXACT_NEQ; }
00968   template<typename C> static inline bool
00969   op (const C& x, const C& y) { return exact_neq (x, y); }
00970   static inline syntactic
00971   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
00972   template<typename C> static inline bool
00973   not_op (const C& x, const C& y) { return exact_eq (x, y); }
00974   template<typename C> static inline nat
00975   hash_op (const C& x) { return exact_hash (x); }
00976 };
00977 
00978 struct equal_op {
00979   static generic name () { return GEN_EQUAL; }
00980   template<typename C> static inline bool
00981   op (const C& x, const C& y) { return x == y; }
00982   static inline syntactic
00983   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
00984   template<typename C> static inline bool
00985   not_op (const C& x, const C& y) { return x != y; }
00986   template<typename C> static inline nat
00987   hash_op (const C& x) { return hash (x); }
00988 };
00989 
00990 struct unequal_op {
00991   static generic name () { return GEN_UNEQUAL; }
00992   template<typename C> static inline bool
00993   op (const C& x, const C& y) { return x != y; }
00994   static inline syntactic
00995   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
00996   template<typename C> static inline bool
00997   not_op (const C& x, const C& y) { return x == y; }
00998   template<typename C> static inline nat
00999   hash_op (const C& x) { return hash (x); }
01000 };
01001 
01002 struct less_op {
01003   static generic name () { return GEN_LESS; }
01004   template<typename C> static inline bool
01005   op (const C& x, const C& y) { return x < y; }
01006   static inline syntactic
01007   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
01008   template<typename C> static inline bool
01009   not_op (const C& x, const C& y) { return !(x < y); }
01010 };
01011 
01012 struct lesseq_op {
01013   static generic name () { return GEN_LESSEQ; }
01014   template<typename C> static inline bool
01015   op (const C& x, const C& y) { return x <= y; }
01016   static inline syntactic
01017   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
01018   template<typename C> static inline bool
01019   not_op (const C& x, const C& y) { return !(x <= y); }
01020 };
01021 
01022 struct gtr_op {
01023   static generic name () { return GEN_GTR; }
01024   template<typename C> static inline bool
01025   op (const C& x, const C& y) { return x > y; }
01026   static inline syntactic
01027   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
01028   template<typename C> static inline bool
01029   not_op (const C& x, const C& y) { return !(x > y); }
01030 };
01031 
01032 struct gtreq_op {
01033   static generic name () { return GEN_GTREQ; }
01034   template<typename C> static inline bool
01035   op (const C& x, const C& y) { return x >= y; }
01036   static inline syntactic
01037   op (const syntactic& x, const syntactic& y) { return apply (name(), x, y); }
01038   template<typename C> static inline bool
01039   not_op (const C& x, const C& y) { return !(x >= y); }
01040 };
01041 
01042 /******************************************************************************
01043 * Ordering related operators
01044 ******************************************************************************/
01045 
01046 struct min_op {
01047   static generic name () { return GEN_MIN; }
01048   template<typename C> static inline C
01049   neutral () { return Maximal (C); }
01050   template<typename R> static inline void
01051   set_neutral (R& x) { set_maximal (x); }
01052   template<typename C> static inline C
01053   op (const C& x, const C& y) { return min (x, y); }
01054   template<typename R, typename C> static inline void
01055   set_op (R& x, const C& y) { x= min (x, y); }
01056   template<typename R, typename C1, typename C2> static inline void
01057   set_op (R& x, const C1& y1, const C2& y2) { x= min (y1, y2); }
01058 };
01059 
01060 struct max_op {
01061   static generic name () { return GEN_MAX; }
01062   template<typename C> static inline C
01063   neutral () { return Minimal (C); }
01064   template<typename R> static inline void
01065   set_neutral (R& x) { set_minimal (x); }
01066   template<typename C> static inline C
01067   op (const C& x, const C& y) { return max (x, y); }
01068   template<typename R, typename C> static inline void
01069   set_op (R& x, const C& y) { x= max (x, y); }
01070   template<typename R, typename C1, typename C2> static inline void
01071   set_op (R& x, const C1& y1, const C2& y2) { x= max (y1, y2); }
01072 };
01073 
01074 struct inf_op {
01075   static generic name () { return GEN_INF; }
01076   template<typename C> static inline C
01077   neutral () { return Maximal (C); }
01078   template<typename R> static inline void
01079   set_neutral (R& x) { set_maximal (x); }
01080   template<typename C> static inline C
01081   op (const C& x, const C& y) { return inf (x, y); }
01082   template<typename R, typename C> static inline void
01083   set_op (R& x, const C& y) { x= inf (x, y); }
01084   template<typename R, typename C1, typename C2> static inline void
01085   set_op (R& x, const C1& y1, const C2& y2) { x= inf (y1, y2); }
01086 };
01087 
01088 struct sup_op {
01089   static generic name () { return GEN_SUP; }
01090   template<typename C> static inline C
01091   neutral () { return Minimal (C); }
01092   template<typename R> static inline void
01093   set_neutral (R& x) { set_minimal (x); }
01094   template<typename C> static inline C
01095   op (const C& x, const C& y) { return sup (x, y); }
01096   template<typename R, typename C> static inline void
01097   set_op (R& x, const C& y) { x= sup (x, y); }
01098   template<typename R, typename C1, typename C2> static inline void
01099   set_op (R& x, const C1& y1, const C2& y2) { x= sup (y1, y2); }
01100 };
01101 
01102 struct abs_op {
01103   static generic name () { return GEN_ABS; }
01104   template<typename C> static inline Abs_type(C)
01105   op (const C& x) { return abs (x); }
01106   static inline generic
01107   op (const generic& x) { return abs (x); }
01108   static inline syntactic
01109   op (const syntactic& x) { return abs (x); }
01110   template<typename R, typename C> static inline void
01111   set_op (R& x, const C& y) { x= abs (y); }
01112 };
01113 
01114 struct abs_as_op {
01115   static generic name () { return GEN_ABS; }
01116   template<typename R, typename C> static inline R
01117   op (const C& x) { return as<R> (abs (x)); }
01118   template<typename R, typename C> static inline void
01119   set_op (R& x, const C& y) { x= as<R> (abs (y)); }
01120 };
01121 
01122 REPLACEABLE_RETURN(abs_as_op);
01123 
01124 struct sign_op {
01125   static generic name () { return GEN_SIGN; }
01126   template<typename C> static inline int
01127   op (const C& x) { return sign (x); }
01128   static inline generic
01129   op (const generic& x) { return gen (GEN_SIGN, x); }
01130   static inline syntactic
01131   op (const syntactic& x) { return apply (GEN_SIGN, x); }
01132   template<typename C> static inline void
01133   set_op (int& x, const C& y) { x= sign (y); }
01134 };
01135 
01136 /******************************************************************************
01137 * Elementary functions
01138 ******************************************************************************/
01139 
01140 struct sqrt_op {
01141   static generic name () { return GEN_SQRT; }
01142   template<typename C> static inline C
01143   op (const C& x) { return sqrt (x); }
01144   template<typename R, typename C> static inline void
01145   set_op (R& x, const C& y) { x= sqrt (y); }
01146   template<typename C, typename I> static inline C
01147   op_init (const C& x, const I& i) { return sqrt_init (x, i); }
01148   template<typename C> static inline C
01149   diff_op (const C& me, const C& x) {
01150     return derive (x) / (2 * me); }
01151   static inline nat nr_init () { return 1; }
01152   template<typename C> static inline C
01153   def (const C& me, const C& f) {
01154     if (f[0] == 0) {
01155       nat val= 0;
01156       for (val=0; val< C::get_cancel_order () && f[val]==0; val++);
01157       ASSERT (val< C::get_cancel_order () , "valuation too high");
01158       ASSERT ((val&1) == 0, "square root is not a series");
01159       return lshiftz (sqrt (rshiftz (f, (int) val)), (int) (val/2));
01160     }
01161     return integrate (derive (f) / (2*me)); }
01162 };
01163 
01164 struct cbrt_op {
01165   static generic name () { return GEN_CBRT; }
01166   template<typename C> static inline C
01167   op (const C& x) { return cbrt (x); }
01168   template<typename R, typename C> static inline void
01169   set_op (R& x, const C& y) { x= cbrt (y); }
01170 };
01171 
01172 struct hypot_op {
01173   static generic name () { return GEN_HYPOT; }
01174   template<typename C> static inline C
01175   op (const C& x, const C& y) { return hypot (x, y); }
01176   template<typename R, typename C1, typename C2> static inline void
01177   set_op (R& x, const C1& y1, const C2& y2) { x= hypot (y1, y2); }
01178 };
01179 
01180 struct exp_op {
01181   static generic name () { return GEN_EXP; }
01182   template<typename C> static inline C
01183   op (const C& x) { return exp (x); }
01184   template<typename R, typename C> static inline void
01185   set_op (R& x, const C& y) { x= exp (y); }
01186   template<typename C, typename I> static inline C
01187   op_init (const C& x, const I& i) { (void) i; return exp (x); }
01188   template<typename C> static inline C
01189   diff_op (const C& me, const C& x) {
01190     return derive (x) * me; }
01191   static inline nat nr_init () { return 1; }
01192   template<typename C> static inline C
01193   def (const C& me, const C& f) {
01194     return integrate (diff_op (me, f)); }
01195 };
01196 
01197 struct exp2_op {
01198   static generic name () { return GEN_EXP2; }
01199   template<typename C> static inline C
01200   op (const C& x) { return exp2 (x); }
01201   template<typename R, typename C> static inline void
01202   set_op (R& x, const C& y) { x= exp2 (y); }
01203 };
01204 
01205 struct exp10_op {
01206   static generic name () { return GEN_EXP10; }
01207   template<typename C> static inline C
01208   op (const C& x) { return exp10 (x); }
01209   template<typename R, typename C> static inline void
01210   set_op (R& x, const C& y) { x= exp10 (y); }
01211 };
01212 
01213 struct log_op {
01214   static generic name () { return GEN_LOG; }
01215   template<typename C> static inline C
01216   op (const C& x) { return log (x); }
01217   template<typename R, typename C> static inline void
01218   set_op (R& x, const C& y) { x= log (y); }
01219   template<typename C,typename I> static inline C
01220   op_init (const C& x, const I& i) { return log_init (x, i); }
01221   template<typename C> static inline C
01222   diff_op (const C& me, const C& x) {
01223     (void) me; return derive (x) / x; }
01224   static inline nat nr_init () { return 1; }
01225   template<typename C> static inline C
01226   def (const C& me, const C& f) {
01227     return integrate (diff_op (me, f)); }
01228 };
01229 
01230 struct log2_op {
01231   static generic name () { return GEN_LOG2; }
01232   template<typename C> static inline C
01233   op (const C& x) { return log2 (x); }
01234   template<typename R, typename C> static inline void
01235   set_op (R& x, const C& y) { x= log2 (y); }
01236 };
01237 
01238 struct log10_op {
01239   static generic name () { return GEN_LOG10; }
01240   template<typename C> static inline C
01241   op (const C& x) { return log10 (x); }
01242   template<typename R, typename C> static inline void
01243   set_op (R& x, const C& y) { x= log10 (y); }
01244 };
01245 
01246 struct pow_op {
01247   static generic name () { return GEN_POWER; }
01248   template<typename C1, typename C2> static inline C1
01249   op (const C1& x, const C2& y) { return pow (x, y); }
01250   template<typename R, typename C1, typename C2> static inline void
01251   set_op (R& x, const C1& y1, const C2& y2) { x= pow (y1, y2); }
01252 };
01253 
01254 typedef pow_op rpow_op;
01255 
01256 struct lpow_op {
01257   static generic name () { return GEN_POWER; }
01258   template<typename C1, typename C2> static inline C1
01259   op (const C1& y, const C2& x) { return pow (x, y); }
01260   template<typename R, typename C1, typename C2> static inline void
01261   set_op (R& x, const C1& y2, const C2& y1) { x= pow (y1, y2); }
01262 };
01263 
01264 struct trig_op {
01265   template<typename C> static inline C
01266   op (const C& x) { return trig (x); }
01267   template<typename R, typename C> static inline void
01268   set_op (R& x, const C& y) { x= trig (y); }
01269   template<typename C, typename I> static inline C
01270   op_init (const C& x, const I& i) { (void) i; return trig (x); }
01271   static inline generic
01272   op (const generic& x) { return xsqtuple (comma (cos (x), sin (x))); }
01273   static inline syntactic
01274   op (const syntactic& x) { return as_syntactic (op (as_generic (x))); }
01275   template<typename C> static inline C
01276   diff_op (const C& me, const C& x);
01277   static inline nat nr_init () { return 1; }
01278   template<typename V,typename C> static inline V
01279   def (const V& me, const C& f) {
01280     return integrate (diff_op (me, f)); }
01281 };
01282 
01283 struct cos_op {
01284   static generic name () { return GEN_COS; }
01285   template<typename C> static inline C
01286   op (const C& x) { return cos (x); }
01287   template<typename R, typename C> static inline void
01288   set_op (R& x, const C& y) { x= cos (y); }
01289   template<typename C, typename I> static inline C
01290   op_init (const C& x, const I& i) { (void) i; return cos (x); }
01291   template<typename C> static inline C
01292   diff_op (const C& me, const C& x) {
01293     (void) me; return -derive (x) * sin (x); }
01294   static inline nat nr_init () { return 1; }
01295   template<typename C> static inline C
01296   def (const C& me, const C& f) {
01297     (void) me; return cos_sin (f) [0]; }
01298 };
01299 
01300 struct sin_op {
01301   static generic name () { return GEN_SIN; }
01302   template<typename C> static inline C
01303   op (const C& x) { return sin (x); }
01304   template<typename R, typename C> static inline void
01305   set_op (R& x, const C& y) { x= sin (y); }
01306   template<typename C, typename I> static inline C
01307   op_init (const C& x, const I& i) { (void) i; return sin (x); }
01308   template<typename C> static inline C
01309   diff_op (const C& me, const C& x) {
01310     (void) me; return derive (x) * cos (x); }
01311   static inline nat nr_init () { return 1; }
01312   template<typename C> static inline C
01313   def (const C& me, const C& f) {
01314     (void) me; return cos_sin (f) [1]; }
01315 };
01316 
01317 struct tan_op {
01318   static generic name () { return GEN_TAN; }
01319   template<typename C> static inline C
01320   op (const C& x) { return tan (x); }
01321   template<typename R, typename C> static inline void
01322   set_op (R& x, const C& y) { x= tan (y); }
01323   template<typename C, typename I> static inline C
01324   op_init (const C& x, const I& i) { (void) i; return tan (x); }
01325   template<typename C> static inline C
01326   diff_op (const C& me, const C& x) {
01327     (void) me; return derive (x) / square (cos (x)); }
01328   static inline nat nr_init () { return 1; }
01329   template<typename C> static inline C
01330   def (const C& me, const C& f);
01331 };
01332 
01333 struct acos_op {
01334   static generic name () { return GEN_ARCCOS; }
01335   template<typename C> static inline C
01336   op (const C& x) { return acos (x); }
01337   template<typename R, typename C> static inline void
01338   set_op (R& x, const C& y) { x= acos (y); }
01339   template<typename C, typename I> static inline C
01340   op_init (const C& x, const I& i) { return acos_init (x, i); }
01341   template<typename C> static inline C
01342   diff_op (const C& me, const C& x) {
01343     (void) me; return -derive (x) / sqrt (1 - square (x)); }
01344   static inline nat nr_init () { return 1; }
01345   template<typename C> static inline C
01346   def (const C& me, const C& f) {
01347     return integrate (diff_op (me, f)); }
01348 };
01349 
01350 struct asin_op {
01351   static generic name () { return GEN_ARCSIN; }
01352   template<typename C> static inline C
01353   op (const C& x) { return asin (x); }
01354   template<typename R, typename C> static inline void
01355   set_op (R& x, const C& y) { x= asin (y); }
01356   template<typename C, typename I> static inline C
01357   op_init (const C& x, const I& i) { return asin_init (x, i); }
01358   template<typename C> static inline C
01359   diff_op (const C& me, const C& x) {
01360     (void) me; return derive (x) / sqrt (1 - square (x)); }
01361   static inline nat nr_init () { return 1; }
01362   template<typename C> static inline C
01363   def (const C& me, const C& f) {
01364     return integrate (diff_op (me, f)); }
01365 };
01366 
01367 struct atan_op {
01368   static generic name () { return GEN_ARCTAN; }
01369   template<typename C> static inline C
01370   op (const C& x) { return atan (x); }
01371   template<typename R, typename C> static inline void
01372   set_op (R& x, const C& y) { x= atan (y); }
01373   template<typename C, typename I> static inline C
01374   op_init (const C& x, const I& i) { return atan_init (x, i); }
01375   template<typename C> static inline C
01376   diff_op (const C& me, const C& x) {
01377     (void) me; return derive (x) / (square (x) + 1); }
01378   static inline nat nr_init () { return 1; }
01379   template<typename C> static inline C
01380   def (const C& me, const C& f) {
01381     return integrate (diff_op (me, f)); }
01382 };
01383 
01384 struct atan2_op {
01385   static generic name () { return GEN_ARCTAN2; }
01386   template<typename C> static inline C
01387   op (const C& x, const C& y) { return atan2 (x, y); }
01388   template<typename R, typename C1, typename C2> static inline void
01389   set_op (R& x, const C1& y1, const C2& y2) { x= atan2 (y1, y2); }
01390 };
01391 
01392 struct cosh_op {
01393   static generic name () { return GEN_CH; }
01394   template<typename C> static inline C
01395   op (const C& x) { return cosh (x); }
01396   template<typename R, typename C> static inline void
01397   set_op (R& x, const C& y) { x= cosh (y); }
01398   template<typename C, typename I> static inline C
01399   op_init (const C& x, const I& i) { (void) i; return cosh (x); }
01400   template<typename C> static inline C
01401   diff_op (const C& me, const C& x) {
01402     (void) me; return derive (x) * sinh (x); }
01403 };
01404 
01405 struct sinh_op {
01406   static generic name () { return GEN_SH; }
01407   template<typename C> static inline C
01408   op (const C& x) { return sinh (x); }
01409   template<typename R, typename C> static inline void
01410   set_op (R& x, const C& y) { x= sinh (y); }
01411   template<typename C, typename I> static inline C
01412   op_init (const C& x, const I& i) { (void) i; return sinh (x); }
01413   template<typename C> static inline C
01414   diff_op (const C& me, const C& x) {
01415     (void) me; return derive (x) * cosh (x); }
01416 };
01417 
01418 struct tanh_op {
01419   static generic name () { return GEN_TH; }
01420   template<typename C> static inline C
01421   op (const C& x) { return tanh (x); }
01422   template<typename R, typename C> static inline void
01423   set_op (R& x, const C& y) { x= tanh (y); }
01424   template<typename C, typename I> static inline C
01425   op_init (const C& x, const I& i) { (void) i; return tanh (x); }
01426   template<typename C> static inline C
01427   diff_op (const C& me, const C& x) {
01428     (void) me; return derive (x) / square (cosh (x)); }
01429 };
01430 
01431 struct acosh_op {
01432   static generic name () { return GEN_ARGCH; }
01433   template<typename C> static inline C
01434   op (const C& x) { return acosh (x); }
01435   template<typename R, typename C> static inline void
01436   set_op (R& x, const C& y) { x= acosh (y); }
01437   template<typename C, typename I> static inline C
01438   op_init (const C& x, const I& i) { return acosh_init (x, i); }
01439   template<typename C> static inline C
01440   diff_op (const C& me, const C& x) {
01441     (void) me; return derive (x) / sqrt (square (x) - 1); }
01442 };
01443 
01444 struct asinh_op {
01445   static generic name () { return GEN_ARGSH; }
01446   template<typename C> static inline C
01447   op (const C& x) { return asinh (x); }
01448   template<typename R, typename C> static inline void
01449   set_op (R& x, const C& y) { x= asinh (y); }
01450   template<typename C, typename I> static inline C
01451   op_init (const C& x, const I& i) { return asinh_init (x, i); }
01452   template<typename C> static inline C
01453   diff_op (const C& me, const C& x) {
01454     (void) me; return derive (x) / sqrt (square (x) + 1); }
01455 };
01456 
01457 struct atanh_op {
01458   static generic name () { return GEN_ARGTH; }
01459   template<typename C> static inline C
01460   op (const C& x) { return atanh (x); }
01461   template<typename R, typename C> static inline void
01462   set_op (R& x, const C& y) { x= atanh (y); }
01463   template<typename C, typename I> static inline C
01464   op_init (const C& x, const I& i) { return atanh_init (x, i); }
01465   template<typename C> static inline C
01466   diff_op (const C& me, const C& x) {
01467     (void) me; return derive (x) / (1 - square (x)); }
01468 };
01469 
01470 /******************************************************************************
01471 * Special functions
01472 ******************************************************************************/
01473 
01474 struct gamma_op {
01475   static generic name () { return GEN_GAMMA; }
01476   template<typename C> static inline C
01477   op (const C& x) { return gamma (x); }
01478   template<typename R, typename C> static inline void
01479   set_op (R& x, const C& y) { x= gamma (y); }
01480 };
01481 
01482 struct zeta_op {
01483   static generic name () { return GEN_ZETA; }
01484   template<typename C> static inline C
01485   op (const C& x) { return zeta (x); }
01486   template<typename R, typename C> static inline void
01487   set_op (R& x, const C& y) { x= zeta (y); }
01488 };
01489 
01490 struct erf_op {
01491   static generic name () { return GEN_ERF; }
01492   template<typename C> static inline C
01493   op (const C& x) { return erf (x); }
01494   template<typename R, typename C> static inline void
01495   set_op (R& x, const C& y) { x= erf (y); }
01496 };
01497 
01498 /******************************************************************************
01499 * Special operations for approximate and rounded arithmetic
01500 ******************************************************************************/
01501 
01502 struct is_finite_op {
01503   template<typename T> static inline bool
01504   op (const T& x) { return is_finite (x); }
01505   template<typename T> static inline bool
01506   not_op (const T& x) { return !is_finite (x); }
01507 };
01508 
01509 struct is_infinite_op {
01510   template<typename T> static inline bool
01511   op (const T& x) { return is_infinite (x); }
01512   template<typename T> static inline bool
01513   not_op (const T& x) { return !is_infinite (x); }
01514 };
01515 
01516 struct is_fuzz_op {
01517   template<typename T> static inline bool
01518   op (const T& x) { return is_fuzz (x); }
01519   template<typename T> static inline bool
01520   not_op (const T& x) { return !is_fuzz (x); }
01521 };
01522 
01523 struct is_nan_op {
01524   template<typename T> static inline bool
01525   op (const T& x) { return is_nan (x); }
01526   template<typename T> static inline bool
01527   not_op (const T& x) { return !is_nan (x); }
01528 };
01529 
01530 struct is_reliable_op {
01531   // Returns true for ball and interval types, as well as exact types
01532   template<typename T> static inline bool
01533   op (const T& x) { return is_reliable (x); }
01534   template<typename T> static inline bool
01535   not_op (const T& x) { return !is_reliable (x); }
01536 };
01537 
01538 struct and_is_finite_op {
01539   template<typename B> static inline B
01540   neutral () { return true; }
01541   template<typename R> static inline void
01542   set_neutral (R& r) { set_true (r); }
01543   template<typename B, typename C> static inline void
01544   set_op (B& x, const C& y) { x= x && is_finite (y); }
01545   template<typename T> static inline bool
01546   op (const T& x) { return is_finite (x); }
01547 };
01548 
01549 struct or_is_infinite_op {
01550   template<typename B> static inline B
01551   neutral () { return false; }
01552   template<typename R> static inline void
01553   set_neutral (R& r) { set_false (r); }
01554   template<typename B, typename C> static inline void
01555   set_op (B& x, const C& y) { x= x || is_infinite (y); }
01556   template<typename T> static inline bool
01557   op (const T& x) { return is_infinite (x); }
01558 };
01559 
01560 struct or_is_fuzz_op {
01561   template<typename B> static inline B
01562   neutral () { return false; }
01563   template<typename R> static inline void
01564   set_neutral (R& r) { set_false (r); }
01565   template<typename B, typename C> static inline void
01566   set_op (B& x, const C& y) { x= x || is_fuzz (y); }
01567   template<typename T> static inline bool
01568   op (const T& x) { return is_fuzz (x); }
01569 };
01570 
01571 struct or_is_nan_op {
01572   template<typename B> static inline B
01573   neutral () { return false; }
01574   template<typename R> static inline void
01575   set_neutral (R& r) { set_false (r); }
01576   template<typename B, typename C> static inline void
01577   set_op (B& x, const C& y) { x= x || is_nan (y); }
01578   template<typename T> static inline bool
01579   op (const T& x) { return is_nan (x); }
01580 };
01581 
01582 template<typename C> struct unary_return_type_helper<is_finite_op,C> {
01583   typedef bool RET; };
01584 template<typename C> struct unary_return_type_helper<is_infinite_op,C> {
01585   typedef bool RET; };
01586 template<typename C> struct unary_return_type_helper<is_fuzz_op,C> {
01587   typedef bool RET; };
01588 template<typename C> struct unary_return_type_helper<is_nan_op,C> {
01589   typedef bool RET; };
01590 template<typename C> struct unary_return_type_helper<and_is_finite_op,C> {
01591   typedef bool RET; };
01592 template<typename C> struct unary_return_type_helper<or_is_infinite_op,C> {
01593   typedef bool RET; };
01594 template<typename C> struct unary_return_type_helper<or_is_fuzz_op,C> {
01595   typedef bool RET; };
01596 template<typename C> struct unary_return_type_helper<or_is_nan_op,C> {
01597   typedef bool RET; };
01598 
01599 struct exponent_op {
01600   // Get the exponent of a floating point like number
01601   static generic name () { return GEN_EXPONENT; }
01602   template<typename C> static inline xint
01603   op (const C& x) { return exponent (x); }
01604   template<typename R, typename C> static inline void
01605   set_op (R& x, const C& y) { x= exponent (y); }
01606 };
01607 
01608 struct max_exponent_op {
01609   template<typename C> static inline C
01610   neutral () { return Minimal (C); }
01611   template<typename R> static inline void
01612   set_neutral (R& x) { set_minimal (x); }
01613   template<typename R, typename C> static inline void
01614   set_op (R& x, const C& y) { x= max (x, exponent (y)); }
01615 };
01616 
01617 template<typename C> struct unary_return_type_helper<exponent_op,C> {
01618   typedef xint RET; };
01619 template<typename C> struct unary_return_type_helper<max_exponent_op,C> {
01620   typedef xint RET; };
01621 
01622 struct magnitude_op {
01623   // Get the fractional exponent of a floating point like number.
01624   // For instance, if z is an ordinary or complex floating point number,
01625   // then its magnitude is given by log2 abs z.
01626   static generic name () { return GEN_MAGNITUDE; }
01627   template<typename C> static inline double
01628   op (const C& x) { return magnitude (x); }
01629   template<typename R, typename C> static inline void
01630   set_op (R& x, const C& y) { x= magnitude (y); }
01631 };
01632 
01633 struct max_magnitude_op {
01634   template<typename C> static inline C
01635   neutral () { return Minimal (C); }
01636   template<typename R> static inline void
01637   set_neutral (R& x) { set_minimal (x); }
01638   template<typename R, typename C> static inline void
01639   set_op (R& x, const C& y) { x= max (x, magnitude (y)); }
01640 };
01641 
01642 template<typename C> struct unary_return_type_helper<magnitude_op,C> {
01643   typedef double RET; };
01644 template<typename C> struct unary_return_type_helper<max_magnitude_op,C> {
01645   typedef double RET; };
01646 
01647 struct precision_op {
01648   // Get the actual precision of a multiple precision floating point
01649   // like number. For vectorial inputs, we take the minimum over all entries
01650   static generic name () { return GEN_PRECISION; }
01651   template<typename C> static inline xnat
01652   op (const C& x) { return precision (x); }
01653   template<typename R, typename C> static inline void
01654   set_op (R& x, const C& y) { x= precision (y); }
01655 };
01656 
01657 struct min_precision_op {
01658   template<typename C> static inline C
01659   neutral () { return Maximal (C); }
01660   template<typename R> static inline void
01661   set_neutral (R& x) { set_minimal (x); }
01662   template<typename R, typename C> static inline void
01663   set_op (R& x, const C& y) { x= min (x, precision (y)); }
01664 };
01665 
01666 template<typename C> struct unary_return_type_helper<precision_op,C> {
01667   typedef xnat RET; };
01668 template<typename C> struct unary_return_type_helper<min_precision_op,C> {
01669   typedef xnat RET; };
01670 
01671 struct change_precision_op {
01672   // Change the actual precision of a multiple precision
01673   // floating point like number
01674   static generic name () { return GEN_CHANGE_PRECISION; }
01675   template<typename C> static inline C
01676   op (const C& x, xnat p) { return change_precision (x, p); }
01677   template<typename R, typename C> static inline void
01678   set_op (R& x, const C& y, xnat p) { x= change_precision (y, p); }
01679 };
01680 
01681 struct rounding_error_op {
01682   // When the number x is the result of a floating point computation,
01683   // rounding_error (x) is an upper bound for the distance between x and
01684   // the corresponding exact computation. For instance, for real x,
01685   // taking rounding_error (x) = max (next_above x - x, x - next_below x)
01686   // is potentially slow, but correct for all rounding modes
01687   static generic name () { return GEN_ROUNDING_ERROR; }
01688   template<typename C> static inline Abs_type(C)
01689   op (const C& x) { return rounding_error (x); }
01690   template<typename R, typename C> static inline void
01691   set_op (R& x, const C& y) { x= as<R> (rounding_error (y)); }
01692 };
01693 
01694 struct additive_error_op {
01695   // This is a variant of rounding_error_op to be used in
01696   // the specific cases of addition, subtraction and truncation
01697   static generic name () { return GEN_ADDITIVE_ERROR; }
01698   template<typename C> static inline Abs_type(C)
01699   op (const C& x) { return additive_error (x); }
01700   template<typename R, typename C> static inline void
01701   set_op (R& x, const C& y) { x= as<R> (additive_error (y)); }
01702 };
01703 
01704 struct multiplicative_error_op {
01705   // This is a variant of rounding_error_op to be used in
01706   // the specific cases of multiplication, division, shifting,
01707   // sqrt, hypot and abs
01708   static generic name () { return GEN_MULTIPLICATIVE_ERROR; }
01709   template<typename C> static inline Abs_type(C)
01710   op (const C& x) { return multiplicative_error (x); }
01711   template<typename R, typename C> static inline void
01712   set_op (R& x, const C& y) { x= as<R> (multiplicative_error (y)); }
01713 };
01714 
01715 struct elementary_error_op {
01716   // This is a variant of rounding_error_op to be used in
01717   // the specific cases of elementary functions
01718   static generic name () { return GEN_ELEMENTARY_ERROR; }
01719   template<typename C> static inline Abs_type(C)
01720   op (const C& x) { return elementary_error (x); }
01721   template<typename R, typename C> static inline void
01722   set_op (R& x, const C& y) { x= as<R> (elementary_error (y)); }
01723 };
01724 
01725 struct floor_op {
01726   // closest integer below
01727   static generic name () { return GEN_FLOOR; }
01728   template<typename C> static inline C
01729   op (const C& x) { return floor (x); }
01730   template<typename C> static inline void
01731   set_op (C& x) { x= floor (x); }
01732   template<typename R, typename C> static inline void
01733   set_op (R& x, const C& y) { x= floor (y); }
01734 };
01735 
01736 struct trunc_op {
01737   // closest integer when rounding towards zero
01738   static generic name () { return GEN_TRUNC; }
01739   template<typename C> static inline C
01740   op (const C& x) { return trunc (x); }
01741   template<typename C> static inline void
01742   set_op (C& x) { x= trunc (x); }
01743   template<typename R, typename C> static inline void
01744   set_op (R& x, const C& y) { x= trunc (y); }
01745 };
01746 
01747 struct ceil_op {
01748   // closest integer above
01749   static generic name () { return GEN_CEIL; }
01750   template<typename C> static inline C
01751   op (const C& x) { return ceil (x); }
01752   template<typename C> static inline void
01753   set_op (C& x) { x= ceil (x); }
01754   template<typename R, typename C> static inline void
01755   set_op (R& x, const C& y) { x= ceil (y); }
01756 };
01757 
01758 struct round_op {
01759   // closest integer
01760   static generic name () { return GEN_ROUND; }
01761   template<typename C> static inline C
01762   op (const C& x) { return round (x); }
01763   template<typename C> static inline void
01764   set_op (C& x) { x= round (x); }
01765   template<typename R, typename C> static inline void
01766   set_op (R& x, const C& y) { x= round (y); }
01767 };
01768 
01769 /******************************************************************************
01770 * Operators on complex number like types
01771 ******************************************************************************/
01772 
01773 struct gaussian_op {
01774   static generic name () { return GEN_GAUSSIAN; }
01775   template<typename C> static inline Complex_type(C)
01776   op (const C& x, const C& y) { return gaussian (x, y); }
01777   static inline generic
01778   op (const generic& x, const generic& y) { return gaussian (x, y); }
01779   static inline syntactic
01780   op (const syntactic& x, const syntactic& y) { return gaussian (x, y); }
01781   template<typename R, typename C1, typename C2> static inline void
01782   set_op (R& x, const C1& y1, const C2& y2) { gaussian_as (x, y1, y2); }
01783 };
01784 
01785 struct polar_op {
01786   static generic name () { return GEN_POLAR; }
01787   template<typename C> static inline Complex_type(C)
01788   op (const C& x, const C& y) { return polar (x, y); }
01789   static inline generic
01790   op (const generic& x, const generic& y) { return polar (x, y); }
01791   template<typename R, typename C1, typename C2> static inline void
01792   set_op (R& x, const C1& y1, const C2& y2) { x= polar (y1, y2); }
01793 };
01794 
01795 template<typename C>
01796 struct binary_return_type_helper<polar_op,C,C> {
01797   typedef Complex_type(C) RET;
01798 };
01799 
01800 struct Re_op {
01801   static generic name () { return GEN_RE; }
01802   template<typename C> static inline Real_type(C)
01803   op (const C& z) { return Re (z); }
01804   static inline generic
01805   op (const generic& z) { return Re (z); }
01806   static inline syntactic
01807   op (const syntactic& z) { return Re (z); }
01808   template<typename R, typename C> static inline void
01809   set_op (R& x, const C& y) { x= Re (y); }
01810 };
01811 
01812 struct Im_op {
01813   static generic name () { return GEN_IM; }
01814   template<typename C> static inline Real_type(C)
01815   op (const C& z) { return Im (z); }
01816   static inline generic
01817   op (const generic& z) { return Im (z); }
01818   static inline syntactic
01819   op (const syntactic& z) { return Im (z); }
01820   template<typename R, typename C> static inline void
01821   set_op (R& x, const C& y) { x= Im (y); }
01822 };
01823 
01824 template<typename C>
01825 struct unary_return_type_helper<Im_op,C> {
01826   typedef Real_type(C) RET;
01827 };
01828 
01829 struct arg_op {
01830   static generic name () { return GEN_ARG; }
01831   template<typename C> static inline Real_type(C)
01832   op (const C& z) { return arg (z); }
01833   static inline generic
01834   op (const generic& z) { return arg (z); }
01835   static inline syntactic
01836   op (const syntactic& z) { return arg (z); }
01837   template<typename R, typename C> static inline void
01838   set_op (R& x, const C& y) { x= arg (y); }
01839 };
01840 
01841 template<typename C>
01842 struct unary_return_type_helper<arg_op,C> {
01843   typedef Real_type(C) RET;
01844 };
01845 
01846 struct conj_op {
01847   static generic name () { return GEN_CONJ; }
01848   template<typename C> static inline C
01849   op (const C& z) { return conj (z); }
01850   template<typename R, typename C> static inline void
01851   set_op (R& x, const C& y) { x= conj (y); }
01852 };
01853 
01854 /******************************************************************************
01855 * Operators on ball like types
01856 ******************************************************************************/
01857 
01858 struct ball_op {
01859   static generic name () { return GEN_BALL; }
01860   template<typename B, typename C, typename R> static inline B
01861   op (const C& c, const R& r) {
01862     return make_ball<B> (c, r); }
01863   template<typename B, typename C, typename R> static inline void
01864   set_op (B& b, const C& c, const R& r) {
01865     b= make_ball<B> (c, r); }
01866 };
01867 
01868 struct center_op {
01869   static generic name () { return GEN_CENTER; }
01870   template<typename C> static inline Center_type(C)
01871   op (const C& x) { return center (x); }
01872   template<typename R, typename C> static inline void
01873   set_op (R& x, const C& y) { x= center (y); }
01874 };
01875 
01876 struct radius_op {
01877   static generic name () { return GEN_RADIUS; }
01878   template<typename C> static inline Radius_type(C)
01879   op (const C& x) { return radius (x); }
01880   template<typename R, typename C> static inline void
01881   set_op (R& x, const C& y) { x= radius (y); }
01882 };
01883 
01884 struct interval_op {
01885   static generic name () { return GEN_INTERVAL; }
01886   template<typename B, typename R> static inline B
01887   op (const R& l, const R& r) {
01888     return make_interval<B> (l, r); }
01889   template<typename B, typename R> static inline void
01890   set_op (B& b, const R& l, const R& r) {
01891     b= make_interval<B> (l, r); }
01892 };
01893 
01894 struct lower_op {
01895   static generic name () { return GEN_LOWER; }
01896   template<typename C> static inline Center_type(C)
01897   op (const C& x) { return lower (x); }
01898   template<typename R, typename C> static inline void
01899   set_op (R& x, const C& y) { x= lower (y); }
01900 };
01901 
01902 template<typename C>
01903 struct unary_return_type_helper<lower_op,C> {
01904   typedef Center_type(C) RET;
01905 };
01906 
01907 struct upper_op {
01908   static generic name () { return GEN_UPPER; }
01909   template<typename C> static inline Center_type(C)
01910   op (const C& x) { return upper (x); }
01911   template<typename R, typename C> static inline void
01912   set_op (R& x, const C& y) { x= upper (y); }
01913 };
01914 
01915 template<typename C>
01916 struct unary_return_type_helper<upper_op,C> {
01917   typedef Center_type(C) RET;
01918 };
01919 
01920 struct sharpen_op {
01921   // return number with same center and zero radius
01922   static generic name () { return GEN_SHARPEN; }
01923   template<typename C> static inline C
01924   op (const C& x) { return sharpen (x); }
01925   template<typename R, typename C> static inline void
01926   set_op (R& x, const C& y) { x= sharpen (y); }
01927 };
01928 
01929 struct blur_op {
01930   // increase radius by a given amount
01931   static generic name () { return GEN_BLUR; }
01932   template<typename C, typename D> static inline C
01933   op (const C& x, const D& y) { return blur (x, y); }
01934   template<typename R, typename C, typename D> static inline void
01935   set_op (R& x, const C& y, const D& z) { x= blur (y, z); }
01936 };
01937 
01938 /******************************************************************************
01939 * Operators on quotient types
01940 ******************************************************************************/
01941 
01942 struct numerator_op {
01943   static generic name () { return GEN_NUMERATOR; }
01944   template<typename C> static inline Numerator_type(C)
01945   op (const C& z) { return numerator (z); }
01946   static inline generic
01947   op (const generic& z) { return numerator (z); }
01948   static inline syntactic
01949   op (const syntactic& z) { return numerator (z); }
01950   template<typename R, typename C> static inline void
01951   set_op (R& x, const C& y) { x= numerator (y); }
01952 };
01953 
01954 struct denominator_op {
01955   static generic name () { return GEN_DENOMINATOR; }
01956   template<typename C> static inline Denominator_type(C)
01957   op (const C& z) { return denominator (z); }
01958   static inline generic
01959   op (const generic& z) { return denominator (z); }
01960   static inline syntactic
01961   op (const syntactic& z) { return denominator (z); }
01962   template<typename R, typename C> static inline void
01963   set_op (R& x, const C& y) { x= denominator (y); }
01964 };
01965 
01966 /******************************************************************************
01967 * Operators on modular and fibered like types
01968 ******************************************************************************/
01969 
01970 template<typename R>
01971 struct lift_helper {
01972   template<typename C> static inline R
01973   op (const C& x) { return as<R> (lift (x)); }
01974 };
01975 
01976 struct lift_op {
01977   static generic name () { return GEN_LIFT; }
01978   template<typename C> static inline Lift_type(C)
01979   op (const C& x) { return lift (x); }
01980   template<typename R, typename C> static inline void
01981   set_op (R& x, const C& y) { x= lift_helper<R>::op (y); }
01982 };
01983 
01984 template<typename C>
01985 struct unary_return_type_helper<lift_op,C> {
01986   typedef Lift_type(C) RET;
01987 };
01988 
01989 template<typename R>
01990 struct project_helper {
01991   template<typename C> static inline R
01992   op (const C& x) { return as<R> (project (x)); }
01993 };
01994 
01995 struct project_op {
01996   static generic name () { return GEN_PROJECT; }
01997   template<typename C> static inline Project_type(C)
01998   op (const C& x) { return project (x); }
01999   template<typename R, typename C> static inline void
02000   set_op (R& x, const C& y) { x= project_helper<R>::op (y); }
02001 };
02002 
02003 template<typename C>
02004 struct unary_return_type_helper<project_op,C> {
02005   typedef Project_type(C) RET;
02006 };
02007 
02008 /******************************************************************************
02009 * Calculus
02010 ******************************************************************************/
02011 
02012 struct derive_op {
02013   static generic name () { return GEN_DERIVE; }
02014   template<typename C> static inline C
02015   op (const C& x) { return derive (x); }
02016   template<typename R, typename C> static inline void
02017   set_op (R& x, const C& y) { x= derive (y); }
02018   template<typename C,typename V> static inline C
02019   op (const C& x, const V& v) { return derive (x, v); }
02020   template<typename R, typename C, typename V> static inline void
02021   set_op (R& x, const C& y, const V& v) { x= derive (y, v); }
02022 };
02023 
02024 struct xderive_op {
02025   static generic name () { return GEN_XDERIVE; }
02026   template<typename C> static inline C
02027   op (const C& x) { return xderive (x); }
02028   template<typename R, typename C> static inline void
02029   set_op (R& x, const C& y) { return xderive (y); }
02030   template<typename C,typename V> static inline C
02031   op (const C& x, const V& v) { return xderive (x, v); }
02032   template<typename R, typename C, typename V> static inline void
02033   set_op (R& x, const C& y, const V& v) { x= xderive (y, v); }
02034 };
02035 
02036 struct integrate_op {
02037   static generic name () { return GEN_INTEGRATE; }
02038   template<typename C> static inline C
02039   op (const C& x) { return integrate (x); }
02040   template<typename R, typename C> static inline void
02041   set_op (R& x, const C& y) { x= integrate (y); }
02042   template<typename C,typename V> static inline C
02043   op (const C& x, const V& v) { return integrate (x, v); }
02044   template<typename R, typename C, typename V> static inline void
02045   set_op (R& x, const C& y, const V& v) { x= integrate (y, v); }
02046   template<typename C,typename I> static inline C
02047   op_init (const C& x, const I& i) { return integrate_init (x, i); }
02048   template<typename C,typename V,typename I> static inline C
02049   op_init (const C& x, const V& v, const I& i) {
02050     return integrate_init (x, v, i); }
02051 };
02052 
02053 struct compose_op {
02054   static generic name () { return GEN_COMPOSE; }
02055   template<typename C1,typename C2> static inline C1
02056   op (const C1& x, const C2& y) { return compose (x, y); }
02057   template<typename R, typename C1, typename C2> static inline void
02058   set_op (R& x, const C1& y1, const C2& y2) { x= compose (y1, y2); }
02059   template<typename C> static inline C
02060   diff_op (const C& me, const C& x, const C& y) {
02061     (void) me; return derive (y) * compose (derive (x), y); }
02062 };
02063 
02064 struct reverse_op {
02065   static generic name () { return GEN_REVERSE; }
02066   template<typename C> static inline C
02067   op (const C& x) { return reverse (x); }
02068   template<typename R, typename C> static inline void
02069   set_op (R& x, const C& y) { x= reverse (y); }
02070   template<typename C> static inline C
02071   diff_op (const C& me, const C& x) {
02072     return 1 / compose (derive (x), me); }
02073 };
02074 
02075 struct append_op {
02076   static generic name () { return GEN_APPEND; }
02077   template<typename C1,typename C2> static inline C1
02078   op (const C1& x, const C2& y) { return append (x, y); }
02079   template<typename R, typename C1, typename C2> static inline void
02080   set_op (R& x, const C1& y1, const C2& y2) { x= append (y1, y2); }
02081 };
02082 
02083 struct solve_vector_lde_op {
02084   template<typename C> static inline C
02085   op (const C& x) { ERROR ("must initialize (solve_vector_lde_op::op)"); }
02086   template<typename C, typename I> static inline C
02087   op_init (const C& x, const I& i) { return solve_vector_lde_init (x, i); }
02088   static inline generic op_init (const generic& x, const generic& i) { 
02089     return solve_lde_init (x, i); }
02090   static inline syntactic op_init (const syntactic& x, const syntactic& i) { 
02091     return solve_lde_init (x, i); }
02092   template<typename C> static inline C
02093   diff_op (const C& me, const C& x);
02094   static inline nat nr_init () { return 1; }
02095   template<typename C> static inline C
02096   def (const C& me, const C& f) {
02097     return integrate (diff_op (me, f)); }
02098 };
02099 
02100 struct solve_matrix_lde_op {
02101   template<typename C> static inline C
02102   op (const C& x) { ERROR ("must initialize (solve_matrix_lde_op::op)"); }
02103   template<typename C, typename I> static inline C
02104   op_init (const C& x, const I& i) { return solve_matrix_lde_init (x, i); }
02105   static inline generic op_init (const generic& x, const generic& i) { 
02106     return solve_lde_init (x, i); }
02107   static inline syntactic op_init (const syntactic& x, const syntactic& i) { 
02108     return solve_lde_init (x, i); }
02109   template<typename C> static inline C diff_op (const C& me, const C& x) {
02110     return x * me; }
02111   static inline nat nr_init () { return 1; }
02112   template<typename C> static inline C def (const C& me, const C& f) {
02113     return integrate (diff_op (me, f)); }
02114 };
02115 
02116 /******************************************************************************
02117 * Asymptotic relations
02118 ******************************************************************************/
02119 
02120 struct is_infinitesimal_op {
02121   template<typename T> static inline bool
02122   op (const T& x) { return x << 1; }
02123   template<typename T> static inline bool
02124   not_op (const T& x) { return !(x << 1); }
02125 };
02126 
02127 struct is_non_infinitesimal_op {
02128   template<typename T> static inline bool
02129   op (const T& x) { return !(x << 1); }
02130   template<typename T> static inline bool
02131   not_op (const T& x) { return x << 1; }
02132 };
02133 
02134 struct is_bounded_op {
02135   template<typename T> static inline bool
02136   op (const T& x) { return x <<= 1; }
02137   template<typename T> static inline bool
02138   not_op (const T& x) { return !(x <<= 1); }
02139 };
02140 
02141 struct is_non_bounded_op {
02142   template<typename T> static inline bool
02143   op (const T& x) { return !(x <<= 1); }
02144   template<typename T> static inline bool
02145   not_op (const T& x) { return x <<= 1; }
02146 };
02147 
02148 struct is_infinitely_large_op {
02149   template<typename T> static inline bool
02150   op (const T& x) { return x >> 1; }
02151   template<typename T> static inline bool
02152   not_op (const T& x) { return !(x >> 1); }
02153 };
02154 
02155 struct is_non_infinitely_large_op {
02156   template<typename T> static inline bool
02157   op (const T& x) { return !(x >> 1); }
02158   template<typename T> static inline bool
02159   not_op (const T& x) { return x >> 1; }
02160 };
02161 
02162 struct is_constant_op {
02163   template<typename T> static inline bool
02164   op (const T& x) { return x == 1; }
02165   template<typename T> static inline bool
02166   not_op (const T& x) { return x != 1; }
02167 };
02168 
02169 struct is_non_constant_op {
02170   template<typename T> static inline bool
02171   op (const T& x) { return x != 1; }
02172   template<typename T> static inline bool
02173   not_op (const T& x) { return x == 1; }
02174 };
02175 
02176 struct smaller_equal_op {
02177   template<typename T1, typename T2> static inline bool
02178   op (const T1& x1, const T2& x2) { return x1 <<= x2; }
02179   template<typename T1, typename T2> static inline bool
02180   not_op (const T1& x1, const T2& x2) { return !(x1 <<= x2); }
02181 };
02182 
02183 struct not_smaller_equal_op {
02184   template<typename T1, typename T2> static inline bool
02185   op (const T1& x1, const T2& x2) { return !(x1 <<= x2); }
02186   template<typename T1, typename T2> static inline bool
02187   not_op (const T1& x1, const T2& x2) { return x1 <<= x2; }
02188 };
02189 
02190 struct smaller_op {
02191   template<typename T1, typename T2> static inline bool
02192   op (const T1& x1, const T2& x2) { return x1 << x2; }
02193   template<typename T1, typename T2> static inline bool
02194   not_op (const T1& x1, const T2& x2) { return !(x1 << x2); }
02195 };
02196 
02197 struct not_smaller_op {
02198   template<typename T1, typename T2> static inline bool
02199   op (const T1& x1, const T2& x2) { return !(x1 << x2); }
02200   template<typename T1, typename T2> static inline bool
02201   not_op (const T1& x1, const T2& x2) { return x1 << x2; }
02202 };
02203 
02204 struct larger_equal_op {
02205   template<typename T> static inline bool
02206   op (const T& x1, const T& x2) { return x1 >>= x2; }
02207   template<typename T> static inline bool
02208   not_op (const T& x1, const T& x2) { return !(x1 >>= x2); }
02209 };
02210 
02211 struct not_larger_equal_op {
02212   template<typename T> static inline bool
02213   op (const T& x1, const T& x2) { return !(x1 >>= x2); }
02214   template<typename T> static inline bool
02215   not_op (const T& x1, const T& x2) { return x1 >>= x2; }
02216 };
02217 
02218 struct larger_op {
02219   template<typename T> static inline bool
02220   op (const T& x1, const T& x2) { return x1 >> x2; }
02221   template<typename T> static inline bool
02222   not_op (const T& x1, const T& x2) { return !(x1 >> x2); }
02223 };
02224 
02225 struct not_larger_op {
02226   template<typename T> static inline bool
02227   op (const T& x1, const T& x2) { return !(x1 >> x2); }
02228   template<typename T> static inline bool
02229   not_op (const T& x1, const T& x2) { return x1 >> x2; }
02230 };
02231 
02232 /******************************************************************************
02233 * Restriction of support
02234 ******************************************************************************/
02235 
02236 struct common_part_op {
02237   typedef zero_op lop;
02238   typedef zero_op rop;
02239   static generic name () { return "common_part"; }
02240   template<typename T> static inline T
02241   op (const T& x, const T& y) { return common_part (x, y); }
02242 };
02243 
02244 struct dominant_part_op {
02245   static generic name () { return "dominant_part"; }
02246   template<typename T> static inline T
02247   op (const T& x) { return dominant_part (x); }
02248 };
02249 
02250 struct remainder_part_op {
02251   static generic name () { return "remainder_part"; }
02252   template<typename T> static inline T
02253   op (const T& x) { return remainder_part (x); }
02254 };
02255 
02256 struct infinitesimal_part_op {
02257   typedef is_infinitesimal_op pred;
02258   static generic name () { return "infinitesimal_part"; }
02259   template<typename T> static inline T
02260   op (const T& x) { return infinitesimal_part (x); }
02261 };
02262 
02263 struct non_infinitesimal_part_op {
02264   typedef is_non_infinitesimal_op pred;
02265   static generic name () { return "non_infinitesimal_part"; }
02266   template<typename T> static inline T
02267   op (const T& x) { return non_infinitesimal_part (x); }
02268 };
02269 
02270 struct bounded_part_op {
02271   typedef is_bounded_op pred;
02272   static generic name () { return "bounded_part"; }
02273   template<typename T> static inline T
02274   op (const T& x) { return bounded_part (x); }
02275 };
02276 
02277 struct non_bounded_part_op {
02278   typedef is_non_bounded_op pred;
02279   static generic name () { return "non_bounded_part"; }
02280   template<typename T> static inline T
02281   op (const T& x) { return non_bounded_part (x); }
02282 };
02283 
02284 struct infinite_part_op {
02285   typedef is_infinitely_large_op pred;
02286   static generic name () { return "infinite_part"; }
02287   template<typename T> static inline T
02288   op (const T& x) { return infinite_part (x); }
02289 };
02290 
02291 struct non_infinite_part_op {
02292   typedef is_non_infinitely_large_op pred;
02293   static generic name () { return "non_infinite_part"; }
02294   template<typename T> static inline T
02295   op (const T& x) { return non_infinite_part (x); }
02296 };
02297 
02298 struct constant_part_op {
02299   typedef is_constant_op pred;
02300   static generic name () { return "constant_part"; }
02301   template<typename T> static inline T
02302   op (const T& x) { return constant_part (x); }
02303 };
02304 
02305 struct non_constant_part_op {
02306   typedef is_non_constant_op pred;
02307   static generic name () { return "non_constant_part"; }
02308   template<typename T> static inline T
02309   op (const T& x) { return non_constant_part (x); }
02310 };
02311 
02312 /******************************************************************************
02313 * Miscellaneous operators
02314 ******************************************************************************/
02315 
02316 struct access_op {
02317   static generic name () { return GEN_ACCESS; }
02318   template<typename C, typename I>
02319   static inline Binary_return_type(access_op,C,I)
02320   op (const C& x, const I& i) { return x[i]; }
02321   template<typename R, typename C, typename I> static inline void
02322   set_op (R& x, const C& y, const I& i) { x= y[i]; }
02323 };
02324 
02325 struct mv_inject_op {
02326   static generic name () { return "inject"; }
02327   template<typename C, typename I, typename D> static inline C
02328   op (const C& x, const I& i, const D& d) { return inject (x, i, d); }
02329   template<typename R, typename C, typename I, typename D> static inline void
02330   set_op (R& x, const C& y, const I& i, const D& d) { x= inject (y, i, d); }
02331 };
02332 
02333 struct mv_project_op {
02334   static generic name () { return "project"; }
02335   template<typename C, typename I> static inline C
02336   op (const C& x, const I& i) { return project (x, i); }
02337   template<typename R, typename C, typename I> static inline void
02338   set_op (R& x, const C& y, const I& i) { x= project (y, i); }
02339 };
02340 
02341 } // namespace mmx
02342 #endif // __MMX_OPERATORS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines