vec.hh

00001 // Copyright (C) 2001, 2002, 2003  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef NTG_VECT_VEC_HH
00029 # define NTG_VECT_VEC_HH
00030 
00031 # include <ntg/basics.hh>
00032 # include <ntg/core/internal/macros.hh>
00033 # include <ntg/vect/vect_value.hh>
00034 
00035 # include <mlc/array/all.hh>
00036 # include <mlc/type.hh>
00037 
00038 /*--------------------.
00039 | assignements macros |
00040 `--------------------*/
00041 
00042 # define ASSIGN_VECTOR_VECTOR_OPERATOR(Name, Op)        \
00043 template <class T1, class T2> inline                    \
00044 static T1&                                              \
00045 Name(T1& lhs, const T2& rhs)                            \
00046 {                                                       \
00047   ntg_is_a(T1, ntg::vectorial)::ensure();               \
00048   ntg_is_a(T2, ntg::vectorial)::ensure();               \
00049   precondition(lhs.size() == rhs.size());               \
00050   unsigned s = lhs.size();                              \
00051   for (unsigned i = 0; i < s; ++i)                      \
00052     lhs[i] Op rhs[i];                                   \
00053   return lhs;                                           \
00054 }
00055 
00056 # define ASSIGN_VECTOR_SCALAR_OPERATOR(Name, Op)        \
00057 template <class T1, class T2> inline                    \
00058 static T1&                                              \
00059 Name(T1& lhs, const T2& rhs)                            \
00060 {                                                       \
00061   ntg_is_a(T1, ntg::vectorial)::ensure();               \
00062   ntg_is_a(T2, ntg::real)::ensure();                    \
00063   unsigned s = lhs.size();                              \
00064   for (unsigned i = 0; i < s; ++i)                      \
00065     lhs[i] Op rhs;                                      \
00066   return lhs;                                           \
00067 }
00068 
00069 # define ARITH_VECTOR_VECTOR_OPERATOR(Name, Op)         \
00070 template <class T1, class T2>                           \
00071 inline static                                           \
00072 ntg_return_type(Name,T1, T2)                            \
00073 Name(const T1& lhs, const T2& rhs)                      \
00074 {                                                       \
00075   ntg_is_a(T1, ntg::vectorial)::ensure();               \
00076   ntg_is_a(T2, ntg::vectorial)::ensure();               \
00077   typedef ntg_return_type(Name,T1, T2) return_type;     \
00078   return_type result(lhs);                              \
00079   result Op rhs;                                        \
00080   return result;                                        \
00081 }
00082 
00083 namespace ntg {
00084 
00085   namespace internal {
00086 
00087     /*----------------.
00088     | typetraits<vec> |
00089     `----------------*/
00090 
00091     template <unsigned N, class T, class Self>
00092     struct typetraits<vec<N, T, Self> > : public typetraits<vect_value<vec<N, T, Self> > >
00093     {
00094       enum { nb_comp = N };
00095 
00096       typedef vec<N, T, Self>   self;
00097       typedef vectorial         abstract_type;
00098       typedef self              ntg_type;
00099       typedef optraits<self>    optraits_type;
00100 
00101       ntg_build_value_type(vect_value<E>);
00102 
00103       // FIXME: document comp_type
00104       typedef T                                  comp_type;
00105       typedef self                               base_type;
00106       typedef T                                  storage_type[N];
00107       typedef typename typetraits<T>::cumul_type cumul_type[N];
00108 
00109       static const self &sup()
00110       {
00111         static self tmp = mkSup();
00112 
00113         return tmp;
00114       };
00115 
00116     protected:
00117       static self mkSup()
00118       {
00119         self tmp;
00120 
00121         for (unsigned i = 0; i < N; ++i)
00122           tmp[i] = ntg_sup_val(T);
00123         return tmp;
00124       };
00125     };
00126 
00127   } // end of internal.
00128 
00129   /*----------.
00130   | vec<N, T> |
00131   `----------*/
00132 
00133   template <unsigned N, class T, class E>
00134   class vec :
00135     public vect_value<typename mlc::exact_vt<vec<N, T, mlc::final>, E>::ret>
00136   {
00137   public :
00138 
00139     vec()
00140     {
00141       _fill (ntg_zero_val(T));
00142     }
00143 
00144     /* A vector can be built from a 1xM array.  */
00145     template<int ncols, class T2>
00146     vec(const mlc::array2d< mlc::array2d_info<1, ncols>, T2>& arr)
00147     {
00148       mlc::is_true< ncols == N >::ensure();
00149       for (unsigned i = 0; i < N; ++i)
00150         this->val_[i] = arr[i];
00151     }
00152 
00153     template<class U, class E2>
00154     vec(const vec<N, U, E2>& v)
00155     {
00156       for (unsigned i = 0; i < N; ++i)
00157         this->val_[i] = v[i];
00158     }
00159 
00160     template<class U, class E2>
00161     vec<N, T>& operator=(const vec<N, U, E2>& v)
00162     {
00163       for (unsigned i = 0; i < N; ++i)
00164         this->val_[i] = v[i];
00165       return *this;
00166     }
00167 
00168     static const vec<N,T> zero() { return vec(); }
00169     // There is no unit() for vec<>.
00170 
00171     ~vec() {}
00172 
00173   protected:
00174     vec& _fill(T t)
00175     {
00176       for (unsigned i = 0; i < N; ++i)
00177         this->val_[i] = t;
00178       return *this;
00179     }
00180   };
00181 
00182   template<unsigned N,class T> inline
00183   std::ostream&
00184   operator<<(std::ostream& ostr, const vec<N,T>& rhs)
00185   {
00186     // dev note: we use an ostringstream to make only one output
00187     // on the ostream. This allows calling procedures to consider
00188     // data type printing as atomic, thus ostr.width(...) can
00189     // work.
00190     std::ostringstream str;
00191     str << "[";
00192     for (unsigned i = 0; i < N; ++i)
00193       str << rhs[i] << ((i < N-1) ? "," : "]");
00194     ostr << str.str();
00195     return ostr;
00196   }
00197 
00198   namespace internal
00199   {
00200 
00201     /*--------------.
00202     | optraits<vec> |
00203     `--------------*/
00204 
00205     template <unsigned N, class T, class E>
00206     class optraits<vec<N, T, E> > : public optraits<vect_value<vec<N, T, E> > >
00207     {
00208       typedef vec<N, T, E> self;
00209       typedef ntgi_storage_type(self) storage_type_;
00210 
00211     public:
00212       static self zero ()
00213       {
00214         // A vectorial type MUST return a zero initialized value.
00215         return self();
00216       }
00217 
00218       static unsigned max_print_width ()
00219       {
00220         return (N * ntg_max_print_width(T)) + (N - 1) + 2;
00221       }
00222 
00223       static std::string
00224       name() {
00225         std::ostringstream out;
00226         out << "vec<" << N << ", " << ntg_name(T) << ">"<< std::ends;
00227         return out.str();
00228       }
00229 
00230       // No unit() for vector.
00231       // static storage_type_ unit ();
00232 
00233       ASSIGN_VECTOR_VECTOR_OPERATOR(plus_equal,  +=)
00234       ASSIGN_VECTOR_VECTOR_OPERATOR(minus_equal, -=)
00235       ASSIGN_VECTOR_SCALAR_OPERATOR(times_equal, *=)
00236       ASSIGN_VECTOR_SCALAR_OPERATOR(div_equal,   /=)
00237       ASSIGN_VECTOR_SCALAR_OPERATOR(mod_equal,   %=)
00238 
00239       ARITH_VECTOR_VECTOR_OPERATOR(plus, +=)
00240       ARITH_VECTOR_VECTOR_OPERATOR(minus, -=)
00241 
00242       // division
00243 
00244       template <class T1, class T2>
00245       inline static
00246       ntg_return_type(div, T1, T2)
00247       div(const T1& lhs, const T2& rhs)
00248       {
00249         ntg_is_a(T1, ntg::vectorial)::ensure();
00250         ntg_is_a(T2, ntg::real)::ensure();
00251         typedef ntg_return_type(div, T1, T2) return_type;
00252         return_type result(lhs);
00253         result /= rhs;
00254         return result;
00255       }
00256 
00257       // modulo
00258 
00259       template <class T1, class T2>
00260       inline static
00261       ntg_return_type(mod, T1, T2)
00262       mod(const T1& lhs, const T2& rhs)
00263       {
00264         ntg_is_a(T1, ntg::vectorial)::ensure();
00265         ntg_is_a(T2, ntg::real)::ensure();
00266         typedef ntg_return_type(mod, T1, T2) return_type;
00267         return_type result(lhs);
00268         result %= rhs;
00269         return result;
00270       }
00271 
00272       // multiplication
00273 
00274       // dot-product
00275       template <unsigned M, class T1, class T2>
00276       inline static typename
00277       internal::deduce_from_traits<internal::operator_times,
00278                                    vec<M, T1>,
00279                                    vec<M, T2> >::ret
00280       times(const vec<M, T1>& lhs, const vec<M, T2>& rhs)
00281       {
00282         typedef vec<M, T1> vec1;
00283         typedef vec<M, T2> vec2;
00284         ntg_is_a(vec1, ntg::vectorial)::ensure();
00285         ntg_is_a(vec2, ntg::vectorial)::ensure();
00286         typedef typename
00287           internal::deduce_from_traits<internal::operator_times,
00288           vec<M, T1>, vec<M, T2> >::ret return_type;
00289         precondition(lhs.size() == rhs.size());
00290 
00291         return_type result = optraits<return_type>::zero();
00292         unsigned s = lhs.size();
00293         for (unsigned i = 0; i < s; ++i)
00294           result += lhs[i] * rhs[i];
00295 
00296         return result;
00297       }
00298 
00299       // vector * scalar
00300       template <class T1, class T2>
00301       inline static
00302       ntg_return_type(times, T1, T2)
00303       times(const vect_value<T1>& lhs, const T2& rhs)
00304       {
00305         ntg_is_a(T1, ntg::vectorial)::ensure();
00306         ntg_is_a(T2, ntg::real)::ensure();
00307         typedef ntg_return_type(times, T1, T2) return_type;
00308         return_type result(lhs.exact());
00309         result *= rhs;
00310         return result;
00311       }
00312 
00313       // scalar * vector
00314       template <class T1, class T2>
00315       inline static
00316       ntg_return_type(times, T1, T2)
00317       times(const T1& lhs, const vect_value<T2>& rhs)
00318       {
00319         return times(rhs, lhs);
00320       }
00321 
00322 
00323       template <class T1, class T2>
00324       inline static bool
00325       cmp_eq (const T1& lhs, const T2& rhs)
00326       {
00327         ntg_is_a(T1, ntg::vectorial)::ensure();
00328         ntg_is_a(T2, ntg::vectorial)::ensure();
00329         ntg_assert(lhs.size() == rhs.size());
00330 
00331         typedef ntg_return_type(cmp, T1, T2) tmp_type;
00332 
00333         unsigned s = lhs.size();
00334         for (unsigned i = 0; i < s; ++i)
00335           if (lhs[i] != rhs[i])
00336             return false;
00337         return true;
00338       }
00339     };
00340 
00341     /*----------------.
00342     | operator traits |
00343     `----------------*/
00344 
00345     //
00346     // plus
00347     //
00348 
00349     // vec + vec
00350 
00351     template<unsigned N, class T1, class T2, class S1, class S2>
00352     struct operator_traits<operator_plus, vec<N, T1, S1>, vec<N, T2, S2> >
00353     {
00354       enum { commutative = true };
00355       typedef vec<N, ntg_return_type(plus, T1, T2)> ret;
00356       typedef vec<N, T1> impl;
00357     };
00358 
00359     //
00360     // minus
00361     //
00362 
00363     // vec - vec
00364 
00365     template<unsigned N, class T1, class T2>
00366     struct operator_traits<operator_minus, vec<N, T1>, vec<N, T2> >
00367     {
00368       enum { commutative = true };
00369       typedef vec<N, ntg_return_type(minus, T1, T2)> ret;
00370       typedef vec<N, T1> impl;
00371     };
00372 
00373     //
00374     // times
00375     //
00376 
00377     // vec * s; s * vec
00378 
00379     template<unsigned N, class T1, class T2>
00380     struct operator_traits<operator_times, vec<N, T1>, T2>
00381     {
00382       enum { commutative = true };
00383       typedef vec<N, ntg_return_type(times, T1, T2)> ret;
00384       typedef vec<N, T1> impl;
00385     };
00386 
00387     // vec * vec
00388 
00389     template<unsigned N, class T1, class T2>
00390     struct operator_traits<operator_times, vec<N, T1>, vec<N, T2> >
00391     {
00392       enum { commutative = true };
00393       typedef ntg_return_type(times,T1,T2) t;
00394       typedef typename typetraits<t>::cumul_type ret;
00395       typedef vec<N, T1> impl;
00396     };
00397 
00398     //
00399     // div
00400     //
00401 
00402     // vec / s
00403 
00404     template<unsigned N, class T1, class T2>
00405     struct operator_traits<operator_div, vec<N, T1>, T2>
00406     {
00407       enum { commutative = false };
00408       typedef vec<N, ntg_return_type(div, T1, T2)> ret;
00409       typedef vec<N, T1> impl;
00410     };
00411 
00412     //
00413     // mod
00414     //
00415 
00416     // vec % s
00417 
00418     template<unsigned N, class T1, class T2>
00419     struct operator_traits<operator_mod, vec<N, T1>, T2>
00420     {
00421       enum { commutative = false };
00422       typedef vec<N, ntg_return_type(mod, T1, T2)> ret;
00423       typedef vec<N, T1> impl;
00424     };
00425 
00426     //
00427     // Comparison operator
00428     //
00429 
00430     // vec compared with vec
00431 
00432     template<unsigned N, class T1, class T2, class S1, class S2>
00433     struct operator_traits<operator_cmp, vec<N, T1, S1>, vec<N, T2, S2> >
00434     {
00435       enum { commutative = true };
00436       typedef vec<N, ntg_return_type(cmp, T1, T2)> ret;
00437       typedef vec<N, T1> impl;
00438     };
00439 
00440   } // end of internal.
00441 
00442 } // end of ntg.
00443 
00444 #endif // !NTG_VECT_VEC_HH

Generated on Thu Apr 15 20:13:15 2004 for Olena by doxygen 1.3.6-20040222