blitz Version 0.9
|
00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * blitz/ops.h Function objects for math operators 00004 * 00005 * $Id: ops.h,v 1.7 2004/03/09 21:56:00 julianc Exp $ 00006 * 00007 * Copyright (C) 1997-2001 Todd Veldhuizen <tveldhui@oonumerics.org> 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * Suggestions: blitz-dev@oonumerics.org 00020 * Bugs: blitz-bugs@oonumerics.org 00021 * 00022 * For more information, please see the Blitz++ Home Page: 00023 * http://oonumerics.org/blitz/ 00024 * 00025 *************************************************************************/ 00026 00027 #ifndef BZ_OPS_H 00028 #define BZ_OPS_H 00029 00030 #include <blitz/blitz.h> 00031 #include <blitz/promote.h> 00032 #include <blitz/prettyprint.h> 00033 00034 BZ_NAMESPACE(blitz) 00035 00036 /* 00037 * Originally these function objects had no template arguments, e.g. 00038 * 00039 * struct Add { 00040 * template<typename T_numtype1, typename T_numtype2> 00041 * static inline BZ_PROMOTE(T_numtype1, T_numtype2) 00042 * apply(T_numtype1 a, T_numtype2 b) 00043 * { return a + b; } 00044 * }; 00045 * 00046 * This made for neater expression templates syntax. However, there are 00047 * some situations in which users may want to override type promotion 00048 * for certain operations. For example, in theoretical physics, there 00049 * are U1 objects which when multiplied yield U1 objects, but when added 00050 * yield a different type. To allow for this kind of behaviour, function 00051 * objects have been changed to take template parameters: 00052 * 00053 * template<typename T_numtype1, typename T_numtype2> 00054 * struct Add { 00055 * typedef BZ_PROMOTE(T_numtype1, T_numtype2) T_numtype; 00056 * 00057 * static inline T_numtype apply(T_numtype1 a, T_numtype2 b) 00058 * { return a + b; } 00059 * }; 00060 * 00061 * Type promotion is performed inside the function object. The expression 00062 * templates code always looks inside the function object to determine 00063 * the type promotion, e.g. Add<int,float>::T_numtype 00064 * 00065 * Users are free to specialize these function objects for their own types. 00066 */ 00067 00068 /* Unary operators that return same type as argument */ 00069 00070 #define BZ_DEFINE_UNARY_OP(name,op) \ 00071 template<typename T_numtype1> \ 00072 struct name { \ 00073 typedef T_numtype1 T_numtype; \ 00074 \ 00075 static inline T_numtype \ 00076 apply(T_numtype1 a) \ 00077 { return op a; } \ 00078 \ 00079 template<typename T1> \ 00080 static inline void prettyPrint(BZ_STD_SCOPE(string) &str, \ 00081 prettyPrintFormat& format, const T1& t1) \ 00082 { \ 00083 str += #op; \ 00084 t1.prettyPrint(str, format); \ 00085 } \ 00086 }; 00087 00088 BZ_DEFINE_UNARY_OP(BitwiseNot,~) 00089 BZ_DEFINE_UNARY_OP(UnaryPlus,+) 00090 BZ_DEFINE_UNARY_OP(UnaryMinus,-) 00091 00092 00093 /* Unary operators that return a specified type */ 00094 00095 #define BZ_DEFINE_UNARY_OP_RET(name,op,ret) \ 00096 template<typename T_numtype1> \ 00097 struct name { \ 00098 typedef ret T_numtype; \ 00099 static inline T_numtype \ 00100 apply(T_numtype1 a) \ 00101 { return op a; } \ 00102 \ 00103 template<typename T1> \ 00104 static inline void prettyPrint(BZ_STD_SCOPE(string) &str, \ 00105 prettyPrintFormat& format, const T1& t1) \ 00106 { \ 00107 str += #op; \ 00108 t1.prettyPrint(str, format); \ 00109 } \ 00110 }; 00111 00112 BZ_DEFINE_UNARY_OP_RET(LogicalNot,!,bool) 00113 00114 00115 /* Binary operators that return type based on type promotion */ 00116 00117 #define BZ_DEFINE_BINARY_OP(name,op) \ 00118 template<typename T_numtype1, typename T_numtype2> \ 00119 struct name { \ 00120 typedef BZ_PROMOTE(T_numtype1, T_numtype2) T_numtype; \ 00121 \ 00122 static inline T_numtype \ 00123 apply(T_numtype1 a, T_numtype2 b) \ 00124 { return a op b; } \ 00125 \ 00126 template<typename T1, typename T2> \ 00127 static inline void prettyPrint(BZ_STD_SCOPE(string) &str, \ 00128 prettyPrintFormat& format, const T1& t1, \ 00129 const T2& t2) \ 00130 { \ 00131 str += "("; \ 00132 t1.prettyPrint(str, format); \ 00133 str += #op; \ 00134 t2.prettyPrint(str, format); \ 00135 str += ")"; \ 00136 } \ 00137 }; 00138 00139 BZ_DEFINE_BINARY_OP(Add,+) 00140 BZ_DEFINE_BINARY_OP(Subtract,-) 00141 BZ_DEFINE_BINARY_OP(Multiply,*) 00142 BZ_DEFINE_BINARY_OP(Divide,/) 00143 BZ_DEFINE_BINARY_OP(Modulo,%) 00144 BZ_DEFINE_BINARY_OP(BitwiseXor,^) 00145 BZ_DEFINE_BINARY_OP(BitwiseAnd,&) 00146 BZ_DEFINE_BINARY_OP(BitwiseOr,|) 00147 BZ_DEFINE_BINARY_OP(ShiftRight,>>) 00148 BZ_DEFINE_BINARY_OP(ShiftLeft,<<) 00149 00150 00151 /* Binary operators that return a specified type */ 00152 00153 #define BZ_DEFINE_BINARY_OP_RET(name,op,ret) \ 00154 template<typename T_numtype1, typename T_numtype2> \ 00155 struct name { \ 00156 typedef ret T_numtype; \ 00157 static inline T_numtype \ 00158 apply(T_numtype1 a, T_numtype2 b) \ 00159 { return a op b; } \ 00160 \ 00161 template<typename T1, typename T2> \ 00162 static inline void prettyPrint(BZ_STD_SCOPE(string) &str, \ 00163 prettyPrintFormat& format, const T1& t1, \ 00164 const T2& t2) \ 00165 { \ 00166 str += "("; \ 00167 t1.prettyPrint(str, format); \ 00168 str += #op; \ 00169 t2.prettyPrint(str, format); \ 00170 str += ")"; \ 00171 } \ 00172 }; 00173 00174 BZ_DEFINE_BINARY_OP_RET(Greater,>,bool) 00175 BZ_DEFINE_BINARY_OP_RET(Less,<,bool) 00176 BZ_DEFINE_BINARY_OP_RET(GreaterOrEqual,>=,bool) 00177 BZ_DEFINE_BINARY_OP_RET(LessOrEqual,<=,bool) 00178 BZ_DEFINE_BINARY_OP_RET(Equal,==,bool) 00179 BZ_DEFINE_BINARY_OP_RET(NotEqual,!=,bool) 00180 BZ_DEFINE_BINARY_OP_RET(LogicalAnd,&&,bool) 00181 BZ_DEFINE_BINARY_OP_RET(LogicalOr,||,bool) 00182 00183 00184 BZ_NAMESPACE_END 00185 00186 #endif // BZ_OPS_H 00187 00188