00001 #ifndef __FIBEROPERATIONS_RANGE_HPP
00002 #define __FIBEROPERATIONS_RANGE_HPP
00003
00004 #include <field/MemBase.hpp>
00005 #include <grid/Representation.hpp>
00006 #include "fiberopDllApi.h"
00007
00008 #ifdef USE_OPENMP
00009 #include <omp.h>
00010 #endif
00011
00012 #include <algorithm>
00013
00014 namespace Fiber
00015 {
00016
00020 struct fiberop_API DataRangeBase : public Interface<DataRangeBase>, public MemCore::Ageable
00021 {
00022 struct fiberop_API NoDataRange : std::exception
00023 {
00024 ~NoDataRange() throw ();
00025
00026 override const char*what() const throw();
00027 };
00028
00030 DataRangeBase();
00031
00033 DataRangeBase(const MemCore::Ageable&Age);
00034
00036 virtual ~DataRangeBase() = 0;
00037
00039 virtual void expandRange(const RefPtr<DataRangeBase>&DRB) = 0;
00040 };
00041
00045 template <class Type>
00046 struct fiberop_API DataRange : DataRangeBase
00047 {
00048 Type Minimum, Maximum;
00049
00050 public:
00052 DataRange()
00053 {}
00054
00056 const Type&Min() const
00057 {
00058 return Minimum;
00059 }
00060
00062 const Type&Max() const
00063 {
00064 return Maximum;
00065 }
00066
00068 template <class OtherType>
00069 DataRange(const DataRange<OtherType>&DR)
00070 : Minimum(DR.Min() )
00071 , Maximum(DR.Max() )
00072 {}
00073
00075 template <class OtherType>
00076 void expand(const DataRange<OtherType>&DR)
00077 {
00078 if (Minimum > DR.Min() ) Minimum = DR.Min();
00079 if (Maximum < DR.Max() ) Maximum = DR.Max();
00080 update( DR );
00081 }
00082
00084 override void expandRange(const RefPtr<DataRangeBase>&DRB)
00085 {
00086 if (RefPtr<DataRange<Type> > DR = DRB)
00087 {
00088 expand(*DR);
00089 }
00090 }
00091
00095 template <class CompareType>
00096 bool contains(const CompareType&Value) const
00097 {
00098 if (Value<Minimum) return false;
00099 if (Value>Maximum) return false;
00100 return true;
00101 }
00102
00107 static RefPtr<DataRange> get(CreativeArrayBase&CAB)
00108 {
00109 if (RefPtr<DataRange> DR = interface_cast<DataRange>(CAB) )
00110 {
00111 if ( !DR->isOlderThan( CAB ) )
00112 return DR;
00113 }
00114
00115 return NullPtr();
00116 }
00117
00122 static RefPtr<DataRange> get(Field&F)
00123 {
00124 if (RefPtr<DataRange> DR = interface_cast<DataRange>(F) )
00125 {
00126 if ( !DR->isOlderThan( F ) )
00127 return DR;
00128 }
00129
00130 return NullPtr();
00131 }
00132
00136 static RefPtr<DataRange> compute(CreativeArrayBase&CAB)
00137 {
00138 RefPtr<MemBase> ArrayBase = CAB.create();
00139 RefPtr<TypedArray<Type> > DataArray = ArrayBase;
00140 if (!DataArray)
00141 return NullPtr();
00142
00143 CreativeIterator<Type>*values = DataArray->creativeIterator();
00144 if (!values)
00145 return NullPtr();
00146
00147 if (!*values)
00148 {
00149 return NullPtr();
00150 }
00151 const Iterator<Type>&Data = *values;
00152
00153 index_t count = Data.count();
00154 if (count<1)
00155 return NullPtr();
00156
00157
00158
00159 RefPtr<DataRange> DR = new DataRange();
00160
00161 Type &MinValue = DR->Minimum,
00162 &MaxValue = DR->Maximum;
00163 MinValue = MaxValue = Data[ 0 ];
00164
00165 #ifdef USE_OPENMP
00166
00167
00168 const int max_threads_possible = omp_get_max_threads();
00169
00170
00171 std::vector<Type> minList(max_threads_possible);
00172 std::vector<Type> maxList(max_threads_possible);
00173
00174 std::vector<int> valueFound(max_threads_possible);
00175
00176 for(int i=0; i<max_threads_possible; i++)
00177 {
00178 valueFound[i] = 0;
00179 }
00180
00181
00182 #pragma omp parallel
00183 {
00184 Type localMin = Data[0];
00185 Type localMax = Data[0];
00186
00187
00188 #pragma omp for
00189 for(index_t i = 1; i<count ; i++)
00190 {
00191
00192
00193 const Type&value = Data[i];
00194 if (value < localMin) localMin = value;
00195 if (value > localMax) localMax = value;
00196 }
00197
00198 const int my_thread_id = omp_get_thread_num();
00199
00200 minList[my_thread_id] = localMin;
00201 maxList[my_thread_id] = localMax;
00202
00203 valueFound[my_thread_id] = 1;
00204 }
00205
00206
00207
00208
00209
00210 for( int i=0; i<max_threads_possible; i++)
00211 {
00212 if( valueFound[i] == 1 )
00213 {
00214 if( minList[i] < MinValue ) MinValue = minList[i];
00215 if( maxList[i] > MaxValue ) MaxValue = maxList[i];
00216 }
00217 }
00218 #else
00219
00220 for(index_t i=1; i<count ; i++)
00221 {
00222 const Type&value = Data[i];
00223 if (value < MinValue) MinValue = value;
00224 if (value > MaxValue) MaxValue = value;
00225 }
00226 #endif
00227
00228
00229
00230 CAB.addInterface( DR );
00231 DR->update( CAB );
00232
00233 return DR;
00234 }
00235
00236 static RefPtr<DataRange> retrieve(CreativeArrayBase&CAB)
00237 {
00238 RefPtr<DataRange> DR = get(CAB);
00239 if (DR) return DR;
00240
00241 return compute(CAB);
00242 }
00243 };
00244
00245
00246 template <class Type>
00247 struct FieldRange : Field::Iterator
00248 {
00249 RefPtr<DataRange<Type> > theRange;
00250
00251 override bool apply(const RefPtr<FragmentID>&f, const RefPtr<CreativeArrayBase>&F)
00252 {
00253 if (!F)
00254 return true;
00255
00256 if (RefPtr<DataRange<Type> > FragmentRange = DataRange<Type>::retrieve( *F) )
00257 {
00258 if (!theRange)
00259 theRange = new DataRange<Type>( *FragmentRange );
00260 else
00261 theRange->expand( *FragmentRange );
00262 }
00263
00264 return true;
00265 }
00266
00267 FieldRange(Field&F, const MemCore::WeakPtr<FragmentSelector>&FS = NullPtr() )
00268 {
00269 if (!FS)
00270 {
00271 theRange = DataRange<Type>::get(F);
00272 #if 0
00273 if (!theRange)
00274 puts("FieldRange: No datarange yet");
00275 else
00276 {
00277 printf("FieldRange: Returning old datarange from %ld, Field is %ld (field %p)\n", theRange->time_value(), F.time_value(), &F );
00278 }
00279 #endif
00280 }
00281 if (!theRange)
00282 {
00283 F.iterate( *this, FS );
00284
00285 if (theRange && !FS)
00286 {
00287 F.addInterface( theRange );
00288 theRange->update( F );
00289
00290 }
00291 }
00292 }
00293 };
00294
00295 extern fiberop_API template struct DataRange<float>;
00296 extern fiberop_API template struct DataRange<double>;
00297
00298 extern fiberop_API template struct FieldRange<float>;
00299 extern fiberop_API template struct FieldRange<double>;
00300
00301 template <class Type>
00302 inline fiberop_API
00303 bool Contains(CreativeArrayBase&CAB, const Type&Value, bool ComputeEventually)
00304 {
00305 if (ComputeEventually)
00306 {
00307 if (RefPtr<DataRange<Type> > DR = DataRange<Type>::retrieve(CAB) )
00308 {
00309 return DR->contains( Value );
00310 }
00311 }
00312 else
00313 {
00314 if (RefPtr<DataRange<Type> > DR = DataRange<Type>::get(CAB) )
00315 {
00316 return DR->contains( Value );
00317 }
00318 }
00319 throw DataRangeBase::NoDataRange();
00320 }
00321
00328 extern fiberop_API RefPtr<DataRangeBase> getRange(Field&);
00329
00330
00331 }
00332
00333
00334 #endif // __FIBEROPERATIONS_RANGE_HPP
00335
00336