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