ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/DataStorage/valuearray.hpp

Go to the documentation of this file.
00001 /*
00002     <one line to give the program's name and a brief idea of what it does.>
00003     Copyright (C) <year>  <name of author>
00004 
00005     This program is free software: you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation, either version 3 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 */
00019 
00020 #ifndef TYPEPTR_HPP
00021 #define TYPEPTR_HPP
00022 
00023 #include <boost/static_assert.hpp>
00024 
00025 #include "valuearray_base.hpp"
00026 #include "valuearray_converter.hpp"
00027 #include "../CoreUtils/value.hpp"
00028 #include "common.hpp"
00029 #include <boost/type_traits/remove_const.hpp>
00030 #include "endianess.hpp"
00031 
00032 namespace isis
00033 {
00034 namespace data
00035 {
00036 
00037 namespace _internal
00038 {
00040 template<typename T, uint8_t STEPSIZE> std::pair<T, T> calcMinMax( const T *data, size_t len )
00041 {
00042     BOOST_STATIC_ASSERT( std::numeric_limits<T>::has_denorm != std::denorm_indeterminate ); //well we're pretty f**ed in this case
00043     std::pair<T, T> result(
00044         std::numeric_limits<T>::max(),
00045         std::numeric_limits<T>::has_denorm ? -std::numeric_limits<T>::max() : std::numeric_limits<T>::min() //for types with denormalization min is _not_ the lowest value
00046     );
00047     LOG( Runtime, verbose_info ) << "using generic min/max computation for " << util::Value<T>::staticName();
00048 
00049     for ( const T *i = data; i < data + len; i += STEPSIZE ) {
00050         if(
00051             std::numeric_limits<T>::has_infinity &&
00052             ( *i == std::numeric_limits<T>::infinity() || *i == -std::numeric_limits<T>::infinity() )
00053         )
00054             continue; // skip this one if its inf
00055 
00056         if ( *i > result.second )result.second = *i; //*i is the new max if its bigger than the current (gets rid of nan as well)
00057 
00058         if ( *i < result.first )result.first = *i; //*i is the new min if its smaller than the current (gets rid of nan as well)
00059     }
00060 
00061     return result;
00062 }
00063 
00064 #ifdef __SSE2__
00065 
00066 // specialize calcMinMax for (u)int(8,16,32)_t /
00068 
00069 template<> std::pair< uint8_t,  uint8_t> calcMinMax< uint8_t, 1>( const  uint8_t *data, size_t len );
00070 template<> std::pair<uint16_t, uint16_t> calcMinMax<uint16_t, 1>( const uint16_t *data, size_t len );
00071 template<> std::pair<uint32_t, uint32_t> calcMinMax<uint32_t, 1>( const uint32_t *data, size_t len );
00072 
00073 template<> std::pair< int8_t,  int8_t> calcMinMax< int8_t, 1>( const  int8_t *data, size_t len );
00074 template<> std::pair<int16_t, int16_t> calcMinMax<int16_t, 1>( const int16_t *data, size_t len );
00075 template<> std::pair<int32_t, int32_t> calcMinMax<int32_t, 1>( const int32_t *data, size_t len );
00076 #endif //__SSE2__
00077 
00078 API_EXCLUDE_BEGIN
00079 template<typename T, bool isNumber> struct getMinMaxImpl { // fallback for unsupported types
00080     std::pair<T, T> operator()( const ValueArray<T> &/*ref*/ ) const {
00081         LOG( Debug, error ) << "min/max computation of " << util::Value<T>::staticName() << " is not supported";
00082         return std::pair<T, T>();
00083     }
00084 };
00085 
00086 template<typename T> struct getMinMaxImpl<T, true> { // generic min-max for numbers (this _must_ not be run on empty ValueArray)
00087     std::pair<T, T> operator()( const ValueArray<T> &ref ) const {
00088         return calcMinMax<T, 1>( &ref[0], ref.getLength() );
00089     }
00090 };
00091 
00092 template<typename T> struct getMinMaxImpl<util::color<T>, false> { // generic min-max for color (get bounding box in color space)
00093     std::pair<util::color<T> , util::color<T> > operator()( const ValueArray<util::color<T> > &ref ) const {
00094         std::pair<util::color<T> , util::color<T> > ret;
00095 
00096         for( uint_fast8_t i = 0; i < 3; i++ ) {
00097             const std::pair<T, T> buff = calcMinMax<T, 3>( &ref[0].r + i, ref.getLength() * 3 );
00098             *( &ret.first.r + i ) = buff.first;
00099             *( &ret.second.r + i ) = buff.second;
00100         }
00101 
00102         return ret;
00103     }
00104 };
00105 template<typename T> struct getMinMaxImpl<std::complex<T>, false> { // generic min-max for complex values (get bounding box in complex space)
00106     std::pair<std::complex<T> , std::complex<T> > operator()( const ValueArray<std::complex<T> > &ref ) const {
00107         BOOST_STATIC_ASSERT( sizeof( std::complex<T> ) == sizeof( T ) * 2 ); // we need this for the calcMinMax-hack below
00108         const std::pair<T, T > real = calcMinMax<T, 2>( &ref[0].real(), ref.getLength() * 2 );
00109         const std::pair<T, T > imag = calcMinMax<T, 2>( &ref[0].imag(), ref.getLength() * 2 );
00110 
00111         return std::make_pair( std::complex<T>( real.first, imag.first ), std::complex<T>( real.second, imag.second ) );
00112     }
00113 };
00115 API_EXCLUDE_END
00116 
00122 template<typename TYPE> class ValueArrayIterator: public std::iterator<std::random_access_iterator_tag, TYPE>
00123 {
00124     TYPE *p;
00125     typedef typename std::iterator<std::random_access_iterator_tag, TYPE>::difference_type distance;
00126     friend class ValueArrayIterator<const TYPE>;
00127 public:
00128     ValueArrayIterator(): p( NULL ) {}
00129     ValueArrayIterator( TYPE *_p ): p( _p ) {}
00130     ValueArrayIterator( const ValueArrayIterator<typename boost::remove_const<TYPE>::type > &src ): p( src.p ) {}
00131 
00132     ValueArrayIterator<TYPE>& operator++() {++p; return *this;}
00133     ValueArrayIterator<TYPE>& operator--() {--p; return *this;}
00134 
00135     ValueArrayIterator<TYPE>  operator++( int ) {ValueArrayIterator<TYPE> tmp = *this; ++*this; return tmp;}
00136     ValueArrayIterator<TYPE>  operator--( int ) {ValueArrayIterator<TYPE> tmp = *this; --*this; return tmp;}
00137 
00138     TYPE &operator*() const { return *p; }
00139     TYPE *operator->() const { return p; }
00140 
00141     bool operator==( const ValueArrayIterator<TYPE> &cmp )const {return p == cmp.p;}
00142     bool operator!=( const ValueArrayIterator<TYPE> &cmp )const {return !( *this == cmp );}
00143 
00144     bool operator>( const ValueArrayIterator<TYPE> &cmp )const {return p > cmp.p;}
00145     bool operator<( const ValueArrayIterator<TYPE> &cmp )const {return p < cmp.p;}
00146 
00147     bool operator>=( const ValueArrayIterator<TYPE> &cmp )const {return p >= cmp.p;}
00148     bool operator<=( const ValueArrayIterator<TYPE> &cmp )const {return p <= cmp.p;}
00149 
00150     ValueArrayIterator<TYPE> operator+( distance n )const {return ValueArrayIterator<TYPE>( p + n );}
00151     ValueArrayIterator<TYPE> operator-( distance n )const {return ValueArrayIterator<TYPE>( p - n );}
00152 
00153     distance operator-( const ValueArrayIterator<TYPE> &cmp )const {return p - cmp.p;}
00154 
00155     ValueArrayIterator<TYPE> &operator+=( distance n ) {p += n; return *this;}
00156     ValueArrayIterator<TYPE> &operator-=( distance n ) {p -= n; return *this;}
00157 
00158     TYPE &operator[]( distance n )const {return *( p + n );}
00159 };
00160 
00161 }
00162 
00171 template<typename TYPE> class ValueArray: public ValueArrayBase
00172 {
00173     boost::shared_ptr<TYPE> m_val;
00174     static const util::ValueReference getValueFrom( const void *p ) {
00175         return util::Value<TYPE>( *reinterpret_cast<const TYPE *>( p ) );
00176     }
00177     static void setValueInto( void *p, const util::ValueBase &val ) {
00178         *reinterpret_cast<TYPE *>( p ) = val.as<TYPE>();
00179     }
00180 protected:
00181     ValueArray() {} // should only be used by child classed who initialize the pointer them self
00182     ValueArrayBase *clone() const {
00183         return new ValueArray( *this );
00184     }
00185 public:
00186     typedef _internal::ValueArrayIterator<TYPE> iterator;
00187     typedef _internal::ValueArrayIterator<const TYPE> const_iterator;
00188     typedef typename iterator::reference reference;
00189     typedef typename const_iterator::reference const_reference;
00190 
00191     static const unsigned short staticID = util::_internal::TypeID<TYPE>::value << 8;
00193     struct NonDeleter {
00194         void operator()( TYPE *p ) {
00195             //we have to cast the pointer to void* here, because in case of uint8_t it will try to print the "string"
00196             LOG( Debug, info ) << "Not freeing pointer " << ( void * )p << " (" << ValueArray<TYPE>::staticName() << ") ";
00197         };
00198     };
00200     struct BasicDeleter {
00201         void operator()( TYPE *p ) {
00202             //we have to cast the pointer to void* here, because in case of uint8_t it will try to print the "string"
00203             LOG( Debug, verbose_info ) << "Freeing pointer " << ( void * )p << " (" << ValueArray<TYPE>::staticName() << ") ";
00204             free( p );
00205         };
00206     };
00213     ValueArray( size_t length ): ValueArrayBase( length ) {
00214         if( length )
00215             m_val.reset( ( TYPE * )calloc( length, sizeof( TYPE ) ), BasicDeleter() );
00216 
00217         LOG_IF( length == 0, Debug, warning )
00218                 << "Creating an empty ValueArray of type " << util::MSubject( staticName() )
00219                 << " you should overwrite it with a useful pointer before using it";
00220     }
00221 
00229     ValueArray( const boost::shared_ptr<TYPE> &ptr, size_t length ): ValueArrayBase( length ), m_val( ptr ) {}
00230 
00238     ValueArray( TYPE *const ptr, size_t length ): ValueArrayBase( length ), m_val( ptr, BasicDeleter() ) {}
00239 
00250     template<typename D> ValueArray( TYPE *const ptr, size_t length, D d ): ValueArrayBase( length ), m_val( ptr, d ) {}
00251 
00252     virtual ~ValueArray() {}
00253 
00254     boost::shared_ptr<const void> getRawAddress( size_t offset = 0 )const {
00255         if( offset ) {
00256             DelProxy proxy( *this );
00257             const uint8_t *const b_ptr = reinterpret_cast<const uint8_t *>( m_val.get() ) + offset;
00258             return boost::shared_ptr<const void>( b_ptr, proxy );
00259         } else
00260             return boost::static_pointer_cast<const void>( m_val );
00261     }
00262     boost::shared_ptr<void> getRawAddress( size_t offset = 0 ) { // use the const version and cast away the const
00263         return boost::const_pointer_cast<void>( const_cast<const ValueArray *>( this )->getRawAddress( offset ) );
00264     }
00265     virtual value_iterator beginGeneric() {
00266         return value_iterator( ( uint8_t * )m_val.get(), ( uint8_t * )m_val.get(), bytesPerElem(), getValueFrom, setValueInto );
00267     }
00268     virtual const_value_iterator beginGeneric()const {
00269         return const_value_iterator( ( uint8_t * )m_val.get(), ( uint8_t * )m_val.get(), bytesPerElem(), getValueFrom, setValueInto );
00270     }
00271 
00272     iterator begin() {return iterator( m_val.get() );}
00273     iterator end() {return begin() + m_len;};
00274     const_iterator begin()const {return const_iterator( m_val.get() );}
00275     const_iterator end()const {return begin() + m_len;}
00276 
00278     virtual std::string toString( bool labeled = false )const {
00279         std::string ret;
00280 
00281         if ( m_len ) {
00282             // if you get trouble with to_tm here include <boost/date_time/gregorian/gregorian.hpp> or <boost/date_time/posix_time/posix_time.hpp> in your cpp
00283             for ( const_iterator i = begin(); i < end() - 1; i++ )
00284                 ret += util::Value<TYPE>( *i ).toString( false ) + "|";
00285 
00286 
00287             ret += util::Value<TYPE>( *( end() - 1 ) ).toString( labeled );
00288         }
00289 
00290         return boost::lexical_cast<std::string>( m_len ) + "#" + ret;
00291     }
00292 
00293     std::string getTypeName()const {return staticName();}
00294     unsigned short getTypeID()const {return staticID;}
00295     bool isFloat() const {return boost::is_float< TYPE >::value;}
00296     bool isInteger() const {return boost::is_integral< TYPE >::value;}
00297 
00299     static std::string staticName() {
00300         return std::string( util::Value<TYPE>::staticName() ) + "*";
00301     }
00302 
00308     TYPE &operator[]( size_t idx ) {
00309         return begin()[idx];
00310     }
00311     const TYPE &operator[]( size_t idx )const {
00312         return begin()[idx];
00313     }
00320     operator boost::shared_ptr<TYPE>&() {return m_val;}
00321     operator const boost::shared_ptr<TYPE>&()const {return m_val;}
00322 
00323     size_t bytesPerElem()const {return sizeof( TYPE );}
00324 
00325     std::pair<util::ValueReference, util::ValueReference> getMinMax()const {
00326         if ( getLength() == 0 ) {
00327             LOG( Debug, error ) << "Skipping computation of min/max on an empty ValueArray";
00328             return std::pair<util::ValueReference, util::ValueReference>();
00329         } else {
00330 
00331             const std::pair<util::Value<TYPE>, util::Value<TYPE> > result = _internal::getMinMaxImpl<TYPE, boost::is_arithmetic<TYPE>::value>()( *this );
00332 
00333             return std::make_pair( util::ValueReference( result.first ), util::ValueReference( result.second ) );
00334         }
00335     }
00336 
00337     std::vector<Reference> splice( size_t size )const {
00338         if ( size >= getLength() ) {
00339             LOG( Debug, warning )
00340                     << "splicing data of the size " << getLength() << " up into blocks of the size " << size << " is kind of useless ...";
00341         }
00342 
00343         const size_t fullSplices = getLength() / size;
00344 
00345         const size_t lastSize = getLength() % size;//rest of the division - size of the last splice
00346 
00347         const size_t splices = fullSplices + ( lastSize ? 1 : 0 );
00348 
00349         std::vector<Reference> ret( splices );
00350 
00351         DelProxy proxy( *this );
00352 
00353         for ( size_t i = 0; i < fullSplices; i++ )
00354             ret[i].reset( new ValueArray( m_val.get() + i * size, size, proxy ) );
00355 
00356         if ( lastSize )
00357             ret.back().reset( new ValueArray( m_val.get() + fullSplices * size, lastSize, proxy ) );
00358 
00359         return ret;
00360     }
00361     //
00362     scaling_pair getScalingTo( unsigned short typeID, autoscaleOption scaleopt = autoscale )const {
00363         if( typeID == staticID && scaleopt == autoscale ) { // if id is the same and autoscale is requested
00364             static const util::Value<uint8_t> one( 1 );
00365             static const util::Value<uint8_t> zero( 0 );
00366             return std::pair<util::ValueReference, util::ValueReference>( one, zero ); // the result is always 1/0
00367         } else { // get min/max and compute the scaling
00368             std::pair<util::ValueReference, util::ValueReference> minmax = getMinMax();
00369             assert( ! ( minmax.first.isEmpty() || minmax.second.isEmpty() ) );
00370             return ValueArrayBase::getScalingTo( typeID, minmax, scaleopt );
00371         }
00372     }
00373     void endianSwap(){
00374         data::endianSwapArray(begin(),end(),begin());
00375     }
00376 };
00378 // specialisation for complex - there shall be no scaling - and we cannot compute minmax
00379 template<> scaling_pair ValueArray<std::complex<float> >::getScalingTo( unsigned short /*typeID*/, autoscaleOption /*scaleopt*/ )const;
00380 template<> scaling_pair ValueArray<std::complex<double> >::getScalingTo( unsigned short /*typeID*/, autoscaleOption /*scaleopt*/ )const;
00382 template<typename T> bool ValueArrayBase::is()const
00383 {
00384     util::checkType<T>();
00385     return getTypeID() == ValueArray<T>::staticID;
00386 }
00387 
00388 
00389 }
00390 }
00391 #endif // TYPEPTR_HPP