//------------------------------------------------------------------------------
//    module util.h   version 2.0b                                            //
//                                                                            //
//    general utilities                                                       //
//                                                                            //
//    copyright (c) 1998-2003 by Lars Haendel                                 //
//    home: www.newty.de                                                      //
//                                                                            //
//    This program is free software; you can redistribute it and/or modify    //
//    it under the terms of the GNU General Public License as published by    //
//    the Free Software Foundation as version 2 of the License.               //
//                                                                            //
//    This program is distributed in the hope that it will be useful,         //
//    but WITHOUT ANY WARRANTY; without even the implied warranty of          //
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
//    GNU General Public License for more details.                            //
//                                                                            //
//    You should have received a copy of the GNU General Public License       //
//    along with this program; if not, write to the Free Software             //
//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               //
//                                                                            //
//------------------------------------------------------------------------------


#ifndef _UTIL_H
#define _UTIL_H

#include <stdlib>       // due to   qsort()
#include <time>         //          clock_t
#include <fstream>


#ifdef BUILDER
using namespace std;    // use namespace if compiled with borland c++ builder
#endif


//----------------------------------------------------------------------------------------------------------------------
// Write given value to text using the specified precision counted from the most signifcant digit. Reduce precision
// if diplayed digits at the end would be "0". Example with prec=1: 0.002545 -> "0.0025", 0.00203 -> "0.002"
void ValueToText(const float value, char* text, const int width=0, const int prec=0);
const char* ValueToText1(const float value, const int width=0, const int prec=0, const bool& f_SpecialMinusOne=false);
const char* ValueToText2(const float value, const int width=0, const int prec=0, const bool& f_SpecialMinusOne=false);


//----------------------------------------------------------------------------------------------------------------------
// write given float value to static variable; fixed precision
const char* ValueToTextFP(const float value, const int width=0, const int prec=0);


//----------------------------------------------------------------------------------------------------------------------
// specialised functions: write float as percentage or time
const char* WritePercentage(const float& value, const int& width=0, const int& prec=1, const bool& f_PercentChar=false);
const char* WriteTime(const clock_t& time, const bool& f_justified=true);
const char* WriteTime2(const clock_t& time);    // write time as hours, minutes and seconds but no milli seconds

const char* TimeStamp();


//----------------------------------------------------------------------------------------------------------------------
//    sort/randomization functions

// vector with id and value, used to sort
struct TIdVec{
   int id;
   float a;    // first criterion
   float b;    // 2nd criterion
};


// comparison functions
int __cdecl IdVecCmpDes(const void* _c, const void* _d);
int __cdecl IdVecCmpAsc(const void* _c, const void* _d);
int __cdecl FloatCmpDes(const void* _c, const void* _d);
int __cdecl FloatCmpAsc(const void* _c, const void* _d);


class TSorter
{
public:

   // constructor
   TSorter(const int& _size);
   ~TSorter() { delete[] vec; };

   void SortAsc() {  qsort((void*) vec, size, sizeof(vec[0]), IdVecCmpAsc); };   // sort ascending
   void SortDes() {  qsort((void*) vec, size, sizeof(vec[0]), IdVecCmpDes); };   // sort descending


   inline float&     GetA(const int& i) { return vec[i].a; };
   inline float&     GetB(const int& i) { return vec[i].b; };
   inline const int& GetId(const int& i) const { return vec[i].id; };
   inline const int& Size() const { return size; };

private:
   TIdVec* vec;
   int size;
};



// return field with random order of the values 0..N-1
int* /*cr*/ RandomId(const int& N, const unsigned int& seed=1);

// return entries of <_vec> in randomized order in a new vector, delete old one
int* /*cr*/ Randomize(int*& /*ce*/ vec, const int& nId, const unsigned int& seed=1);



//----------------------------------------------------------------------------------------------------------------------
// memory allocation for matrices

// release matrix with <nRows> rows
template <class Type> void DeleteMatrix(Type**& mat, const int& nRows)
{
   if(!mat)                      // do not delete NULL pointer
      return;

   for(int i=0;i<nRows;i++)      // delete
      delete[] mat[i];
   delete[] mat;

   mat = NULL;
}


// allocate memory for <nRows> x <nCols> matrix
template <class Type> Type** MakeMatrix(Type, const int nRows, const int nCols)
{
   Type** mat=new Type*[nRows];
   for(int i=0;i<nRows;i++)
      mat[i]=new Type[nCols];

   return mat;
}



//----------------------------------------------------------------------------------------------------------------------
// equidistant discretization/quantization functions

// calculate interval width
// const float CalcIntWidth(const float& max, const float& min, const float& N, const bool& classify=false);

// discretize 'x' into one of N equally spaced intervals
int Quant(const float& x, const float& max, const float& min, const float& N, const bool& f_Integer=false);

// dequantize: return median value of discretization interval 'id'
const float DeQuant(const int& id, const float& max, const float& min, const float& N, const bool& f_Integer=false);




//----------------------------------------------------------------------------------------------------------------------
// bitwise access functions
#define MaxBits ((int) sizeof(float)*8)

inline bool IsBitSet (const int& value, const int& bit) { return ( (value >> bit) & 1);  };  // is bit no. 'bit' set ?
inline void SetBit   (int& value, const int& bit)       { value |= (1 << bit);   };          // set bit no. 'bit'
inline void ClearBit (int& value, const int& bit)       { value &= ~(1 << bit); };           // unset bit no. 'bit'

inline void SetAllBits  (int& value) { value |= ~0; };                                       // set all bits
inline void ClearAllBits(int& value) { value &= 0; };                                        // clear all bits

// write maximal 'max' bits stored in value to given ofstream
void WriteBits(ofstream& file, const int& value, const int max=MaxBits);

// write bits stored in value to cout
void PrintBits(const int& value);
#endif