Index: trunk/FACT++/src/fitsdump.cc
===================================================================
--- trunk/FACT++/src/fitsdump.cc	(revision 12849)
+++ trunk/FACT++/src/fitsdump.cc	(revision 12850)
@@ -136,4 +136,5 @@
     {
         case 'L': return "bool(8)";
+        case 'A': return "char(8)";
         case 'B': return "byte(8)";
         case 'I': return "short(16)";
@@ -143,5 +144,5 @@
         case 'D': return "double(64)";
     default:
-        return "unknwown";
+        return "unknown";
     }
 }
@@ -151,4 +152,5 @@
     switch (type)
     {
+        case 'A': return sizeof(int8_t);
         case 'L': return sizeof(uint8_t);
         case 'B': return sizeof(int8_t);
@@ -396,55 +398,57 @@
     out << "#" << endl;
 
-
-    // Loop over all columns in our list of requested columns
-    vector<pair<char, char*> > columnsData;
-
-    for (vector<string>::const_iterator it=listNamesOnly.begin(); it!=listNamesOnly.end(); it++)
-    {
-        fits::Table::Column& cCol = fColMap.find(*it)->second;
-        columnsData.push_back(make_pair(cCol.type, new char[cCol.num*cCol.size]));
-        fFile->SetPtrAddress(*it, columnsData[columnsData.size()-1].second);
-    }
-    int numRows = fFile->GetInt("NAXIS2");
-    int row = 0;
-    while (fFile->GetNextRow() && row < numRows)
-    {
-        row++;
+    while (fFile->GetNextRow())
+    {
+        const size_t row = fFile->GetRow();
+        if (row==fFile->GetNumRows())
+            break;
+
         rangesIt = ranges.begin();
-        for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++)
+
+        for (vector<string>::const_iterator in=listNamesOnly.begin(); in!=listNamesOnly.end(); in++, rangesIt++)
         {
+            const void *ptr = fFile->SetPtrAddress(*in);
+
+            const fits::Table::Column &cCol = fColMap.find(*in)->second;
+
+            string msg;
             for (int i=rangesIt->first; i<rangesIt->second; i++)
             {
-            switch (it->first) {
+                switch (cCol.type)
+                {
+                case 'A':
+                    msg += reinterpret_cast<const char*>(ptr)[i];
+                    break;
+                case 'B':
+                    out << (unsigned int)reinterpret_cast<const unsigned char*>(ptr)[i] << " ";
+                    break;
                 case 'L':
-                        out << reinterpret_cast<bool*>(it->second)[i] << " ";
-                        break;
-                case 'B':
-                        out << reinterpret_cast<char*>(it->second)[i] << " ";
-                        break;
+                    out << reinterpret_cast<const bool*>(ptr)[i] << " ";
+                    break;
                 case 'I':
-                        out << reinterpret_cast<int16_t*>(it->second)[i] << " ";
-                        break;
+                    out << reinterpret_cast<const int16_t*>(ptr)[i] << " ";
+                    break;
                 case 'J':
-                        out << reinterpret_cast<int32_t*>(it->second)[i] << " ";
-                        break;
+                    out << reinterpret_cast<const int32_t*>(ptr)[i] << " ";
+                    break;
                 case 'K':
-                        out << reinterpret_cast<int64_t*>(it->second)[i] << " ";
-                        break;
+                    out << reinterpret_cast<const int64_t*>(ptr)[i] << " ";
+                    break;
                 case 'E':
-                        out << reinterpret_cast<float*>(it->second)[i] << " ";
-                        break;
+                    out << reinterpret_cast<const float*>(ptr)[i] << " ";
+                    break;
                 case 'D':
-                        out << reinterpret_cast<double*>(it->second)[i] << " ";
-                        break;
+                    out << reinterpret_cast<const double*>(ptr)[i] << " ";
+                    break;
                 default:
                     ;
+                }
             }
-            }
+
+            if (cCol.type=='A')
+                out << "'" << msg << "' ";
         }
         out << endl;
     }
-    for (auto it = columnsData.begin(); it != columnsData.end(); it++)
-        delete[] it->second;
     return true;
 }
@@ -591,4 +595,5 @@
     double max;
     double average;
+    double squared;
     long numValues;
     minMaxStruct() : min(1e10), max(-1e10), average(0), numValues(0) {}
@@ -599,7 +604,7 @@
     //first of all, let's separate the columns from their ranges and check that the requested columns are indeed part of the file
     vector<pair<int, int> > ranges;
-    vector<string> listNamesOnly;
-
-    if (!separateColumnsFromRanges(list, ranges, listNamesOnly))
+    vector<string> names;
+
+    if (!separateColumnsFromRanges(list, ranges, names))
     {
         cerr << "Something went wrong while extracting the columns names from parameters. Aborting" << endl;
@@ -616,5 +621,119 @@
     out.precision(precision);
 
+    vector<minMaxStruct> statData(names.size());
+
     // Loop over all columns in our list of requested columns
+    while (fFile->GetNextRow())
+    {
+        const size_t row = fFile->GetRow();
+        if (row==fFile->GetNumRows())
+            break;
+
+        auto rangesIt = ranges.begin();
+        auto statsIt  = statData.begin();
+
+        for (auto in=names.begin(); in!=names.end(); in++, rangesIt++, statsIt++)
+        {
+            const void *ptr = fFile->SetPtrAddress(*in);
+
+            const fits::Table::Column &cCol = fColMap.find(*in)->second;
+
+            if (*in=="UnixTimeUTC" || *in=="PCTime")
+            {
+                const uint32_t *val = reinterpret_cast<const uint32_t*>(ptr);
+                if (fNoZeroPlease && val[0]==0 && val[1]==0)
+                    continue;
+
+                const double cValue = Time(val[0], val[1]).Mjd();
+
+                statsIt->average += cValue;
+                statsIt->squared += cValue*cValue;
+
+                if (cValue < statsIt->min)
+                    statsIt->min = cValue;
+
+                if (cValue > statsIt->max)
+                    statsIt->max = cValue;
+
+                statsIt->numValues++;
+
+                continue;
+            }
+
+            for (int i=rangesIt->first; i<rangesIt->second; i++)
+            {
+                double cValue = 0;
+                switch (cCol.type)
+                {
+                case 'L':
+                        cValue = reinterpret_cast<const bool*>(ptr)[i];
+                        break;
+                case 'B':
+                        cValue = reinterpret_cast<const int8_t*>(ptr)[i];
+                        break;
+                case 'I':
+                        cValue = reinterpret_cast<const int16_t*>(ptr)[i];
+                        break;
+                case 'J':
+                        cValue = reinterpret_cast<const int32_t*>(ptr)[i];
+                        break;
+                case 'K':
+                        cValue = reinterpret_cast<const int64_t*>(ptr)[i];
+                        break;
+                case 'E':
+                        cValue = reinterpret_cast<const float*>(ptr)[i];
+                        break;
+                case 'D':
+                        cValue = reinterpret_cast<const double*>(ptr)[i];
+                        break;
+                default:
+                    ;
+                }
+
+                if (fNoZeroPlease && cValue == 0)
+                    continue;
+
+                statsIt->average += cValue;
+                statsIt->squared += cValue*cValue;
+
+                if (cValue < statsIt->min)
+                    statsIt->min = cValue;
+
+                if (cValue > statsIt->max)
+                    statsIt->max = cValue;
+
+                statsIt->numValues++;
+            }
+        }
+    }
+
+    // okay. So now I've got ALL the data, loaded.
+    // let's do the summing and averaging in a safe way (i.e. avoid overflow
+    // of variables as much as possible)
+    auto statsIt = statData.begin();
+
+    for (auto it=names.begin(); it!=names.end(); it++, statsIt++)
+    {
+        cout << "[" << *it << "]" << endl;
+        if (statsIt->numValues == 0)
+        {
+            out << "Min: -\nMax: -\nAvg: -\nRms: -" << endl;
+            continue;
+        }
+
+        double &avg = statsIt->average;
+        double &rms = statsIt->squared;
+        long   &num = statsIt->numValues;
+
+        avg /= num;
+        rms  = sqrt(rms/num - avg*avg);
+
+        out << "Min: " << statsIt->min << '\n';
+        out << "Max: " << statsIt->max << '\n';
+        out << "Avg: " << avg << '\n';
+        out << "Rms: " << rms << endl;
+    }
+
+    /*
     vector<pair<char, char*> > columnsData;
     vector<minMaxStruct> statData;
@@ -644,5 +763,5 @@
             switch (it->first) {
                 case 'L':
-                        cValue = reinterpret_cast<bool*>(it->second)[i];
+                        cValue = reinterpret_cast<unsigned char*>(it->second)[i];
                         break;
                 case 'B':
@@ -709,28 +828,5 @@
     for (auto it = columnsData.begin(); it != columnsData.end(); it++)
         delete[] it->second;
-
-    //okay. So now I've got ALL the data, loaded.
-    //let's do the summing and averaging in a safe way (i.e. avoid overflow of variables as much as possible)
-    rangesIt = ranges.begin();
-    auto statsIt = statData.begin();
-
-    auto nameIt = listNamesOnly.begin();
-    for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++, statsIt++, nameIt++)
-    {
-//        int span = rangesIt->second - rangesIt->first;
-        cout << *nameIt << ": " << endl;
-        if (statsIt->numValues != 0)
-        {
-            statsIt->average /= statsIt->numValues;
-            out << "min: " << statsIt->min << endl;
-            out << "max: " << statsIt->max << endl;
-            out << "mea: " << statsIt->average << endl;
-        }
-        else
-        {
-            out << "min: 0" << endl << "max: 0" << endl << "mea: " << endl;
-        }
-
-    }
+*/
     return true;
 }
@@ -854,24 +950,38 @@
 void displayStats(char* array, int numElems, ofstream& out)
 {
-	if (numElems == 0)
-	{
-		out << "Min: 0" << endl;
-		out << "Max: 0" << endl;
-		out << "Med: 0" << endl;
-		out << "Mea: 0" << endl;
-		return;
-	}
-    sort(reinterpret_cast<T*>(array), &reinterpret_cast<T*>(array)[numElems]);
-    out << "Min: " << reinterpret_cast<T*>(array)[0] << endl;
-    out << "Max: " << reinterpret_cast<T*>(array)[numElems-1] << endl;
-    if (numElems%2 == 0)
-        out << "Med: " << (reinterpret_cast<T*>(array)[numElems/2] + reinterpret_cast<int16_t*>(array)[numElems/2+1])/2.f << endl;
-    else
-        out << "Med: " << reinterpret_cast<T*>(array)[numElems/2+1] << endl;
-
-    double average = 0;
+    if (numElems == 0)
+    {
+        out << "Min: -\nMax: -\nMed: -\nAvg: -\nRms: -" << endl;
+        return;
+    }
+
+    T *val = reinterpret_cast<T*>(array);
+
+    sort(val, val+numElems);
+
+    out << "Min: " << double(val[0]) << '\n';
+    out << "Max: " << double(val[numElems-1]) << '\n';
+
+    if (numElems>2)
+    {
+        if (numElems%2 == 0)
+            out << "Med: " << double(val[numElems/2] + val[numElems/2+1])/2 << '\n';
+        else
+            out << "Med: " << double(val[numElems/2+1]) << '\n';
+    }
+
+    double avg = 0;
+    double rms = 0;
     for (int i=0;i<numElems;i++)
-        average += reinterpret_cast<T*>(array)[i];
-    out << "Mea: " << average/(double)numElems << endl;
+    {
+        avg += val[i];
+        rms += val[i]*val[i];
+    }
+
+    avg /= numElems;
+    rms  = sqrt(rms/numElems - avg*avg);
+
+    out << "Avg: " << avg << '\n';
+    out << "Rms: " << rms << endl;
 
 }
@@ -881,7 +991,7 @@
     //first of all, let's separate the columns from their ranges and check that the requested columns are indeed part of the file
     vector<pair<int, int> > ranges;
-    vector<string> listNamesOnly;
-
-    if (!separateColumnsFromRanges(list, ranges, listNamesOnly))
+    vector<string> names;
+
+    if (!separateColumnsFromRanges(list, ranges, names))
     {
         cerr << "Something went wrong while extracting the columns names from parameters. Aborting" << endl;
@@ -899,57 +1009,62 @@
 
     // Loop over all columns in our list of requested columns
-    vector<pair<char, char*> > columnsData;
     vector<char*> statData;
-    int numRows = fFile->GetInt("NAXIS2");
+
     auto rangesIt = ranges.begin();
-    for (vector<string>::const_iterator it=listNamesOnly.begin(); it!=listNamesOnly.end(); it++, rangesIt++)
-    {
-        fits::Table::Column& cCol = fColMap.find(*it)->second;
-        columnsData.push_back(make_pair(cCol.type, new char[cCol.num*cCol.size]));
-        statData.push_back(new char[(rangesIt->second - rangesIt->first)*cCol.size*numRows]);
-        fFile->SetPtrAddress(*it, columnsData[columnsData.size()-1].second);
-    }
-
-    int row = 0;
-    while (fFile->GetNextRow() && row < numRows)
-    {
+    for (auto in=names.begin(); in!=names.end(); in++, rangesIt++)
+    {
+        cout << *in << endl;
+        const fits::Table::Column &cCol = fColMap.find(*in)->second;
+        statData.push_back(new char[(rangesIt->second - rangesIt->first)*cCol.size*fFile->GetNumRows()]);
+    }
+
+    while (fFile->GetNextRow())
+    {
+        const size_t row = fFile->GetRow();
+        if (row==fFile->GetNumRows())
+            break;
+
         rangesIt = ranges.begin();
         auto statsIt = statData.begin();
-        for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++, statsIt++)
+
+        for (auto in=names.begin(); in!=names.end(); in++, rangesIt++, statsIt++)
         {
-            int span = rangesIt->second - rangesIt->first;
+            const void *ptr = fFile->SetPtrAddress(*in);
+
+            const fits::Table::Column &cCol = fColMap.find(*in)->second;
+
+            const int span = rangesIt->second - rangesIt->first;
+
             for (int i=rangesIt->first; i<rangesIt->second; i++)
             {
-            switch (it->first) {
+                switch (cCol.type)
+                {
                 case 'L':
-                        reinterpret_cast<bool*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<bool*>(it->second)[i];
+                        reinterpret_cast<bool*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<const bool*>(ptr)[i];
                         break;
                 case 'B':
-                        reinterpret_cast<char*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<char*>(it->second)[i];
+                        reinterpret_cast<char*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<const char*>(ptr)[i];
                         break;
                 case 'I':
-                        reinterpret_cast<int16_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<int16_t*>(it->second)[i];
+                        reinterpret_cast<int16_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<const int16_t*>(ptr)[i];
                         break;
                 case 'J':
-                        reinterpret_cast<int32_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<int32_t*>(it->second)[i];
+                        reinterpret_cast<int32_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<const int32_t*>(ptr)[i];
                         break;
                 case 'K':
-                        reinterpret_cast<int64_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<int64_t*>(it->second)[i];
+                        reinterpret_cast<int64_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<const int64_t*>(ptr)[i];
                         break;
                 case 'E':
-                        reinterpret_cast<float*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<float*>(it->second)[i];
+                        reinterpret_cast<float*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<const float*>(ptr)[i];
                         break;
                 case 'D':
-                        reinterpret_cast<double*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<double*>(it->second)[i];
+                        reinterpret_cast<double*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<const double*>(ptr)[i];
                         break;
                 default:
                     ;
+                }
             }
-            }
-        }
-        row++;
-    }
-    for (auto it = columnsData.begin(); it != columnsData.end(); it++)
-        delete[] it->second;
+        }
+    }
 
     //okay. So now I've got ALL the data, loaded.
@@ -958,30 +1073,33 @@
     auto statsIt = statData.begin();
 
-    auto nameIt = list.begin();
-    for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++, statsIt++, nameIt++)
-    {
-        int span = rangesIt->second - rangesIt->first;
-        out << *nameIt << ": " << endl;
-        switch (it->first) {
+    for (auto it=list.begin(); it!=list.end(); it++, rangesIt++, statsIt++)
+    {
+        const fits::Table::Column &cCol = fColMap.find(*it)->second;
+
+        const int span = rangesIt->second - rangesIt->first;
+
+        out << "[" << *it << "]" << endl;
+        switch (cCol.type)
+        {
             case 'L':
-                    displayStats<bool>(*statsIt, numRows*span, out);
+                    displayStats<bool>(*statsIt, fFile->GetNumRows()*span, out);
                     break;
             case 'B':
-                    displayStats<char>(*statsIt, numRows*span, out);
+                    displayStats<char>(*statsIt, fFile->GetNumRows()*span, out);
                     break;
             case 'I':
-                    displayStats<int16_t>(*statsIt, numRows*span, out);
+                    displayStats<int16_t>(*statsIt, fFile->GetNumRows()*span, out);
                     break;
             case 'J':
-                    displayStats<int32_t>(*statsIt, numRows*span, out);
+                    displayStats<int32_t>(*statsIt, fFile->GetNumRows()*span, out);
                     break;
             case 'K':
-                    displayStats<int64_t>(*statsIt, numRows*span, out);
+                    displayStats<int64_t>(*statsIt, fFile->GetNumRows()*span, out);
                     break;
             case 'E':
-                    displayStats<float>(*statsIt, numRows*span, out);
+                    displayStats<float>(*statsIt, fFile->GetNumRows()*span, out);
                     break;
             case 'D':
-                    displayStats<double>(*statsIt, numRows*span, out);
+                    displayStats<double>(*statsIt, fFile->GetNumRows()*span, out);
                     break;
             default:
@@ -989,4 +1107,5 @@
         }
     }
+
     return true;
 }
