CCfits  2.4
ColumnT.h
00001 //      Astrophysics Science Division,
00002 //      NASA/ Goddard Space Flight Center
00003 //      HEASARC
00004 //      http://heasarc.gsfc.nasa.gov
00005 //      e-mail: ccfits@legacy.gsfc.nasa.gov
00006 //
00007 //      Original author: Ben Dorman
00008 
00009 #ifndef COLUMNT_H
00010 #define COLUMNT_H
00011 
00012 #ifdef _MSC_VER
00013 #include "MSconfig.h"
00014 #endif
00015 
00016 #include "ColumnData.h"
00017 #include "ColumnVectorData.h"
00018 #include "FITSUtil.h"
00019 #include <typeinfo>
00020 #include <vector>
00021 #include <algorithm>
00022 #include "NewKeyword.h"
00023 
00024 #ifdef SSTREAM_DEFECT
00025 #       include <strstream>
00026 #else
00027 #       include <sstream>
00028 #endif
00029 
00030 
00031 // by design, if the data are not read yet we will return an exception.
00032 // here the test is if the entire column has already been read. 
00033 using std::complex;
00034 using std::valarray;
00035 
00036 // get specified elements of a scalar column. These two functions allow the
00037 // user to return either a vector or a valarray depending on the input container.
00038 
00039 namespace CCfits 
00040 {
00041    template <typename S>
00042    void Column::read(std::vector<S>& vals, long first, long last) 
00043    {
00044            read(vals,first,last,static_cast<S*>(0));
00045    }
00046 
00047 
00048    template <typename S>
00049    void Column::read(std::vector<S>& vals, long first, long last, S* nullValue) 
00050    {
00051            // problem: S does not give the type of the Column, but the return type,
00052            // so the user must specify this.
00053            parent()->makeThisCurrent();
00054            long nelements = numberOfElements(first,last);
00055 
00056            if  (ColumnData<S>* col = dynamic_cast<ColumnData<S>*>(this))
00057            {
00058                    // fails if user requested outputType different from input type.
00059 
00060 
00061                    if (!isRead()) col->readColumnData(first,nelements,nullValue);
00062                    // scalar column with vector output can just be assigned.
00063                    FITSUtil::fill(vals,col->data(),first,last);
00064            }
00065            else
00066            {
00067                    FITSUtil::MatchType<S> outputType;
00068                    if ( outputType() == type() ) 
00069                    { 
00070                            // in this case user tried to read vector data from scalar,
00071                            // (i.e. first argument was vector<valarray<S> >.
00072                            // since the cast won't fail on template parameter grounds.
00073                            throw Column::WrongColumnType(name());
00074                    }
00075 
00076                    try
00077                    {
00078                        // about exceptions. The dynamic_casts could throw
00079                        // std::bad_cast. If this happens something is seriously
00080                        // wrong since the Column stores the value of type() 
00081                        // appropriate to each of the casts on construction.
00082                        // 
00083                        // the InvalidDataType exception should not be possible.
00084                        if  ( type() == Tdouble )
00085                        {
00086                                ColumnData<double>& col 
00087                                          = dynamic_cast<ColumnData<double>&>(*this);
00088                                if (!isRead()) col.readColumnData(first,nelements);                                  
00089                                FITSUtil::fill(vals,col.data(),first,last);
00090 
00091                        }
00092                        else if (type() == Tfloat)
00093                        {
00094                                ColumnData<float>& col 
00095                                        = dynamic_cast<ColumnData<float>&>(*this);
00096                                if (!isRead()) col.readColumnData(first,nelements);                                  
00097                                FITSUtil::fill(vals,col.data(),first,last);
00098                        }
00099                        else if (type() == Tint)
00100                        {
00101                                int nullVal(0);
00102                                if (nullValue) nullVal = static_cast<int>(*nullValue);
00103                                ColumnData<int>& col  
00104                                   = dynamic_cast<ColumnData<int>&>(*this);
00105                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00106                                FITSUtil::fill(vals,col.data(),first,last);
00107                        }
00108                        else if (type() == Tshort)
00109                        {
00110                                short nullVal(0);
00111                                if (nullValue) nullVal = static_cast<short>(*nullValue);
00112                                ColumnData<short>& col 
00113                                 = dynamic_cast<ColumnData<short>&>(*this);
00114                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00115                                FITSUtil::fill(vals,col.data(),first,last);
00116                        }
00117                        else if (type() == Tlong)
00118                        {        
00119                                long nullVal(0);
00120                                if (nullValue) nullVal = static_cast<long>(*nullValue); 
00121                                ColumnData<long>& col 
00122                                  = dynamic_cast<ColumnData<long>&>(*this);
00123                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00124                                FITSUtil::fill(vals,col.data(),first,last);
00125                        }
00126                        else if (type() == Tlonglong)
00127                        {        
00128                                LONGLONG nullVal(0);
00129                                if (nullValue) nullVal = static_cast<LONGLONG>(*nullValue); 
00130                                ColumnData<LONGLONG>& col 
00131                                  = dynamic_cast<ColumnData<LONGLONG>&>(*this);
00132                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00133                                FITSUtil::fill(vals,col.data(),first,last);
00134                        }
00135                        else if (type() == Tlogical)
00136                        {        
00137                                bool nullVal(0);
00138                                if (nullValue) nullVal = static_cast<bool>(*nullValue); 
00139                                ColumnData<bool>& col 
00140                                  = dynamic_cast<ColumnData<bool>&>(*this);
00141                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00142                                FITSUtil::fill(vals,col.data(),first,last);
00143                        }
00144                        else if (type() == Tbit || type() == Tbyte)
00145                        {
00146                                unsigned char nullVal(0);
00147                                if (nullValue) nullVal = static_cast<unsigned char>(*nullValue); 
00148                                ColumnData<unsigned char>& col 
00149                                        = dynamic_cast<ColumnData<unsigned char>&>(*this);
00150                                if (!isRead()) col.readColumnData(first,nelements,&nullVal); 
00151                                FITSUtil::fill(vals,col.data(),first,last);
00152                        }
00153                        else if (type() == Tushort)
00154                        {
00155                                unsigned short nullVal(0);
00156                                if (nullValue) nullVal= static_cast<unsigned short>(*nullValue);
00157                                ColumnData<unsigned short>& col 
00158                                        = dynamic_cast<ColumnData<unsigned short>&>(*this);
00159                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00160                                FITSUtil::fill(vals,col.data(),first,last);
00161                        }
00162                        else if (type() == Tuint)
00163                        {
00164                                unsigned int nullVal(0);
00165                                if (nullValue) nullVal = static_cast<unsigned int>(*nullValue);
00166                                ColumnData<unsigned int>& col 
00167                                        = dynamic_cast<ColumnData<unsigned int>&>(*this);
00168                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00169                                FITSUtil::fill(vals,col.data(),first,last);
00170                        }
00171                        else if (type() == Tulong)
00172                        {
00173                                unsigned long nullVal(0);
00174                                if (nullValue) nullVal = static_cast<unsigned long>(*nullValue);
00175                                ColumnData<unsigned long>& col 
00176                                         = dynamic_cast<ColumnData<unsigned long>&>(*this);
00177                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                  
00178                                FITSUtil::fill(vals,col.data(),first,last);
00179                        }
00180                        else
00181                        {
00182                                  throw InvalidDataType(name());
00183 
00184                        }
00185 
00186                    }
00187                    catch (std::bad_cast)
00188                    {
00189                            throw WrongColumnType(name());
00190                    }
00191            }
00192 
00193    }
00194 
00195    template <typename S>
00196    void Column::read(std::valarray<S>& vals, long first, long last) 
00197    {
00198            read(vals,first,last,static_cast<S*>(0));
00199    }
00200 
00201 
00202    template <typename S>
00203    void Column::read(std::valarray<S>& vals, long first, long last, S* nullValue) 
00204    {        
00205            // require the whole scalar column to have been read.
00206 
00207 
00208            long nelements = numberOfElements(first,last);
00209            parent()->makeThisCurrent();                
00210            if ( ColumnData<S>* col = dynamic_cast<ColumnData<S>*>(this))
00211            {
00212                    // fails if user requested outputType different from input type.
00213 
00214 
00215                    if (!isRead()) col->readColumnData(first,nelements,nullValue);                                  
00216                    FITSUtil::fill(vals,col->data(),first,last);
00217 
00218            }
00219            else
00220            {
00221                    FITSUtil::MatchType<S> outputType;
00222                    if ( outputType() == type() ) 
00223                    { 
00224                            // in this case user tried to read vector data from scalar,
00225                            // (i.e. first argument was vector<valarray<S> >.
00226                            // since the cast won't fail on template parameter grounds.
00227                            throw Column::WrongColumnType(name());
00228                    }
00229 
00230                    try
00231                    {
00232                        // about exceptions. The dynamic_casts could throw
00233                        // std::bad_cast. If this happens something is seriously
00234                        // wrong since the Column stores the value of type() 
00235                        // appropriate to each of the casts on construction.
00236                        // 
00237                        // the InvalidDataType exception should not be possible.
00238                        if  ( type() == Tdouble )
00239                        {
00240                                ColumnData<double>& col 
00241                                          = dynamic_cast<ColumnData<double>&>(*this);
00242                                if (!isRead()) col.readColumnData(first,nelements);                                  
00243                                FITSUtil::fill(vals,col.data(),first,last);
00244                        }
00245                        else if (type() == Tfloat)
00246                        {
00247                                ColumnData<float>& col 
00248                                        = dynamic_cast<ColumnData<float>&>(*this);
00249                                if (!isRead()) col.readColumnData(first,nelements);                                  
00250                                FITSUtil::fill(vals,col.data(),first,last);
00251                        }
00252                        else if (type() == Tint)
00253                        {
00254                                int nullVal(0);
00255                                if (nullValue) nullVal = static_cast<int>(*nullValue); 
00256                                ColumnData<int>& col  
00257                                        = dynamic_cast<ColumnData<int>&>(*this);
00258                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                    
00259                                FITSUtil::fill(vals,col.data(),first,last);
00260                        }
00261                        else if (type() == Tshort)
00262                        {
00263                                short nullVal(0);
00264                                if (nullValue) nullVal = static_cast<short>(*nullValue); 
00265                                ColumnData<short>& col 
00266                                        = dynamic_cast<ColumnData<short>&>(*this);
00267                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                    
00268                                FITSUtil::fill(vals,col.data(),first,last);
00269                        }
00270                        else if (type() == Tlong)
00271                        {        
00272                                long nullVal(0);
00273                                if (nullValue) nullVal = static_cast<long>(*nullValue); 
00274                                ColumnData<long>& col 
00275                                        = dynamic_cast<ColumnData<long>&>(*this);
00276                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);
00277                                FITSUtil::fill(vals,col.data(),first,last);
00278                        }
00279                        else if (type() == Tlonglong)
00280                        {        
00281                                LONGLONG nullVal(0);
00282                                if (nullValue) nullVal = static_cast<LONGLONG>(*nullValue); 
00283                                ColumnData<LONGLONG>& col 
00284                                        = dynamic_cast<ColumnData<LONGLONG>&>(*this);
00285                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);
00286                                FITSUtil::fill(vals,col.data(),first,last);
00287                        }
00288                        else if (type() == Tlogical)
00289                        {        
00290                                bool nullVal(0);
00291                                if (nullValue) nullVal = static_cast<bool>(*nullValue); 
00292                                ColumnData<bool>& col 
00293                                        = dynamic_cast<ColumnData<bool>&>(*this);
00294                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                    
00295                                FITSUtil::fill(vals,col.data(),first,last);
00296                        }
00297                        else if (type() == Tbit || type() == Tbyte)
00298                        {
00299                                unsigned char nullVal(0);
00300                                if (nullValue) nullVal = static_cast<unsigned char>(*nullValue); 
00301                                ColumnData<unsigned char>& col 
00302                                        = dynamic_cast<ColumnData<unsigned char>&>(*this);
00303                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                    
00304                                FITSUtil::fill(vals,col.data(),first,last);
00305                        }
00306                        else if (type() == Tushort)
00307                        {
00308                                unsigned short nullVal(0);
00309                                if (nullValue) nullVal 
00310                                        = static_cast<unsigned short>(*nullValue); 
00311                                ColumnData<unsigned short>& col 
00312                                        = dynamic_cast<ColumnData<unsigned short>&>(*this);
00313                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                    
00314                                FITSUtil::fill(vals,col.data(),first,last);
00315                        }
00316                        else if (type() == Tuint)
00317                        {
00318                                unsigned int nullVal(0);
00319                                if (nullValue) nullVal 
00320                                        = static_cast<unsigned int>(*nullValue); 
00321                                ColumnData<unsigned int>& col 
00322                                        = dynamic_cast<ColumnData<unsigned int>&>(*this);
00323                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                    
00324                                FITSUtil::fill(vals,col.data(),first,last);
00325                        }
00326                        else if (type() == Tulong)
00327                        {
00328                                unsigned long nullVal(0);
00329                                if (nullValue) nullVal 
00330                                        = static_cast<unsigned long>(*nullValue); 
00331                                ColumnData<unsigned long>& col 
00332                                        = dynamic_cast<ColumnData<unsigned long>&>(*this);
00333                                if (!isRead()) col.readColumnData(first,nelements,&nullVal);                                    
00334                                FITSUtil::fill(vals,col.data(),first,last);
00335                        }
00336                        else
00337                        {
00338                                  throw InvalidDataType(name());
00339 
00340                        }
00341 
00342                    }
00343                    catch (std::bad_cast)
00344                    {
00345                         throw WrongColumnType(name());
00346                    }
00347                }
00348 
00349    }
00350 
00351    // get a single row from a vector column. There's no default row number, must
00352    // be specified.
00353    template <typename S>
00354    void Column::read(std::valarray<S>& vals, long row) 
00355    {
00356            read(vals,row,static_cast<S*>(0));
00357    }
00358 
00359 
00360    template <typename S>
00361    void Column::read(std::valarray<S>& vals, long row, S* nullValue) 
00362    {
00363            if (row > parent()->rows())
00364            {
00365               throw Column::InvalidRowNumber(name());
00366            }
00367            parent()->makeThisCurrent();                
00368            // isRead() returns true if the data were read in the ctor.
00369            if ( ColumnVectorData<S>* col = dynamic_cast<ColumnVectorData<S>*>(this))
00370            {
00371                    // fails if user requested outputType different from input type.
00372 
00373 
00374 
00375                    // input and output are both valarrays. Since one should not
00376                    // be able to call a constructor for a non-numeric valarray type,
00377                    // there shouldn't be any InvalidType problems. However, there
00378                    // is still the vector/scalar possibility and the implicit
00379                    // conversion request to deal with.
00380 
00381                    if (!isRead()) col->readRow(row,nullValue);
00382                    FITSUtil::fill(vals,col->data(row));
00383            }
00384            else
00385            {
00386                    FITSUtil::MatchType<S> outputType;
00387                    if ( outputType() == type() ) 
00388                    { 
00389                            // in this case user tried to read vector row from scalar column.
00390                            // one could be charitable and return a valarray of size 1,
00391                            // but... I'm going to throw an exception suggesting the user
00392                            // might not have meant that.
00393 
00394                            throw Column::WrongColumnType(name());
00395                    }
00396 
00397                    // the InvalidDataType exception should not be possible.
00398                    try
00399                    {
00400                        // about exceptions. The dynamic_casts could throw
00401                        // std::bad_cast. If this happens something is seriously
00402                        // wrong since the Column stores the value of type() 
00403                        // appropriate to each of the casts on construction.
00404                        // 
00405                        // the InvalidDataType exception should not be possible.
00406                        if  ( type() == Tdouble || type() == VTdouble )
00407                        {
00408                                ColumnVectorData<double>& col 
00409                                          = dynamic_cast<ColumnVectorData<double>&>(*this);
00410                                if (!isRead()) col.readRow(row);                                  
00411                                FITSUtil::fill(vals,col.data(row));
00412 
00413                        }
00414                        else if (type() == Tfloat  || type() == VTfloat )
00415                        { 
00416                                ColumnVectorData<float>& col 
00417                                      = dynamic_cast<ColumnVectorData<float>&>(*this);
00418                                if (!isRead()) col.readRow(row); 
00419                                FITSUtil::fill(vals,col.data(row));
00420                        }
00421                        else if (type() == Tint  || type() == VTint )
00422                        {
00423                                int nullVal(0);
00424                                if (nullValue) nullVal = static_cast<int>(*nullValue); 
00425                                ColumnVectorData<int>& col  
00426                                        = dynamic_cast<ColumnVectorData<int>&>(*this);
00427                                if (!isRead()) col.readRow(row,&nullVal); 
00428                                FITSUtil::fill(vals,col.data(row));
00429                        }
00430                        else if (type() == Tshort  || type() == VTshort  )
00431                        {
00432                                short nullVal(0);
00433                                if (nullValue) nullVal = static_cast<short>(*nullValue); 
00434                                ColumnVectorData<short>& col 
00435                                        = dynamic_cast<ColumnVectorData<short>&>(*this);
00436                                if (!isRead()) col.readRow(row,&nullVal); 
00437                                FITSUtil::fill(vals,col.data(row));
00438                        }
00439                        else if (type() == Tlong  || type() == VTlong )
00440                        {        
00441                                long nullVal(0);
00442                                if (nullValue) nullVal = static_cast<long>(*nullValue); 
00443                                ColumnVectorData<long>& col 
00444                                        = dynamic_cast<ColumnVectorData<long>&>(*this);
00445                                if (!isRead()) col.readRow(row,&nullVal); 
00446                                FITSUtil::fill(vals,col.data(row));
00447                        }
00448                        else if (type() == Tlonglong  || type() == VTlonglong )
00449                        {        
00450                                LONGLONG nullVal(0);
00451                                if (nullValue) nullVal = static_cast<LONGLONG>(*nullValue); 
00452                                ColumnVectorData<LONGLONG>& col 
00453                                        = dynamic_cast<ColumnVectorData<LONGLONG>&>(*this);
00454                                if (!isRead()) col.readRow(row,&nullVal); 
00455                                FITSUtil::fill(vals,col.data(row));
00456                        }
00457                        else if (type() == Tlogical  || type() == VTlogical )
00458                        {        
00459                                bool nullVal(0);
00460                                if (nullValue) nullVal = static_cast<bool>(*nullValue); 
00461                                ColumnVectorData<bool>& col 
00462                                        = dynamic_cast<ColumnVectorData<bool>&>(*this);
00463                                if (!isRead()) col.readRow(row,&nullVal); 
00464                                FITSUtil::fill(vals,col.data(row));
00465                        }
00466                        else if (type() == Tbit || type() == Tbyte ||  
00467                                type() == VTbit || type() == VTbyte )
00468                        {
00469                                unsigned char nullVal(0);
00470                                if (nullValue) nullVal 
00471                                            = static_cast<unsigned char>(*nullValue); 
00472                                ColumnVectorData<unsigned char>& col 
00473                                      = dynamic_cast<ColumnVectorData<unsigned char>&>(*this);
00474                                if (!isRead()) col.readRow(row,&nullVal); 
00475                                FITSUtil::fill(vals,col.data(row));
00476                        }
00477                        else if (type() == Tushort || type() == VTushort)
00478                        {
00479                                unsigned short nullVal(0);
00480                                if (nullValue) nullVal 
00481                                            = static_cast<unsigned short>(*nullValue); 
00482                                ColumnVectorData<unsigned short>& col 
00483                                      = dynamic_cast<ColumnVectorData<unsigned short>&>(*this);
00484                                if (!isRead()) col.readRow(row,&nullVal); 
00485                                FITSUtil::fill(vals,col.data(row));
00486                        }
00487                        else if (type() == Tuint || type() == VTuint)
00488                        {
00489                                unsigned int nullVal(0);
00490                                if (nullValue) nullVal 
00491                                            = static_cast<unsigned int>(*nullValue); 
00492                                ColumnVectorData<unsigned int>& col 
00493                                      = dynamic_cast<ColumnVectorData<unsigned int>&>(*this);
00494                                if (!isRead()) col.readRow(row,&nullVal); 
00495                                FITSUtil::fill(vals,col.data(row));
00496                        }
00497                        else if (type() == Tulong || type() == VTulong)
00498                        {
00499                                unsigned long nullVal(0);
00500                                if (nullValue) nullVal 
00501                                            = static_cast<unsigned long>(*nullValue); 
00502                                ColumnVectorData<unsigned long>& col 
00503                                        = dynamic_cast<ColumnVectorData<unsigned long>&>(*this);
00504                                if (!isRead()) col.readRow(row,&nullVal); 
00505                                FITSUtil::fill(vals,col.data(row));
00506                        }
00507                        else
00508                        {
00509                                throw InvalidDataType(name());
00510 
00511                        }
00512 
00513                    }
00514                    catch (std::bad_cast)
00515                    {
00516                        throw WrongColumnType(name());
00517                    }     
00518             }
00519    }
00520 
00521    template <typename S>
00522    void Column::readArrays(std::vector<std::valarray<S> >& vals, long first, long last)  
00523    {
00524            readArrays(vals,first,last,static_cast<S*>(0));
00525    }
00526 
00527    template <typename S>
00528    void Column::readArrays(std::vector<std::valarray<S> >& vals, 
00529                            long first, long last, S* nullValue)
00530    {
00531 
00532            parent()->makeThisCurrent();
00533            // again, can only call this if the entire column has been read from disk.
00534            // user expects 1 based indexing. If 0 based indices are supplied,
00535            // add one to both ranges.
00536            long range = numberOfElements(first,last);
00537 
00538            vals.resize(range);
00539 
00540 
00541            if ( ColumnVectorData<S>* col = dynamic_cast<ColumnVectorData<S>*>(this))
00542            {
00543                    for (int j = 0; j < range; ++j) 
00544                    {
00545                            if (!isRead()) col->readRow(j + first,nullValue);                             
00546                            FITSUtil::fill(vals[j],col->data(j+first));
00547                    }
00548            }
00549            else
00550            {
00551                    FITSUtil::MatchType<S> outputType;
00552                    if ( outputType() == type() ) 
00553                    { 
00554                            // in this case user tried to read vector data from scalar,
00555                            // (i.e. first argument was vector<valarray<S> >.
00556                            // since the cast won't fail on template parameter grounds.
00557                            throw Column::WrongColumnType(name());
00558                    }
00559                    // the InvalidDataType exception should not be possible.
00560                    try
00561                    {
00562                        if  ( type() == Tdouble || type() == VTdouble )
00563                        {
00564                                ColumnVectorData<double>& col 
00565                                        = dynamic_cast<ColumnVectorData<double>&>(*this);
00566                                for (int j = 0; j < range; ++j) 
00567                                {
00568                                    if (!isRead()) col.readRow(j + first); 
00569                                    FITSUtil::fill(vals[j],col.data(j+first));
00570                                }
00571                        }
00572                        else if  ( type() == Tfloat || type() == VTfloat  )
00573                        {
00574                                ColumnVectorData<float>& col 
00575                                        = dynamic_cast<ColumnVectorData<float>&>(*this);
00576                                for (int j = 0; j < range; ++j) 
00577                                {
00578                                    if (!isRead()) col.readRow(j + first); 
00579                                    FITSUtil::fill(vals[j],col.data(j+first));
00580                                }
00581                        }
00582                        else if  ( type() == Tint   || type() == VTint )
00583                        {
00584                                int nullVal(0);
00585                                if (nullValue) nullVal  = static_cast<int>(*nullValue); 
00586                                ColumnVectorData<int>& col  
00587                                        = dynamic_cast<ColumnVectorData<int>&>(*this);
00588                                for (int j = 0; j < range; ++j) 
00589                                {
00590                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00591                                    FITSUtil::fill(vals[j],col.data(j+first));
00592                                }
00593                        }
00594                        else if  ( type() == Tshort  || type() == VTshort )
00595                        {
00596                                short nullVal(0);
00597                                if (nullValue) nullVal  = static_cast<short>(*nullValue); 
00598                                ColumnVectorData<short>& col 
00599                                        = dynamic_cast<ColumnVectorData<short>&>(*this);
00600                                for (int j = 0; j < range; ++j) 
00601                                {
00602                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00603                                    FITSUtil::fill(vals[j],col.data(j+first));
00604                                }
00605                        }
00606                        else if  ( type() == Tlong   || type() == VTlong )
00607                        {
00608                                long nullVal(0);
00609                                if (nullValue) nullVal  = static_cast<long>(*nullValue); 
00610                                ColumnVectorData<long>& col 
00611                                        = dynamic_cast<ColumnVectorData<long>&>(*this);
00612                                for (int j = 0; j < range; ++j) 
00613                                {
00614                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00615                                    FITSUtil::fill(vals[j],col.data(j+first));
00616                                }
00617                        }
00618                        else if  ( type() == Tlonglong   || type() == VTlonglong )
00619                        {
00620                                LONGLONG nullVal(0);
00621                                if (nullValue) nullVal  = static_cast<LONGLONG>(*nullValue); 
00622                                ColumnVectorData<LONGLONG>& col 
00623                                        = dynamic_cast<ColumnVectorData<LONGLONG>&>(*this);
00624                                for (int j = 0; j < range; ++j) 
00625                                {
00626                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00627                                    FITSUtil::fill(vals[j],col.data(j+first));
00628                                }
00629                        }
00630                        else if  ( type() == Tlogical   || type() == VTlogical )
00631                        {
00632                                bool nullVal(0);
00633                                if (nullValue) nullVal   = static_cast<bool>(*nullValue); 
00634                                ColumnVectorData<bool>& col 
00635                                        = dynamic_cast<ColumnVectorData<bool>&>(*this);
00636                                for (int j = 0; j < range; ++j) 
00637                                {
00638                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00639                                    FITSUtil::fill(vals[j],col.data(j+first));
00640                                }
00641                        }
00642                        else if (type() == Tbit || type() == Tbyte ||  
00643                                type() == VTbit || type() == VTbyte )
00644                        {
00645                                unsigned char nullVal(0);
00646                                if (nullValue) nullVal 
00647                                            = static_cast<unsigned char>(*nullValue); 
00648                                ColumnVectorData<unsigned char>& col 
00649                                       = dynamic_cast<ColumnVectorData<unsigned char>&>(*this);
00650                                for (int j = 0; j < range; ++j) 
00651                                {
00652                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00653                                    FITSUtil::fill(vals[j],col.data(j+first));
00654                                }
00655                        }                            
00656                        else if  ( type() == Tushort   || type() == VTushort )
00657                        {
00658                                unsigned short nullVal(0);
00659                                if (nullValue) nullVal 
00660                                            = static_cast<unsigned short>(*nullValue); 
00661                                ColumnVectorData<unsigned short>& col 
00662                                    = dynamic_cast<ColumnVectorData<unsigned short>&>(*this);
00663                                for (int j = 0; j < range; ++j) 
00664                                {
00665                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00666                                    FITSUtil::fill(vals[j],col.data(j+first));
00667                                }
00668                        }
00669                        else if  ( type() == Tuint   || type() == VTuint )
00670                        {
00671                                unsigned int nullVal(0);
00672                                if (nullValue) nullVal 
00673                                            = static_cast<unsigned int>(*nullValue); 
00674                                ColumnVectorData<unsigned int>& col 
00675                                        = dynamic_cast<ColumnVectorData<unsigned int>&>(*this);
00676                                for (int j = 0; j < range; ++j) 
00677                                {
00678                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00679                                    FITSUtil::fill(vals[j],col.data(j+first));
00680                                }
00681                        }
00682                        else if  ( type() == Tulong   || type() == VTulong  )
00683                        {
00684                                unsigned long nullVal(0);
00685                                if (nullValue) nullVal 
00686                                            = static_cast<unsigned long>(*nullValue); 
00687                                ColumnVectorData<unsigned long>& col 
00688                                      = dynamic_cast<ColumnVectorData<unsigned long>&>(*this);
00689                                for (int j = 0; j < range; ++j) 
00690                                {
00691                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00692                                    FITSUtil::fill(vals[j],col.data(j+first));
00693                                }
00694                        } 
00695                        else
00696                        {
00697                                throw InvalidDataType(name());
00698                        }
00699 
00700                    }
00701                    catch (std::bad_cast)
00702                    {
00703                        throw WrongColumnType(name());
00704 
00705                    }     
00706 
00707            }        
00708    }
00709 
00710    template <typename S>                   
00711    void Column::write (const std::vector<S>& indata, long firstRow)
00712    {
00713       // nullValue is now a pointer, so this is ok. 
00714       // got to cast the 0 to a pointer to S to avoid
00715       // overloading ambiguities.      
00716       write(indata,firstRow,static_cast<S*>(0));
00717    }
00718 
00719    template <typename S>                   
00720    void Column::write (const std::valarray<S>& indata, long firstRow)
00721    {
00722       size_t n(indata.size());
00723       std::vector<S> __tmp(n);
00724       for (size_t j = 0; j < n; ++j) __tmp[j] = indata[j];
00725       write(__tmp,firstRow,static_cast<S*>(0));
00726    }
00727 
00728    template <typename S>                   
00729    void Column::write (S* indata, long nRows, long firstRow)
00730    {
00731       write(indata,nRows,firstRow,static_cast<S*>(0));                
00732    }
00733 
00734 
00735    template <typename S>                   
00736    void Column::write (const std::vector<S>& indata, long firstRow, S* nullValue)
00737    {
00738       // although underlying code needs to convert the input vector
00739       // into a C array, this must be the underlying implementation
00740       // [which the others call] because it accepts string arguments
00741       // which the version with a pointer won't. [no version that
00742       // translates to a char** argument].
00743 
00744 
00745       parent()->makeThisCurrent();
00746       firstRow = std::max(firstRow,static_cast<long>(1));
00747       if (ColumnData<S>* col = dynamic_cast<ColumnData<S>*>(this))
00748       {
00749          col->writeData(indata,firstRow,nullValue);
00750       }
00751       else
00752       {
00753          // alright, input data type has to be rewritten as output
00754          // data type.
00755          FITSUtil::MatchType<S> inType;
00756          if ( inType() == type()) 
00757          {
00758                  String msg("Incorrect call: writing to vector column ");
00759                  msg += name();
00760                  msg += " requires specification of # rows or vector lengths";
00761                  throw WrongColumnType(msg);
00762          }
00763          else
00764          {
00765              if  ( type() == Tdouble )
00766              {
00767                  ColumnData<double>& col 
00768                          = dynamic_cast<ColumnData<double>&>(*this);
00769                  std::vector<double> __tmp;
00770                  FITSUtil::fill(__tmp,indata,1,indata.size());
00771                  col.writeData(__tmp,firstRow);
00772              }
00773              else if  ( type() == Tfloat )
00774              {
00775                  ColumnData<float>& col 
00776                          = dynamic_cast<ColumnData<float>&>(*this);
00777                  std::vector<float> __tmp;
00778                  FITSUtil::fill(__tmp,indata,1,indata.size());
00779                  col.writeData(__tmp,firstRow);
00780              }
00781              else if  ( type() == Tint )
00782              {
00783                  int nullVal = 0;
00784                  int* pNullVal = 0;
00785                  if (nullValue)
00786                  {
00787                     nullVal = static_cast<int>(*nullValue);
00788                     pNullVal = &nullVal;
00789                  }
00790                  if (nullValue) nullVal = static_cast<int>(*nullValue); 
00791                  ColumnData<int>& col  
00792                          = dynamic_cast<ColumnData<int>&>(*this);
00793                  std::vector<int> __tmp;
00794                  FITSUtil::fill(__tmp,indata,1,indata.size());
00795                  col.writeData(__tmp,firstRow,pNullVal);
00796              }
00797              else if  ( type() == Tshort )
00798              {
00799                  short nullVal(0);
00800                  short* pNullVal = 0;
00801                  if (nullValue) 
00802                  {
00803                     nullVal = static_cast<short>(*nullValue); 
00804                     pNullVal = &nullVal;
00805                  }
00806                  ColumnData<short>& col 
00807                          = dynamic_cast<ColumnData<short>&>(*this);
00808                  std::vector<short> __tmp;
00809                  FITSUtil::fill(__tmp,indata,1,indata.size());
00810                  col.writeData(__tmp,firstRow,pNullVal);
00811              }
00812              else if  ( type() == Tlong )
00813              {
00814                  long nullVal(0);
00815                  long* pNullVal = 0;
00816                  if (nullValue)
00817                  {
00818                     nullVal = static_cast<long>(*nullValue); 
00819                     pNullVal = &nullVal;
00820                  }
00821                  ColumnData<long>& col 
00822                          = dynamic_cast<ColumnData<long>&>(*this);
00823                  std::vector<long> __tmp;
00824                  FITSUtil::fill(__tmp,indata,1,indata.size());
00825                  col.writeData(__tmp,firstRow,pNullVal);
00826              }
00827              else if  ( type() == Tlonglong )
00828              {
00829                  LONGLONG nullVal(0);
00830                  LONGLONG* pNullVal = 0;
00831                  if (nullValue)
00832                  {
00833                     nullVal = static_cast<LONGLONG>(*nullValue); 
00834                     pNullVal = &nullVal;
00835                  }
00836                  ColumnData<LONGLONG>& col 
00837                          = dynamic_cast<ColumnData<LONGLONG>&>(*this);
00838                  std::vector<LONGLONG> __tmp;
00839                  FITSUtil::fill(__tmp,indata,1,indata.size());
00840                  col.writeData(__tmp,firstRow,pNullVal);
00841              }
00842              else if  ( type() == Tlogical )
00843              {
00844                  bool nullVal(0);
00845                  bool* pNullVal = 0;
00846                  if (nullValue)
00847                  {
00848                     nullVal = static_cast<bool>(*nullValue); 
00849                     pNullVal = &nullVal;
00850                  }
00851                  ColumnData<bool>& col 
00852                          = dynamic_cast<ColumnData<bool>&>(*this);
00853                  std::vector<bool> __tmp;
00854                  FITSUtil::fill(__tmp,indata,1,indata.size());
00855                  col.writeData(__tmp,firstRow,pNullVal);
00856              }
00857              else if  ( type() == Tbyte )
00858              {
00859                  unsigned char nullVal(0);
00860                  unsigned char* pNullVal = 0;
00861                  if (nullValue)
00862                  {
00863                     nullVal = static_cast<unsigned char>(*nullValue); 
00864                     pNullVal = &nullVal;
00865                  }
00866                  ColumnData<unsigned char>& col 
00867                          = dynamic_cast<ColumnData<unsigned char>&>(*this);
00868                  std::vector<unsigned char> __tmp;
00869                  FITSUtil::fill(__tmp,indata,1,indata.size());
00870                  col.writeData(__tmp,firstRow,pNullVal);
00871              }                            
00872              else if  ( type() == Tushort )
00873              {
00874                  unsigned short nullVal(0);
00875                  unsigned short* pNullVal = 0;
00876                  if (nullValue)
00877                  {
00878                     nullVal = static_cast<unsigned short>(*nullValue);
00879                     pNullVal = &nullVal;
00880                  } 
00881                  ColumnData<unsigned short>& col 
00882                          = dynamic_cast<ColumnData<unsigned short>&>(*this);
00883                  std::vector<unsigned short> __tmp;
00884                  FITSUtil::fill(__tmp,indata,1,indata.size());
00885                  col.writeData(__tmp,firstRow,pNullVal);
00886              }
00887              else if  ( type() == Tuint )
00888              {
00889                  unsigned int nullVal(0);
00890                  unsigned int* pNullVal = 0;
00891                  if (nullValue)
00892                  {
00893                     nullVal = static_cast<unsigned int>(*nullValue);
00894                     pNullVal = &nullVal;
00895                  } 
00896                  ColumnData<unsigned int>& col 
00897                          = dynamic_cast<ColumnData<unsigned int>&>(*this);
00898                  std::vector<unsigned int> __tmp;
00899                  FITSUtil::fill(__tmp,indata,1,indata.size());
00900                  col.writeData(__tmp,firstRow,pNullVal);
00901              }
00902              else if  ( type() == Tulong )
00903              {
00904                  unsigned long nullVal(0);
00905                  unsigned long* pNullVal = 0;
00906                  if (nullValue)
00907                  {
00908                     nullVal = static_cast<unsigned long>(*nullValue); 
00909                     pNullVal = &nullVal;
00910                  }
00911                  ColumnData<unsigned long>& col 
00912                          = dynamic_cast<ColumnData<unsigned long>&>(*this);
00913                  std::vector<unsigned long> __tmp;
00914                  FITSUtil::fill(__tmp,indata,1,indata.size());
00915                  col.writeData(__tmp,firstRow,pNullVal);
00916              } 
00917              else
00918              {
00919                      throw InvalidDataType(name());
00920              }
00921          }
00922       }
00923    }
00924 
00925 
00926    template <typename S>                   
00927    void Column::write (const std::valarray<S>& indata, long firstRow, S* nullValue)
00928    {
00929       // for scalar columns.        
00930       std::vector<S> __tmp;
00931       FITSUtil::fill(__tmp,indata);    
00932       write(__tmp,firstRow,nullValue);          
00933    }
00934 
00935    template <typename S>                   
00936    void Column::write (S* indata, long nRows, long firstRow, S* nullValue)
00937    {
00938       // for scalar columns, data specified with C array
00939       if (nRows <= 0) throw InvalidNumberOfRows(nRows);
00940       std::vector<S> __tmp(nRows);
00941       std::copy(&indata[0],&indata[nRows],__tmp.begin());
00942       write(__tmp,firstRow, nullValue);
00943 
00944    }
00945 
00946    template <typename S>
00947    void Column::write (const std::valarray<S>& indata, const std::vector<long>& vectorLengths,  
00948                            long firstRow)
00949    {
00950       // variable length arrays written from an input valarray.
00951       // does not allow NULL value.
00952 
00953       using namespace std;
00954       const size_t nRows = vectorLengths.size();
00955       // Calculate the sums of the vector lengths first simply to do a 
00956       //   check against the size of indata.
00957       vector<long> sums(nRows+1);
00958       sums[0] = 0;
00959       vector<long>::iterator itSums = sums.begin() + 1;
00960       partial_sum(vectorLengths.begin(), vectorLengths.end(), itSums);
00961       if (indata.size() < static_cast<size_t>(sums[nRows]))
00962       {
00963 #ifdef SSTREAM_DEFECT
00964          ostrstream msgStr;
00965 #else
00966          ostringstream msgStr;
00967 #endif            
00968          msgStr << " input data size: " << indata.size() << " vector length sum: " << sums[nRows];
00969 #ifdef SSTREAM_DEFECT
00970          msgStr << std::ends;
00971 #endif            
00972 
00973          String msg(msgStr.str());
00974          throw Column::InsufficientElements(msg);     
00975       }
00976       vector<valarray<S> > vvArray(nRows);
00977       for (size_t iRow=0; iRow<nRows; ++iRow)
00978       {
00979          valarray<S>& vArray = vvArray[iRow];
00980          long first = sums[iRow];
00981          long last = sums[iRow+1];
00982          vArray.resize(last - first);
00983          for (long iElem=first; iElem<last; ++iElem)
00984          {
00985             vArray[iElem - first] = indata[iElem];
00986          }
00987       }
00988       writeArrays(vvArray, firstRow, static_cast<S*>(0));  
00989    }
00990 
00991 template <typename S>
00992 void Column::write (const std::vector<S>& indata,const std::vector<long>& vectorLengths,
00993                       long firstRow)
00994    {
00995       // variable length write
00996       // implement as valarray version
00997       std::valarray<S> __tmp(indata.size());
00998       std::copy(indata.begin(),indata.end(),&__tmp[0]);
00999       write(__tmp,vectorLengths,firstRow);  
01000 
01001    }
01002 
01003    template <typename S>
01004    void Column::write (S* indata, long nelements, const std::vector<long>& vectorLengths,
01005                                    long firstRow)
01006    {
01007       // implement as valarray version, which will also check array size.
01008       size_t n(vectorLengths.size());
01009       std::valarray<S> __tmp(indata,nelements);
01010       write(__tmp,vectorLengths,firstRow);
01011    }        
01012 
01013    template <typename S>
01014    void Column::write (const std::valarray<S>& indata, long nRows, long firstRow)
01015    {
01016       write(indata,nRows,firstRow,static_cast<S*>(0));
01017    }
01018 
01019    template <typename S>
01020    void Column::write (const std::vector<S>& indata, long nRows, long firstRow)
01021    {
01022       write(indata,nRows,firstRow,static_cast<S*>(0));  
01023    }
01024 
01025    template <typename S>
01026    void Column::write (S* indata, long nelements, long nRows, long firstRow)
01027    {
01028       write(indata,nelements,nRows,firstRow,static_cast<S*>(0));              
01029    }        
01030 
01031 
01032 
01033    template <typename S>
01034    void Column::write (const std::valarray<S>& indata, long nRows, long firstRow,
01035                            S* nullValue)
01036    {
01037       // Write equivalent lengths of data to rows of a vector column.
01038       // The column may be either fixed or variable width, but if it's fixed
01039       // width the lengths must equal the column's repeat value or an
01040       // exception is thrown.
01041       if (nRows <= 0)
01042          throw InvalidNumberOfRows(nRows);
01043       firstRow = std::max(firstRow,static_cast<long>(1));
01044 #ifdef SSTREAM_DEFECT
01045       std::ostrstream msgStr;
01046 #else
01047       std::ostringstream msgStr;
01048 #endif 
01049       const size_t numRows = static_cast<size_t>(nRows);           
01050       if (indata.size() % numRows)
01051       {
01052          msgStr << "To use this write function, input array size"
01053             <<"\n must be exactly divisible by requested num rows: "
01054             << nRows;
01055          throw InsufficientElements(msgStr.str());
01056       }
01057       
01058       const size_t cellsize = indata.size()/numRows;
01059       if (!varLength() && cellsize != repeat() )
01060       {      
01061          msgStr << "column: " << name() 
01062                 <<  "\n input data size: " << indata.size() 
01063                 << " required: " << nRows*repeat();
01064          String msg(msgStr.str());
01065          throw InsufficientElements(msg);     
01066       }
01067       
01068       std::vector<std::valarray<S> > vvArray(numRows);
01069       for (size_t i=0; i<numRows; ++i)
01070       {
01071          vvArray[i].resize(cellsize);
01072          vvArray[i] = indata[std::slice(cellsize*i,cellsize,1)];
01073       }
01074       writeArrays(vvArray, firstRow, nullValue);
01075    }
01076 
01077    template <typename S>
01078    void Column::write (const std::vector<S>& indata, long nRows, long firstRow, S* nullValue)
01079    {
01080       // fixed length write of vector
01081       // implement as valarray version
01082       if (nRows <= 0) throw InvalidNumberOfRows(nRows);
01083       std::valarray<S> __tmp(indata.size());
01084       std::copy(indata.begin(),indata.end(),&__tmp[0]);
01085       write(__tmp,nRows,firstRow, nullValue);  
01086    }
01087 
01088    template <typename S>
01089    void Column::write (S* indata, long nelements, long nRows, long firstRow, S* nullValue)
01090    {
01091       // fixed length write of C-array
01092       // implement as valarray version
01093       if (nRows <= 0) throw InvalidNumberOfRows(nRows);
01094       std::valarray<S> __tmp(indata,nelements);
01095       write(__tmp,nRows,firstRow, nullValue);              
01096    }        
01097 
01098 
01099    template <typename S>
01100    void Column::writeArrays (const std::vector<std::valarray<S> >& indata, long firstRow)
01101    {
01102       // vector<valarray>, no null value. 
01103       writeArrays(indata,firstRow,static_cast<S*>(0));
01104    } 
01105 
01106    template <typename S>
01107    void Column::writeArrays (const std::vector<std::valarray<S> >& indata, long firstRow,
01108                                    S* nullValue)
01109    {
01110       // vector<valarray>, null value. primary
01111 
01112 
01113       using std::valarray;
01114       using std::vector;
01115       parent()->makeThisCurrent();
01116       firstRow = std::max(firstRow,static_cast<long>(1));
01117       if (ColumnVectorData<S>* col = dynamic_cast<ColumnVectorData<S>*>(this))
01118       {
01119           col->writeData(indata,firstRow,nullValue);
01120       }
01121       else
01122       {
01123          // alright, input data type has to be rewritten as output
01124          // data type.
01125          FITSUtil::MatchType<S> inType;
01126          if ( inType() == type()) 
01127          {
01128                  String msg("Incorrect call: writing vectors to scalar column ");
01129                  throw WrongColumnType(msg);
01130          }
01131          else
01132          {
01133              size_t n(indata.size());                            
01134              if  ( type() == Tdouble || type() == VTdouble)
01135              {
01136                  ColumnVectorData<double>& col 
01137                          = dynamic_cast<ColumnVectorData<double>&>(*this);
01138                  vector<valarray<double> > __tmp(n);
01139                  for (size_t i = 0; i < n; ++i)
01140                  {
01141                          FITSUtil::fill(__tmp[i],indata[i]);
01142                  }
01143                  col.writeData(__tmp,firstRow);
01144              }
01145              else if  ( type() == Tfloat || type() == VTfloat)
01146              {
01147                  ColumnVectorData<float>& col 
01148                          = dynamic_cast<ColumnVectorData<float>&>(*this);
01149                  vector<valarray<float> > __tmp(n);
01150                  for (size_t i = 0; i < n; ++i)
01151                  {
01152                          FITSUtil::fill(__tmp[i],indata[i]);
01153                  }                                
01154                  col.writeData(__tmp,firstRow);
01155              }
01156              else if  ( type() == Tint || type() == VTint)
01157              {
01158                  ColumnVectorData<int>& col  
01159                          = dynamic_cast<ColumnVectorData<int>&>(*this);
01160                  vector<valarray<int> > __tmp(n);
01161                  int nullVal(0);
01162                  int* pNullVal = 0;
01163                  if (nullValue)
01164                  {
01165                     nullVal = static_cast<int>(*nullValue);
01166                     pNullVal = &nullVal;
01167                  }
01168                  for (size_t i = 0; i < n; ++i)
01169                  {
01170                          FITSUtil::fill(__tmp[i],indata[i]);
01171                  }                                
01172                  col.writeData(__tmp,firstRow,pNullVal);
01173              }
01174              else if  ( type() == Tshort || type() == VTshort)
01175              {
01176                  ColumnVectorData<short>& col 
01177                          = dynamic_cast<ColumnVectorData<short>&>(*this);
01178                  vector<valarray<short> > __tmp(n);
01179                  short nullVal(0);
01180                  short* pNullVal = 0;
01181                  if (nullValue)
01182                  {
01183                     nullVal = static_cast<short>(*nullValue);
01184                     pNullVal = &nullVal;
01185                  }
01186                  for (size_t i = 0; i < n; ++i)
01187                  {
01188                          FITSUtil::fill(__tmp[i],indata[i]);
01189                  }                                
01190                  col.writeData(__tmp,firstRow,pNullVal);
01191              }
01192              else if  ( type() == Tlong || type() == VTlong)
01193              {
01194                  ColumnVectorData<long>& col 
01195                          = dynamic_cast<ColumnVectorData<long>&>(*this);
01196                  vector<valarray<long> > __tmp(n);
01197                  long nullVal(0);
01198                  long* pNullVal = 0;
01199                  if (nullValue)
01200                  {
01201                     nullVal = static_cast<long>(*nullValue);
01202                     pNullVal = &nullVal;
01203                  }
01204                  for (size_t i = 0; i < n; ++i)
01205                  {
01206                          FITSUtil::fill(__tmp[i],indata[i]);
01207                  }                                
01208                  col.writeData(__tmp,firstRow,pNullVal);
01209              }
01210              else if  ( type() == Tlonglong || type() == VTlonglong)
01211              {
01212                  ColumnVectorData<LONGLONG>& col 
01213                          = dynamic_cast<ColumnVectorData<LONGLONG>&>(*this);
01214                  vector<valarray<LONGLONG> > __tmp(n);
01215                  LONGLONG nullVal(0);
01216                  LONGLONG* pNullVal = 0;
01217                  if (nullValue)
01218                  {
01219                     nullVal = static_cast<LONGLONG>(*nullValue);
01220                     pNullVal = &nullVal;
01221                  }
01222                  for (size_t i = 0; i < n; ++i)
01223                  {
01224                          FITSUtil::fill(__tmp[i],indata[i]);
01225                  }                                
01226                  col.writeData(__tmp,firstRow,pNullVal);
01227              }
01228              else if  ( type() == Tlogical || type() == VTlogical)
01229              {
01230                  ColumnVectorData<bool>& col 
01231                          = dynamic_cast<ColumnVectorData<bool>&>(*this);
01232                  bool nullVal(0);
01233                  bool* pNullVal = 0;
01234                  if (nullValue)
01235                  {
01236                     nullVal = static_cast<bool>(*nullValue);
01237                     pNullVal = &nullVal;
01238                  }
01239                  vector<valarray<bool> > __tmp(n);
01240                  for (size_t i = 0; i < n; ++i)
01241                  {
01242                          FITSUtil::fill(__tmp[i],indata[i]);
01243                  }                                
01244                  col.writeData(__tmp,firstRow,pNullVal);
01245              }
01246              else if  ( type() == Tbyte || type() == VTbyte)
01247              {
01248                  ColumnVectorData<unsigned char>& col 
01249                          = dynamic_cast<ColumnVectorData<unsigned char>&>(*this);
01250                  unsigned char nullVal(0);
01251                  unsigned char* pNullVal = 0;
01252                  if (nullValue)
01253                  {
01254                     nullVal = static_cast<unsigned char>(*nullValue);
01255                     pNullVal = &nullVal;
01256                  }
01257                  vector<valarray<unsigned char> > __tmp(n);
01258                  for (size_t i = 0; i < n; ++i)
01259                  {
01260                          FITSUtil::fill(__tmp[i],indata[i]);
01261                  }                                                                
01262                  col.writeData(__tmp,firstRow,&nullVal);
01263              }                            
01264              else if  ( type() == Tushort || type() == VTushort)
01265              {
01266                  ColumnVectorData<unsigned short>& col 
01267                          = dynamic_cast<ColumnVectorData<unsigned short>&>(*this);
01268                  unsigned short nullVal(0);
01269                  unsigned short* pNullVal = 0;
01270                  if (nullValue)
01271                  {
01272                     nullVal = static_cast<unsigned short>(*nullValue);
01273                     pNullVal = &nullVal;
01274                  }
01275                  vector<valarray<unsigned short> > __tmp(n);
01276                  for (size_t i = 0; i < n; ++i)
01277                  {
01278                          FITSUtil::fill(__tmp[i],indata[i]);
01279                  }                                
01280                  col.writeData(__tmp,firstRow,pNullVal);
01281              }
01282              else if  ( type() == Tuint || type() == VTuint)
01283              {
01284                  ColumnVectorData<unsigned int>& col 
01285                          = dynamic_cast<ColumnVectorData<unsigned int>&>(*this);
01286                  unsigned int nullVal(0);
01287                  unsigned int* pNullVal = 0;
01288                  if (nullValue)
01289                  {
01290                     nullVal = static_cast<unsigned int>(*nullValue);
01291                     pNullVal = &nullVal;
01292                  }
01293                  vector<valarray<unsigned int> > __tmp(n);
01294                  for (size_t i = 0; i < n; ++i)
01295                  {
01296                          FITSUtil::fill(__tmp[i],indata[i]);
01297                  }                                
01298                  col.writeData(__tmp,firstRow,pNullVal);
01299              }
01300              else if  ( type() == Tulong || type() == VTulong)
01301              {
01302                  ColumnVectorData<unsigned long>& col 
01303                          = dynamic_cast<ColumnVectorData<unsigned long>&>(*this);
01304                  unsigned long nullVal(0);
01305                  unsigned long* pNullVal = 0;
01306                  if (nullValue)
01307                  {
01308                     nullVal = static_cast<unsigned long>(*nullValue);
01309                     pNullVal = &nullVal;
01310                  }
01311                  vector<valarray<unsigned long> > __tmp(n);
01312                  for (size_t i = 0; i < n; ++i)
01313                  {
01314                          FITSUtil::fill(__tmp[i],indata[i]);
01315                  }                                
01316                  col.writeData(__tmp,firstRow,pNullVal);
01317              } 
01318              else
01319              {
01320                      throw InvalidDataType(name());
01321              }
01322          }
01323       }
01324    } 
01325 
01326 
01327    template <typename T>
01328    void Column::addNullValue(T nullVal)
01329    {
01330       parent()->makeThisCurrent();
01331       int status(0);
01332 #ifdef SSTREAM_DEFECT
01333       std::ostrstream keyName;
01334       keyName << "TNULL" << index() << std::ends;
01335       char* nullKey = const_cast<char*>(keyName.str());
01336 #else
01337       std::ostringstream keyName;          
01338       keyName << "TNULL" << index();
01339       String keyNameStr = keyName.str();
01340       char* nullKey = const_cast<char*>(keyNameStr.c_str());
01341 #endif
01342 
01343 
01344       FITSUtil::MatchType<T> inputType;
01345       int dataType = static_cast<int>(inputType());
01346       if (dataType == static_cast<int>(Tstring))
01347          throw InvalidDataType("attempting to set TNULLn to a string.");
01348 
01349       // update key but don't add to keyword list because it's really a column
01350       // property not a table metadata property. And it needs to be automatically
01351       // renumbered if columns are inserted or deleted.
01352       if (fits_update_key(fitsPointer(),dataType,nullKey,&nullVal,0,&status))
01353               throw FitsError(status);
01354 
01355       // The following is called to make sure the HDU struct is immediately 
01356       // updated in case a column write operation is performed shortly after this
01357       // function exits. 
01358       if (fits_set_hdustruc(fitsPointer(),&status)) throw FitsError(status); 
01359 
01360    }
01361 
01362    template <typename T>
01363    bool Column::getNullValue(T* nullVal) const
01364    {
01365       parent()->makeThisCurrent();
01366 #ifdef SSTREAM_DEFECT
01367       std::ostrstream keyName;
01368       keyName << "TNULL" << index() << std::ends;
01369       char* nullKey = const_cast<char*>(keyName.str());
01370 #else
01371       std::ostringstream keyName;          
01372       keyName << "TNULL" << index();
01373       String keyNameStr = keyName.str();
01374       char* nullKey = const_cast<char*>(keyNameStr.c_str());
01375 #endif
01376 
01377       int status=0;
01378       FITSUtil::MatchType<T> inputType;
01379       int dataType = static_cast<int>(inputType());
01380       if (dataType == static_cast<int>(Tstring))
01381          throw InvalidDataType("attempting to read TNULLn into a string.");
01382       T tmpVal(*nullVal);
01383 
01384       bool keyExists = false;
01385       if (fits_read_key(m_parent->fitsPointer(), dataType, nullKey, &tmpVal, 0, &status))
01386       {
01387          if (status == KEY_NO_EXIST  || status == VALUE_UNDEFINED)
01388             return keyExists;
01389          else
01390             throw FitsError(status);
01391       }
01392       keyExists = true;
01393       *nullVal = tmpVal;       
01394       return keyExists;
01395    }
01396 
01397 } // namespace CCfits
01398 
01399 #endif