X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2Fcml%2Fmatrix%2Fclass_ops.h;fp=src%2FMoof%2Fcml%2Fmatrix%2Fclass_ops.h;h=d2a8dbd12cf37ef5ede1bef0912598f2c7a1a691;hp=0000000000000000000000000000000000000000;hb=c2321281bf12a7efaedde930422c7ddbc92080d4;hpb=87bc17e55b0c1dc73ecc66df856d3f08fd7a7724 diff --git a/src/Moof/cml/matrix/class_ops.h b/src/Moof/cml/matrix/class_ops.h new file mode 100644 index 0000000..d2a8dbd --- /dev/null +++ b/src/Moof/cml/matrix/class_ops.h @@ -0,0 +1,341 @@ +/* -*- 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 + * + * @note GCC4 requires a copy constructor to elide---it won't elide a + * compiler-generated copy constructor! + */ + +#ifndef matrix_class_ops_h +#define matrix_class_ops_h + +#if defined(_MSC_VER) && _MSC_VER < 1400 +#pragma warning(disable:4003) +// XXX Horrible hack to turn off warnings about "not enough actual params" +// for the macros below. +#endif + +/* This is to circumvent the problem of commas in a macro argument. It's + * used to instantiate CML_ACCUMULATED_MATRIX_MULT: + */ +#define TEMPLATED_MATRIX_MACRO matrix + +/* XXX HACK!!! This is a hack to resize in the assign() functions only when + * auto resizing is turned off. + */ +#if !defined(CML_MATRIX_RESIZE_ON_ASSIGNMENT) +#define _DO_MATRIX_SET_RESIZE(_R_,_C_) cml::et::detail::Resize(*this,_R_,_C_) +#else +#define _DO_MATRIX_SET_RESIZE(_R_,_C_) +#endif + +/** Set a matrix from 2x2 values. + * + * The layout assumed for the values is that of the matrix being assigned. + */ +#define CML_ASSIGN_MAT_22 \ +matrix_type& \ +set( \ + ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \ + ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11 \ + ) \ +{ \ + _DO_MATRIX_SET_RESIZE(2,2); \ + /* This is overkill, but simplifies size checking: */ \ + value_type v[2][2] = {{e00,e01},{e10,e11}}; \ + typedef et::OpAssign OpT; \ + typedef const value_type element; \ + cml::matrix, basis_orient, row_major> \ + src(&v[0][0]); \ + et::UnrollAssignment(*this,src); \ + return *this; \ +} + +/** Create a matrix from 3x3 values. + * + * The layout assumed for the values is that of the matrix being assigned. + */ +#define CML_ASSIGN_MAT_33 \ +matrix_type& \ +set( \ + ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, ELEMENT_ARG_TYPE e02, \ + ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, ELEMENT_ARG_TYPE e12, \ + ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, ELEMENT_ARG_TYPE e22 \ + ) \ +{ \ + _DO_MATRIX_SET_RESIZE(3,3); \ + /* This is overkill, but simplifies size checking: */ \ + value_type v[3][3] = { \ + {e00,e01,e02}, \ + {e10,e11,e12}, \ + {e20,e21,e22} \ + }; \ + typedef et::OpAssign OpT; \ + typedef const value_type element; \ + cml::matrix, basis_orient, row_major> \ + src(&v[0][0]); \ + et::UnrollAssignment(*this,src); \ + return *this; \ +} + +/** Create a matrix from 4x4 values. + * + * The layout assumed for the values is that of the matrix being assigned. + */ +#define CML_ASSIGN_MAT_44 \ +matrix_type& \ +set( \ + ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \ + ELEMENT_ARG_TYPE e02, ELEMENT_ARG_TYPE e03, \ + ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, \ + ELEMENT_ARG_TYPE e12, ELEMENT_ARG_TYPE e13, \ + ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, \ + ELEMENT_ARG_TYPE e22, ELEMENT_ARG_TYPE e23, \ + ELEMENT_ARG_TYPE e30, ELEMENT_ARG_TYPE e31, \ + ELEMENT_ARG_TYPE e32, ELEMENT_ARG_TYPE e33 \ + ) \ +{ \ + _DO_MATRIX_SET_RESIZE(4,4); \ + /* This is overkill, but simplifies size checking: */ \ + value_type v[4][4] = { \ + {e00,e01,e02,e03}, \ + {e10,e11,e12,e13}, \ + {e20,e21,e22,e23}, \ + {e30,e31,e32,e33} \ + }; \ + typedef et::OpAssign OpT; \ + typedef const value_type element; \ + cml::matrix, basis_orient, row_major> \ + src(&v[0][0]); \ + et::UnrollAssignment(*this,src); \ + return *this; \ +} + +/** Create a matrix from 2x2 values. + * + * The layout assumed for the values is that of the matrix being assigned. + */ +#define CML_CONSTRUCT_MAT_22 \ +matrix( \ + ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \ + ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11 \ + ) \ +{ \ + set( \ + e00,e01, \ + e10,e11 \ + ); \ +} + +/** Create a matrix from 3x3 values. + * + * The layout assumed for the values is that of the matrix being assigned. + */ +#define CML_CONSTRUCT_MAT_33 \ +matrix( \ + ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, ELEMENT_ARG_TYPE e02, \ + ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, ELEMENT_ARG_TYPE e12, \ + ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, ELEMENT_ARG_TYPE e22 \ + ) \ +{ \ + set( \ + e00,e01,e02, \ + e10,e11,e12, \ + e20,e21,e22 \ + ); \ +} + +/** Create a matrix from 4x4 values. + * + * The layout assumed for the values is that of the matrix being assigned. + */ +#define CML_CONSTRUCT_MAT_44 \ +matrix( \ + ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \ + ELEMENT_ARG_TYPE e02, ELEMENT_ARG_TYPE e03, \ + ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, \ + ELEMENT_ARG_TYPE e12, ELEMENT_ARG_TYPE e13, \ + ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, \ + ELEMENT_ARG_TYPE e22, ELEMENT_ARG_TYPE e23, \ + ELEMENT_ARG_TYPE e30, ELEMENT_ARG_TYPE e31, \ + ELEMENT_ARG_TYPE e32, ELEMENT_ARG_TYPE e33 \ + ) \ +{ \ + set( \ + e00,e01,e02,e03, \ + e10,e11,e12,e13, \ + e20,e21,e22,e23, \ + e30,e31,e32,e33 \ + ); \ +} + +/** Copy-construct a matrix from a fixed-size array of values. */ +#define CML_MAT_COPY_FROM_FIXED_ARRAY(_R_,_C_) \ +matrix(const value_type m[_R_][_C_]) { \ + typedef et::OpAssign OpT; \ + cml::matrix, \ + basis_orient, row_major> src(&m[0][0]); \ + et::UnrollAssignment(*this,src); \ +} + +/** Copy-construct a matrix from a runtime-sized array of values. */ +#define CML_MAT_COPY_FROM_ARRAY(_add_) \ +matrix(const value_type* const v, size_t R, size_t C) _add_ { \ + typedef et::OpAssign OpT; \ + cml::matrix, basis_orient, \ + row_major > src(const_cast(v),R,C); \ + et::UnrollAssignment(*this,src); \ +} + +/** Copy this matrix from another using the given elementwise op. + * + * @internal This is required for GCC4, since it won't elide the default + * copy constructor. + */ +#define CML_MAT_COPY_FROM_MATTYPE \ +matrix(const matrix_type& m) : array_type() { \ + typedef et::OpAssign OpT; \ + et::UnrollAssignment(*this,m); \ +} + +/** Copy this matrix from another using the given elementwise op. + * + * This allows copies from arbitrary matrix types. + */ +#define CML_MAT_COPY_FROM_MAT \ +template \ +matrix(const TEMPLATED_MATRIX_MACRO& m) { \ + typedef et::OpAssign OpT; \ + et::UnrollAssignment(*this,m); \ +} + +/** Declare a function to copy this matrix from a matrix expression. */ +#define CML_MAT_COPY_FROM_MATXPR \ +template \ +matrix(MATXPR_ARG_TYPE e) { \ + /* Verify that a promotion exists at compile time: */ \ + typedef typename et::MatrixPromote< \ + matrix_type, typename XprT::result_type>::type result_type; \ + typedef typename XprT::value_type src_value_type; \ + typedef et::OpAssign OpT; \ + et::UnrollAssignment(*this,e); \ +} + +#if defined(CML_USE_GENERATED_MATRIX_ASSIGN_OP) +#define CML_MAT_ASSIGN_FROM_MATTYPE +#else +/** Assign from the same matrix type. + * + * @param m the matrix to copy from. + * + * @note This is required for GCC4, otherwise it generates a slow + * assignment operator using memcpy. + * + * @note ICC9/Linux-x86 seems to prefer its own assignment operator (need + * to figure out why). + */ +#define CML_MAT_ASSIGN_FROM_MATTYPE \ +matrix_type& operator=(const matrix_type& m) { \ + typedef et::OpAssign OpT; \ + et::UnrollAssignment(*this,m); \ + return *this; \ +} +#endif + + +/** Assign this matrix from another using the given elementwise op. + * + * This allows assignment from arbitrary matrix types. + * + * @param _op_ the operator (e.g. +=) + * @param _op_name_ the op functor (e.g. et::OpAssign) + */ +#define CML_MAT_ASSIGN_FROM_MAT(_op_, _op_name_) \ +template matrix_type& \ +operator _op_ (const TEMPLATED_MATRIX_MACRO& m) { \ + typedef _op_name_ OpT; \ + et::UnrollAssignment(*this,m); \ + return *this; \ +} + +/** Declare a function to assign this matrix from a matrix expression. + * + * @param _op_ the operator (e.g. +=) + * @param _op_name_ the op functor (e.g. et::OpAssign) + */ +#define CML_MAT_ASSIGN_FROM_MATXPR(_op_, _op_name_) \ +template matrix_type& \ +operator _op_ (MATXPR_ARG_TYPE e) { \ + /* Verify that a promotion exists at compile time: */ \ + typedef typename et::MatrixPromote< \ + matrix_type, typename XprT::result_type>::type result_type; \ + typedef typename XprT::value_type src_value_type; \ + typedef _op_name_ OpT; \ + et::UnrollAssignment(*this,e); \ + return *this; \ +} + +/** Declare a function to assign this matrix from a scalar. + * + * @param _op_ the operator (e.g. +=) + * @param _op_name_ the op functor (e.g. et::OpAssign) + * + * @internal This shouldn't be used for ops, like +=, which aren't + * defined in vector algebra. + */ +#define CML_MAT_ASSIGN_FROM_SCALAR(_op_, _op_name_) \ +matrix_type& operator _op_ (ELEMENT_ARG_TYPE s) { \ + typedef _op_name_ OpT; \ + et::UnrollAssignment(*this,s); \ + return *this; \ +} + + +/** Accumulated matrix multiplication. + * + * @throws std::invalid_argument if the matrices are not square. + */ +#define CML_ACCUMULATED_MATRIX_MULT(_arg_type_) \ +matrix_type& operator*=(_arg_type_ m) { \ + typedef typename et::MatrixPromote< \ + matrix_type, _arg_type_>::type result_type; \ + cml::et::CheckedSquare(*this, typename result_type::size_tag()); \ + return (*this = (*this)*m); \ +} + + +/* These should only be used for testing: */ +#define CML_MATRIX_BRACE_OPERATORS \ +template struct row_ref { \ + typedef typename Matrix::reference reference; \ + reference operator[](size_t col) { return m(row,col); } \ + Matrix& m; \ + size_t row; \ +}; \ + \ +template struct const_row_ref { \ + typedef typename Matrix::const_reference const_reference; \ + const_reference operator[](size_t col) const { return m(row,col); } \ + const Matrix& m; \ + size_t row; \ +}; \ + \ +row_ref operator[](size_t row) { \ + row_ref ref = { *this, row }; return ref; \ +} \ + \ +const_row_ref operator[](size_t row) const { \ + const_row_ref ref = { *this, row }; return ref; \ +} + +#endif + +// ------------------------------------------------------------------------- +// vim:ft=cpp