//------------------------------------------------------------------------------ // Main data class -- // (C) Piero Giubilato 2008-2010, Berkeley Lab -- //------------------------------------------------------------------------------ //______________________________________________________________________________ // {Trace} // [File name] "data_Layer.cpp" // [Author] "Piero Giubilato" // [Version] "1.0" // [Modified by] "Piero Giubilato" // [Last revision] "17 Feb 2009" // [Language] "C++" // [Compiler] "Visual C++ 9.x" // [Member of] "Cool SEAL" // [Project] "SEAL" // [Description] "Main data class" // [Key documentation] // "Root user's guide" // "Visual C++ Reference Help" // {Trace} //______________________________________________________________________________ // Overloading check #ifndef data_Layer_C #define data_Layer_C // Standard components #include // Application components #include "data_Layer.h" // ***************************************************************************** // **** SPECIAL MEMBERS **** // ***************************************************************************** //______________________________________________________________________________ template data_Layer::data_Layer(): data_Object(), dp_Array(0), dp_array_col_Count(0), dp_array_row_Count(0) { // Provides the base class for raw data storage. // A layer can handle a 2D, 1D or 0D array of data of any arbitrary type. // Data addressing is implemented both via col, row indexes and via global // Idx indexing. // A layer object is a complete data type, i.e. it provides complete copy // constructor and assign operator; both defined for same type or type // casting operations. // // WARNING: this class provides also low-level data access methods (bare // pointers) to save memory space and access time: this implies that memory // corruption errors may arise if the access is not correctly implemented! // Debug dbg_Print("data_Layer::data_Layer:()", DBG_LVL_ZERO); // Data preset with no parameters (1 data point) data_Resize(1, 1); } //______________________________________________________________________________ template data_Layer::data_Layer(UInt_t col_Count, UInt_t row_Count): data_Object(), dp_Array(0), dp_array_col_Count(0), dp_array_row_Count(0) { // Constructor with assigned number of cols and rows dbg_Print("data_Layer::data_Layer:(col, row)", DBG_LVL_ZERO); // Sizes the data array (set col and rows) data_Resize(col_Count, row_Count); } //______________________________________________________________________________ template data_Layer::data_Layer(const data_Layer& layer_Ref): data_Object(), dp_Array(0), dp_array_col_Count(0), dp_array_row_Count(0) { // Default copy construnctor (to avoid compiler override) dbg_Print("data_Layer::data_Layer:(data_layer&)", DBG_LVL_ZERO); // Sizes the data array (set col and rows) data_Copy(layer_Ref); } //______________________________________________________________________________ template template data_Layer::data_Layer(const data_Layer& ref): data_Object(), dp_Array(0), dp_array_col_Count(0), dp_array_row_Count(0) { // Casting copy constructor dbg_Print("data_Layer::data_Layer:(U&)", DBG_LVL_ZERO); // Sizes the data array (set col and rows) data_Copy(ref); } //______________________________________________________________________________ template data_Layer::~data_Layer () { // Standard destructor dbg_Print("data_Layer::~data_Layer:()", DBG_LVL_ZERO); // Decreases the global memory allocation counter data_Object::stc_data_size_Del(dp_Size()); // Frees all allocated memory delete []dp_Array; } // ***************************************************************************** // **** PRIVATE OBJECT ACCESS **** // ***************************************************************************** //______________________________________________________________________________ template void data_Layer::data_Resize(UInt_t col_Count, UInt_t row_Count) { // Sets the size of the data container (dp_Array) accordingly to the given size. dbg_Print("data_Layer::data_Resize:(UInt, UInt)", DBG_LVL_STEP); // Decreases the global memory allocation counter data_Object::stc_data_size_Del(sizeof(T) * dp_array_col_Count * dp_array_row_Count); // Check if (col_Count == 0) col_Count = 1; if (row_Count == 0) row_Count = 1; // Clears present mem locations if (dp_Array) delete []dp_Array; // Allocates the new array if (!(dp_Array = new T[col_Count * row_Count])) throw DBG_WHERE; // Increases the global memory allocation counter data_Object::stc_data_size_Add(sizeof(T) * col_Count * row_Count); // Stores the new dimensions dp_array_col_Count = col_Count; dp_array_row_Count = row_Count; } //______________________________________________________________________________ template template void data_Layer::data_Copy(const data_Layer& Source) { // Copies the data from 'Source', casting them. Does not copy anything // if the source is the same as the target. dbg_Print("data_Layer::data_Copy:(data_Layer&)", DBG_LVL_STEP); // Self copy check if (this == (data_Layer*)&Source) return; // Parent copy data_Object::operator=(Source); // Resizes the dp_Array only if necessary if((dp_Array == 0) || (Source.dp_col_Count() != dp_col_Count()) || (Source.dp_row_Count() != dp_row_Count())) data_Resize(Source.dp_col_Count(), Source.dp_row_Count()); // Deep and fast copy T* tF = this->dp_Front(); U* sF = Source.dp_Front(); UInt_t iCnt = Source.dp_Count(); for (UInt_t i = 0; i < iCnt; i++) tF[i] = (T)sF[i]; } //______________________________________________________________________________ template template void data_Layer::data_Math(const U& Source, UInt_t Operation) { // Performs the operation specified by 'Operation' by applying Scalar to // '*this', accordingly to Operation and applying cast. dbg_Print("data_Layer::data_Math:(U&, UInt)", DBG_LVL_STEP); // Checks for division by zero, in case returns a 0 filled layer if (Operation == km_Div && Source == 0) return; // Creates a target object for new assignement T* tF = this->dp_Front(); UInt_t iCnt = dp_Count(); // Performs the scalar algebra switch(Operation) { case km_Set: for (UInt_t i = 0; i < iCnt; i++) tF[i] = (T)Source; break; case km_Add: for (UInt_t i = 0; i < iCnt; i++) tF[i] += (T)Source; break; case km_Sub: for (UInt_t i = 0; i < iCnt; i++) tF[i] -= (T)Source; break; case km_Mul: for (UInt_t i = 0; i < iCnt; i++) tF[i] *= (T)Source; break; case km_Div: for (UInt_t i = 0; i < iCnt; i++) tF[i] /= (T)Source; break; case km_Sqr: for (UInt_t i = 0; i < iCnt; i++) tF[i] = (T)sqrt((double)tF[i]); break; case km_Pow: for (UInt_t i = 0; i < iCnt; i++) tF[i] = (T)pow((double)tF[i], (int)Source); break; case km_Mir: for (UInt_t i = 0; i < iCnt; i++) tF[i] = (T)(Source - tF[i]); break; } } //______________________________________________________________________________ template template void data_Layer::data_Math(const data_Layer& Source, UInt_t Operation) { // Performs the operation specified by 'Operation' value between 'Source' and // '*this', applying cast. If the dimensions do not match, only the overlapping // part of '*this' will be affected by the manipulation, while the remaining // will retain the same value it had before. dbg_Print("data_Layer::data_Math:(data_Layer&, UInt)", DBG_LVL_STEP); // Determines the overlap Region boundaries UInt_t cCnt; UInt_t rCnt; UInt_t tcCnt = dp_array_col_Count; UInt_t trCnt = dp_array_row_Count; UInt_t scCnt = Source.dp_col_Count(); UInt_t srCnt = Source.dp_row_Count(); (tcCnt <= scCnt) ? cCnt = tcCnt : cCnt = scCnt; (trCnt <= srCnt) ? rCnt = trCnt : rCnt = srCnt; // Gets the arrays fronts T* tF = this->dp_Front(); U* sF = Source.dp_Front(); UInt_t iCnt = dp_Count(); // If dimensions do not match, goes for an overlap area algebra if((scCnt != tcCnt) || (srCnt != trCnt)) { switch(Operation) { case km_Add: for (UInt_t col = 0; col < cCnt; col++) for (UInt_t row = 0; row < rCnt; row++) tF[row * tcCnt + col] += (T)sF[row * scCnt + col]; break; case km_Sub: for (UInt_t col = 0; col < cCnt; col++) for (UInt_t row = 0; row < rCnt; row++) tF[row * tcCnt + col] -= (T)sF[row * scCnt + col]; break; case km_Mul: for (UInt_t col = 0; col < cCnt; col++) for (UInt_t row = 0; row < rCnt; row++) tF[row * tcCnt + col] *= (T)sF[row * scCnt + col]; break; case km_Div: for (UInt_t col = 0; col < cCnt; col++) for (UInt_t row = 0; row < rCnt; row++) tF[row * tcCnt + col] /= (T)sF[row * scCnt + col]; break; } // Otherwise, uses a faster linear matching } else { switch(Operation) { case km_Add: for (UInt_t i = 0; i < iCnt; i++) tF[i] += (T)sF[i]; break; case km_Sub: for (UInt_t i = 0; i < iCnt; i++) tF[i] -= (T)sF[i]; break; case km_Mul: for (UInt_t i = 0; i < iCnt; i++) tF[i] *= (T)sF[i]; break; case km_Div: for (UInt_t i = 0; i < iCnt; i++) tF[i] /= (T)sF[i]; break; } } } //______________________________________________________________________________ template void data_Layer::dp_all_Stat(Double_t& avg, Double_t& sgm) const { // Performs basic stat calculations dbg_Print("data_Layer::dp_all_Stat:()", DBG_LVL_FLOW); // Returns the minimum value present into the array UInt_t i_Count = dp_Count(); //T min = dp_Array[0]; //T max = dp_Array[0]; Double_t sum = (Double_t)dp_Array[0]; Double_t sum2 = pow((Double_t)dp_Array[0], 2); avg = (Double_t)dp_Array[0]; for (UInt_t i = 1; i < i_Count; i++) { //if (dp_Array[i] < min) min = dp_Array[i]; //if (dp_Array[i] > max) max = dp_Array[i]; avg += (Double_t)dp_Array[i]; sum += (Double_t)dp_Array[i]; sum2 += pow((Double_t)dp_Array[i], 2); } // Calculates results avg /= i_Count; sgm = sqrt(pow(sum, 2) + (sum2 /= I_Count)); } //______________________________________________________________________________ template void data_Layer::dp_all_Limits(T& min, T& max) const { // Gets the max e min values inside the layer dbg_Print("data_Layer::dp_all_Limit:()", DBG_LVL_FLOW); // Returns the minimum value present into the array min = dp_Array[0]; max = dp_Array[0]; // Find the min, max UInt_t i_Count = dp_Count(); for (UInt_t i = 1; i < i_Count; i++) { if (dp_Array[i] < min) min = dp_Array[i]; if (dp_Array[i] > max) max = dp_Array[i]; } } //______________________________________________________________________________ template UInt_t data_Layer::obj_Type() const { // Returns the object type (the class type itself) return data_Object::kot_Layer; } //______________________________________________________________________________ template UInt_t data_Layer::data_Type() const { // Returns the data type (the object storage data type) dbg_Print("data_Layer::data_Type:()", DBG_LVL_STEP); // Try matching if(typeid(T) == typeid(UShort_t)) return data_Object::kdt_UShort; if(typeid(T) == typeid(Short_t)) return data_Object::kdt_Short; if(typeid(T) == typeid(UInt_t)) return data_Object::kdt_UInt; if(typeid(T) == typeid(Int_t)) return data_Object::kdt_Int; if(typeid(T) == typeid(Float_t)) return data_Object::kdt_Float; if(typeid(T) == typeid(Double_t)) return data_Object::kdt_Double; // Do we really need those? //if(typeid(T) == typeid(unsigned short)) return data_Object::kdt_Short; //if(typeid(T) == typeid(short)) return data_Object::kdt_Short; //if(typeid(T) == typeid(int)) return data_Object::kdt_Int; //if(typeid(T) == typeid(float)) return data_Object::kdt_Int; //if(typeid(T) == typeid(double)) return data_Object::kdt_Double; // No matching data, returns null return data_Object::kdt_Null; } // ***************************************************************************** // **** SIZE SET/READ **** // ***************************************************************************** //______________________________________________________________________________ template inline UInt_t data_Layer::dp_col_Count() const { // Returns the number of columns of px_Array. return dp_array_col_Count; } //______________________________________________________________________________ template UInt_t data_Layer::dp_col_Count(UInt_t col_Count) { // Sets the number of columns of dp_Array. Attention: this will // RESET the dp_Array! Returns the new number of columns, 0 on error. dbg_Print("data_Layer::dp_col_Count:(UInt)", DBG_LVL_STEP); // Check if (col_Count == 0) return dp_array_col_Count; // Resizes data_Resize(col_Count, dp_array_row_Count); // Return col number return dp_array_col_Count; } //______________________________________________________________________________ template inline UInt_t data_Layer::dp_row_Count() const { // Returns the number of rows of px_Array. return dp_array_row_Count; } //______________________________________________________________________________ template UInt_t data_Layer::dp_row_Count(UInt_t row_Count) { // Sets the number of rows and rows of dp_Array. Attention: this will // RESET the dp_Array! Returns the new number of rows, 0 on error. dbg_Print("data_Layer::dp_row_Count:(UInt)", DBG_LVL_STEP); // Check if (row_Count == 0) return dp_array_row_Count; // Resizes data_Resize(dp_array_col_Count, row_Count); // Return row number return dp_array_row_Count; } //______________________________________________________________________________ template inline UInt_t data_Layer::dp_Count() const { // Returns the current number of pixels stored. return dp_array_col_Count * dp_array_row_Count; } //______________________________________________________________________________ template UInt_t data_Layer::dp_Count(UInt_t Count) { // Sets the number of data point assuming a 1-dim array (1 row). This will // RESET the dp_Array! Returns the new number of data points, 0 on error. dbg_Print("data_Layer::dp_Count:(UInt)", DBG_LVL_STEP); // Checks if (Count == 0) return dp_Count(); // Resizes data_Resize(Count, 1); // Returns back the actual dp_Count return dp_Count(); } //______________________________________________________________________________ template UInt_t data_Layer::dp_Count(UInt_t col_Count, UInt_t row_Count) { // Sets the number of columns and rows of dp_Array. Attention: this will // RESET the dp_Array! Returns the new number of data points, 0 on error. dbg_Print("data_Layer::dp_Count:(UInt, UInt)", DBG_LVL_STEP); // Checks if (col_Count == 0) return dp_Count(); if (row_Count == 0) return dp_Count(); // Resizes dp_Array data_Resize(col_Count, row_Count); // All OK return dp_Count(); } // ***************************************************************************** // **** DATA ACCESS **** // ***************************************************************************** //______________________________________________________________________________ template inline UInt_t data_Layer::dp_Idx(UInt_t Col, UInt_t Row) const { // Returns the indexed (Idx) address of a data point from its // column and row address return Row * dp_array_col_Count + Col; } //______________________________________________________________________________ template inline UInt_t data_Layer::dp_Col(UInt_t Idx) const { // Returns the column address of a data point from its index return (Idx % dp_array_col_Count); } //______________________________________________________________________________ template inline UInt_t data_Layer::dp_Row(UInt_t Idx) const { // Returns the row address of a data point from its index return ((Idx - (Idx % dp_array_col_Count)) / dp_array_col_Count); } //______________________________________________________________________________ template inline T data_Layer::dp_Value(UInt_t Idx) const { // Retrives the value of a data point at a given position, safe access // method. By using the direct memory access through the dp_Front // reference value will give a 3 times faster data access. // Checks for out of bounds if (Idx >= dp_Count()) Idx = 0; // Returns the value return dp_Array[Idx]; } //______________________________________________________________________________ template inline T& data_Layer::dp_Value(UInt_t Idx) { // Checks for out of bounds if (Idx >= dp_Count()) Idx = 0; // Returns the value return dp_Array[Idx]; } //______________________________________________________________________________ template inline T data_Layer::dp_Value(UInt_t Col, UInt_t Row) const { // Retrives the value of a data point at a given position, safe access // method. By using the direct memory access through the dp_Front // reference value will give a 4.5 times faster data access, at the price // of no safety check and col/row addressing. // Check for out of bounds if (Col >= dp_array_col_Count) Col = 0; if (Row >= dp_array_row_Count) Row = 0; // Returns the value return dp_Array[Row * dp_array_col_Count + Col]; } //______________________________________________________________________________ template inline T& data_Layer::dp_Value(UInt_t Col, UInt_t Row) { // Check for out of bounds if (Col >= dp_array_col_Count) Col = 0; if (Row >= dp_array_row_Count) Row = 0; // Returns the value return dp_Array[Row * dp_array_col_Count + Col]; } //______________________________________________________________________________ template data_Layer& data_Layer::dp_all_Range(T value_Start, T value_Step) { // Sets all the dp starting from 'value_Start' and increasing by // 'value_Step' at each point. UInt_t i_Count = dp_Count(); for (UInt_t i = 0; i < i_Count; i++) { dp_Array[i] = value_Start; value_Start += value_Step; } // Returns itself return *this; } //______________________________________________________________________________ template inline T* data_Layer::dp_Front() const { // Returns the address of dp_Array. return dp_Array; } //______________________________________________________________________________ template size_t data_Layer::dp_Size() const { // Returns the current size of dp_Array (bytes). return dp_Count() * sizeof(T); } // ***************************************************************************** // **** ROOT OVERLOADS **** // ***************************************************************************** //______________________________________________________________________________ template void data_Layer::Dump(UInt_t level) const { // Dumps all the object data into std::out TString space(' ', level); // Shows the header std::cout << space.Data() << "*data_Layer: " << (int*)this << "\n"; std::cout << space.Data() << "class_Ver: " << class_Ver << "\n"; // Show the parent object data_Object::Dump(level + 2); // Shows and the data members std::cout << space.Data() << "col_Count: " << dp_array_col_Count << "\n"; std::cout << space.Data() << "row_Count: " << dp_array_row_Count << "\n"; // Show the data matrix member for (UInt_t row = 0; row < dp_array_row_Count; row++) { std::cout << space.Data(); for (UInt_t col = 0; col < dp_array_col_Count; col++) { std::cout << dp_Value(col, row) << " "; } std::cout << "\n"; } } //______________________________________________________________________________ template void data_Layer::Streamer(TBuffer& b) { // Fills the standar root streamer with the current data points // Read if (b.IsReading()) { // Debug dbg_Print ("data_Layer::Streamer:(read TBuffer&)", DBG_LVL_STEP) // Reads class version UShort_t class_ver_Read = 0; b >> class_ver_Read; // Check version if (class_ver_Read != class_Ver) { // Debug dbg_Print ("data_Layer::Streamer:(read): version mismatch", DBG_LVL_WARN) dbg_Value(class_ver_Read, DBG_LVL_WARN); dbg_Value(class_Ver, DBG_LVL_WARN); } // Reads parent class data_Object::Streamer(b); // Reads data points b >> dp_array_col_Count; b >> dp_array_row_Count; // Allocates the needed storage space data_Resize(dp_array_row_Count, dp_array_col_Count); // Read the data into the matrix b.ReadFastArray(dp_Array, dp_array_row_Count * dp_array_col_Count); // Writes } else { // Debug dbg_Print ("data_Layer::Streamer:(write TBuffer&)",DBG_LVL_STEP) // Writes class version b << class_Ver; // Writes parent class data_Object::Streamer(b); // Writes the data points b << dp_array_col_Count; b << dp_array_row_Count; b.WriteFastArray(dp_Array, dp_array_row_Count * dp_array_col_Count); } } // Overloading check #endif