?? functorexpr.h
字號:
// -*- C++ -*-/*************************************************************************** * blitz/array/functorExpr.h User-defined functors for arrays * * $Id: functorExpr.h,v 1.8 2005/05/07 04:17:57 julianc Exp $ * * Copyright (C) 1997-2001 Todd Veldhuizen <tveldhui@oonumerics.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Suggestions: blitz-dev@oonumerics.org * Bugs: blitz-bugs@oonumerics.org * * For more information, please see the Blitz++ Home Page: * http://oonumerics.org/blitz/ * ****************************************************************************//* This header file is designed to allow the use of Blitz++ with functors (classes defining an operator()) and more general member functions. It works best if you have access to the class source code; there is limited support for classes that cannot be modified. The best approach in that case is usually to write an adapter class. This works with class methods that take one, two or three arguments. If you have a functor, add the following to your (public) class declaration: BZ_DECLARE_FUNCTOR(classname) // for one argument functors BZ_DECLARE_FUNCTOR2(classname) // for two argument functors BZ_DECLARE_FUNCTOR3(classname) // for three argument functors or BZ_DECLARE_FUNCTOR_RET(classname, returnType) BZ_DECLARE_FUNCTOR2_RET(classname, returnType) BZ_DECLARE_FUNCTOR3_RET(classname, returnType) for classes whose operator() has a return type that is not what you would deduce from the usual C++ promotion rules (e.g., takes two doubles and returns a bool). You can then use your class in Blitz++ expressions and no temporaries will be generated. For example, assuming that your class is named T, and that A, B and C are Arrays, you can write T classInstance( ... ); A = C + classInstance(B * tensor::i); A = C + classInstance(tensor::i, tensor::j) It also works for member functions: BZ_DECLARE_MEMBER_FUNCTION(classname, funcname) BZ_DECLARE_MEMBER_FUNCTION2(classname, funcname) BZ_DECLARE_MEMBER_FUNCTION3(classname, funcname) or BZ_DECLARE_MEMBER_FUNCTION_RET(classname, funcname, returnType) BZ_DECLARE_MEMBER_FUNCTION2_RET(classname, funcname, returnType) BZ_DECLARE_MEMBER_FUNCTION3_RET(classname, funcname, returnType) allows you to write stuff like A = C + classInstance.funcname(B * tensor::i); A = C + classInstance.funcname(tensor::i, tensor::j) All the member functions to be applied must be declared const. There is also some support for classes where the source code is not available or not to be tampered with. For example, A = C + applyFunctor(classInstance, B * tensor::i); A = C + applyFunctor(classInstance, tensor::i, tensor::j); This approach does not work for arbitrary member functions. The class must be a proper functor with an operator(). */#ifndef BZ_ARRAY_FUNCTOREXPR_H#define BZ_ARRAY_FUNCTOREXPR_H#ifndef BZ_ARRAY_H #error <blitz/array/functorExpr.h> must be included via <blitz/array.h>#endif#include <blitz/prettyprint.h>#include <blitz/shapecheck.h>#include <blitz/tinyvec.h>BZ_NAMESPACE(blitz)template<typename P_functor, typename P_expr, typename P_result>class _bz_FunctorExpr {public: typedef P_functor T_functor; typedef P_expr T_expr; typedef _bz_typename T_expr::T_numtype T_numtype1; typedef P_result T_numtype; typedef T_expr T_ctorArg1; typedef int T_ctorArg2; // dummy typedef int T_ctorArg3; // dummy static const int numArrayOperands = T_expr::numArrayOperands, numIndexPlaceholders = T_expr::numIndexPlaceholders, rank = T_expr::rank; _bz_FunctorExpr(const _bz_FunctorExpr<P_functor,P_expr,P_result>& a) : f_(a.f_), iter_(a.iter_) { } _bz_FunctorExpr(BZ_ETPARM(T_functor) f, BZ_ETPARM(T_expr) a) : f_(f), iter_(a) { } _bz_FunctorExpr(BZ_ETPARM(T_functor) f, _bz_typename T_expr::T_ctorArg1 a) : f_(f), iter_(a) { }#if BZ_TEMPLATE_CTOR_DOESNT_CAUSE_HAVOC template<typename T1> explicit _bz_FunctorExpr(BZ_ETPARM(T_functor) f, BZ_ETPARM(T1) a) : f_(f), iter_(a) { }#endif T_numtype operator*() { return f_(*iter_); }#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE template<int N_rank> T_numtype operator()(TinyVector<int,N_rank> i) { return f_(iter_(i)); }#else template<int N_rank> T_numtype operator()(const TinyVector<int,N_rank>& i) { return f_(iter_(i)); }#endif int ascending(int rank) { return iter_.ascending(rank); } int ordering(int rank) { return iter_.ordering(rank); } int lbound(int rank) { return iter_.lbound(rank); } int ubound(int rank) { return iter_.ubound(rank); } void push(int position) { iter_.push(position); } void pop(int position) { iter_.pop(position); } void advance() { iter_.advance(); } void advance(int n) { iter_.advance(n); } void loadStride(int rank) { iter_.loadStride(rank); } bool isUnitStride(int rank) const { return iter_.isUnitStride(rank); } void advanceUnitStride() { iter_.advanceUnitStride(); } bool canCollapse(int outerLoopRank, int innerLoopRank) const { return iter_.canCollapse(outerLoopRank, innerLoopRank); } T_numtype operator[](int i) { return f_(iter_[i]); } T_numtype fastRead(int i) { return f_(iter_.fastRead(i)); } int suggestStride(int rank) const { return iter_.suggestStride(rank); } bool isStride(int rank, int stride) const { return iter_.isStride(rank,stride); } void prettyPrint(BZ_STD_SCOPE(string) &str, prettyPrintFormat& format) const { str += BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(T_functor); str += "("; iter_.prettyPrint(str, format); str += ")"; } template<typename T_shape> bool shapeCheck(const T_shape& shape) { return iter_.shapeCheck(shape); } template<int N_rank> void moveTo(const TinyVector<int,N_rank>& i) { iter_.moveTo(i); }protected: _bz_FunctorExpr() { } T_functor f_; T_expr iter_;};template<typename P_functor, typename P_expr1, typename P_expr2, typename P_result>class _bz_FunctorExpr2 {public: typedef P_functor T_functor; typedef P_expr1 T_expr1; typedef P_expr2 T_expr2; typedef _bz_typename T_expr1::T_numtype T_numtype1; typedef _bz_typename T_expr2::T_numtype T_numtype2; typedef P_result T_numtype; typedef T_expr1 T_ctorArg1; typedef T_expr1 T_ctorArg2; typedef int T_ctorArg3; // dummy static const int numArrayOperands = T_expr1::numArrayOperands + T_expr2::numArrayOperands, numIndexPlaceholders = T_expr1::numIndexPlaceholders + T_expr2::numIndexPlaceholders, rank = T_expr1::rank > T_expr2::rank ? T_expr1::rank : T_expr2::rank; _bz_FunctorExpr2(const _bz_FunctorExpr2<P_functor, P_expr1, P_expr2, P_result>& a) : f_(a.f_), iter1_(a.iter1_), iter2_(a.iter2_) { } _bz_FunctorExpr2(BZ_ETPARM(T_functor) f, BZ_ETPARM(T_expr1) a, BZ_ETPARM(T_expr2) b) : f_(f), iter1_(a), iter2_(b) { } template<typename T1, typename T2> _bz_FunctorExpr2(BZ_ETPARM(T_functor) f, BZ_ETPARM(T1) a, BZ_ETPARM(T2) b) : f_(f), iter1_(a), iter2_(b) { } T_numtype operator*() { return f_(*iter1_, *iter2_); }#ifdef BZ_ARRAY_EXPR_PASS_INDEX_BY_VALUE template<int N_rank> T_numtype operator()(TinyVector<int, N_rank> i) { return f_(iter1_(i), iter2_(i)); }#else template<int N_rank> T_numtype operator()(const TinyVector<int, N_rank>& i) { return f_(iter1_(i), iter2_(i)); }#endif int ascending(int rank) { return bounds::compute_ascending(rank, iter1_.ascending(rank), iter2_.ascending(rank)); } int ordering(int rank) { return bounds::compute_ordering(rank, iter1_.ordering(rank), iter2_.ordering(rank)); } int lbound(int rank) { return bounds::compute_lbound(rank, iter1_.lbound(rank), iter2_.lbound(rank)); } int ubound(int rank) { return bounds::compute_ubound(rank, iter1_.ubound(rank), iter2_.ubound(rank)); } void push(int position) { iter1_.push(position); iter2_.push(position); } void pop(int position) { iter1_.pop(position); iter2_.pop(position); } void advance() { iter1_.advance(); iter2_.advance(); } void advance(int n) { iter1_.advance(n); iter2_.advance(n); } void loadStride(int rank) { iter1_.loadStride(rank); iter2_.loadStride(rank); } bool isUnitStride(int rank) const { return iter1_.isUnitStride(rank) && iter2_.isUnitStride(rank); } void advanceUnitStride() { iter1_.advanceUnitStride();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -