#line 1 "/user/cvsspst/ees1cg/RAVL/RAVL-0.7/Core/Container/SArray/SArray1d.hh" // This file is part of RAVL, Recognition And Vision Library // Copyright (C) 2001, University of Surrey // This code may be redistributed under the terms of the GNU Lesser // General Public License (LGPL). See the lgpl.licence file for details or // see http://www.gnu.org/copyleft/lesser.html // file-header-ends-here #ifndef RAVL_SARRAY1D_HEADER #define RAVL_SARRAY1D_HEADER //////////////////////////////////////////////////////////////////////////// //! file="Ravl/Core/Container/SArray/SArray1d.hh" //! lib=RavlCore //! author="Radek Marik" //! docentry="Ravl.Core.Arrays.1D" //! date="21/2/1996" //! rcsid="$Id: SArray1d.hh,v 1.16 2002/08/12 15:20:33 craftit Exp $" #include "Ravl/Buffer.hh" #include "Ravl/SBfAcc.hh" #include "Ravl/Pair.hh" #include "Ravl/BfAccIter.hh" #include "Ravl/BfAccIter2.hh" #include "Ravl/BfAccIter3.hh" #include "Ravl/StdHash.hh" #include "Ravl/Stream.hh" namespace RavlN { template class SArray1dIterC; template class Array1dC; template class Slice1dC; template class Slice1dIterC; class BinIStreamC; class BinOStreamC; //! userlevel=Advanced //: A simple 1 dimensional array // The class SArray1dC is a simple reference counted // container with a fixed number of items // which can accessed randomly using indexing. The item is expected // to have a default constructor, a copy constructor, and an assigment. // The class SArray1dC is a big object, eg. it has a reference counter. template class SArray1dC : public SizeBufferAccessC { public: typedef DataT ElementT; //: Allow function templates to find type of array. typedef IndexC KeyT; //: Allow function templates to find type of index. typedef SArray1dIterC IteratorT; //: Type of iterator. //:--------------------------------------- // Constructors, assigment, and destructor SArray1dC(); //: Create an array of zero length SArray1dC(const SizeT dim); //: Creates an uninitialized array with the range <0, 'dim'-1>. SArray1dC(const Slice1dC &slice,bool alwaysCopy = true); //: Make an array from a slice. // This will create an array with the values from the slice. // if the stride of the slice is not 1, and alwaysCopy is true the // a copy is done. SArray1dC(const PairC & pr); //: Creates an array with two elements from a PairC object. SArray1dC(const SArray1dC & vv); //: Another access to the array 'vv'. SArray1dC(DataT * data, const SizeT dim, bool removable = true); //: The array is created from the memory location 'data' with the range //: of access in <0, 'dim'-1>. // If flag 'removable' is false, 'data' is not deallocated during // destructing of the array. SArray1dC(BufferC & bf,SizeT dim,SizeT offsetInBuff = 0); //: Creates the array of size 'dim' using the buffer 'bf'. // Use buffer 'bf', make access of 'dim' elements. // the start of the buffer should be 'offsetInBuff' elements into // the buffer. SArray1dC(const SArray1dC & vv, const SizeT dim,SizeT offsetInBuff = 0); //: The subarray of the 'vv' with size 'dim'. SArray1dC(const BufferC & vv, const SizeBufferAccessC &sbf); //: Construct from a buffer an size buffer access. SArray1dC Copy() const; //: Creates a new physical copy of the array. SArray1dC Copy(UIntT extend) const; //: Creates a new physical copy of the array. // 'extend' extra elements initalised by the default constuctor // are appended to the end of the array. void CopyFrom(const Slice1dC &slice); //: Copy contents of slice into array. // The first element of the slice is copied to element // 0 of this array, second to 1 etc. If this array isn't // large enough an exception is thrown. inline const SArray1dC & operator=(const SArray1dC & vv); //: Assign this handle to the data in VV. SArray1dC operator+(const SArray1dC & arr) const; //: Sums 2 numerical arrays. // The operator returns the result as a new array. SArray1dC operator-(const SArray1dC & arr) const; //: Subtract 2 numerical arrays. // The operator returns the result as a new array. SArray1dC operator*(const SArray1dC & arr) const; //: Mutliplies 2 numerical arrays. // The operator returns the result as a new array. SArray1dC operator/(const SArray1dC & arr) const; //: Divides 2 numerical arrays. // The operator returns the result as a new array. SArray1dC operator*(const DataT &number) const; //: Multiplys the array by the 'number'. // The operator returns the result as a new array. SArray1dC operator/(const DataT &number) const; //: Divides all array items by the 'number'. // The operator returns the result as a new array. SArray1dC operator+(const DataT &number) const; //: Adds 'number' to the array. // The operator returns the result as a new array. SArray1dC operator-(const DataT &number) const; //: Subtracts 'number' from all array items. // The operator returns the result as a new array. const SArray1dC & operator+=(const SArray1dC & arr); //: Adds the 2nd array to this array. const SArray1dC & operator-=(const SArray1dC & arr); //: Subtracts the 2nd array from this array. const SArray1dC & operator*=(const SArray1dC & arr); //: Multiplies the 2nd array to this array. const SArray1dC & operator/=(const SArray1dC & arr); //: Divides the 2nd array from this array. const SArray1dC & operator+=(const DataT &number); //: Adds 'number' to all array items. const SArray1dC & operator-=(const DataT &number); //: Subtracts 'number' from all array items. const SArray1dC & operator*=(const DataT &number); //: Multiplies the array by the 'number'. const SArray1dC & operator/=(const DataT &number); //: Divides the array elements by the 'number'. DataT Sum() const; //: Calculate the sum of all elements in the array DataT SumSqr() const; //: Calculate the sum of the squares of all elements in the array //:----------------------------------- // Access to the object and its parts. inline const SArray1dC & SArray1d() const { return *this; } //: Access to the whole constant array. inline SArray1dC & SArray1d() { return *this; } //: Access to the whole array. Slice1dC Slice1d() { return Slice1dC(buff,DataStart(),Size(),1); } //: Access array as a slice. //:----------------------------------- // Modifications of the representation inline SArray1dC & Append(const SArray1dC & a); // This array is extended by the length of the array 'a' and the contents // of both arrays are copied to it. Empty arrays are handled correctly. SArray1dC Join(const SArray1dC &Oth) const; // Join this Array and another into a new Array which // is returned. This does not change either of its arguments. // This is placed in the array first, followed by 'Oth'. SArray1dC From(UIntT offset) { if(offset >= Size()) return SArray1dC(); // Empty array. SizeT nsize = Size() - offset; return SArray1dC(*this,nsize,offset); } //: Return array from offset to the end of the array. // If offset is larger than the array an empty array // is returned, SArray1dC From(UIntT offset,UIntT size) { if((offset + size) > Size()) return SArray1dC(); // Empty array. return SArray1dC(*this,size,offset); } //: Return array from offset to the end of the array. // If offset is larger than the array an empty array // is returned, SArray1dC After(UIntT offset) { return From(offset+1); } //: Return array after offset to the end of the array. // If offset is larger than the array an empty array // is returned, //:------------------ // Special operations BufferC &Buffer() { return buff; } //: Access base data buffer. // Experts only. const BufferC &Buffer() const { return buff; } //: Constant access base data buffer. // Experts only. void Sort(); //: Sort the array in place. // This does a simple bubble sort. // FIXME:- we could do with something better! bool operator==(const SArray1dC & vv); //: Comparison operator // Returns true if the two arrays are the same length and // their contents are identical. UIntT Hash() const; //: Compute a hash value for the array. inline DataT * DataStart() const { return SizeBufferAccessC::ReferenceElm(); } //: Returns the address of element 0. // If the array has zero length a null pointer may // be returned. protected: SArray1dC(BufferC & bf,DataT *start, const SizeT dim); //: Creates the array of size 'dim' using the buffer 'bf', with //: 0'th element at start. // Used for building SArray's from Arrays. private: BufferC buff; // The reference counted storage. friend class SArray1dIterC; friend class Array1dC; }; template BinOStreamC & operator<<(BinOStreamC & s, const SArray1dC & arr); // Prints array into the stream 's'. template BinIStreamC & operator>>(BinIStreamC& s, SArray1dC & arr); // Assigns the values into the array 'arr'. template SArray1dC & BubbleSort(SArray1dC & arr); // Sorts arr using operator <. template istream & operator>>(istream & s, SArray1dC & arr); // Assigns the values into the array 'arr'. template SArray1dC & BubbleSort(SArray1dC & arr); // Sorts arr using operator <. ///////////////////////////////////////////////////////////////////////////// template inline const SArray1dC & SArray1dC::operator=(const SArray1dC & vv) { if (this == &vv) return *this; SizeBufferAccessC::operator=(vv); buff=vv.buff; return *this; } template inline SArray1dC & SArray1dC::Append(const SArray1dC & a) { (*this) = Join(a); return *this; } template SArray1dC::SArray1dC() : SizeBufferAccessC(), buff() {} template SArray1dC::SArray1dC(const PairC & pr) : SizeBufferAccessC(), buff(2) { Attach(buff,2); (*this)[0] = pr[0]; (*this)[1] = pr[1]; } template SArray1dC::SArray1dC(const Slice1dC &slice,bool alwaysCopy) { if(!alwaysCopy && slice.Stride() == 1) { buff = slice.Buffer(); SizeBufferAccessC::operator=(SizeBufferAccessC(const_cast(&(slice[0])), slice.Size())); return ; } buff = BufferC(slice.Size()); Attach(buff,slice.Size()); // Copy data. DataT *at = buff.ReferenceElm(); for(Slice1dIterC it(slice);it;it++,at++) *at = *it; } template SArray1dC::SArray1dC(const SizeT dim) : SizeBufferAccessC(), buff(dim) { Attach(buff,dim); } template SArray1dC::SArray1dC(const SArray1dC & vv) : SizeBufferAccessC(vv), buff(vv.buff) {} template SArray1dC::SArray1dC(DataT *data, SizeT dim, bool removable) : SizeBufferAccessC(data, dim), buff(dim,data,false, removable) {} template SArray1dC::SArray1dC(BufferC & bf,SizeT dim,SizeT offsetInBuff) : SizeBufferAccessC(bf.BufferAccess() + offsetInBuff, dim), buff(bf) {} template SArray1dC::SArray1dC(BufferC & bf, DataT *start, const SizeT dim) : SizeBufferAccessC(start, dim), buff(bf) {} template SArray1dC::SArray1dC(const BufferC & bf, const SizeBufferAccessC &sbf) : SizeBufferAccessC(sbf), buff(bf) {} template SArray1dC::SArray1dC(const SArray1dC & vv, const SizeT dim, SizeT offsetInBuff) : SizeBufferAccessC(vv.SAccess() + offsetInBuff, dim), buff(vv.buff) { RavlAssert(vv.Size() >= (offsetInBuff + dim)); // Make sure its big enought. } template SArray1dC SArray1dC::Copy() const { return SArray1dC(SizeBufferAccessC::Copy().ReferenceElm(), Size(),true); } template SArray1dC SArray1dC::Copy(UIntT extend) const { SArray1dC ret(Size() + extend); for(BufferAccessIter2C it(*this,ret);it;it++) it.Data2() = it.Data1(); return ret; } template void SArray1dC::CopyFrom(const Slice1dC &slice) { RavlAssert(slice.Size() <= Size()); DataT *at = DataStart(); for(Slice1dIterC it(slice);it;it++,at++) *at = *it; } template SArray1dC SArray1dC::Join(const SArray1dC &Oth) const { // FIXME :- Do this more efficently, with ptrs. const SizeT len1 = Size(); const SizeT len2 = Oth.Size(); SArray1dC newarr(len1 + len2); for(BufferAccessIter2C it(*this,newarr);it;it++) it.Data2() = it.Data1(); for(BufferAccessIter2C it(Oth,newarr,0,len1);it;it++) it.Data2() = it.Data1(); return newarr; } template ostream & operator<<(ostream & s, const SArray1dC & arr) { s << arr.Size() << '\n'; for(BufferAccessIterC it(arr);it;it++) s << ((const DataT &) *it) << '\n'; return s; } template istream & operator>>(istream & s, SArray1dC & arr) { SizeT n = 0; s >> n; if (n != arr.Size()) { SArray1dC brr(n); arr = brr; } for(BufferAccessIterC it(arr);it;it++) s >> *it; return s; } template SArray1dC & BubbleSort(SArray1dC & arr) { IndexC low = 0; IndexC upp = arr.Size()-1; bool change; DataT ev; do { change = false; for (IndexC i = low; i < upp; ++i) { if (arr[i] < arr[i+1]) { ev = arr[i]; arr[i] = arr[i+1]; arr[i+1] = ev; change = true; } } --upp; // at the moment the last item is the smallest one }while(change); return arr; } template BinOStreamC & operator<<(BinOStreamC & s, const SArray1dC & arr) { s << arr.Size(); for(BufferAccessIterC it(arr);it;it++) s << it.Data(); return s; } template BinIStreamC & operator>>(BinIStreamC & s, SArray1dC & arr) { UIntT size; s >> size; arr = SArray1dC(size); for(BufferAccessIterC it(arr);it;it++) s >> it.Data(); return s; } template SArray1dC SArray1dC::operator+(const SArray1dC & arr) const { SArray1dC ret(Size()); for(BufferAccessIter3C it(ret,*this,arr);it;it++) it.Data1() = it.Data2() + it.Data3(); return ret; } template SArray1dC SArray1dC::operator-(const SArray1dC & arr) const { SArray1dC ret(Size()); for(BufferAccessIter3C it(ret,*this,arr);it;it++) it.Data1() = it.Data2() - it.Data3(); return ret; } template SArray1dC SArray1dC::operator*(const SArray1dC & arr) const { SArray1dC ret(Size()); for(BufferAccessIter3C it(ret,*this,arr);it;it++) it.Data1() = it.Data2() * it.Data3(); return ret; } template SArray1dC SArray1dC::operator/(const SArray1dC & arr) const { SArray1dC ret(Size()); for(BufferAccessIter3C it(ret,*this,arr);it;it++) it.Data1() = it.Data2() / it.Data3(); return ret; } template SArray1dC SArray1dC::operator+(const DataT &number) const { SArray1dC ret(Size()); for(BufferAccessIter2C it(ret,*this);it;it++) it.Data1() = it.Data2() + number; return ret; } template SArray1dC SArray1dC::operator-(const DataT &number) const { SArray1dC ret(Size()); for(BufferAccessIter2C it(ret,*this);it;it++) it.Data1() = it.Data2() - number; return ret; } template SArray1dC SArray1dC::operator*(const DataT &number) const { SArray1dC ret(Size()); for(BufferAccessIter2C it(ret,*this);it;it++) it.Data1() = it.Data2() * number; return ret; } template SArray1dC SArray1dC::operator/(const DataT &number) const { SArray1dC ret(Size()); for(BufferAccessIter2C it(ret,*this);it;it++) it.Data1() = it.Data2() / number; return ret; } template const SArray1dC & SArray1dC::operator+=(const SArray1dC & arr) { for(BufferAccessIter2C it(*this,arr);it;it++) it.Data1() += it.Data2(); return *this; } template const SArray1dC & SArray1dC::operator-=(const SArray1dC & arr) { for(BufferAccessIter2C it(*this,arr);it;it++) it.Data1() -= it.Data2(); return *this; } template const SArray1dC & SArray1dC::operator*=(const SArray1dC & arr) { for(BufferAccessIter2C it(*this,arr);it;it++) it.Data1() *= it.Data2(); return *this; } template const SArray1dC & SArray1dC::operator/=(const SArray1dC & arr) { for(BufferAccessIter2C it(*this,arr);it;it++) it.Data1() /= it.Data2(); return *this; } template const SArray1dC & SArray1dC::operator+=(const DataT &number) { for(BufferAccessIterC it(*this);it;it++) it.Data1() += number; return *this; } template const SArray1dC & SArray1dC::operator-=(const DataT &number) { for(BufferAccessIterC it(*this);it;it++) it.Data1() -= number; return *this; } template const SArray1dC & SArray1dC::operator*=(const DataT &number) { for(BufferAccessIterC it(*this);it;it++) it.Data1() *= number; return *this; } template const SArray1dC & SArray1dC::operator/=(const DataT &number) { for(BufferAccessIterC it(*this);it;it++) it.Data1() /= number; return *this; } template DataT SArray1dC::Sum() const { if(Size() == 0) { DataT ret; SetZero(ret); return ret; } BufferAccessIterC it(*this); DataT ret = StdCopy(*it); for(it++;it;it++) ret += *it; return ret; } template DataT SArray1dC::SumSqr() const { if(Size() == 0) { DataT ret; SetZero(ret); return ret; } BufferAccessIterC it(*this); DataT ret = Sqr(*it); for(it++;it;it++) ret += Sqr(*it); return ret; } template void SArray1dC::Sort() { BufferAccessIterC it(*this); if(!it) return ; // Empty, so we're done. DataT *lv; bool changed = true; do { changed = false; it.First(*this); lv = &(*it); it++; for(;it;it++) { if(*lv < *it) { DataT t = *lv; *lv = *it; *it = t; changed = true; } lv = &(*it); } } while(changed) ; return ; } template bool SArray1dC::operator==(const SArray1dC & vv) { if(Size() != vv.Size()) return false; for(BufferAccessIter2C it(*this,vv);it;it++) if(it.Data1() != it.Data2()) return false; return true; } template UIntT SArray1dC::Hash() const { UIntT ret = Size(); for(BufferAccessIterC it(*this);it;it++) ret += StdHash(it.Data()) ^ (ret >> 1) ; return ret; } } #endif