matrix_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  *-----------------------------------------------------------------------*/
00017 #ifndef matrix_comparison_h
00018 #define matrix_comparison_h
00019 
00020 #include <cml/core/cml_assert.h>
00021 #include <cml/et/size_checking.h>
00022 #include <cml/et/scalar_ops.h>
00023 
00024 /* This is used below to create a more meaningful compile-time error when
00025  * matrix_comparison is not provided with matrix or MatrixExpr arguments:
00026  */
00027 struct matrix_comparison_expects_matrix_args_error;
00028 
00029 #define CML_MAT_MAT_ORDER(_order_, _op_, _OpT_)                         \
00030 template<typename E1, class AT1, typename L1,                           \
00031          typename E2, class AT2, typename L2, typename BO>              \
00032 inline bool                                                             \
00033 _op_ (                                                                  \
00034         const matrix<E1,AT1,L1,BO>& left,                               \
00035         const matrix<E2,AT2,L2,BO>& right)                              \
00036 {                                                                       \
00037     return detail::matrix_##_order_ (left, right, _OpT_ <E1,E2>());     \
00038 }
00039 
00040 #define CML_MAT_MATXPR_ORDER(_order_, _op_, _OpT_)                      \
00041 template<typename E, class AT, typename L, typename BO, class XprT>     \
00042 inline bool                                                             \
00043 _op_ (                                                                  \
00044         const matrix<E,AT,L,BO>& left,                                  \
00045         MATXPR_ARG_TYPE right)                                          \
00046 {                                                                       \
00047     return detail::matrix_##_order_ (left, right,                       \
00048             _OpT_ <E, typename XprT::value_type>());                    \
00049 }
00050 
00051 #define CML_MATXPR_MAT_ORDER(_order_, _op_, _OpT_)                      \
00052 template<class XprT, typename E, class AT, typename L, typename BO>     \
00053 inline bool                                                             \
00054 _op_ (                                                                  \
00055         MATXPR_ARG_TYPE left,                                           \
00056         const matrix<E,AT,L,BO>& right)                                 \
00057 {                                                                       \
00058     return detail::matrix_##_order_ (left, right,                       \
00059             _OpT_ <typename XprT::value_type, E>());                    \
00060 }
00061 
00062 #define CML_MATXPR_MATXPR_ORDER(_order_, _op_, _OpT_)                   \
00063 template<class XprT1, class XprT2>                                      \
00064 inline bool                                                             \
00065 _op_ (                                                                  \
00066         MATXPR_ARG_TYPE_N(1) left,                                      \
00067         MATXPR_ARG_TYPE_N(2) right)                                     \
00068 {                                                                       \
00069     return detail::matrix_##_order_ (left, right,                       \
00070             _OpT_ <                                                     \
00071                 typename XprT1::value_type,                             \
00072                 typename XprT2::value_type>());                         \
00073 }
00074 
00075 
00076 namespace cml {
00077 namespace detail {
00078 
00085 template<typename LeftT, typename RightT, typename OpT>
00086 inline bool
00087 matrix_weak_order(const LeftT& left, const RightT& right, OpT)
00088 {
00089     /* Shorthand: */
00090     typedef et::ExprTraits<LeftT> left_traits;
00091     typedef et::ExprTraits<RightT> right_traits;
00092 
00093     /* matrix_comparison() requires matrix expressions: */
00094     CML_STATIC_REQUIRE_M(
00095             (et::MatrixExpressions<LeftT,RightT>::is_true),
00096             matrix_comparison_expects_matrix_args_error);
00097     /* Note: parens are required here so that the preprocessor ignores the
00098      * commas:
00099      */
00100 
00101     typedef typename et::MatrixPromote<
00102         typename left_traits::result_type,
00103         typename right_traits::result_type
00104     >::type result_type;
00105     typedef typename result_type::size_tag size_tag;
00106 
00107     /* Verify expression size: */
00108     matrix_size N = et::CheckedSize(left,right,size_tag());
00109     for(ssize_t i = 0; i < N.first; ++ i) {
00110         for(ssize_t j = 0; j < N.second; ++ j) {
00111             if(OpT().apply(
00112                         left_traits().get(left,i,j),
00113                         right_traits().get(right,i,j)
00114                         ))
00115             {
00116                 /* If weak order (a < b) is satisfied, return true: */
00117                 return true;
00118             } else if(OpT().apply(
00119                         right_traits().get(right,i,j),
00120                         left_traits().get(left,i,j)
00121                         ))
00122             {
00123                 /* If !(b < a), then return false: */
00124                 return false;
00125             } else {
00126 
00127                 /* Have !(a < b) && !(b < a) <=> (a >= b && b >= a)
00128                  * <=> (a == b).  so need to test next element:
00129                  */
00130                 continue;
00131             }
00132         }
00133     }
00134     /* XXX Can this be unrolled in any reasonable way? */
00135 
00136     /* If we get here, then left == right: */
00137     return false;
00138 }
00139 
00145 template<typename LeftT, typename RightT, typename OpT>
00146 inline bool
00147 matrix_total_order(const LeftT& left, const RightT& right, OpT)
00148 {
00149     /* Shorthand: */
00150     typedef et::ExprTraits<LeftT> left_traits;
00151     typedef et::ExprTraits<RightT> right_traits;
00152 
00153     /* matrix_comparison() requires matrix expressions: */
00154     CML_STATIC_REQUIRE_M(
00155             (et::MatrixExpressions<LeftT,RightT>::is_true),
00156             matrix_comparison_expects_matrix_args_error);
00157     /* Note: parens are required here so that the preprocessor ignores the
00158      * commas:
00159      */
00160 
00161     typedef typename et::MatrixPromote<
00162         typename left_traits::result_type,
00163         typename right_traits::result_type
00164     >::type result_type;
00165     typedef typename result_type::size_tag size_tag;
00166 
00167     /* Verify expression size: */
00168     matrix_size N = et::CheckedSize(left,right,size_tag());
00169     for(ssize_t i = 0; i < N.first; ++ i) {
00170         for(ssize_t j = 0; j < N.second; ++ j) {
00171 
00172             /* Test total order: */
00173             if(OpT().apply(
00174                         left_traits().get(left,i,j),
00175                         right_traits().get(right,i,j)
00176                         ))
00177             {
00178                 /* Automatically true if weak order (a <= b) && !(b <= a)
00179                  * <=> (a <= b) && (b > a) <=> (a < b) is satisfied:
00180                  */
00181                 if(!OpT().apply(
00182                             right_traits().get(right,i,j),
00183                             left_traits().get(left,i,j)
00184                             ))
00185                     return true;
00186 
00187                 /* Otherwise, have equality (a <= b) && (b <= a), so
00188                  * continue to next element:
00189                  */
00190                 else
00191                     continue;
00192 
00193             } else {
00194 
00195                 /* Total order isn't satisfied (a > b), so return false: */
00196                 return false;
00197             }
00198         }
00199     }
00200     /* XXX Can this be unrolled in any reasonable way? */
00201 
00202     /* Total (==) or weak (<) order was satisfied, so return true: */
00203     return true;
00204 }
00205 
00206 }
00207 
00208 } // namespace cml
00209 
00210 /* XXX There is a better way to handle these with operator traits... */
00211 
00212 CML_MAT_VEC_ORDER(       total_order, operator==, et::OpEqual)
00213 CML_MATXPR_MAT_ORDER(    total_order, operator==, et::OpEqual)
00214 CML_MAT_MATXPR_ORDER(    total_order, operator==, et::OpEqual)
00215 CML_MATXPR_VECXPR_ORDER( total_order, operator==, et::OpEqual)
00216 
00217 CML_MAT_VEC_ORDER(       weak_order, operator!=, et::OpNotEqual)
00218 CML_MATXPR_MAT_ORDER(    weak_order, operator!=, et::OpNotEqual)
00219 CML_MAT_MATXPR_ORDER(    weak_order, operator!=, et::OpNotEqual)
00220 CML_MATXPR_VECXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
00221 
00222 CML_MAT_VEC_ORDER(       weak_order, operator<, et::OpLess)
00223 CML_MATXPR_MAT_ORDER(    weak_order, operator<, et::OpLess)
00224 CML_MAT_MATXPR_ORDER(    weak_order, operator<, et::OpLess)
00225 CML_MATXPR_VECXPR_ORDER( weak_order, operator<, et::OpLess)
00226 
00227 CML_MAT_VEC_ORDER(       weak_order, operator>, et::OpGreater)
00228 CML_MATXPR_MAT_ORDER(    weak_order, operator>, et::OpGreater)
00229 CML_MAT_MATXPR_ORDER(    weak_order, operator>, et::OpGreater)
00230 CML_MATXPR_VECXPR_ORDER( weak_order, operator>, et::OpGreater)
00231 
00232 CML_MAT_VEC_ORDER(       total_order, operator<=, et::OpLessEqual)
00233 CML_MATXPR_MAT_ORDER(    total_order, operator<=, et::OpLessEqual)
00234 CML_MAT_MATXPR_ORDER(    total_order, operator<=, et::OpLessEqual)
00235 CML_MATXPR_VECXPR_ORDER( total_order, operator<=, et::OpLessEqual)
00236 
00237 CML_MAT_VEC_ORDER(       total_order, operator>=, et::OpGreaterEqual)
00238 CML_MATXPR_MAT_ORDER(    total_order, operator>=, et::OpGreaterEqual)
00239 CML_MAT_MATXPR_ORDER(    total_order, operator>=, et::OpGreaterEqual)
00240 CML_MATXPR_VECXPR_ORDER( total_order, operator>=, et::OpGreaterEqual)
00241 
00242 #endif
00243 
00244 // -------------------------------------------------------------------------
00245 // vim:ft=cpp

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