core/vnl/vnl_vector_fixed_ref.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_vector_fixed_ref.h
00002 #ifndef vnl_vector_fixed_ref_h_
00003 #define vnl_vector_fixed_ref_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Fixed size vnl_vector using user-supplied storage
00010 // See vnl_matrix_fixed_ref for rationale.
00011 // See also vnl_vector_ref, vnl_vector_fixed
00012 //
00013 // \author Paul P. Smyth, Vicon Motion Systems Ltd.
00014 // \date 02 May 2001
00015 //
00016 // \verbatim
00017 //  Modifications
00018 //    4-Jul-2003 - Paul Smyth - general cleanup and rewrite; interface now as vnl_vector_fixed
00019 //   30-Mar-2009 - Peter Vanroose - added arg_min() and arg_max()
00020 //   24-Oct-2010 - Peter Vanroose - mutators and setters now return *this
00021 // \endverbatim
00022 
00023 #include <vcl_cassert.h>
00024 #include <vnl/vnl_vector_fixed.h>
00025 #include <vcl_iosfwd.h>
00026 
00027 
00028 template <class T, unsigned int n>
00029 class vnl_vector_fixed_ref_const
00030 {
00031  protected:
00032   const T* data_;
00033 
00034  public:
00035   typedef unsigned int size_type;
00036 
00037   vnl_vector_fixed_ref_const(vnl_vector_fixed<T,n> const& rhs) : data_(rhs.data_block()) {}
00038 
00039   explicit vnl_vector_fixed_ref_const(const T * dataptr) : data_(dataptr) {}
00040 
00041   vnl_vector_fixed_ref_const(const vnl_vector_fixed_ref_const<T,n> & rhs) : data_(rhs.data_block()) {}
00042 
00043   const T * data_block() const { return data_; }
00044 
00045   // Don't out-of-line the constructors, as the extra function call
00046   // adds a significant overhead. (memcpy is often implemented with a
00047   // couple of assembly instructions.)
00048 
00049 
00050   //: Length of the vector.
00051   // This is always \a n.
00052   unsigned size() const { return n; }
00053 
00054   //: Get value at element i
00055   T get (unsigned int i) const { return data_[i]; }
00056 
00057   //: Copy elements to ptr[i]
00058   //  Note: ptr[i] must be valid for i=0..size()-1
00059   void copy_out( T* ptr ) const {
00060     for ( size_type i = 0; i < n; ++i )
00061       ptr[i] = data_[i];
00062   }
00063 
00064 
00065   //: Return reference to the element at specified index.
00066   // There are assert style boundary checks - #define NDEBUG to turn them off.
00067   T const & operator() (unsigned int i) const
00068   {
00069 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00070     assert(i<n);   // Check the index is valid
00071 #endif
00072     return data_[i];
00073   }
00074 
00075 
00076   //: Return the i-th element
00077   const T& operator[] ( unsigned int i ) const { return data_[i]; }
00078 
00079 
00080   //----------------------------------------------------------------------
00081   // Conversion to vnl_vector_ref.
00082 
00083   // The const version of as_ref should return a const vnl_vector_ref
00084   // so that the vnl_vector_ref::non_const() cannot be used on
00085   // it. This prevents a vnl_vector_fixed_ref_const from being cast into a
00086   // non-const vnl_vector reference, giving a slight increase in type safety.
00087 
00088   //: Explicit conversion to a vnl_vector_ref.
00089   // This is a cheap conversion for those functions that have an interface
00090   // for vnl_vector_ref but not for vnl_vector_fixed_ref. There is also a
00091   // conversion operator that should work most of the time.
00092   // \sa vnl_vector_ref::non_const
00093   const vnl_vector_ref<T> as_ref() const { return vnl_vector_ref<T>( n, const_cast<T*>(data_) ); }
00094 
00095   //: Cheap conversion to vnl_vector_ref
00096   // Sometimes, such as with templated functions, the compiler cannot
00097   // use this user-defined conversion. For those cases, use the
00098   // explicit as_ref() method instead.
00099   operator const vnl_vector_ref<T>() const { return vnl_vector_ref<T>( n, const_cast<T*>(data_) ); }
00100 
00101   //----------------------------------------------------------------------
00102 
00103   //: Type defs for iterators
00104   typedef T element_type;
00105   //: Type defs for iterators
00106   typedef T const *iterator;
00107 
00108   //: Const iterator type
00109   typedef T const *const_iterator;
00110   //: Iterator pointing to start of data
00111   const_iterator begin() const { return data_; }
00112   //: Iterator pointing to element beyond end of data
00113   const_iterator end() const { return data_+n; }
00114 
00115 
00116   //: Apply f to each element.
00117   // Returns a new vector with the result.
00118   vnl_vector_fixed<T,n> apply(T (*f)(T)) const;
00119 
00120   //: Apply f to each element.
00121   // Returns a new vector with the result.
00122   vnl_vector_fixed<T,n> apply(T (*f)(const T&)) const;
00123 
00124   //:
00125   vnl_vector_fixed<T,n> operator-() const {
00126     vnl_vector_fixed<T,n> result;
00127     sub( (T)0, data_, result.data_block() );
00128     return result;
00129   }
00130 
00131   //: Returns a subvector specified by the start index and length. O(n).
00132   vnl_vector<T> extract (unsigned int len, unsigned int start=0) const;
00133 
00134   //: Convert to a vnl_vector.
00135   vnl_vector<T> as_vector() const { return extract(n); }
00136 
00137 
00138   // norms etc
00139   typedef typename vnl_c_vector<T>::abs_t abs_t;
00140 
00141   //: Return sum of squares of elements
00142   abs_t squared_magnitude() const { return vnl_c_vector<T>::two_nrm2(begin(), n); }
00143 
00144   //: Return magnitude (length) of vector
00145   abs_t magnitude() const { return two_norm(); }
00146 
00147   //: Return sum of absolute values of the elements
00148   abs_t one_norm() const { return vnl_c_vector<T>::one_norm(begin(), n); }
00149 
00150   //: Return sqrt of sum of squares of values of elements
00151   abs_t two_norm() const { return vnl_c_vector<T>::two_norm(begin(), n); }
00152 
00153   //: Return largest absolute element value
00154   abs_t inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), n); }
00155 
00156 
00157   // These next 6 functions are should really be helper functions since they aren't
00158   // really proper functions on a vector in a philosophical sense.
00159 
00160   //: Root Mean Squares of values
00161   abs_t rms     () const { return vnl_c_vector<T>::rms_norm(begin(), n); }
00162 
00163   //: Smallest value
00164   T min_value () const { return vnl_c_vector<T>::min_value(begin(), n); }
00165 
00166   //: Largest value
00167   T max_value () const { return vnl_c_vector<T>::max_value(begin(), n); }
00168 
00169   //: Location of smallest value
00170   unsigned arg_min() const { return vnl_c_vector<T>::arg_min(begin(), n); }
00171 
00172   //: Location of largest value
00173   unsigned arg_max() const { return vnl_c_vector<T>::arg_max(begin(), n); }
00174 
00175   //: Mean of values in vector
00176   T mean() const { return vnl_c_vector<T>::mean(begin(), n); }
00177 
00178   //: Sum of values in a vector
00179   T sum() const { return vnl_c_vector<T>::sum(begin(), n); }
00180 
00181 
00182   //: Check that size()==sz if not, abort();
00183   // This function does or tests nothing if NDEBUG is defined
00184   void assert_size( unsigned sz ) const { assert( sz == n ); }
00185 
00186   //: Check that this is finite if not, abort();
00187   // This function does or tests nothing if NDEBUG is defined
00188   void assert_finite() const {
00189 #ifndef NDEBUG
00190     assert_finite_internal();
00191 #endif
00192   }
00193 
00194   //: Return true if it's finite
00195   bool is_finite() const;
00196 
00197   //: Return true iff all the entries are zero.
00198   bool is_zero() const;
00199 
00200   //: Return true iff the size is zero.
00201   bool empty() const { return n==0; }
00202 
00203   //: Return true if *this == v
00204   bool operator_eq (vnl_vector_fixed_ref_const<T,n> const& v) const {
00205     for ( size_type i = 0; i < n; ++i )
00206       if ( (*this)[i] != v[i] )
00207         return false;
00208     return true;
00209   }
00210 
00211   //: Return true if *this == v
00212   bool operator_eq (vnl_vector<T> const& v) const {
00213     assert( v.size() == n );
00214     for ( size_type i = 0; i < n; ++i )
00215       if ( (*this)[i] != v[i] )
00216         return false;
00217     return true;
00218   }
00219 
00220 
00221   //: Display the vector
00222   // Output each element separated by a single space.
00223   void print( vcl_ostream& s ) const;
00224 
00225  public:
00226   // Helper routines for arithmetic. n is the size, and is the
00227   // template parameter.
00228 
00229   inline static void add( const T* a, const T* b, T* r ) {
00230     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00231       *r = *a + *b;
00232   }
00233 
00234   inline static void add( const T* a, T b, T* r ) {
00235     for ( unsigned int i=0; i < n; ++i,++r,++a )
00236       *r = *a + b;
00237   }
00238 
00239   inline static void sub( const T* a, const T* b, T* r ) {
00240     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00241       *r = *a - *b;
00242   }
00243 
00244   inline static void sub( const T* a, T b, T* r ) {
00245     for ( unsigned int i=0; i < n; ++i,++r,++a )
00246       *r = *a - b;
00247   }
00248 
00249   inline static void sub( T a, const T* b, T* r ) {
00250     for ( unsigned int i=0; i < n; ++i,++r,++b )
00251       *r = a - *b;
00252   }
00253 
00254   inline static void mul( const T* a, const T* b, T* r ) {
00255     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00256       *r = *a * *b;
00257   }
00258 
00259   inline static void mul( const T* a, T b, T* r ) {
00260     for ( unsigned int i=0; i < n; ++i,++r,++a )
00261       *r = *a * b;
00262   }
00263 
00264   inline static void div( const T* a, const T* b, T* r ) {
00265     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00266       *r = *a / *b;
00267   }
00268 
00269   inline static void div( const T* a, T b, T* r ) {
00270     for ( unsigned int i=0; i < n; ++i,++r,++a )
00271       *r = *a / b;
00272   }
00273 
00274 
00275   //: Equality operator
00276   bool operator==(vnl_vector_fixed_ref_const<T,n> const &that) const { return  this->operator_eq(that); }
00277 
00278   //: Inequality operator
00279   bool operator!=(vnl_vector_fixed_ref_const<T,n> const &that) const { return !this->operator_eq(that); }
00280 
00281  private:
00282   //: See assert_finite().
00283   const vnl_vector_fixed_ref_const<T,n> & operator=(const vnl_vector_fixed<T,n> & ) const
00284   {
00285     assert(!"Assignment is illegal for a vnl_vector_fixed_ref_const");
00286     return *this;
00287   }
00288   const vnl_vector_fixed_ref_const<T,n> & operator=(const vnl_vector_fixed_ref_const<T,n> & ) const
00289   {
00290     assert(!"Assignment is illegal for a vnl_vector_fixed_ref_const");
00291     return *this;
00292   }
00293   void assert_finite_internal() const;
00294 };
00295 
00296 // Non const vector fixed reference
00297 
00298 template <class T, unsigned n>
00299 class vnl_vector_fixed_ref : public vnl_vector_fixed_ref_const<T,n>
00300 {
00301   typedef vnl_vector_fixed_ref_const<T,n> base;
00302 
00303  public:
00304   typedef unsigned int size_type;
00305 
00306   // this is the only point where the const_cast happens
00307   // the base class is used to store the pointer, so that conversion is not necessary
00308   T * data_block() const { return const_cast<T*>(this->data_); }
00309 
00310   vnl_vector_fixed_ref(vnl_vector_fixed<T,n>& rhs) : base(rhs.data_block()) {}
00311 
00312   explicit vnl_vector_fixed_ref(T * dataptr) : base(dataptr) {}
00313 
00314   //: Copy operator
00315   vnl_vector_fixed_ref<T,n> const & operator=( const vnl_vector_fixed<T,n>& rhs ) const {
00316     vcl_memcpy( data_block(), rhs.data_block(), n * sizeof(T) );
00317     return *this;
00318   }
00319 
00320   //: Copy operator
00321   vnl_vector_fixed_ref<T,n> const& operator=( const vnl_vector_fixed_ref<T,n>& rhs ) const {
00322     vcl_memcpy( data_block(), rhs.data_block(), n * sizeof(T) );
00323     return *this;
00324   }
00325 
00326   //: Copy operator
00327   vnl_vector_fixed_ref<T,n> const& operator=( const vnl_vector_fixed_ref_const<T,n>& rhs ) const {
00328     vcl_memcpy( data_block(), rhs.data_block(), n * sizeof(T) );
00329     return *this;
00330   }
00331 
00332 
00333   //: Put value at given position in vector.
00334   void put (unsigned int i, T const& v) const { data_block()[i] = v; }
00335 
00336   //: Set all values to v
00337   vnl_vector_fixed_ref& fill( T const& v )
00338   {
00339     for ( size_type i = 0; i < n; ++i ) data_block()[i] = v;
00340     return *this;
00341   }
00342 
00343   //: Sets elements to ptr[i]
00344   //  Note: ptr[i] must be valid for i=0..size()-1
00345   vnl_vector_fixed_ref const& copy_in( T const * ptr ) const
00346   {
00347     for ( size_type i = 0; i < n; ++i ) data_block()[i] = ptr[i];
00348     return *this;
00349   }
00350 
00351   //: Sets elements to ptr[i]
00352   //  Note: ptr[i] must be valid for i=0..size()-1
00353   vnl_vector_fixed_ref const& set( T const *ptr ) const { copy_in(ptr); return *this; }
00354 
00355   //: Return reference to the element at specified index.
00356   // There are assert style boundary checks - #define NDEBUG to turn them off.
00357   T       & operator() (unsigned int i) const
00358   {
00359 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00360     assert(i<n);   // Check the index is valid.
00361 #endif
00362     return data_block()[i];
00363   }
00364 
00365   //: Return the i-th element
00366   T& operator[] ( unsigned int i ) const { return data_block()[i]; }
00367 
00368   // \sa vnl_vector_ref::non_const
00369   vnl_vector_ref<T> as_ref() { return vnl_vector_ref<T>( n, data_block() ); }
00370 
00371   typedef T       *iterator;
00372   //: Iterator pointing to start of data
00373   iterator begin() const { return data_block(); }
00374 
00375   //: Iterator pointing to element beyond end of data
00376   iterator end() const { return begin()+n; }
00377 
00378   //: Replaces elements with index beginning at start, by values of v. O(n).
00379   vnl_vector_fixed_ref const& update (vnl_vector<T> const&, unsigned int start=0) const;
00380 
00381   //: Read from text stream
00382   bool read_ascii(vcl_istream& s) const;
00383 
00384   vnl_vector_fixed_ref const& flip() const;
00385 
00386   //:
00387   vnl_vector_fixed_ref<T,n> const & operator+=( T s ) const {
00388     base::add( data_block(), s, data_block() ); return *this;
00389   }
00390 
00391   //:
00392   vnl_vector_fixed_ref<T,n> const & operator-=( T s ) const {
00393     base::sub( data_block(), s, data_block() ); return *this;
00394   }
00395 
00396   //:
00397   vnl_vector_fixed_ref<T,n> const & operator*=( T s ) const {
00398     base::mul( data_block(), s, data_block() ); return *this;
00399   }
00400 
00401   //:
00402   vnl_vector_fixed_ref<T,n> const & operator/=( T s ) const {
00403     base::div( data_block(), s, data_block() ); return *this;
00404   }
00405 
00406   //:
00407   vnl_vector_fixed_ref<T,n> const & operator+=( const vnl_vector_fixed<T,n>& v ) const {
00408     base::add( data_block(), v.data_block(), data_block() ); return *this;
00409   }
00410 
00411   //:
00412   vnl_vector_fixed_ref<T,n> const & operator-=( const vnl_vector_fixed<T,n>& v ) const {
00413     base::sub( data_block(), v.data_block(), data_block() ); return *this;
00414   }
00415 
00416   //:
00417   vnl_vector_fixed_ref<T,n> const & operator+=( const vnl_vector<T>& v ) const {
00418     assert( v.size() == n );
00419     base::add( data_block(), v.data_block(), data_block() ); return *this;
00420   }
00421 
00422   //:
00423   vnl_vector_fixed_ref<T,n> const & operator-=( const vnl_vector<T>& v ) const {
00424     assert( v.size() == n );
00425     base::sub( data_block(), v.data_block(), data_block() ); return *this;
00426   }
00427 };
00428 
00429 
00430 // Make the operators below inline because (1) they are small and
00431 // (2) we then have less explicit instantiation trouble.
00432 
00433 
00434 // --- Vector-scalar operators ----------------------------------------
00435 
00436 
00437 //: \relatesalso vnl_vector_fixed
00438 template<class T, unsigned int n>
00439 inline vnl_vector_fixed<T,n> operator+( const vnl_vector_fixed_ref_const<T,n>& v, T s )
00440 {
00441   vnl_vector_fixed<T,n> r;
00442   vnl_vector_fixed<T,n>::add( v.data_block(), s, r.data_block() );
00443   return r;
00444 }
00445 
00446 //: \relatesalso vnl_vector_fixed
00447 template<class T, unsigned int n>
00448 inline vnl_vector_fixed<T,n> operator+( T s, const vnl_vector_fixed_ref_const<T,n>& v )
00449 {
00450   vnl_vector_fixed<T,n> r;
00451   vnl_vector_fixed<T,n>::add( v.data_block(), s, r.data_block() );
00452   return r;
00453 }
00454 
00455 //: \relatesalso vnl_vector_fixed
00456 template<class T, unsigned int n>
00457 inline vnl_vector_fixed<T,n> operator-( const vnl_vector_fixed_ref_const<T,n>& v, T s )
00458 {
00459   vnl_vector_fixed<T,n> r;
00460   vnl_vector_fixed<T,n>::sub( v.data_block(), s, r.data_block() );
00461   return r;
00462 }
00463 
00464 //: \relatesalso vnl_vector_fixed
00465 template<class T, unsigned int n>
00466 inline vnl_vector_fixed<T,n> operator-( T s, const vnl_vector_fixed_ref_const<T,n>& v )
00467 {
00468   vnl_vector_fixed<T,n> r;
00469   vnl_vector_fixed<T,n>::sub( s, v.data_block(), r.data_block() );
00470   return r;
00471 }
00472 
00473 //: \relatesalso vnl_vector_fixed
00474 template<class T, unsigned int n>
00475 inline vnl_vector_fixed<T,n> operator*( const vnl_vector_fixed_ref_const<T,n>& v, T s )
00476 {
00477   vnl_vector_fixed<T,n> r;
00478   vnl_vector_fixed<T,n>::mul( v.data_block(), s, r.data_block() );
00479   return r;
00480 }
00481 
00482 //: \relatesalso vnl_vector_fixed
00483 template<class T, unsigned int n>
00484 inline vnl_vector_fixed<T,n> operator*( T s, const vnl_vector_fixed_ref_const<T,n>& v )
00485 {
00486   vnl_vector_fixed<T,n> r;
00487   vnl_vector_fixed<T,n>::mul( v.data_block(), s, r.data_block() );
00488   return r;
00489 }
00490 
00491 //: \relatesalso vnl_vector_fixed
00492 template<class T, unsigned int n>
00493 inline vnl_vector_fixed<T,n> operator/( const vnl_vector_fixed_ref_const<T,n>& v, T s )
00494 {
00495   vnl_vector_fixed<T,n> r;
00496   vnl_vector_fixed<T,n>::div( v.data_block(), s, r.data_block() );
00497   return r;
00498 }
00499 
00500 
00501 // --- Vector-vector operators ----------------------------------------
00502 
00503 
00504 //: \relatesalso vnl_vector_fixed
00505 template<class T, unsigned int n>
00506 inline vnl_vector_fixed<T,n> operator+( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00507 {
00508   vnl_vector_fixed<T,n> r;
00509   vnl_vector_fixed<T,n>::add( a.data_block(), b.data_block(), r.data_block() );
00510   return r;
00511 }
00512 
00513 //: \relatesalso vnl_vector_fixed
00514 template<class T, unsigned int n>
00515 inline vnl_vector_fixed<T,n> operator-( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00516 {
00517   vnl_vector_fixed<T,n> r;
00518   vnl_vector_fixed<T,n>::sub( a.data_block(), b.data_block(), r.data_block() );
00519   return r;
00520 }
00521 
00522 template<class T, unsigned int n>
00523 inline vnl_vector_fixed<T,n> element_product( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00524 {
00525   vnl_vector_fixed<T,n> r;
00526   vnl_vector_fixed<T,n>::mul( a.data_block(), b.data_block(), r.data_block() );
00527   return r;
00528 }
00529 
00530 template<class T, unsigned int n>
00531 inline vnl_vector_fixed<T,n> element_quotient( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00532 {
00533   vnl_vector_fixed<T,n> r;
00534   vnl_vector_fixed<T,n>::div( a.data_block(), b.data_block(), r.data_block() );
00535   return r;
00536 }
00537 
00538 template<class T>
00539 vnl_vector_fixed<T,3> vnl_cross_3d(vnl_vector_fixed_ref_const<T,3> const& v1, vnl_vector_fixed_ref_const<T,3> const& v2)
00540 {
00541   vnl_vector_fixed<T,3> result;
00542 
00543   result[0] = v1[1] * v2[2] - v1[2] * v2[1];
00544   result[1] = v1[2] * v2[0] - v1[0] * v2[2];
00545   result[2] = v1[0] * v2[1] - v1[1] * v2[0];
00546   return result;
00547 }
00548 
00549 // These overloads for the common case of mixing a fixed with a
00550 // non-fixed. Because the operator* are templated, the fixed will not
00551 // be automatically converted to a non-fixed-ref. These do it for you.
00552 
00553 template<class T, unsigned int n>
00554 inline vnl_vector<T> operator+( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector<T>& b )
00555 {
00556   return a.as_ref() + b;
00557 }
00558 
00559 template<class T, unsigned int n>
00560 inline vnl_vector<T> operator+( const vnl_vector<T>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00561 {
00562   return a + b.as_ref();
00563 }
00564 
00565 template<class T, unsigned int n>
00566 inline vnl_vector<T> operator-( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector<T>& b )
00567 {
00568   return a.as_ref() - b;
00569 }
00570 
00571 template<class T, unsigned int n>
00572 inline vnl_vector<T> operator-( const vnl_vector<T>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00573 {
00574   return a - b.as_ref();
00575 }
00576 
00577 
00578 template<class T, unsigned n>
00579 inline T dot_product( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00580 {
00581   return dot_product( a.as_ref(), b.as_ref() );
00582 }
00583 
00584 template<class T, unsigned n>
00585 inline T dot_product( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector<T>& b )
00586 {
00587   return dot_product( a.as_ref(), b );
00588 }
00589 
00590 template<class T, unsigned n>
00591 inline T dot_product( const vnl_vector<T>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00592 {
00593   return dot_product( a, b.as_ref() );
00594 }
00595 
00596 template<class T, unsigned int m, unsigned int n>
00597 inline vnl_matrix_fixed<T,m,n> outer_product( const vnl_vector_fixed_ref_const<T,m>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00598 {
00599   vnl_matrix_fixed<T,m,n> out; // = a.column() * b.row()
00600   for (unsigned int i = 0; i < m; i++)
00601     for (unsigned int j = 0; j < n; j++)
00602       out[i][j] = a[i] * b[j];
00603   return out;
00604 }
00605 
00606 template<class T,unsigned int n>
00607   inline vnl_vector_fixed<T,n> vnl_cross_3d( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector<T>& b ) {
00608   return vnl_cross_3d( a.as_ref(), b);
00609 }
00610 
00611 template<class T,unsigned int n>
00612   inline vnl_vector_fixed<T,n> vnl_cross_3d( const vnl_vector<T>& a, const vnl_vector_fixed_ref_const<T,n>& b ) {
00613   return vnl_cross_3d( a, b.as_ref());
00614 }
00615 
00616 template<class T, unsigned int n>
00617 inline vnl_matrix<T> outer_product( const vnl_vector<T>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00618 {
00619   return outer_product( a, b.as_ref());
00620 }
00621 
00622 template<class T, unsigned int n>
00623 inline vnl_matrix<T> outer_product( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector<T>& b )
00624 {
00625   return outer_product( a.as_ref(), b);
00626 }
00627 
00628 template<class T, unsigned n>
00629 inline T angle( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00630 {
00631   return angle( a.as_ref(), b.as_ref() );
00632 }
00633 
00634 template<class T, unsigned n>
00635 inline T angle( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector<T>& b )
00636 {
00637   return angle( a.as_ref(), b );
00638 }
00639 
00640 template<class T, unsigned n>
00641 inline T angle( const vnl_vector<T>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00642 {
00643   return angle( a, b.as_ref() );
00644 }
00645 
00646 
00647 template<class T, unsigned n>
00648 inline T vnl_vector_ssd( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00649 {
00650   return vnl_vector_ssd( a.as_ref(), b.as_ref() );
00651 }
00652 
00653 template<class T, unsigned n>
00654 inline T vnl_vector_ssd( const vnl_vector_fixed_ref_const<T,n>& a, const vnl_vector<T>& b )
00655 {
00656   return vnl_vector_ssd( a.as_ref(), b );
00657 }
00658 
00659 template<class T, unsigned n>
00660 inline T vnl_vector_ssd( const vnl_vector<T>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00661 {
00662   return vnl_vector_ssd( a, b.as_ref() );
00663 }
00664 
00665 
00666 // --- I/O operators -------------------------------------------------
00667 
00668 
00669 //: \relatesalso vnl_vector_fixed
00670 template<class T, unsigned int n>
00671 inline
00672 vcl_ostream& operator<<(vcl_ostream& o,const vnl_vector_fixed_ref_const<T,n>& v)
00673 {
00674   v.print(o);
00675   return o;
00676 }
00677 
00678 //: \relatesalso vnl_vector_fixed
00679 template<class T, unsigned int n>
00680 inline
00681 vcl_istream& operator>>(vcl_istream& i, const vnl_vector_fixed_ref<T,n>& v)
00682 {
00683   v.read_ascii(i);
00684   return i;
00685 }
00686 
00687 
00688 #endif // vnl_vector_fixed_ref_h_