vector_comparison.h

Go to the documentation of this file.
00001 /* -*- C++ -*- ------------------------------------------------------------
00002  
00003 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
00004 
00005 The Configurable Math Library (CML) is distributed under the terms of the
00006 Boost Software License, v1.0 (see cml/LICENSE for details).
00007 
00008  *-----------------------------------------------------------------------*/
00013 #ifndef vector_comparison_h
00014 #define vector_comparison_h
00015 
00016 #include <cml/core/cml_assert.h>
00017 #include <cml/et/size_checking.h>
00018 #include <cml/et/scalar_ops.h>
00019 
00020 /* This is used below to create a more meaningful compile-time error when
00021  * vector_comparison is not provided with vector or VectorExpr arguments:
00022  */
00023 struct vector_comparison_expects_vector_args_error;
00024 
00025 #define CML_VEC_VEC_ORDER(_order_, _op_, _OpT_)                         \
00026 template<typename E1, class AT1, typename E2, class AT2>                \
00027 inline bool                                                             \
00028 _op_ (                                                                  \
00029         const vector<E1,AT1>& left,                                     \
00030         const vector<E2,AT2>& right)                                    \
00031 {                                                                       \
00032     return detail::vector_##_order_ (left, right, _OpT_ <E1,E2>());     \
00033 }
00034 
00035 #define CML_VEC_VECXPR_ORDER(_order_, _op_, _OpT_)                      \
00036 template<typename E, class AT, class XprT>                              \
00037 inline bool                                                             \
00038 _op_ (                                                                  \
00039         const vector<E,AT>& left,                                       \
00040         VECXPR_ARG_TYPE right)                                          \
00041 {                                                                       \
00042     return detail::vector_##_order_ (left, right,                       \
00043             _OpT_ <E, typename XprT::value_type>());                    \
00044 }
00045 
00046 #define CML_VECXPR_VEC_ORDER(_order_, _op_, _OpT_)                      \
00047 template<class XprT, typename E, class AT>                              \
00048 inline bool                                                             \
00049 _op_ (                                                                  \
00050         VECXPR_ARG_TYPE left,                                           \
00051         const vector<E,AT>& right)                                      \
00052 {                                                                       \
00053     return detail::vector_##_order_ (left, right,                       \
00054             _OpT_ <typename XprT::value_type, E>());                    \
00055 }
00056 
00057 #define CML_VECXPR_VECXPR_ORDER(_order_, _op_, _OpT_)                   \
00058 template<class XprT1, class XprT2>                                      \
00059 inline bool                                                             \
00060 _op_ (                                                                  \
00061         VECXPR_ARG_TYPE_N(1) left,                                      \
00062         VECXPR_ARG_TYPE_N(2) right)                                     \
00063 {                                                                       \
00064     return detail::vector_##_order_ (left, right,                       \
00065             _OpT_ <                                                     \
00066                 typename XprT1::value_type,                             \
00067                 typename XprT2::value_type>());                         \
00068 }
00069 
00070 
00071 namespace cml {
00072 namespace detail {
00073 
00080 template<typename LeftT, typename RightT, typename OpT>
00081 inline bool
00082 vector_weak_order(const LeftT& left, const RightT& right, OpT)
00083 {
00084     /* Shorthand: */
00085     typedef et::ExprTraits<LeftT> left_traits;
00086     typedef et::ExprTraits<RightT> right_traits;
00087 
00088     /* vector_comparison() requires vector expressions: */
00089     CML_STATIC_REQUIRE_M(
00090             (et::VectorExpressions<LeftT,RightT>::is_true),
00091             vector_comparison_expects_vector_args_error);
00092     /* Note: parens are required here so that the preprocessor ignores the
00093      * commas:
00094      */
00095 
00096     typedef typename et::VectorPromote<
00097         typename left_traits::result_type,
00098         typename right_traits::result_type
00099     >::type result_type;
00100     typedef typename result_type::size_tag size_tag;
00101 
00102     /* Verify expression size: */
00103     ssize_t N = (ssize_t) et::CheckedSize(left,right,size_tag());
00104     for(ssize_t i = 0; i < N; ++ i) {
00105         if(OpT().apply(
00106                     left_traits().get(left,i),
00107                     right_traits().get(right,i)
00108                     ))
00109         {
00110             /* If weak order (a < b) is satisfied, return true: */
00111             return true;
00112         } else if(OpT().apply(
00113                     right_traits().get(right,i),
00114                     left_traits().get(left,i)
00115                     ))
00116         {
00117             /* If !(b < a), then return false: */
00118             return false;
00119         } else {
00120 
00121             /* Have !(a < b) && !(b < a) <=> (a >= b && b >= a) <=> (a == b).
00122              * so need to test next element:
00123              */
00124             continue;
00125         }
00126     }
00127     /* XXX Can this be unrolled in any reasonable way? */
00128 
00129     /* If we get here, then left == right: */
00130     return false;
00131 }
00132 
00138 template<typename LeftT, typename RightT, typename OpT>
00139 inline bool
00140 vector_total_order(const LeftT& left, const RightT& right, OpT)
00141 {
00142     /* Shorthand: */
00143     typedef et::ExprTraits<LeftT> left_traits;
00144     typedef et::ExprTraits<RightT> right_traits;
00145 
00146     /* vector_comparison() requires vector expressions: */
00147     CML_STATIC_REQUIRE_M(
00148             (et::VectorExpressions<LeftT,RightT>::is_true),
00149             vector_comparison_expects_vector_args_error);
00150     /* Note: parens are required here so that the preprocessor ignores the
00151      * commas:
00152      */
00153 
00154     typedef typename et::VectorPromote<
00155         typename left_traits::result_type,
00156         typename right_traits::result_type
00157     >::type result_type;
00158     typedef typename result_type::size_tag size_tag;
00159 
00160     /* Verify expression size: */
00161     ssize_t N = (ssize_t) et::CheckedSize(left,right,size_tag());
00162     for(ssize_t i = 0; i < N; ++ i) {
00163 
00164         /* Test total order: */
00165         if(OpT().apply(
00166                     left_traits().get(left,i),
00167                     right_traits().get(right,i)
00168             ))
00169         {
00170             /* Automatically true if weak order (a <= b) && !(b <= a) <=>
00171              * (a <= b) && (b > a) <=> (a < b) is satisfied:
00172              */
00173             if(!OpT().apply(
00174                         right_traits().get(right,i),
00175                         left_traits().get(left,i)
00176                         ))
00177                 return true;
00178 
00179             /* Otherwise, have equality (a <= b) && (b <= a), so continue
00180              * to next element:
00181              */
00182             else
00183                 continue;
00184 
00185         } else {
00186             
00187             /* Total order isn't satisfied (a > b), so return false: */
00188             return false;
00189         }
00190     }
00191     /* XXX Can this be unrolled in any reasonable way? */
00192 
00193     /* Total (==) or weak (<) order was satisfied, so return true: */
00194     return true;
00195 }
00196 
00197 }
00198 
00199 /* XXX There is a better way to handle these with operator traits... */
00200 
00201 CML_VEC_VEC_ORDER(       total_order, operator==, et::OpEqual)
00202 CML_VECXPR_VEC_ORDER(    total_order, operator==, et::OpEqual)
00203 CML_VEC_VECXPR_ORDER(    total_order, operator==, et::OpEqual)
00204 CML_VECXPR_VECXPR_ORDER( total_order, operator==, et::OpEqual)
00205 
00206 CML_VEC_VEC_ORDER(       weak_order, operator!=, et::OpNotEqual)
00207 CML_VECXPR_VEC_ORDER(    weak_order, operator!=, et::OpNotEqual)
00208 CML_VEC_VECXPR_ORDER(    weak_order, operator!=, et::OpNotEqual)
00209 CML_VECXPR_VECXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
00210 
00211 CML_VEC_VEC_ORDER(       weak_order, operator<, et::OpLess)
00212 CML_VECXPR_VEC_ORDER(    weak_order, operator<, et::OpLess)
00213 CML_VEC_VECXPR_ORDER(    weak_order, operator<, et::OpLess)
00214 CML_VECXPR_VECXPR_ORDER( weak_order, operator<, et::OpLess)
00215 
00216 CML_VEC_VEC_ORDER(       weak_order, operator>, et::OpGreater)
00217 CML_VECXPR_VEC_ORDER(    weak_order, operator>, et::OpGreater)
00218 CML_VEC_VECXPR_ORDER(    weak_order, operator>, et::OpGreater)
00219 CML_VECXPR_VECXPR_ORDER( weak_order, operator>, et::OpGreater)
00220 
00221 CML_VEC_VEC_ORDER(       total_order, operator<=, et::OpLessEqual)
00222 CML_VECXPR_VEC_ORDER(    total_order, operator<=, et::OpLessEqual)
00223 CML_VEC_VECXPR_ORDER(    total_order, operator<=, et::OpLessEqual)
00224 CML_VECXPR_VECXPR_ORDER( total_order, operator<=, et::OpLessEqual)
00225 
00226 CML_VEC_VEC_ORDER(       total_order, operator>=, et::OpGreaterEqual)
00227 CML_VECXPR_VEC_ORDER(    total_order, operator>=, et::OpGreaterEqual)
00228 CML_VEC_VECXPR_ORDER(    total_order, operator>=, et::OpGreaterEqual)
00229 CML_VECXPR_VECXPR_ORDER( total_order, operator>=, et::OpGreaterEqual)
00230 
00231 } // namespace cml
00232 
00233 #endif
00234 
00235 // -------------------------------------------------------------------------
00236 // vim:ft=cpp

Generated on Sat Jul 18 19:35:32 2009 for CML 1.0 by  doxygen 1.5.9