
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Make metal vec and mat work with traits and scalars. * tests/metal_mat.cc: Inactivate "non" tests. Augment. * tests/metal_vec.cc: Augment. * tests/value_int_u8.cc: Conform to style. * mln/trait/op/eq.hh: Remove dead code. * mln/core/category.hh: Add const version. * mln/core/h_vec.hh: Add traits. * mln/core/ops.hh: Handle const types in traits. * mln/literal/ops.hh: Add traits. * mln/metal/mat.hh: Fix. * mln/metal/vec.hh (sprod): Replace by... (operator*): ...this new operator. * mln/arith/plus.hh (plus_cst): Simplify. * mln/value/ops.hh: Add traits for scalar_. * mln/value/quat.hh: Update. * mln/value/int_u.hh (uminus): New trait. * mln/value/int_u_sat.hh: Fix ctor. * mln/value/builtin/ops.hh: Enhance FIXME txt. * mln/morpho/includes.hh: Update. mln/arith/plus.hh | 5 mln/core/category.hh | 5 mln/core/h_vec.hh | 43 ++++++ mln/core/ops.hh | 32 +++++ mln/literal/ops.hh | 39 +++++- mln/metal/mat.hh | 292 ++++++++++++----------------------------------- mln/metal/vec.hh | 64 +++++----- mln/morpho/includes.hh | 2 mln/trait/op/eq.hh | 8 - mln/value/builtin/ops.hh | 3 mln/value/int_u.hh | 6 mln/value/int_u_sat.hh | 12 + mln/value/ops.hh | 125 +++++++++++++++++++- mln/value/quat.hh | 4 tests/metal_mat.cc | 64 ++++++++-- tests/metal_vec.cc | 14 +- tests/value_int_u8.cc | 1 17 files changed, 434 insertions(+), 285 deletions(-) Index: tests/metal_mat.cc --- tests/metal_mat.cc (revision 1383) +++ tests/metal_mat.cc (working copy) @@ -31,23 +31,63 @@ */ #include <mln/metal/mat.hh> +#include <mln/value/int_u8.hh> + int main() { using namespace mln; - const int - tab1[18] = {3, 6, 5, 2, 4, 8, - 5, 7, 4, 6, 9, 2, - 2, 7, 1, 1, 5, 3}, - tab2[6] = {2, 5, 1, 0, 7, 2}, - tab3[6] = {3, 1, 6, 2, 1, 0}; - - metal::mat<3,6,int> mat36 = make::mat<3,6,18>(tab1); - metal::mat<2,3,int> mat23_1 = make::mat<2,3,6>(tab2); - metal::mat<2,3,int> mat23_2 = make::mat<2,3,6>(tab3); + // FIXME: A test should not print! + + // const int + // tab1[18] = {3, 6, 5, 2, 4, 8, + // 5, 7, 4, 6, 9, 2, + // 2, 7, 1, 1, 5, 3}, + // tab2[6] = {2, 5, 1, 0, 7, 2}, + // tab3[6] = {3, 1, 6, 2, 1, 0}; + + // metal::mat<3,6,int> mat36 = make::mat<3,6,18>(tab1); + // metal::mat<2,3,int> mat23_1 = make::mat<2,3,6>(tab2); + // metal::mat<2,3,int> mat23_2 = make::mat<2,3,6>(tab3); + + // metal::mat<2,3,float> mat23_3 = mat23_1 - mat23_2; + + // std::cout << mat23_3 << std::endl << mat23_3 * mat36 << std::endl; + + using metal::vec; + vec<2,int> v = make::vec(5,1); + + using metal::mat; + mat<2,2, vec<2,int> > mv; + mv.set_all(v); + // std::cout << mv << std::endl; - metal::mat<2,3,float> mat23_3 = mat23_1 - mat23_2; + { + mat<2,2,float> tmp = mv * mv; + // std::cout << tmp << std::endl; + tmp(0,0) = 0; + } + { + vec<2, vec<2,float> > tmp = mv * v; + // std::cout << (mv * v) << std::endl; + tmp[0] = v; + } + { + mat<2,2,float> tmp = value::scalar(v) * mv; + // std::cout << (value::scalar(v) * mv) << std::endl; + tmp(0,0) = 0; + } + { + vec<2, mat<2,2, vec<2,float> > > tmp = v * value::scalar(mv); + // std::cout << (v * value::scalar(mv)) << std::endl; + tmp[0](0,0) = v; + } + { + value::int_u8 i = 0; + mat<2,2, vec<2,int> > tmp = mv * i; + // std::cout << mv * i << std::endl; + tmp(0,0) = v; + } - std::cout << mat23_3 << std::endl << mat23_3 * mat36 << std::endl; } Index: tests/metal_vec.cc --- tests/metal_vec.cc (revision 1383) +++ tests/metal_vec.cc (working copy) @@ -34,6 +34,8 @@ #include <mln/value/int_u8.hh> +struct nu {}; + int main() { using namespace mln; @@ -41,13 +43,11 @@ metal::vec<3,int> v_int = make::vec(3,6,7); metal::vec<3,float> v_f = make::vec(2.6, 1.9, 5.2); - std::cout << v_int + v_f << std::endl; - std::cout << v_f / 3 << std::endl; + mln_assertion((v_int + v_f) = ((v_f + v_int))); + mln_assertion((v_f / 3) = ((3 * v_f) / 9)); - { -// value::int_u8 i = 3; -// std::cout << value::scalar(i) * v_f << std::endl; - // FIXME: Read FIXME in metal::vec::operator* and set up a test! - } + value::int_u8 i = 3; + mln_assertion((i * v_f) = (value::scalar(i) * v_f)); + mln_assertion((literal::zero + v_f) = v_f); } Index: tests/value_int_u8.cc --- tests/value_int_u8.cc (revision 1383) +++ tests/value_int_u8.cc (working copy) @@ -33,6 +33,7 @@ #include <mln/value/int_u8.hh> #include <tests/value_macros.hh> + int main() { using namespace mln; Index: mln/trait/op/eq.hh --- mln/trait/op/eq.hh (revision 1383) +++ mln/trait/op/eq.hh (working copy) @@ -52,14 +52,6 @@ } // end of namespace mln::trait::op - -// /// Default definition of op::eq is 'bool'. -// template <typename L, typename R> -// struct set_binary_< op::eq, Object, L, Object, R > -// { -// typedef bool ret; -// }; - } // end of namespace mln::trait } // end of namespace mln Index: mln/core/category.hh --- mln/core/category.hh (revision 1383) +++ mln/core/category.hh (working copy) @@ -64,6 +64,11 @@ typedef typename T::category ret; // FIXME: if found or Unknown<void> => write a meta-program... }; + template <typename T> + struct category< const T > + { + typedef typename category<T>::ret ret; + }; } // end of namespace mln Index: mln/core/h_vec.hh --- mln/core/h_vec.hh (revision 1383) +++ mln/core/h_vec.hh (working copy) @@ -39,6 +39,49 @@ namespace mln { + // Fwd decl. + template <unsigned d, typename C> struct h_vec; + + + + namespace trait + { + + // For unary traits. + + template < template <class> class Name, + unsigned d, typename C > + struct set_precise_unary_< Name, h_vec<d, C> > + { + typedef mln_trait_unary(Name, C) V; + typedef h_vec<d, V> ret; + }; + + // For binary traits. + + template < template <class, class> class Name, + unsigned d, typename C, + typename Q > + struct set_precise_binary_< Name, + h_vec<d, C>, h_vec<d, Q> > + { + typedef mln_trait_binary(Name, C, Q) V; + typedef h_vec<d, V> ret; + }; + + template < template <class, class> class Name, + unsigned d, typename C, + typename S > + struct set_precise_binary_< Name, + h_vec<d, C>, mln::value::scalar_<S> > + { + typedef mln_trait_binary(Name, C, S) V; + typedef h_vec<d, V> ret; + }; + + } // end of namespace mln::trait + + template <unsigned d, typename C> struct h_vec : public metal::vec<d + 1, C> Index: mln/core/ops.hh --- mln/core/ops.hh (revision 1383) +++ mln/core/ops.hh (working copy) @@ -91,6 +91,38 @@ // FIXME: Same for the other definitions below... + + // Case of "const" in types. + + template< template <class> class Name, + typename O > + struct set_precise_unary_< Name, const O > + { + typedef mln_trait_unary(Name, O) ret; + }; + + template< template <class,class> class Name, + typename O1, typename O2 > + struct set_precise_binary_< Name, O1, const O2 > + { + typedef mln_trait_binary(Name, O1, O2) ret; + }; + + template< template <class,class> class Name, + typename O1, typename O2 > + struct set_precise_binary_< Name, const O1, O2 > + { + typedef mln_trait_binary(Name, O1, O2) ret; + }; + + template< template <class,class> class Name, + typename O1, typename O2 > + struct set_precise_binary_< Name, const O1, const O2 > + { + typedef mln_trait_binary(Name, O1, O2) ret; + }; + + } // end of mln::trait Index: mln/literal/ops.hh --- mln/literal/ops.hh (revision 1383) +++ mln/literal/ops.hh (working copy) @@ -29,7 +29,9 @@ # define MLN_LITERAL_OPS_HH /*! \file mln/literal/ops.hh - * \brief Definitions of some operators. + * + * \brief Definitions of some operators where at least one literal is + * involved. */ # include <mln/core/concept/literal.hh> @@ -42,6 +44,39 @@ namespace mln { + + namespace trait + { + + template < template <class, class> class Name, + typename L, typename O > + struct set_binary_< Name, mln::Literal, L, mln::Object, O > + { + typedef mln_trait_binary(Name, O, O) ret; + }; + + template < template <class, class> class Name, + typename O, typename L > + struct set_binary_< Name, mln::Object, O, mln::Literal, L > + { + typedef mln_trait_binary(Name, O, O) ret; + }; + + template < typename L1, typename L2 > + struct set_binary_< op::eq, mln::Literal, L1, mln::Literal, L2 > + { + typedef bool ret; + }; + + template < typename L1, typename L2 > + struct set_binary_< op::neq, mln::Literal, L1, mln::Literal, L2 > + { + typedef bool ret; + }; + + } // end of namespace mln::trait + + // Arithmetical operators. template <typename O, typename L> @@ -214,7 +249,7 @@ operator=(const Literal<L>& lhs, const Object<O>& rhs) { // mlc_converts_to(L, O)::check(); - return rhs = lhs; + return O(exact(lhs)) = exact(rhs); } template <typename L1, typename L2> Index: mln/metal/mat.hh --- mln/metal/mat.hh (revision 1383) +++ mln/metal/mat.hh (working copy) @@ -100,41 +100,22 @@ namespace trait { - // promote + // Unarys. - template <unsigned n, unsigned m, typename T, typename U> - struct set_precise_binary_<promote, metal::mat<n,m, T>, metal::mat<n,m, U> > + template < template<class> class Name, + unsigned n, unsigned m, typename T > + struct set_precise_unary_< Name, metal::mat<n,m,T> > { - typedef metal::mat<n,m, mln_trait_promote(T, U)> ret; + typedef metal::mat<n, m, mln_trait_unary(Name, T)> ret; }; + // Default for binarys; works for (+), (-), comparisons, and promote. - // mat + mat - - template <unsigned n, unsigned m, typename T, - typename U> - struct set_precise_binary_<op::plus, metal::mat<n, m, T>, metal::mat<n, m, U> > + template < template<class, class> class Name, + unsigned n, unsigned m, typename T, typename U> + struct set_precise_binary_< Name, metal::mat<n,m,T>, metal::mat<n,m,U> > { - typedef metal::mat<n, m, mln_trait_op_plus(T, U)> ret; - }; - - // FIXME: + mat - - // mat - mat - - template <unsigned n, unsigned m, typename T, - typename U> - struct set_precise_binary_<op::minus, metal::mat<n, m, T>, metal::mat<n, m, U> > - { - typedef metal::mat<n, m, mln_trait_op_minus(T, U)> ret; - }; - - // - mat - - template <unsigned n, unsigned m, typename T> - struct set_precise_unary_<op::uminus, metal::mat<n, m, T> > - { - typedef metal::mat<n, m, mln_trait_op_uminus(T)> ret; + typedef metal::mat<n, m, mln_trait_binary(Name, T, U)> ret; }; // mat * mat @@ -143,7 +124,13 @@ unsigned m, typename U> struct set_precise_binary_<op::times, metal::mat<n,o,T>, metal::mat<o,m,U> > { - typedef metal::mat< n, m, mln_trait_op_times(T,U) > ret; + typedef metal::mat<n, m, mln_sum_x(T, U)> ret; + }; + + template < unsigned n, typename T, typename U > + struct set_precise_binary_< op::times, metal::mat<n,n,T>, metal::mat<n,n,U> > + { // Disambiguate between both previous defs. + typedef metal::mat<n, n, mln_sum_x(T, U)> ret; }; // mat * vec @@ -152,17 +139,27 @@ typename U> struct set_precise_binary_<op::times, metal::mat<n,m,T>, metal::vec<m,U> > { - typedef mln_trait_op_times(T,U) TxU; - typedef metal::vec< m, mln_sum(TxU) > ret; + typedef metal::vec<n, mln_sum_x(T, U)> ret; }; // mat * s - template <unsigned n, unsigned m, typename T, + template < template<class, class> class Name, + unsigned n, unsigned m, typename T, typename S> - struct set_precise_binary_<op::times, metal::mat<n,m,T>, S > + struct set_precise_binary_< Name, metal::mat<n,m,T>, mln::value::scalar_<S> > { - typedef metal::mat< n, m, mln_trait_op_times(T,S) > ret; + typedef metal::mat<n, m, mln_trait_binary(Name, T, S)> ret; + }; + + template < template<class, class> class Name, + unsigned n, unsigned m, typename T, + typename S > + struct set_binary_< Name, + mln::Object, metal::mat<n,m,T>, + mln::value::Scalar, S > + { + typedef metal::mat<n, m, mln_trait_binary(Name, T, S)> ret; }; } // end of namespace mln::trait @@ -187,31 +184,19 @@ namespace metal { - // eq + // = template <unsigned n, unsigned m, typename T, typename U> bool - operator=(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs); + operator=(mat<n,m,T>& lhs, const mat<n,m,U>& rhs); - // +- - template <unsigned n, unsigned m, typename T, typename U> - mat<n,m,T>& - operator+=(mat<n,m,T>& lhs, const mat<n,m,U>& rhs); - - // + (binary) + // + template <unsigned n, unsigned m, typename T, typename U> mat<n, m, mln_trait_op_plus(T,U)> operator+(mat<n,m,T>& lhs, const mat<n,m,U>& rhs); - // -- - template <unsigned n, unsigned m, typename T, typename U> - mat<n,m,T>& - operator-=(mat<n,m,T>& lhs, const mat<n,m,U>& rhs); - - // - (binary) + // - template <unsigned n, unsigned m, typename T, typename U> mat<n, m, mln_trait_op_minus(T,U)> @@ -223,67 +208,32 @@ mat<n, m, mln_trait_op_uminus(T)> operator-(const mat<n,m,T>& lhs); - // Operator *. + // mat * mat template <unsigned n, unsigned o, typename T, unsigned m, typename U> - mat<n, m, mln_trait_op_times(T,U)> - operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs); // mat * mat - - -// template <unsigned n, unsigned m, typename T, -// typename S> -// mat<n, m, mln_trait_op_times(T,S)> -// operator*(const mat<n,m,T>& lhs, const S& s); // mat * s - - - // FIXME: Simplification below of the general code above: - - template <unsigned n, unsigned m, typename T> - mat<n, m, T> - operator*(const mat<n,m,T>& lhs, const T& s); // mat * s + mat<n, m, mln_sum_x(T,U)> + operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs); + // mat * vec template <unsigned n, unsigned m, typename T, typename U> - typename mln::trait::op::times< mat<n,m,T>, vec<m,U> >::ret - operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs) // mat * vec - // FIXME: Move below... - { - typedef mat<n,m,T> mat_t; - typedef vec<m,U> vec_t; - mln_trait_op_times(mat_t, vec_t) tmp; - for (unsigned i = 0; i < n; ++i) - { - mln_trait_op_times(T,U) sum = 0; // FIXME: Use literal::zero. - for (unsigned j = 0; j < m; ++j) - sum += lhs(i, j) * rhs[j]; - tmp[i] = sum; - } - return tmp; - } + vec<n, mln_sum_x(T,U)> + operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs); - // *- - template <unsigned n, typename T, typename U> - mat<n,n,T>& - operator*=(mat<n,n,T>& lhs, const mat<n,n,U>& rhs); - - template <unsigned n, unsigned m, typename T, typename U> - mat<n,m,T>& - operator*=(mat<n,m,T>& lhs, const U& rhs); - - // Operator /. + // mat * s - template <unsigned n, unsigned m, typename T, typename S> - mat<n, m, mln_trait_op_times(T,S)> // FIXME: times instead of div... - operator/(const mat<n,m,T>& lhs, const S& s); + template <unsigned n, unsigned m, typename T, + typename S> + mat<n, m, mln_trait_op_times(T,S)> + operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s); - // /+ // mat / s template <unsigned n, unsigned m, typename T, typename S> - mat<n,m,T>& - operator/=(mat<n,m,T>& lhs, const S& s); + mat<n, m, mln_trait_op_div(T,S)> + operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s); // << @@ -291,13 +241,6 @@ std::ostream& operator<<(std::ostream& ostr, const mat<n,m,T>& v); - template <unsigned n, unsigned m> - std::ostream& - operator<<(std::ostream& ostr, const mat<n,m,unsigned char>& v); - - template <unsigned n, unsigned m> - std::ostream& - operator<<(std::ostream& ostr, const mat<n,m,signed char>& v); # ifndef MLN_INCLUDE_ONLY @@ -382,7 +325,8 @@ } - // eq + // Operators. + template <unsigned n, unsigned m, typename T, typename U> bool @@ -395,20 +339,6 @@ return true; } - // +- - template <unsigned n, unsigned m, typename T, typename U> - mat<n,m,T>& - operator+=(mat<n,m,T>& lhs, const mat<n,m,U>& rhs) - { - for (unsigned i = 0; i < n; ++i) - for (unsigned j = 0; j < m; ++j) - lhs(i, j) += rhs(i, j); - return lhs; - } - - // Operator +. - template <unsigned n, unsigned m, typename T, typename U> mat<n, m, mln_trait_op_plus(T,U)> operator+(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs) @@ -420,20 +350,6 @@ return tmp; } - // -- - template <unsigned n, unsigned m, typename T, typename U> - mat<n,m,T>& - operator-=(mat<n,m,T>& lhs, const mat<n,m,U>& rhs) - { - for (unsigned i = 0; i < n; ++i) - for (unsigned j = 0; j < m; ++j) - lhs(i, j) -= rhs(i, j); - return lhs; - } - - // Operators -. - template <unsigned n, unsigned m, typename T, typename U> mat<n,m, mln_trait_op_minus(T,U)> operator-(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs) @@ -456,81 +372,55 @@ return tmp; } - // *- - template <unsigned n, typename T, typename U> - mat<n,n,T>& - operator*=(mat<n,n,T>& lhs, const mat<n,n,U>& rhs) - { - // FIXME: Optimize! - lhs = lhs * rhs; - return lhs; - } - - template <unsigned n, unsigned m, typename T, typename U> - mat<n,m,T>& - operator*=(mat<n,m,T>& lhs, const U& s) - { - for (unsigned i = 0; i < n; ++i) - for (unsigned j = 0; j < m; ++j) - lhs(i, j) *= s; - return lhs; - } - - // Operators *. - template <unsigned n, unsigned o, typename T, unsigned m, typename U> - mat<n,m, mln_trait_op_times(T,U)> + mat<n, m, mln_sum_x(T,U)> operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs) { - mat<n,m, mln_trait_op_times(T,U)> tmp; + mat<n,m, mln_sum_x(T,U)> tmp; for (unsigned i = 0; i < n; ++i) for (unsigned j = 0; j < m; ++j) { - tmp(i, j) = 0; + tmp(i, j) = literal::zero; for (unsigned k = 0; k < o; ++k) tmp(i, j) += lhs(i, k) * rhs(k, j); } return tmp; } - template <unsigned n, unsigned m, typename T> - mat<n, m, T> - operator*(const mat<n,m,T>& lhs, const T& s) // mat * s - - // FIXME: Read above. - -// template <unsigned n, unsigned m, typename T, -// typename S> -// mat<n,m, mln_trait_op_times(T,S)> -// operator*(const mat<n,m,T>& lhs, const S& s) + template <unsigned n, unsigned m, typename T, + typename U> + vec<n, mln_sum_x(T,U)> + operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs) { - mat<n,m, T> tmp; + vec<n, mln_sum_x(T,U)> tmp; for (unsigned i = 0; i < n; ++i) + { + mln_sum_x(T,U) sum(literal::zero); for (unsigned j = 0; j < m; ++j) - tmp(i, j) = lhs(i, j) * s; + sum += lhs(i, j) * rhs[j]; + tmp[i] = sum; + } return tmp; } - // / - template <unsigned n, unsigned m, typename T, typename S> - mat<n,m,T>& - operator/=(mat<n,m,T>& lhs, const S& s) + mat<n, m, mln_trait_op_times(T,S)> + operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s_) { + S s = s_.to_equiv(); + mat<n, m, mln_trait_op_times(T,S)> tmp; for (unsigned i = 0; i < n; ++i) for (unsigned j = 0; j < m; ++j) - lhs(i, j) /= s; - return lhs; + tmp(i, j) = lhs(i, j) * s; + return tmp; } - // Operator /. - template <unsigned n, unsigned m, typename T, typename S> - mat<n,m, mln_trait_op_times(T,S)> // FIXME: Use div, not times! - operator/(const mat<n,m,T>& lhs, const S& s) + mat<n,m, mln_trait_op_div(T,S)> + operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s_) { + S s = s_.to_equiv(); mat<n,m, mln_trait_op_times(T,S)> tmp; for (unsigned i = 0; i < n; ++i) for (unsigned j = 0; j < m; ++j) @@ -546,44 +436,14 @@ { for (unsigned i = 0; i < n; ++i) { - ostr << '('; + ostr << '['; for (unsigned j = 0; j < m; ++j) - ostr << v(i, j) << (j = m - 1 ? ")" : ", "); + ostr << debug::format(v(i, j)) << (j = m - 1 ? "]" : ", "); ostr << std::endl; } return ostr; } - template <unsigned n, unsigned m> - std::ostream& - operator<<(std::ostream& ostr, const mat<n,m,unsigned char>& v) - { - for (unsigned i = 0; i < n; ++i) - { - ostr << '('; - for (unsigned j = 0; j < m; ++j) - ostr << (unsigned int)(v[i][j]) << (j = m - 1 ? ")" : ", "); - ostr << std::endl; - } - return ostr; - } - - template <unsigned n, unsigned m> - std::ostream& - operator<<(std::ostream& ostr, const mat<n,m,signed char>& v) - { - for (unsigned i = 0; i < n; ++i) - { - ostr << '('; - for (unsigned j = 0; j < m; ++j) - ostr << (signed int)(v[i][j]) << (j = m - 1 ? ")" : ", "); - ostr << std::endl; - } - return ostr; - } - - - # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::metal Index: mln/metal/vec.hh --- mln/metal/vec.hh (revision 1383) +++ mln/metal/vec.hh (working copy) @@ -177,8 +177,6 @@ void set_all(const T& val); - T sprod(const vec<n, T>& rhs) const; // FIXME: Return is not T. - unsigned size() const; const vec<n, T>& normalize(); @@ -222,6 +220,14 @@ typedef metal::vec<n, V> ret; }; + template < unsigned n, typename T, + typename U > + struct set_precise_binary_< op::times, + metal::vec<n, T>, metal::vec<n, U> > + { + typedef mln_sum_x(T,U) ret; + }; + template < template <class, class> class Name, unsigned n, typename T, typename S > @@ -232,8 +238,16 @@ typedef metal::vec<n, V> ret; }; - // FIXME: What about scalar * vec!!! - + template < template<class, class> class Name, + unsigned n, typename T, + typename S > + struct set_binary_< Name, + mln::Object, metal::vec<n, T>, + mln::value::Scalar, S > + { + typedef mln_trait_binary(Name, T, S) V; + typedef metal::vec<n, V> ret; + }; } // end of namespace mln::trait @@ -274,17 +288,19 @@ vec<n, mln_trait_op_minus(T,U)> operator-(const vec<n,T>& lhs, const vec<n,U>& rhs); -// template <unsigned n, typename T> -// vec<n, mln_trait_op_uminus(T)> -// operator-(const vec<n,T>& lhs); + // vec * vec - // * + template <unsigned n, typename T, typename U> + mln_sum_x(T,U) + operator*(const vec<n,T>& lhs, const vec<n,U>& rhs); + + // vec * s template <unsigned n, typename T, typename S> vec<n, mln_trait_op_times(T, S)> operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s); - // / + // vec / s template <unsigned n, typename T, typename S> vec<n, mln_trait_op_div(T, S)> @@ -372,16 +388,6 @@ } template <unsigned n, typename T> - T vec<n,T>::sprod(const vec<n, T>& rhs) const - { - T tmp = 0; - - for (unsigned i = 0; i < n; ++i) - tmp += data_[i] * rhs.data_[i]; - return tmp; - } - - template <unsigned n, typename T> unsigned vec<n,T>::size() const { return n; @@ -417,7 +423,8 @@ const vec<n, T> vec<n, T>::origin = all_to(0); - // eq + // Operators. + template <unsigned n, typename T, typename U> bool operator=(const vec<n,T>& lhs, const vec<n,U>& rhs) @@ -428,7 +435,6 @@ return true; } - // + template <unsigned n, typename T, typename U> vec<n, mln_trait_op_plus(T,U)> @@ -440,8 +446,6 @@ return tmp; } - // - - template <unsigned n, typename T, typename U> vec<n, mln_trait_op_minus(T,U)> operator-(const vec<n,T>& lhs, const vec<n,U>& rhs) @@ -452,7 +456,16 @@ return tmp; } - // * + template <unsigned n, typename T, typename U> + mln_sum_x(T,U) + operator*(const vec<n,T>& lhs, const vec<n,U>& rhs) + { + mln_sum_x(T,U) tmp(literal::zero); + for (unsigned i = 0; i < n; ++i) + tmp += lhs[i] * rhs[i]; + return tmp; + } + template <unsigned n, typename T, typename S> vec<n, mln_trait_op_times(T, S)> @@ -474,8 +487,6 @@ return tmp; } - // / - template <unsigned n, typename T, typename S> vec<n, mln_trait_op_div(T, S)> operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s) @@ -487,7 +498,6 @@ return tmp; } - // << template <unsigned n, typename T> std::ostream& Index: mln/arith/plus.hh --- mln/arith/plus.hh (revision 1383) +++ mln/arith/plus.hh (working copy) @@ -178,9 +178,8 @@ void plus_cst(const Image<I>& input, const V& val, Image<O>& output) { mln_precondition(exact(output).domain() = exact(input).domain()); - impl::plus_(mln_trait_image_speed(I)(), exact(input), - trait::image::speed::any(), pw::cst(val) | exact(input).domain(), - mln_trait_image_speed(O)(), exact(output)); // Calls the previous version. + plus(input, pw::cst(val) | exact(input).domain(), output); + // Calls the previous version. } template <typename L, typename R> Index: mln/value/ops.hh --- mln/value/ops.hh (revision 1383) +++ mln/value/ops.hh (working copy) @@ -37,11 +37,16 @@ # include <mln/value/builtin/all.hh> # include <mln/value/concept/all.hh> # include <mln/value/equiv.hh> +# include <mln/value/props.hh> # include <mln/literal/zero.hh> # include <mln/literal/one.hh> +# include <mln/literal/ops.hh> # include <mln/metal/ret.hh> +# define mln_sum_x(T, U) typename mln::value::props< mln_trait_op_times(T,U) >::sum + + // FIXME: In the definitions below, is that equiv or interop? @@ -62,7 +67,8 @@ typedef mln_trait_unary(Name, mln_value_equiv(V)) ret; }; - // Binary traits for any Scalar type. + + // Binary traits for any Scalar type... template < template <class, class> class Name, typename Vl, typename Vr > @@ -71,6 +77,36 @@ typedef mln_trait_binary(Name, mln_value_equiv(Vl), mln_value_equiv(Vr)) ret; }; + // ...and for the special case of a couple of value::scalar_. + + template < template <class, class> class Name, + typename Sl, typename Sr > + struct set_binary_< Name, + mln::value::Scalar, mln::value::scalar_<Sl>, + mln::value::Scalar, mln::value::scalar_<Sr> > + { + typedef mln_trait_binary(Name, mln_value_equiv(Sl), mln_value_equiv(Sr)) ret; + }; + + + // Some binary traits for "scalar(s) OP obj" when OP commutes => "obj OP scalar(s)". + + template < typename S, typename O > + struct set_binary_< op::plus, + mln::value::Scalar, mln::value::scalar_<S>, + mln::Object, O > + { + typedef mln_trait_op_plus(O, mln::value::scalar_<S>) ret; + }; + + template < typename S, typename O > + struct set_binary_< op::times, + mln::value::Scalar, mln::value::scalar_<S>, + mln::Object, O > + { + typedef mln_trait_op_times(O, mln::value::scalar_<S>) ret; + }; + } // end of namespace mln::trait @@ -97,6 +133,16 @@ operator % (const value::Scalar<Vl>& lhs, const value::Scalar<Vr>& rhs); + + template <typename S, typename O> + mln_trait_op_plus(O, value::scalar_<S>) + operator + (const value::scalar_<S>& lhs, const Object<O>& rhs); + + template <typename S, typename O> + mln_trait_op_times(O, value::scalar_<S>) + operator * (const value::scalar_<S>& lhs, const Object<O>& rhs); + + // Arithmetical unary operators. template <typename S> @@ -112,6 +158,29 @@ + // Case of value::scalar_ OP value::scalar_. + + template <typename Sl, typename Sr> + mln_trait_op_plus(Sl, Sr) + operator + (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs); + + template <typename Sl, typename Sr> + mln_trait_op_minus(Sl, Sr) + operator - (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs); + + template <typename Sl, typename Sr> + mln_trait_op_times(Sl, Sr) + operator * (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs); + + template <typename Sl, typename Sr> + mln_trait_op_div(Sl, Sr) + operator / (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs); + + template <typename Sl, typename Sr> + mln_trait_op_mod(Sl, Sr) + operator % (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs); + + # ifndef MLN_INCLUDE_ONLY @@ -157,6 +226,60 @@ return - rhs.to_equiv(); } + template <typename S, typename O> + mln_trait_op_plus(O, value::scalar_<S>) + operator + (const value::scalar_<S>& lhs, const Object<O>& rhs) + { + return exact(rhs) + lhs; + } + + template <typename S, typename O> + mln_trait_op_times(O, value::scalar_<S>) + operator * (const value::scalar_<S>& lhs, const Object<O>& rhs) + { + return exact(rhs) * lhs; + } + + // ... + + + // With scalar_ OP scalar_. + + template <typename Sl, typename Sr> + mln_trait_op_plus(Sl, Sr) + operator + (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs) + { + return value::equiv(lhs) + value::equiv(rhs); + } + + template <typename Sl, typename Sr> + mln_trait_op_minus(Sl, Sr) + operator - (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs) + { + return value::equiv(lhs) - value::equiv(rhs); + } + + template <typename Sl, typename Sr> + mln_trait_op_times(Sl, Sr) + operator * (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs) + { + return value::equiv(lhs) * value::equiv(rhs); + } + + template <typename Sl, typename Sr> + mln_trait_op_div(Sl, Sr) + operator / (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs) + { + return value::equiv(lhs) / value::equiv(rhs); + } + + template <typename Sl, typename Sr> + mln_trait_op_mod(Sl, Sr) + operator % (const value::scalar_<Sl>& lhs, const value::scalar_<Sr>& rhs) + { + return value::equiv(lhs) % value::equiv(rhs); + } + // ... # endif // ! MLN_INCLUDE_ONLY Index: mln/value/quat.hh --- mln/value/quat.hh (revision 1383) +++ mln/value/quat.hh (working copy) @@ -335,7 +335,7 @@ float quat::sprod(const quat& rhs) const { - return v_.sprod(rhs.to_vec()); + return v_ * rhs.to_vec(); } bool quat::is_unit() const @@ -443,7 +443,7 @@ quat operator*(const quat& lhs, const quat& rhs) { - quat tmp(lhs.s() * rhs.s() - lhs.v().sprod(rhs.v()), + quat tmp(lhs.s() * rhs.s() - lhs.v() * rhs.v(), metal::vprod(lhs.v(), rhs.v()) + lhs.s() * rhs.v() + rhs.s() * lhs.v()); return tmp; } Index: mln/value/int_u.hh --- mln/value/int_u.hh (revision 1383) +++ mln/value/int_u.hh (working copy) @@ -59,6 +59,12 @@ { template <unsigned n> + struct set_precise_unary_< op::uminus, mln::value::int_u<n> > + { + typedef int ret; + }; + + template <unsigned n> struct value_< mln::value::int_u<n> > : mln::trait::value_integer_<n> { }; Index: mln/value/int_u_sat.hh --- mln/value/int_u_sat.hh (revision 1383) +++ mln/value/int_u_sat.hh (working copy) @@ -60,7 +60,7 @@ public internal::value_like_< int_u<n>, // Equivalent. mln_enc(int_u<n>), // Encoding. - int, // Interoperation. + unsigned, // Interoperation. int_u_sat<n> > // Exact. { /// Constructor without argument. @@ -130,10 +130,11 @@ template <unsigned n> int_u_sat<n>::int_u_sat(int i) { + static const unsigned max_ = mln_max(int_u<n>); if (i < 0) this->v_ = 0; - else if (i > mln_max(int_u_sat<n>)) - this->v_ = mln_max(int_u_sat<n>); + else if (i > max_) + this->v_ = max_; else this->v_ = i; } @@ -148,10 +149,11 @@ int_u_sat<n>& int_u_sat<n>::operator=(int i) { + static const unsigned max_ = mln_max(int_u<n>); if (i < 0) this->v_ = 0; - else if (i > mln_max(int_u_sat<n>)) - this->v_ = mln_max(int_u_sat<n>); + else if (i > max_) + this->v_ = max_; else this->v_ = i; return *this; Index: mln/value/builtin/ops.hh --- mln/value/builtin/ops.hh (revision 1383) +++ mln/value/builtin/ops.hh (working copy) @@ -284,7 +284,7 @@ struct set_unary_< Name, mln::value::Built_In, B > { - typedef B ret; // FIXME: Wrong! + typedef B ret; // FIXME: Wrong because some types are unsigned! }; @@ -364,7 +364,6 @@ typedef mln_trait_op_mod(mln::value::scalar_<B>, O) ret; }; - } // end of namespace mln::trait Index: mln/morpho/includes.hh --- mln/morpho/includes.hh (revision 1383) +++ mln/morpho/includes.hh (working copy) @@ -38,6 +38,8 @@ # include <mln/core/concept/window.hh> # include <mln/core/concept/neighborhood.hh> +# include <mln/value/ops.hh> + # include <mln/accu/min.hh> # include <mln/accu/max.hh> # include <mln/accu/min_h.hh>