float.h

00001 /***************************************************************************
00002 *   Copyright (C) 2001 by Rick L. Vinyard, Jr.                            *
00003 *   rvinyard@cs.nmsu.edu                                                  *
00004 *                                                                         *
00005 *   This program is free software; you can redistribute it and/or modify  *
00006 *   it under the terms of the GNU Lesser General Public License as        *
00007 *   published by the Free Software Foundation version 2.1.                *
00008 *                                                                         *
00009 *   This program is distributed in the hope that it will be useful,       *
00010 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00011 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00012 *   GNU General Public License for more details.                          *
00013 *                                                                         *
00014 *   You should have received a copy of the GNU Lesser General Public      *
00015 *   License along with this library; if not, write to the                 *
00016 *   Free Software Foundation, Inc.,                                       *
00017 *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
00018 ***************************************************************************/
00019 #ifndef BITFLOAT_H
00020 #define BITFLOAT_H
00021 
00022 #include <typeinfo>
00023 #include <stdexcept>
00024 
00025 #include <bit/enums.h>
00026 #include <bit/utility.h>
00027 #include <bit/pointer.h>
00028 #include <bit/data.h>
00029 
00030 namespace bit
00031 {
00032 
00033   template <typename F> class Float;
00034 
00035   class FloatingPoint
00036   {
00037     public:
00038 
00039       typedef BitPointer<FloatingPoint> pointer;
00040 
00041       FloatingPoint( ByteOrder bo=BYTEORDER_HOST ): byte_order(bo) { }
00042 
00043       virtual ~FloatingPoint() { }
00044 
00045       virtual Data as_data() const = 0;
00046 
00047       virtual size_t size() const = 0;
00048 
00049       virtual const void* voidptr() const = 0;
00050 
00051       virtual pointer clone() const = 0;
00052 
00058       virtual void set_value( const Data d ) = 0;
00059 
00060       virtual void set_value( const void* mem, size_t size ) = 0;
00061 
00067       virtual void set_value( const Data d, ByteOrder databo ) = 0;
00068 
00069       template <typename T> operator T();
00070 
00071       template <typename T> FloatingPoint& operator = ( T f );
00072 
00073       virtual const std::type_info& int_type() = 0;
00074 
00075       ByteOrder byte_order;
00076   };
00077 
00078   template <typename F>
00079   class Float: public FloatingPoint {
00080     public:
00081 
00082       typedef BitPointer< Float<F> > pointer;
00083 
00084       Float(F v=0, ByteOrder bo=BYTEORDER_HOST): FloatingPoint(bo), value(v) { }
00085 
00086       Float(ByteOrder bo): FloatingPoint(bo), value(0) { }
00087 
00094       Float(const Data d, ByteOrder databo=BYTEORDER_HOST, ByteOrder bo=BYTEORDER_HOST): FloatingPoint(bo) {
00095         this->set_value(d, databo);
00096       }
00097 
00098       static pointer create(F v=0, ByteOrder bo=BYTEORDER_HOST) { return pointer(new Float<F>(v,bo)); }
00099 
00100       static pointer create(ByteOrder bo) { return pointer(new Float<F>(bo)); }
00101 
00102       static pointer create(const Data d, ByteOrder databo=BYTEORDER_HOST, ByteOrder bo=BYTEORDER_HOST) {
00103         return pointer(new Float<F>(d,databo,bo));
00104       }
00105 
00106       ~Float() { }
00107 
00108       virtual FloatingPoint::pointer clone() const {
00109         pointer p = this->create(value, byte_order);
00110         return p;
00111       }
00112 
00113       operator F() const { return this->host(); }
00114 
00115       bool operator <  ( F f ) const { return this->host() <  f; }
00116       bool operator <= ( F f ) const { return this->host() <= f; }
00117       bool operator == ( F f ) const { return this->host() == f; }
00118       bool operator != ( F f ) const { return this->host() != f; }
00119       bool operator >= ( F f ) const { return this->host() >= f; }
00120       bool operator >  ( F f ) const { return this->host() >  f; }
00121 
00122       Float<F>& operator = ( F f )
00123       {
00124         value = f;
00125         this->convert_value_from_host_to_type();
00126         return *this;
00127       }
00128 
00129       const Float<F>& operator + ( F f ) const
00130       {
00131         this->convert_value_from_type_to_host();
00132         value += f;
00133         this->convert_value_from_host_to_type();
00134         return *this;
00135       }
00136 
00137       const Float<F>& operator - ( F f ) const
00138       {
00139         this->convert_value_from_type_to_host();
00140         value -= f;
00141         this->convert_value_from_host_to_type();
00142         return *this;
00143       }
00144 
00145       const Float<F>& operator * ( F f ) const
00146       {
00147         this->convert_value_from_type_to_host();
00148         value *= f;
00149         this->convert_value_from_host_to_type();
00150         return *this;
00151       }
00152 
00153       const Float<F>& operator / ( F f ) const
00154       {
00155         this->convert_value_from_type_to_host();
00156         value /= f;
00157         this->convert_value_from_host_to_type();
00158         return *this;
00159       }
00160 
00161       Float<F>& operator += ( F f )
00162       {
00163         this->convert_value_from_type_to_host();
00164         value += f;
00165         this->convert_value_from_host_to_type();
00166         return *this;
00167       }
00168 
00169       Float<F>& operator -= ( F f )
00170       {
00171         this->convert_value_from_type_to_host();
00172         value -= f;
00173         this->convert_value_from_host_to_type();
00174         return *this;
00175       }
00176 
00177       Float<F>& operator *= ( F f )
00178       {
00179         this->convert_value_from_type_to_host();
00180         value *= f;
00181         this->convert_value_from_host_to_type();
00182         return *this;
00183       }
00184 
00185       Float<F>& operator /= ( F f )
00186       {
00187         this->convert_value_from_type_to_host();
00188         value /= f;
00189         this->convert_value_from_host_to_type();
00190         return *this;
00191       }
00192 
00198       virtual void set_value( const Data d ) {
00199         if ( d.size() < sizeof(F) )
00200           throw;
00201 
00202         memcpy( &value, d.data(), sizeof(F) );
00203       }
00204 
00210       virtual void set_value( const void* mem, size_t size ) {
00211         if ( size < sizeof(F) )
00212           throw;
00213 
00214         memcpy( &value, mem, sizeof(F) );
00215       }
00216 
00222       virtual void set_value( const Data d, ByteOrder databo ) {
00223         if ( d.size() < sizeof(F) )
00224           throw;
00225 
00226         memcpy( &value, d.data(), sizeof(F) );
00227 
00228         switch ( byte_order ) {
00229           case BYTEORDER_HOST:
00230             switch ( databo ) {
00231               case BYTEORDER_HOST:
00232                 break;
00233               case BYTEORDER_NETWORK:
00234               case BYTEORDER_BIG_ENDIAN:
00235                 value = be_to_host(value);
00236                 break;
00237               case BYTEORDER_LITTLE_ENDIAN:
00238                 value = le_to_host(value);
00239                 break;
00240             }
00241             break;
00242           case BYTEORDER_NETWORK:
00243           case BYTEORDER_BIG_ENDIAN:
00244             switch ( databo ) {
00245               case BYTEORDER_HOST:
00246                 value = host_to_net(value);
00247                 break;
00248               case BYTEORDER_NETWORK:
00249               case BYTEORDER_BIG_ENDIAN:
00250                 break;
00251               case BYTEORDER_LITTLE_ENDIAN:
00252                 value = le_to_net(value);
00253                 break;
00254             }
00255             break;
00256           case BYTEORDER_LITTLE_ENDIAN:
00257             switch ( databo ) {
00258               case BYTEORDER_HOST:
00259                 value = host_to_le(value);
00260                 break;
00261               case BYTEORDER_NETWORK:
00262               case BYTEORDER_BIG_ENDIAN:
00263                 value = net_to_le(value);
00264                 break;
00265               case BYTEORDER_LITTLE_ENDIAN:
00266                 break;
00267             }
00268             break;
00269         }
00270       }
00271 
00272       virtual Data as_data() const
00273       {
00274         Data d( sizeof(F) );
00275         memcpy( d.data(), &value, sizeof(F) );
00276         return d;
00277       }
00278 
00279       virtual size_t size() const { return sizeof(F); }
00280 
00281       virtual const void* voidptr() const { return &value; }
00282 
00283       virtual const std::type_info& int_type() { return typeid(F); }
00284 
00285       F host() const {
00286         switch ( byte_order )
00287         {
00288           case BYTEORDER_HOST:
00289             return value;
00290           case BYTEORDER_NETWORK:
00291           case BYTEORDER_BIG_ENDIAN:
00292             return net_to_host(value);
00293           case BYTEORDER_LITTLE_ENDIAN:
00294             return le_to_host(value);
00295         }
00296         throw;
00297       }
00298 
00299       F network() const {
00300         switch ( byte_order )
00301         {
00302           case BYTEORDER_HOST:
00303             return host_to_net(value);
00304           case BYTEORDER_NETWORK:
00305           case BYTEORDER_BIG_ENDIAN:
00306             return value;
00307           case BYTEORDER_LITTLE_ENDIAN:
00308             return le_to_net(value);
00309         }
00310         throw;
00311       }
00312 
00313       F big_endian() const {
00314         return this->network();
00315       }
00316 
00317       F little_endian() const {
00318         switch ( byte_order )
00319         {
00320           case BYTEORDER_HOST:
00321             return host_to_le(value);
00322           case BYTEORDER_NETWORK:
00323           case BYTEORDER_BIG_ENDIAN:
00324             return net_to_le(value);
00325           case BYTEORDER_LITTLE_ENDIAN:
00326             return value;
00327         }
00328         throw;
00329       }
00330 
00331       F value;
00332 
00333     protected:
00334       void convert_value_from_type_to_host()
00335       {
00336         switch ( byte_order )
00337         {
00338           case BYTEORDER_HOST:
00339             return;
00340           case BYTEORDER_NETWORK:
00341           case BYTEORDER_BIG_ENDIAN:
00342             value = net_to_host(value);
00343           case BYTEORDER_LITTLE_ENDIAN:
00344             value = le_to_host(value);
00345         }
00346       }
00347 
00348       void convert_value_from_host_to_type()
00349       {
00350         switch ( byte_order )
00351         {
00352           case BYTEORDER_HOST:
00353             return;
00354           case BYTEORDER_NETWORK:
00355           case BYTEORDER_BIG_ENDIAN:
00356             value = host_to_net(value);
00357           case BYTEORDER_LITTLE_ENDIAN:
00358             value = host_to_le(value);
00359         }
00360       }
00361 
00362   };
00363 
00364   typedef Float<float> FloatSingle;
00365   typedef Float<double> FloatDouble;
00366   typedef Float<long double> FloatQuadruple;
00367 
00368   template <typename T> FloatingPoint::operator T()
00369   {
00370     switch ( this->size() )
00371     {
00372       case 4:
00373       {
00374         FloatSingle* f;
00375         f = dynamic_cast<FloatSingle*>(this);
00376         return static_cast<T>(f->host());
00377       }
00378       case 8:
00379       {
00380         FloatDouble* f;
00381         f = dynamic_cast<FloatDouble*>(this);
00382         return static_cast<T>(f->host());
00383       }
00384       case 16:
00385       {
00386         FloatQuadruple* f;
00387         f = dynamic_cast<FloatQuadruple*>(this);
00388         return static_cast<T>(f->host());
00389       }
00390     }
00391     throw std::logic_error("bit::FloatingPoint bad cast");
00392   }
00393 
00394   template <typename T> FloatingPoint& FloatingPoint::operator = ( T i )
00395   {
00396     switch ( this->size() )
00397     {
00398       case 4:
00399       {
00400         FloatSingle* f;
00401         f = dynamic_cast<FloatSingle*>(this);
00402         *f = (float)(i);
00403       }
00404         break;
00405       case 8:
00406       {
00407         FloatDouble* f;
00408         f = dynamic_cast<FloatDouble*>(this);
00409         *f = (double)(i);
00410       }
00411       break;
00412       case 16:
00413       {
00414         FloatQuadruple* f;
00415         f = dynamic_cast<FloatQuadruple*>(this);
00416         *f = (long double)(i);
00417       }
00418       break;
00419     }
00420     return *this;
00421   }
00422 
00423 }
00424 
00425 #endif

Generated on Tue Mar 13 20:00:01 2007 by  doxygen 1.5.1