CCfits  2.5
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    template <typename S>
00359    void Column::read(std::vector<S>& vals, long row) 
00360    {
00361            read(vals,row,static_cast<S*>(0));
00362    }
00363 
00364    template <typename S>
00365    void Column::read(std::vector<S>& vals, long row, S* nullValue) 
00366    {
00367            if (row > parent()->rows())
00368            {
00369               throw Column::InvalidRowNumber(name());
00370            }
00371            parent()->makeThisCurrent();                
00372            // isRead() returns true if the data were read in the ctor.
00373            if ( ColumnVectorData<S>* col = dynamic_cast<ColumnVectorData<S>*>(this))
00374            {
00375                    // fails if user requested outputType different from input type.
00376 
00377 
00378                    if (!isRead()) col->readRow(row,nullValue);
00379                    FITSUtil::fill(vals,col->data(row));
00380            }
00381            else
00382            {
00383                    FITSUtil::MatchType<S> outputType;
00384                    if ( outputType() == type() ) 
00385                    { 
00386                            // in this case user tried to read vector row from scalar column.
00387                            // one could be charitable and return a valarray of size 1,
00388                            // but... I'm going to throw an exception suggesting the user
00389                            // might not have meant that.
00390 
00391                            throw Column::WrongColumnType(name());
00392                    }
00393 
00394                    // the InvalidDataType exception should not be possible.
00395                    try
00396                    {
00397                        // about exceptions. The dynamic_casts could throw
00398                        // std::bad_cast. If this happens something is seriously
00399                        // wrong since the Column stores the value of type() 
00400                        // appropriate to each of the casts on construction.
00401                        // 
00402                        // the InvalidDataType exception should not be possible.
00403                        if  ( type() == Tdouble || type() == VTdouble )
00404                        {
00405                                ColumnVectorData<double>& col 
00406                                          = dynamic_cast<ColumnVectorData<double>&>(*this);
00407                                if (!isRead()) col.readRow(row);                                  
00408                                FITSUtil::fill(vals,col.data(row));
00409 
00410                        }
00411                        else if (type() == Tfloat  || type() == VTfloat )
00412                        { 
00413                                ColumnVectorData<float>& col 
00414                                      = dynamic_cast<ColumnVectorData<float>&>(*this);
00415                                if (!isRead()) col.readRow(row); 
00416                                FITSUtil::fill(vals,col.data(row));
00417                        }
00418                        else if (type() == Tint  || type() == VTint )
00419                        {
00420                                int nullVal(0);
00421                                if (nullValue) nullVal = static_cast<int>(*nullValue); 
00422                                ColumnVectorData<int>& col  
00423                                        = dynamic_cast<ColumnVectorData<int>&>(*this);
00424                                if (!isRead()) col.readRow(row,&nullVal); 
00425                                FITSUtil::fill(vals,col.data(row));
00426                        }
00427                        else if (type() == Tshort  || type() == VTshort  )
00428                        {
00429                                short nullVal(0);
00430                                if (nullValue) nullVal = static_cast<short>(*nullValue); 
00431                                ColumnVectorData<short>& col 
00432                                        = dynamic_cast<ColumnVectorData<short>&>(*this);
00433                                if (!isRead()) col.readRow(row,&nullVal); 
00434                                FITSUtil::fill(vals,col.data(row));
00435                        }
00436                        else if (type() == Tlong  || type() == VTlong )
00437                        {        
00438                                long nullVal(0);
00439                                if (nullValue) nullVal = static_cast<long>(*nullValue); 
00440                                ColumnVectorData<long>& col 
00441                                        = dynamic_cast<ColumnVectorData<long>&>(*this);
00442                                if (!isRead()) col.readRow(row,&nullVal); 
00443                                FITSUtil::fill(vals,col.data(row));
00444                        }
00445                        else if (type() == Tlonglong  || type() == VTlonglong )
00446                        {        
00447                                LONGLONG nullVal(0);
00448                                if (nullValue) nullVal = static_cast<LONGLONG>(*nullValue); 
00449                                ColumnVectorData<LONGLONG>& col 
00450                                        = dynamic_cast<ColumnVectorData<LONGLONG>&>(*this);
00451                                if (!isRead()) col.readRow(row,&nullVal); 
00452                                FITSUtil::fill(vals,col.data(row));
00453                        }
00454                        else if (type() == Tlogical  || type() == VTlogical )
00455                        {        
00456                                bool nullVal(0);
00457                                if (nullValue) nullVal = static_cast<bool>(*nullValue); 
00458                                ColumnVectorData<bool>& col 
00459                                        = dynamic_cast<ColumnVectorData<bool>&>(*this);
00460                                if (!isRead()) col.readRow(row,&nullVal); 
00461                                FITSUtil::fill(vals,col.data(row));
00462                        }
00463                        else if (type() == Tbit || type() == Tbyte ||  
00464                                type() == VTbit || type() == VTbyte )
00465                        {
00466                                unsigned char nullVal(0);
00467                                if (nullValue) nullVal 
00468                                            = static_cast<unsigned char>(*nullValue); 
00469                                ColumnVectorData<unsigned char>& col 
00470                                      = dynamic_cast<ColumnVectorData<unsigned char>&>(*this);
00471                                if (!isRead()) col.readRow(row,&nullVal); 
00472                                FITSUtil::fill(vals,col.data(row));
00473                        }
00474                        else if (type() == Tushort || type() == VTushort)
00475                        {
00476                                unsigned short nullVal(0);
00477                                if (nullValue) nullVal 
00478                                            = static_cast<unsigned short>(*nullValue); 
00479                                ColumnVectorData<unsigned short>& col 
00480                                      = dynamic_cast<ColumnVectorData<unsigned short>&>(*this);
00481                                if (!isRead()) col.readRow(row,&nullVal); 
00482                                FITSUtil::fill(vals,col.data(row));
00483                        }
00484                        else if (type() == Tuint || type() == VTuint)
00485                        {
00486                                unsigned int nullVal(0);
00487                                if (nullValue) nullVal 
00488                                            = static_cast<unsigned int>(*nullValue); 
00489                                ColumnVectorData<unsigned int>& col 
00490                                      = dynamic_cast<ColumnVectorData<unsigned int>&>(*this);
00491                                if (!isRead()) col.readRow(row,&nullVal); 
00492                                FITSUtil::fill(vals,col.data(row));
00493                        }
00494                        else if (type() == Tulong || type() == VTulong)
00495                        {
00496                                unsigned long nullVal(0);
00497                                if (nullValue) nullVal 
00498                                            = static_cast<unsigned long>(*nullValue); 
00499                                ColumnVectorData<unsigned long>& col 
00500                                        = dynamic_cast<ColumnVectorData<unsigned long>&>(*this);
00501                                if (!isRead()) col.readRow(row,&nullVal); 
00502                                FITSUtil::fill(vals,col.data(row));
00503                        }
00504                        else
00505                        {
00506                                throw InvalidDataType(name());
00507 
00508                        }
00509 
00510                    }
00511                    catch (std::bad_cast)
00512                    {
00513                        throw WrongColumnType(name());
00514                    }     
00515             }
00516    }
00517 
00518    template <typename S>
00519    void Column::read(std::valarray<S>& vals, long row, S* nullValue) 
00520    {
00521            if (row > parent()->rows())
00522            {
00523               throw Column::InvalidRowNumber(name());
00524            }
00525            parent()->makeThisCurrent();                
00526            // isRead() returns true if the data were read in the ctor.
00527            if ( ColumnVectorData<S>* col = dynamic_cast<ColumnVectorData<S>*>(this))
00528            {
00529                    // fails if user requested outputType different from input type.
00530 
00531 
00532 
00533                    // input and output are both valarrays. Since one should not
00534                    // be able to call a constructor for a non-numeric valarray type,
00535                    // there shouldn't be any InvalidType problems. However, there
00536                    // is still the vector/scalar possibility and the implicit
00537                    // conversion request to deal with.
00538 
00539                    if (!isRead()) col->readRow(row,nullValue);
00540                    FITSUtil::fill(vals,col->data(row));
00541            }
00542            else
00543            {
00544                    FITSUtil::MatchType<S> outputType;
00545                    if ( outputType() == type() ) 
00546                    { 
00547                            // in this case user tried to read vector row from scalar column.
00548                            // one could be charitable and return a valarray of size 1,
00549                            // but... I'm going to throw an exception suggesting the user
00550                            // might not have meant that.
00551 
00552                            throw Column::WrongColumnType(name());
00553                    }
00554 
00555                    // the InvalidDataType exception should not be possible.
00556                    try
00557                    {
00558                        // about exceptions. The dynamic_casts could throw
00559                        // std::bad_cast. If this happens something is seriously
00560                        // wrong since the Column stores the value of type() 
00561                        // appropriate to each of the casts on construction.
00562                        // 
00563                        // the InvalidDataType exception should not be possible.
00564                        if  ( type() == Tdouble || type() == VTdouble )
00565                        {
00566                                ColumnVectorData<double>& col 
00567                                          = dynamic_cast<ColumnVectorData<double>&>(*this);
00568                                if (!isRead()) col.readRow(row);                                  
00569                                FITSUtil::fill(vals,col.data(row));
00570 
00571                        }
00572                        else if (type() == Tfloat  || type() == VTfloat )
00573                        { 
00574                                ColumnVectorData<float>& col 
00575                                      = dynamic_cast<ColumnVectorData<float>&>(*this);
00576                                if (!isRead()) col.readRow(row); 
00577                                FITSUtil::fill(vals,col.data(row));
00578                        }
00579                        else if (type() == Tint  || type() == VTint )
00580                        {
00581                                int nullVal(0);
00582                                if (nullValue) nullVal = static_cast<int>(*nullValue); 
00583                                ColumnVectorData<int>& col  
00584                                        = dynamic_cast<ColumnVectorData<int>&>(*this);
00585                                if (!isRead()) col.readRow(row,&nullVal); 
00586                                FITSUtil::fill(vals,col.data(row));
00587                        }
00588                        else if (type() == Tshort  || type() == VTshort  )
00589                        {
00590                                short nullVal(0);
00591                                if (nullValue) nullVal = static_cast<short>(*nullValue); 
00592                                ColumnVectorData<short>& col 
00593                                        = dynamic_cast<ColumnVectorData<short>&>(*this);
00594                                if (!isRead()) col.readRow(row,&nullVal); 
00595                                FITSUtil::fill(vals,col.data(row));
00596                        }
00597                        else if (type() == Tlong  || type() == VTlong )
00598                        {        
00599                                long nullVal(0);
00600                                if (nullValue) nullVal = static_cast<long>(*nullValue); 
00601                                ColumnVectorData<long>& col 
00602                                        = dynamic_cast<ColumnVectorData<long>&>(*this);
00603                                if (!isRead()) col.readRow(row,&nullVal); 
00604                                FITSUtil::fill(vals,col.data(row));
00605                        }
00606                        else if (type() == Tlonglong  || type() == VTlonglong )
00607                        {        
00608                                LONGLONG nullVal(0);
00609                                if (nullValue) nullVal = static_cast<LONGLONG>(*nullValue); 
00610                                ColumnVectorData<LONGLONG>& col 
00611                                        = dynamic_cast<ColumnVectorData<LONGLONG>&>(*this);
00612                                if (!isRead()) col.readRow(row,&nullVal); 
00613                                FITSUtil::fill(vals,col.data(row));
00614                        }
00615                        else if (type() == Tlogical  || type() == VTlogical )
00616                        {        
00617                                bool nullVal(0);
00618                                if (nullValue) nullVal = static_cast<bool>(*nullValue); 
00619                                ColumnVectorData<bool>& col 
00620                                        = dynamic_cast<ColumnVectorData<bool>&>(*this);
00621                                if (!isRead()) col.readRow(row,&nullVal); 
00622                                FITSUtil::fill(vals,col.data(row));
00623                        }
00624                        else if (type() == Tbit || type() == Tbyte ||  
00625                                type() == VTbit || type() == VTbyte )
00626                        {
00627                                unsigned char nullVal(0);
00628                                if (nullValue) nullVal 
00629                                            = static_cast<unsigned char>(*nullValue); 
00630                                ColumnVectorData<unsigned char>& col 
00631                                      = dynamic_cast<ColumnVectorData<unsigned char>&>(*this);
00632                                if (!isRead()) col.readRow(row,&nullVal); 
00633                                FITSUtil::fill(vals,col.data(row));
00634                        }
00635                        else if (type() == Tushort || type() == VTushort)
00636                        {
00637                                unsigned short nullVal(0);
00638                                if (nullValue) nullVal 
00639                                            = static_cast<unsigned short>(*nullValue); 
00640                                ColumnVectorData<unsigned short>& col 
00641                                      = dynamic_cast<ColumnVectorData<unsigned short>&>(*this);
00642                                if (!isRead()) col.readRow(row,&nullVal); 
00643                                FITSUtil::fill(vals,col.data(row));
00644                        }
00645                        else if (type() == Tuint || type() == VTuint)
00646                        {
00647                                unsigned int nullVal(0);
00648                                if (nullValue) nullVal 
00649                                            = static_cast<unsigned int>(*nullValue); 
00650                                ColumnVectorData<unsigned int>& col 
00651                                      = dynamic_cast<ColumnVectorData<unsigned int>&>(*this);
00652                                if (!isRead()) col.readRow(row,&nullVal); 
00653                                FITSUtil::fill(vals,col.data(row));
00654                        }
00655                        else if (type() == Tulong || type() == VTulong)
00656                        {
00657                                unsigned long nullVal(0);
00658                                if (nullValue) nullVal 
00659                                            = static_cast<unsigned long>(*nullValue); 
00660                                ColumnVectorData<unsigned long>& col 
00661                                        = dynamic_cast<ColumnVectorData<unsigned long>&>(*this);
00662                                if (!isRead()) col.readRow(row,&nullVal); 
00663                                FITSUtil::fill(vals,col.data(row));
00664                        }
00665                        else
00666                        {
00667                                throw InvalidDataType(name());
00668 
00669                        }
00670 
00671                    }
00672                    catch (std::bad_cast)
00673                    {
00674                        throw WrongColumnType(name());
00675                    }     
00676             }
00677    }
00678 
00679    template <typename S>
00680    void Column::readArrays(std::vector<std::valarray<S> >& vals, long first, long last)  
00681    {
00682            readArrays(vals,first,last,static_cast<S*>(0));
00683    }
00684 
00685    template <typename S>
00686    void Column::readArrays(std::vector<std::valarray<S> >& vals, 
00687                            long first, long last, S* nullValue)
00688    {
00689 
00690            parent()->makeThisCurrent();
00691            // again, can only call this if the entire column has been read from disk.
00692            // user expects 1 based indexing. If 0 based indices are supplied,
00693            // add one to both ranges.
00694            long range = numberOfElements(first,last);
00695 
00696            vals.resize(range);
00697 
00698 
00699            if ( ColumnVectorData<S>* col = dynamic_cast<ColumnVectorData<S>*>(this))
00700            {
00701                    for (int j = 0; j < range; ++j) 
00702                    {
00703                            if (!isRead()) col->readRow(j + first,nullValue);                             
00704                            FITSUtil::fill(vals[j],col->data(j+first));
00705                    }
00706            }
00707            else
00708            {
00709                    FITSUtil::MatchType<S> outputType;
00710                    if ( outputType() == type() ) 
00711                    { 
00712                            // in this case user tried to read vector data from scalar,
00713                            // (i.e. first argument was vector<valarray<S> >.
00714                            // since the cast won't fail on template parameter grounds.
00715                            throw Column::WrongColumnType(name());
00716                    }
00717                    // the InvalidDataType exception should not be possible.
00718                    try
00719                    {
00720                        if  ( type() == Tdouble || type() == VTdouble )
00721                        {
00722                                ColumnVectorData<double>& col 
00723                                        = dynamic_cast<ColumnVectorData<double>&>(*this);
00724                                for (int j = 0; j < range; ++j) 
00725                                {
00726                                    if (!isRead()) col.readRow(j + first); 
00727                                    FITSUtil::fill(vals[j],col.data(j+first));
00728                                }
00729                        }
00730                        else if  ( type() == Tfloat || type() == VTfloat  )
00731                        {
00732                                ColumnVectorData<float>& col 
00733                                        = dynamic_cast<ColumnVectorData<float>&>(*this);
00734                                for (int j = 0; j < range; ++j) 
00735                                {
00736                                    if (!isRead()) col.readRow(j + first); 
00737                                    FITSUtil::fill(vals[j],col.data(j+first));
00738                                }
00739                        }
00740                        else if  ( type() == Tint   || type() == VTint )
00741                        {
00742                                int nullVal(0);
00743                                if (nullValue) nullVal  = static_cast<int>(*nullValue); 
00744                                ColumnVectorData<int>& col  
00745                                        = dynamic_cast<ColumnVectorData<int>&>(*this);
00746                                for (int j = 0; j < range; ++j) 
00747                                {
00748                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00749                                    FITSUtil::fill(vals[j],col.data(j+first));
00750                                }
00751                        }
00752                        else if  ( type() == Tshort  || type() == VTshort )
00753                        {
00754                                short nullVal(0);
00755                                if (nullValue) nullVal  = static_cast<short>(*nullValue); 
00756                                ColumnVectorData<short>& col 
00757                                        = dynamic_cast<ColumnVectorData<short>&>(*this);
00758                                for (int j = 0; j < range; ++j) 
00759                                {
00760                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00761                                    FITSUtil::fill(vals[j],col.data(j+first));
00762                                }
00763                        }
00764                        else if  ( type() == Tlong   || type() == VTlong )
00765                        {
00766                                long nullVal(0);
00767                                if (nullValue) nullVal  = static_cast<long>(*nullValue); 
00768                                ColumnVectorData<long>& col 
00769                                        = dynamic_cast<ColumnVectorData<long>&>(*this);
00770                                for (int j = 0; j < range; ++j) 
00771                                {
00772                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00773                                    FITSUtil::fill(vals[j],col.data(j+first));
00774                                }
00775                        }
00776                        else if  ( type() == Tlonglong   || type() == VTlonglong )
00777                        {
00778                                LONGLONG nullVal(0);
00779                                if (nullValue) nullVal  = static_cast<LONGLONG>(*nullValue); 
00780                                ColumnVectorData<LONGLONG>& col 
00781                                        = dynamic_cast<ColumnVectorData<LONGLONG>&>(*this);
00782                                for (int j = 0; j < range; ++j) 
00783                                {
00784                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00785                                    FITSUtil::fill(vals[j],col.data(j+first));
00786                                }
00787                        }
00788                        else if  ( type() == Tlogical   || type() == VTlogical )
00789                        {
00790                                bool nullVal(0);
00791                                if (nullValue) nullVal   = static_cast<bool>(*nullValue); 
00792                                ColumnVectorData<bool>& col 
00793                                        = dynamic_cast<ColumnVectorData<bool>&>(*this);
00794                                for (int j = 0; j < range; ++j) 
00795                                {
00796                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00797                                    FITSUtil::fill(vals[j],col.data(j+first));
00798                                }
00799                        }
00800                        else if (type() == Tbit || type() == Tbyte ||  
00801                                type() == VTbit || type() == VTbyte )
00802                        {
00803                                unsigned char nullVal(0);
00804                                if (nullValue) nullVal 
00805                                            = static_cast<unsigned char>(*nullValue); 
00806                                ColumnVectorData<unsigned char>& col 
00807                                       = dynamic_cast<ColumnVectorData<unsigned char>&>(*this);
00808                                for (int j = 0; j < range; ++j) 
00809                                {
00810                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00811                                    FITSUtil::fill(vals[j],col.data(j+first));
00812                                }
00813                        }                            
00814                        else if  ( type() == Tushort   || type() == VTushort )
00815                        {
00816                                unsigned short nullVal(0);
00817                                if (nullValue) nullVal 
00818                                            = static_cast<unsigned short>(*nullValue); 
00819                                ColumnVectorData<unsigned short>& col 
00820                                    = dynamic_cast<ColumnVectorData<unsigned short>&>(*this);
00821                                for (int j = 0; j < range; ++j) 
00822                                {
00823                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00824                                    FITSUtil::fill(vals[j],col.data(j+first));
00825                                }
00826                        }
00827                        else if  ( type() == Tuint   || type() == VTuint )
00828                        {
00829                                unsigned int nullVal(0);
00830                                if (nullValue) nullVal 
00831                                            = static_cast<unsigned int>(*nullValue); 
00832                                ColumnVectorData<unsigned int>& col 
00833                                        = dynamic_cast<ColumnVectorData<unsigned int>&>(*this);
00834                                for (int j = 0; j < range; ++j) 
00835                                {
00836                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00837                                    FITSUtil::fill(vals[j],col.data(j+first));
00838                                }
00839                        }
00840                        else if  ( type() == Tulong   || type() == VTulong  )
00841                        {
00842                                unsigned long nullVal(0);
00843                                if (nullValue) nullVal 
00844                                            = static_cast<unsigned long>(*nullValue); 
00845                                ColumnVectorData<unsigned long>& col 
00846                                      = dynamic_cast<ColumnVectorData<unsigned long>&>(*this);
00847                                for (int j = 0; j < range; ++j) 
00848                                {
00849                                    if (!isRead()) col.readRow(j + first,&nullVal); 
00850                                    FITSUtil::fill(vals[j],col.data(j+first));
00851                                }
00852                        } 
00853                        else
00854                        {
00855                                throw InvalidDataType(name());
00856                        }
00857 
00858                    }
00859                    catch (std::bad_cast)
00860                    {
00861                        throw WrongColumnType(name());
00862 
00863                    }     
00864 
00865            }        
00866    }
00867 
00868    template <typename S>                   
00869    void Column::write (const std::vector<S>& indata, long firstRow)
00870    {
00871       // nullValue is now a pointer, so this is ok. 
00872       // got to cast the 0 to a pointer to S to avoid
00873       // overloading ambiguities.      
00874       write(indata,firstRow,static_cast<S*>(0));
00875    }
00876 
00877    template <typename S>                   
00878    void Column::write (const std::valarray<S>& indata, long firstRow)
00879    {
00880       size_t n(indata.size());
00881       std::vector<S> __tmp(n);
00882       for (size_t j = 0; j < n; ++j) __tmp[j] = indata[j];
00883       write(__tmp,firstRow,static_cast<S*>(0));
00884    }
00885 
00886    template <typename S>                   
00887    void Column::write (S* indata, long nRows, long firstRow)
00888    {
00889       write(indata,nRows,firstRow,static_cast<S*>(0));                
00890    }
00891 
00892 
00893    template <typename S>                   
00894    void Column::write (const std::vector<S>& indata, long firstRow, S* nullValue)
00895    {
00896       // although underlying code needs to convert the input vector
00897       // into a C array, this must be the underlying implementation
00898       // [which the others call] because it accepts string arguments
00899       // which the version with a pointer won't. [no version that
00900       // translates to a char** argument].
00901 
00902 
00903       parent()->makeThisCurrent();
00904       firstRow = std::max(firstRow,static_cast<long>(1));
00905       if (ColumnData<S>* col = dynamic_cast<ColumnData<S>*>(this))
00906       {
00907          col->writeData(indata,firstRow,nullValue);
00908       }
00909       else
00910       {
00911          // alright, input data type has to be rewritten as output
00912          // data type.
00913          FITSUtil::MatchType<S> inType;
00914          if ( inType() == type()) 
00915          {
00916                  String msg("Incorrect call: writing to vector column ");
00917                  msg += name();
00918                  msg += " requires specification of # rows or vector lengths";
00919                  throw WrongColumnType(msg);
00920          }
00921          else
00922          {
00923              if  ( type() == Tdouble )
00924              {
00925                  ColumnData<double>& col 
00926                          = dynamic_cast<ColumnData<double>&>(*this);
00927                  std::vector<double> __tmp;
00928                  FITSUtil::fill(__tmp,indata,1,indata.size());
00929                  col.writeData(__tmp,firstRow);
00930              }
00931              else if  ( type() == Tfloat )
00932              {
00933                  ColumnData<float>& col 
00934                          = dynamic_cast<ColumnData<float>&>(*this);
00935                  std::vector<float> __tmp;
00936                  FITSUtil::fill(__tmp,indata,1,indata.size());
00937                  col.writeData(__tmp,firstRow);
00938              }
00939              else if  ( type() == Tint )
00940              {
00941                  int nullVal = 0;
00942                  int* pNullVal = 0;
00943                  if (nullValue)
00944                  {
00945                     nullVal = static_cast<int>(*nullValue);
00946                     pNullVal = &nullVal;
00947                  }
00948                  if (nullValue) nullVal = static_cast<int>(*nullValue); 
00949                  ColumnData<int>& col  
00950                          = dynamic_cast<ColumnData<int>&>(*this);
00951                  std::vector<int> __tmp;
00952                  FITSUtil::fill(__tmp,indata,1,indata.size());
00953                  col.writeData(__tmp,firstRow,pNullVal);
00954              }
00955              else if  ( type() == Tshort )
00956              {
00957                  short nullVal(0);
00958                  short* pNullVal = 0;
00959                  if (nullValue) 
00960                  {
00961                     nullVal = static_cast<short>(*nullValue); 
00962                     pNullVal = &nullVal;
00963                  }
00964                  ColumnData<short>& col 
00965                          = dynamic_cast<ColumnData<short>&>(*this);
00966                  std::vector<short> __tmp;
00967                  FITSUtil::fill(__tmp,indata,1,indata.size());
00968                  col.writeData(__tmp,firstRow,pNullVal);
00969              }
00970              else if  ( type() == Tlong )
00971              {
00972                  long nullVal(0);
00973                  long* pNullVal = 0;
00974                  if (nullValue)
00975                  {
00976                     nullVal = static_cast<long>(*nullValue); 
00977                     pNullVal = &nullVal;
00978                  }
00979                  ColumnData<long>& col 
00980                          = dynamic_cast<ColumnData<long>&>(*this);
00981                  std::vector<long> __tmp;
00982                  FITSUtil::fill(__tmp,indata,1,indata.size());
00983                  col.writeData(__tmp,firstRow,pNullVal);
00984              }
00985              else if  ( type() == Tlonglong )
00986              {
00987                  LONGLONG nullVal(0);
00988                  LONGLONG* pNullVal = 0;
00989                  if (nullValue)
00990                  {
00991                     nullVal = static_cast<LONGLONG>(*nullValue); 
00992                     pNullVal = &nullVal;
00993                  }
00994                  ColumnData<LONGLONG>& col 
00995                          = dynamic_cast<ColumnData<LONGLONG>&>(*this);
00996                  std::vector<LONGLONG> __tmp;
00997                  FITSUtil::fill(__tmp,indata,1,indata.size());
00998                  col.writeData(__tmp,firstRow,pNullVal);
00999              }
01000              else if  ( type() == Tlogical )
01001              {
01002                  bool nullVal(0);
01003                  bool* pNullVal = 0;
01004                  if (nullValue)
01005                  {
01006                     nullVal = static_cast<bool>(*nullValue); 
01007                     pNullVal = &nullVal;
01008                  }
01009                  ColumnData<bool>& col 
01010                          = dynamic_cast<ColumnData<bool>&>(*this);
01011                  std::vector<bool> __tmp;
01012                  FITSUtil::fill(__tmp,indata,1,indata.size());
01013                  col.writeData(__tmp,firstRow,pNullVal);
01014              }
01015              else if  ( type() == Tbyte )
01016              {
01017                  unsigned char nullVal(0);
01018                  unsigned char* pNullVal = 0;
01019                  if (nullValue)
01020                  {
01021                     nullVal = static_cast<unsigned char>(*nullValue); 
01022                     pNullVal = &nullVal;
01023                  }
01024                  ColumnData<unsigned char>& col 
01025                          = dynamic_cast<ColumnData<unsigned char>&>(*this);
01026                  std::vector<unsigned char> __tmp;
01027                  FITSUtil::fill(__tmp,indata,1,indata.size());
01028                  col.writeData(__tmp,firstRow,pNullVal);
01029              }                            
01030              else if  ( type() == Tushort )
01031              {
01032                  unsigned short nullVal(0);
01033                  unsigned short* pNullVal = 0;
01034                  if (nullValue)
01035                  {
01036                     nullVal = static_cast<unsigned short>(*nullValue);
01037                     pNullVal = &nullVal;
01038                  } 
01039                  ColumnData<unsigned short>& col 
01040                          = dynamic_cast<ColumnData<unsigned short>&>(*this);
01041                  std::vector<unsigned short> __tmp;
01042                  FITSUtil::fill(__tmp,indata,1,indata.size());
01043                  col.writeData(__tmp,firstRow,pNullVal);
01044              }
01045              else if  ( type() == Tuint )
01046              {
01047                  unsigned int nullVal(0);
01048                  unsigned int* pNullVal = 0;
01049                  if (nullValue)
01050                  {
01051                     nullVal = static_cast<unsigned int>(*nullValue);
01052                     pNullVal = &nullVal;
01053                  } 
01054                  ColumnData<unsigned int>& col 
01055                          = dynamic_cast<ColumnData<unsigned int>&>(*this);
01056                  std::vector<unsigned int> __tmp;
01057                  FITSUtil::fill(__tmp,indata,1,indata.size());
01058                  col.writeData(__tmp,firstRow,pNullVal);
01059              }
01060              else if  ( type() == Tulong )
01061              {
01062                  unsigned long nullVal(0);
01063                  unsigned long* pNullVal = 0;
01064                  if (nullValue)
01065                  {
01066                     nullVal = static_cast<unsigned long>(*nullValue); 
01067                     pNullVal = &nullVal;
01068                  }
01069                  ColumnData<unsigned long>& col 
01070                          = dynamic_cast<ColumnData<unsigned long>&>(*this);
01071                  std::vector<unsigned long> __tmp;
01072                  FITSUtil::fill(__tmp,indata,1,indata.size());
01073                  col.writeData(__tmp,firstRow,pNullVal);
01074              } 
01075              else
01076              {
01077                      throw InvalidDataType(name());
01078              }
01079          }
01080       }
01081    }
01082 
01083 
01084    template <typename S>                   
01085    void Column::write (const std::valarray<S>& indata, long firstRow, S* nullValue)
01086    {
01087       // for scalar columns.        
01088       std::vector<S> __tmp;
01089       FITSUtil::fill(__tmp,indata);    
01090       write(__tmp,firstRow,nullValue);          
01091    }
01092 
01093    template <typename S>                   
01094    void Column::write (S* indata, long nRows, long firstRow, S* nullValue)
01095    {
01096       // for scalar columns, data specified with C array
01097       if (nRows <= 0) throw InvalidNumberOfRows(nRows);
01098       std::vector<S> __tmp(nRows);
01099       std::copy(&indata[0],&indata[nRows],__tmp.begin());
01100       write(__tmp,firstRow, nullValue);
01101 
01102    }
01103 
01104    template <typename S>
01105    void Column::write (const std::valarray<S>& indata, const std::vector<long>& vectorLengths,  
01106                            long firstRow)
01107    {
01108       // variable length arrays written from an input valarray.
01109       // does not allow NULL value.
01110 
01111       using namespace std;
01112       const size_t nRows = vectorLengths.size();
01113       // Calculate the sums of the vector lengths first simply to do a 
01114       //   check against the size of indata.
01115       vector<long> sums(nRows+1);
01116       sums[0] = 0;
01117       vector<long>::iterator itSums = sums.begin() + 1;
01118       partial_sum(vectorLengths.begin(), vectorLengths.end(), itSums);
01119       if (indata.size() < static_cast<size_t>(sums[nRows]))
01120       {
01121 #ifdef SSTREAM_DEFECT
01122          ostrstream msgStr;
01123 #else
01124          ostringstream msgStr;
01125 #endif            
01126          msgStr << " input data size: " << indata.size() << " vector length sum: " << sums[nRows];
01127 #ifdef SSTREAM_DEFECT
01128          msgStr << std::ends;
01129 #endif            
01130 
01131          String msg(msgStr.str());
01132          throw Column::InsufficientElements(msg);     
01133       }
01134       vector<valarray<S> > vvArray(nRows);
01135       for (size_t iRow=0; iRow<nRows; ++iRow)
01136       {
01137          valarray<S>& vArray = vvArray[iRow];
01138          long first = sums[iRow];
01139          long last = sums[iRow+1];
01140          vArray.resize(last - first);
01141          for (long iElem=first; iElem<last; ++iElem)
01142          {
01143             vArray[iElem - first] = indata[iElem];
01144          }
01145       }
01146       writeArrays(vvArray, firstRow, static_cast<S*>(0));  
01147    }
01148 
01149 template <typename S>
01150 void Column::write (const std::vector<S>& indata,const std::vector<long>& vectorLengths,
01151                       long firstRow)
01152    {
01153       // variable length write
01154       // implement as valarray version
01155       std::valarray<S> __tmp(indata.size());
01156       std::copy(indata.begin(),indata.end(),&__tmp[0]);
01157       write(__tmp,vectorLengths,firstRow);  
01158 
01159    }
01160 
01161    template <typename S>
01162    void Column::write (S* indata, long nelements, const std::vector<long>& vectorLengths,
01163                                    long firstRow)
01164    {
01165       // implement as valarray version, which will also check array size.
01166       std::valarray<S> __tmp(indata,nelements);
01167       write(__tmp,vectorLengths,firstRow);
01168    }        
01169 
01170    template <typename S>
01171    void Column::write (const std::valarray<S>& indata, long nRows, long firstRow)
01172    {
01173       write(indata,nRows,firstRow,static_cast<S*>(0));
01174    }
01175 
01176    template <typename S>
01177    void Column::write (const std::vector<S>& indata, long nRows, long firstRow)
01178    {
01179       write(indata,nRows,firstRow,static_cast<S*>(0));  
01180    }
01181 
01182    template <typename S>
01183    void Column::write (S* indata, long nelements, long nRows, long firstRow)
01184    {
01185       write(indata,nelements,nRows,firstRow,static_cast<S*>(0));              
01186    }        
01187 
01188 
01189 
01190    template <typename S>
01191    void Column::write (const std::valarray<S>& indata, long nRows, long firstRow,
01192                            S* nullValue)
01193    {
01194       // Write equivalent lengths of data to rows of a vector column.
01195       // The column may be either fixed or variable width, but if it's fixed
01196       // width the lengths must equal the column's repeat value or an
01197       // exception is thrown.
01198       if (nRows <= 0)
01199          throw InvalidNumberOfRows(nRows);
01200       firstRow = std::max(firstRow,static_cast<long>(1));
01201 #ifdef SSTREAM_DEFECT
01202       std::ostrstream msgStr;
01203 #else
01204       std::ostringstream msgStr;
01205 #endif 
01206       const size_t numRows = static_cast<size_t>(nRows);           
01207       if (indata.size() % numRows)
01208       {
01209          msgStr << "To use this write function, input array size"
01210             <<"\n must be exactly divisible by requested num rows: "
01211             << nRows;
01212          throw InsufficientElements(msgStr.str());
01213       }
01214       
01215       const size_t cellsize = indata.size()/numRows;
01216       if (!varLength() && cellsize != repeat() )
01217       {      
01218          msgStr << "column: " << name() 
01219                 <<  "\n input data size: " << indata.size() 
01220                 << " required: " << nRows*repeat();
01221          String msg(msgStr.str());
01222          throw InsufficientElements(msg);     
01223       }
01224       
01225       std::vector<std::valarray<S> > vvArray(numRows);
01226       for (size_t i=0; i<numRows; ++i)
01227       {
01228          vvArray[i].resize(cellsize);
01229          vvArray[i] = indata[std::slice(cellsize*i,cellsize,1)];
01230       }
01231       writeArrays(vvArray, firstRow, nullValue);
01232    }
01233 
01234    template <typename S>
01235    void Column::write (const std::vector<S>& indata, long nRows, long firstRow, S* nullValue)
01236    {
01237       // fixed length write of vector
01238       // implement as valarray version
01239       if (nRows <= 0) throw InvalidNumberOfRows(nRows);
01240       std::valarray<S> __tmp(indata.size());
01241       std::copy(indata.begin(),indata.end(),&__tmp[0]);
01242       write(__tmp,nRows,firstRow, nullValue);  
01243    }
01244 
01245    template <typename S>
01246    void Column::write (S* indata, long nelements, long nRows, long firstRow, S* nullValue)
01247    {
01248       // fixed length write of C-array
01249       // implement as valarray version
01250       if (nRows <= 0) throw InvalidNumberOfRows(nRows);
01251       std::valarray<S> __tmp(indata,nelements);
01252       write(__tmp,nRows,firstRow, nullValue);              
01253    }        
01254 
01255 
01256    template <typename S>
01257    void Column::writeArrays (const std::vector<std::valarray<S> >& indata, long firstRow)
01258    {
01259       // vector<valarray>, no null value. 
01260       writeArrays(indata,firstRow,static_cast<S*>(0));
01261    } 
01262 
01263    template <typename S>
01264    void Column::writeArrays (const std::vector<std::valarray<S> >& indata, long firstRow,
01265                                    S* nullValue)
01266    {
01267       // vector<valarray>, null value. primary
01268 
01269 
01270       using std::valarray;
01271       using std::vector;
01272       parent()->makeThisCurrent();
01273       firstRow = std::max(firstRow,static_cast<long>(1));
01274       if (ColumnVectorData<S>* col = dynamic_cast<ColumnVectorData<S>*>(this))
01275       {
01276           col->writeData(indata,firstRow,nullValue);
01277       }
01278       else
01279       {
01280          // alright, input data type has to be rewritten as output
01281          // data type.
01282          FITSUtil::MatchType<S> inType;
01283          if ( inType() == type()) 
01284          {
01285                  String msg("Incorrect call: writing vectors to scalar column ");
01286                  throw WrongColumnType(msg);
01287          }
01288          else
01289          {
01290              size_t n(indata.size());                            
01291              if  ( type() == Tdouble || type() == VTdouble)
01292              {
01293                  ColumnVectorData<double>& col 
01294                          = dynamic_cast<ColumnVectorData<double>&>(*this);
01295                  vector<valarray<double> > __tmp(n);
01296                  for (size_t i = 0; i < n; ++i)
01297                  {
01298                          FITSUtil::fill(__tmp[i],indata[i]);
01299                  }
01300                  col.writeData(__tmp,firstRow);
01301              }
01302              else if  ( type() == Tfloat || type() == VTfloat)
01303              {
01304                  ColumnVectorData<float>& col 
01305                          = dynamic_cast<ColumnVectorData<float>&>(*this);
01306                  vector<valarray<float> > __tmp(n);
01307                  for (size_t i = 0; i < n; ++i)
01308                  {
01309                          FITSUtil::fill(__tmp[i],indata[i]);
01310                  }                                
01311                  col.writeData(__tmp,firstRow);
01312              }
01313              else if  ( type() == Tint || type() == VTint)
01314              {
01315                  ColumnVectorData<int>& col  
01316                          = dynamic_cast<ColumnVectorData<int>&>(*this);
01317                  vector<valarray<int> > __tmp(n);
01318                  int nullVal(0);
01319                  int* pNullVal = 0;
01320                  if (nullValue)
01321                  {
01322                     nullVal = static_cast<int>(*nullValue);
01323                     pNullVal = &nullVal;
01324                  }
01325                  for (size_t i = 0; i < n; ++i)
01326                  {
01327                          FITSUtil::fill(__tmp[i],indata[i]);
01328                  }                                
01329                  col.writeData(__tmp,firstRow,pNullVal);
01330              }
01331              else if  ( type() == Tshort || type() == VTshort)
01332              {
01333                  ColumnVectorData<short>& col 
01334                          = dynamic_cast<ColumnVectorData<short>&>(*this);
01335                  vector<valarray<short> > __tmp(n);
01336                  short nullVal(0);
01337                  short* pNullVal = 0;
01338                  if (nullValue)
01339                  {
01340                     nullVal = static_cast<short>(*nullValue);
01341                     pNullVal = &nullVal;
01342                  }
01343                  for (size_t i = 0; i < n; ++i)
01344                  {
01345                          FITSUtil::fill(__tmp[i],indata[i]);
01346                  }                                
01347                  col.writeData(__tmp,firstRow,pNullVal);
01348              }
01349              else if  ( type() == Tlong || type() == VTlong)
01350              {
01351                  ColumnVectorData<long>& col 
01352                          = dynamic_cast<ColumnVectorData<long>&>(*this);
01353                  vector<valarray<long> > __tmp(n);
01354                  long nullVal(0);
01355                  long* pNullVal = 0;
01356                  if (nullValue)
01357                  {
01358                     nullVal = static_cast<long>(*nullValue);
01359                     pNullVal = &nullVal;
01360                  }
01361                  for (size_t i = 0; i < n; ++i)
01362                  {
01363                          FITSUtil::fill(__tmp[i],indata[i]);
01364                  }                                
01365                  col.writeData(__tmp,firstRow,pNullVal);
01366              }
01367              else if  ( type() == Tlonglong || type() == VTlonglong)
01368              {
01369                  ColumnVectorData<LONGLONG>& col 
01370                          = dynamic_cast<ColumnVectorData<LONGLONG>&>(*this);
01371                  vector<valarray<LONGLONG> > __tmp(n);
01372                  LONGLONG nullVal(0);
01373                  LONGLONG* pNullVal = 0;
01374                  if (nullValue)
01375                  {
01376                     nullVal = static_cast<LONGLONG>(*nullValue);
01377                     pNullVal = &nullVal;
01378                  }
01379                  for (size_t i = 0; i < n; ++i)
01380                  {
01381                          FITSUtil::fill(__tmp[i],indata[i]);
01382                  }                                
01383                  col.writeData(__tmp,firstRow,pNullVal);
01384              }
01385              else if  ( type() == Tlogical || type() == VTlogical)
01386              {
01387                  ColumnVectorData<bool>& col 
01388                          = dynamic_cast<ColumnVectorData<bool>&>(*this);
01389                  bool nullVal(0);
01390                  bool* pNullVal = 0;
01391                  if (nullValue)
01392                  {
01393                     nullVal = static_cast<bool>(*nullValue);
01394                     pNullVal = &nullVal;
01395                  }
01396                  vector<valarray<bool> > __tmp(n);
01397                  for (size_t i = 0; i < n; ++i)
01398                  {
01399                          FITSUtil::fill(__tmp[i],indata[i]);
01400                  }                                
01401                  col.writeData(__tmp,firstRow,pNullVal);
01402              }
01403              else if  ( type() == Tbyte || type() == VTbyte)
01404              {
01405                  ColumnVectorData<unsigned char>& col 
01406                          = dynamic_cast<ColumnVectorData<unsigned char>&>(*this);
01407                  unsigned char nullVal(0);
01408                  unsigned char* pNullVal = 0;
01409                  if (nullValue)
01410                  {
01411                     nullVal = static_cast<unsigned char>(*nullValue);
01412                     pNullVal = &nullVal;
01413                  }
01414                  vector<valarray<unsigned char> > __tmp(n);
01415                  for (size_t i = 0; i < n; ++i)
01416                  {
01417                          FITSUtil::fill(__tmp[i],indata[i]);
01418                  }                                                                
01419                  col.writeData(__tmp,firstRow,pNullVal);
01420              }                            
01421              else if  ( type() == Tushort || type() == VTushort)
01422              {
01423                  ColumnVectorData<unsigned short>& col 
01424                          = dynamic_cast<ColumnVectorData<unsigned short>&>(*this);
01425                  unsigned short nullVal(0);
01426                  unsigned short* pNullVal = 0;
01427                  if (nullValue)
01428                  {
01429                     nullVal = static_cast<unsigned short>(*nullValue);
01430                     pNullVal = &nullVal;
01431                  }
01432                  vector<valarray<unsigned short> > __tmp(n);
01433                  for (size_t i = 0; i < n; ++i)
01434                  {
01435                          FITSUtil::fill(__tmp[i],indata[i]);
01436                  }                                
01437                  col.writeData(__tmp,firstRow,pNullVal);
01438              }
01439              else if  ( type() == Tuint || type() == VTuint)
01440              {
01441                  ColumnVectorData<unsigned int>& col 
01442                          = dynamic_cast<ColumnVectorData<unsigned int>&>(*this);
01443                  unsigned int nullVal(0);
01444                  unsigned int* pNullVal = 0;
01445                  if (nullValue)
01446                  {
01447                     nullVal = static_cast<unsigned int>(*nullValue);
01448                     pNullVal = &nullVal;
01449                  }
01450                  vector<valarray<unsigned int> > __tmp(n);
01451                  for (size_t i = 0; i < n; ++i)
01452                  {
01453                          FITSUtil::fill(__tmp[i],indata[i]);
01454                  }                                
01455                  col.writeData(__tmp,firstRow,pNullVal);
01456              }
01457              else if  ( type() == Tulong || type() == VTulong)
01458              {
01459                  ColumnVectorData<unsigned long>& col 
01460                          = dynamic_cast<ColumnVectorData<unsigned long>&>(*this);
01461                  unsigned long nullVal(0);
01462                  unsigned long* pNullVal = 0;
01463                  if (nullValue)
01464                  {
01465                     nullVal = static_cast<unsigned long>(*nullValue);
01466                     pNullVal = &nullVal;
01467                  }
01468                  vector<valarray<unsigned long> > __tmp(n);
01469                  for (size_t i = 0; i < n; ++i)
01470                  {
01471                          FITSUtil::fill(__tmp[i],indata[i]);
01472                  }                                
01473                  col.writeData(__tmp,firstRow,pNullVal);
01474              } 
01475              else
01476              {
01477                      throw InvalidDataType(name());
01478              }
01479          }
01480       }
01481    } 
01482 
01483 
01484    template <typename T>
01485    void Column::addNullValue(T nullVal)
01486    {
01487       parent()->makeThisCurrent();
01488       int status(0);
01489 #ifdef SSTREAM_DEFECT
01490       std::ostrstream keyName;
01491       keyName << "TNULL" << index() << std::ends;
01492       char* nullKey = const_cast<char*>(keyName.str());
01493 #else
01494       std::ostringstream keyName;          
01495       keyName << "TNULL" << index();
01496       String keyNameStr = keyName.str();
01497       char* nullKey = const_cast<char*>(keyNameStr.c_str());
01498 #endif
01499 
01500 
01501       FITSUtil::MatchType<T> inputType;
01502       int dataType = static_cast<int>(inputType());
01503       if (dataType == static_cast<int>(Tstring))
01504          throw InvalidDataType("attempting to set TNULLn to a string.");
01505 
01506       // update key but don't add to keyword list because it's really a column
01507       // property not a table metadata property. And it needs to be automatically
01508       // renumbered if columns are inserted or deleted.
01509       if (fits_update_key(fitsPointer(),dataType,nullKey,&nullVal,0,&status))
01510               throw FitsError(status);
01511 
01512       // The following is called to make sure the HDU struct is immediately 
01513       // updated in case a column write operation is performed shortly after this
01514       // function exits. 
01515       if (fits_set_hdustruc(fitsPointer(),&status)) throw FitsError(status); 
01516 
01517    }
01518 
01519    template <typename T>
01520    bool Column::getNullValue(T* nullVal) const
01521    {
01522       parent()->makeThisCurrent();
01523 #ifdef SSTREAM_DEFECT
01524       std::ostrstream keyName;
01525       keyName << "TNULL" << index() << std::ends;
01526       char* nullKey = const_cast<char*>(keyName.str());
01527 #else
01528       std::ostringstream keyName;          
01529       keyName << "TNULL" << index();
01530       String keyNameStr = keyName.str();
01531       char* nullKey = const_cast<char*>(keyNameStr.c_str());
01532 #endif
01533 
01534       int status=0;
01535       FITSUtil::MatchType<T> inputType;
01536       int dataType = static_cast<int>(inputType());
01537       if (dataType == static_cast<int>(Tstring))
01538          throw InvalidDataType("attempting to read TNULLn into a string.");
01539       T tmpVal(*nullVal);
01540 
01541       bool keyExists = false;
01542       if (fits_read_key(m_parent->fitsPointer(), dataType, nullKey, &tmpVal, 0, &status))
01543       {
01544          if (status == KEY_NO_EXIST  || status == VALUE_UNDEFINED)
01545             return keyExists;
01546          else
01547             throw FitsError(status);
01548       }
01549       keyExists = true;
01550       *nullVal = tmpVal;       
01551       return keyExists;
01552    }
01553 
01554 } // namespace CCfits
01555 
01556 #endif