X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2Fcml%2Fvector%2Fvector_unroller.h;fp=src%2FMoof%2Fcml%2Fvector%2Fvector_unroller.h;h=0000000000000000000000000000000000000000;hp=eed6da66577b78d6eb4f004cc4ba141a2f27bae7;hb=831f04d4bc19a390415ac0bbac4331c7a65509bc;hpb=299af4f2047e767e5d79501c26444473bda64c64 diff --git a/src/Moof/cml/vector/vector_unroller.h b/src/Moof/cml/vector/vector_unroller.h deleted file mode 100644 index eed6da6..0000000 --- a/src/Moof/cml/vector/vector_unroller.h +++ /dev/null @@ -1,259 +0,0 @@ -/* -*- C++ -*- ------------------------------------------------------------ - -Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ - -The Configurable Math Library (CML) is distributed under the terms of the -Boost Software License, v1.0 (see cml/LICENSE for details). - - *-----------------------------------------------------------------------*/ -/** @file - * @brief - * - * Defines vector unrollers. - * - * @todo Add unrolling for dynamic vectors, and for vectors longer than - * CML_VECTOR_UNROLL_LIMIT. - * - * @todo Does it make sense to unroll an assignment if either side of the - * assignment has a fixed size, or just when the target vector is fixed - * size? - */ - -#ifndef vector_unroller_h -#define vector_unroller_h - -#include -#include -#include - -#if !defined(CML_VECTOR_UNROLL_LIMIT) -#error "CML_VECTOR_UNROLL_LIMIT is undefined." -#endif - -namespace cml { -namespace et { -namespace detail { - -/** Unroll a binary assignment operator on a fixed-size vector. - * - * This uses forward iteration to make efficient use of the cache. - * - * @sa cml::vector - * @sa cml::et::OpAssign - * - * @bug Need to verify that OpT is actually an assignment operator. - */ -template -class VectorAssignmentUnroller -{ - protected: - - /* Forward declare: */ - template struct Eval; - - /* The vector type being assigned to: */ - typedef cml::vector vector_type; - - /* Record traits for the arguments: */ - typedef ExprTraits dest_traits; - typedef ExprTraits src_traits; - - /** Evaluate the binary operator for the first Len-1 elements. */ - template struct Eval { - void operator()(vector_type& dest, const SrcT& src) const { - - /* Apply to current N: */ - OpT().apply(dest[N], src_traits().get(src,N)); - /* Note: we don't need get(), since dest is a vector. */ - - /* Apply to N+1: */ - Eval()(dest, src); - } - }; - - /** Evaluate the binary operator at element Last. */ - template struct Eval { - void operator()(vector_type& dest, const SrcT& src) const { - - /* Apply to last element: */ - OpT().apply(dest[Last], src_traits().get(src,Last)); - /* Note: we don't need get(), since dest is a vector. */ - } - }; - - - /** Evaluate the binary operator using a loop. - * - * This is used when the vector's length is longer than - * CML_VECTOR_UNROLL_LIMIT - */ - template struct Eval { - void operator()(vector_type& dest, const SrcT& src) const { - for(size_t i = 0; i <= Last; ++i) { - OpT().apply(dest[i], src_traits().get(src,i)); - /* Note: we don't need get(), since dest is a vector. */ - } - } - }; - - - public: - - /** Unroll assignment to a fixed-sized vector. */ - void operator()(vector_type& dest, const SrcT& src, cml::fixed_size_tag) - { - typedef cml::vector vector_type; - enum { Len = vector_type::array_size }; - typedef typename VectorAssignmentUnroller::template - Eval<0, Len-1, (Len <= CML_VECTOR_UNROLL_LIMIT)> Unroller; - /* Note: Len is the array size, so Len-1 is the last element. */ - - /* Use a run-time check if src is a run-time sized expression: */ - typedef typename ExprTraits::size_tag src_size; - typedef typename select_if< - same_type::is_true, - dynamic_size_tag, fixed_size_tag>::result size_tag; - - /* Check the expression size (the returned size isn't needed): */ - CheckedSize(dest,src,size_tag()); - /* Note: for two fixed-size expressions, the if-statements and - * comparisons should be completely eliminated as dead code. If src - * is a dynamic-sized expression, the check will still happen. - */ - - /* Now, call the unroller: */ - Unroller()(dest,src); - } - - - private: - /* XXX Blah, a temp. hack to fix the auto-resizing stuff below. */ - size_t CheckOrResize( - vector_type& dest, const SrcT& src, cml::resizable_tag) - { -#if defined(CML_AUTOMATIC_VECTOR_RESIZE_ON_ASSIGNMENT) - /* Get the size of src. This also causes src to check its size: */ - size_t N = std::max(dest.size(),src_traits().size(src)); - - /* Set the destination vector's size: */ - cml::et::detail::Resize(dest,N); -#else - size_t N = CheckedSize(dest,src,dynamic_size_tag()); -#endif - - return N; - } - - size_t CheckOrResize( - vector_type& dest, const SrcT& src, cml::not_resizable_tag) - { - return CheckedSize(dest,src,dynamic_size_tag()); - } - /* XXX Blah, a temp. hack to fix the auto-resizing stuff below. */ - public: - - - /** Just use a loop to assign to a runtime-sized vector. */ - void operator()(vector_type& dest, const SrcT& src, cml::dynamic_size_tag) - { - /* Shorthand: */ - typedef ExprTraits src_traits; - size_t N = this->CheckOrResize( - dest,src,typename vector_type::resizing_tag()); - for(size_t i = 0; i < N; ++i) { - OpT().apply(dest[i], src_traits().get(src,i)); - /* Note: we don't need get(), since dest is a vector. */ - } - } - -}; - -/** Unroll a vector accumulation/reduction operator. - * - * This uses forward iteration to make efficient use of the cache. - */ -template -struct VectorAccumulateUnroller -{ - /* Forward declare: */ - template struct Eval; - - /* Record traits for the arguments: */ - typedef ExprTraits left_traits; - typedef ExprTraits right_traits; - - /* Figure out the return type: */ - typedef typename AccumT::value_type result_type; - - /** Evaluate for the first Len-1 elements. */ - template struct Eval { - result_type operator()( - const LeftT& left, const RightT& right) const - { - /* Apply to last value: */ - return AccumT().apply( - OpT().apply(left[N], right_traits().get(right,N)), - Eval()(left, right)); - /* Note: we don't need get(), since dest is a vector. */ - } - }; - - /** Evaluate the binary operator at element Last. */ - template struct Eval { - result_type operator()( - const LeftT& left, const RightT& right) const - { - return OpT().apply(left[Last],right_traits().get(right,Last)); - /* Note: we don't need get(), since dest is a vector. */ - } - }; - - /** Evaluate using a loop. */ - template struct Eval { - result_type operator()( - const LeftT& left, const RightT& right) const - { - result_type accum = OpT().apply(left[0],right[0]); - for(size_t i = 1; i <= Last; ++i) { - /* XXX This might not be optimized properly by some compilers, - * but to do anything else requires changing the requirements - * of a scalar operator. - */ - accum = AccumT().apply(accum, OpT().apply( - left[i],right_traits().get(right,i))); - /* Note: we don't need get(), since dest is a vector. */ - } - } - }; -}; - -} - -/** Construct an assignment unroller. - * - * The operator must be an assignment op, otherwise, this doesn't make any - * sense. - * - * @bug Need to verify that OpT is actually an assignment operator. - */ -template inline -void UnrollAssignment(cml::vector& dest, const SrcT& src) -{ - /* Record the destination vector type, and the expression traits: */ - typedef cml::vector vector_type; - - /* Record the type of the unroller: */ - typedef detail::VectorAssignmentUnroller unroller; - - /* Do the unroll call: */ - unroller()(dest, src, typename vector_type::size_tag()); - /* XXX It may make sense to unroll if either side is a fixed size. */ -} - -} // namespace et -} // namespace cml - -#endif - -// ------------------------------------------------------------------------- -// vim:ft=cpp