ISIS Core Library 0.7.2 (api 3.0.0)
|
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