From 6b8ec8dc9a8a38d0400da927fb3c0894b749c09f Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Tue, 2 Oct 2007 09:02:20 +0000
Subject: [PATCH] First batch of changes to support the new data type
 Float16_t. For more info about Float16_t see TBufferFile::WriteFloat16.

git-svn-id: http://root.cern.ch/svn/root/trunk@20170 27541ba8-7e3a-0410-8455-c3a389f83636
---
 base/inc/LinkDef1.h                 |   1 +
 base/inc/Rtypes.h                   |   1 +
 base/inc/TBuffer.h                  |   7 +
 cint/src/v6_tmplt.cxx               |   6 +
 cint7/src/v6_tmplt.cxx              |   6 +
 io/inc/TBufferFile.h                |   7 +
 io/inc/TStreamerInfo.h              |   2 +-
 io/src/TBufferFile.cxx              | 296 ++++++++++++++++++++++++++++
 io/src/TEmulatedCollectionProxy.cxx |   2 +
 io/src/TEmulatedMapProxy.cxx        |   3 +
 io/src/TGenCollectionStreamer.cxx   |   5 +
 meta/inc/TDataType.h                |   2 +-
 meta/inc/TVirtualStreamerInfo.h     |  12 +-
 meta/src/TDataType.cxx              |   6 +
 meta/src/TStreamerElement.cxx       |   4 +
 metautils/src/TClassEdit.cxx        |   2 +-
 odbc/src/TODBCStatement.cxx         |   1 +
 sql/inc/TBufferSQL2.h               |   7 +
 sql/src/TBufferSQL2.cxx             |  60 +++++-
 sql/src/TSQLFile.cxx                |  16 +-
 sql/src/TSQLStructure.cxx           |   2 +
 tree/inc/TBufferSQL.h               |   1 +
 tree/src/TBufferSQL.cxx             |   7 +
 utils/src/rootcint.cxx              | 102 +++++++++-
 xml/inc/TBufferXML.h                |   7 +
 xml/src/TBufferXML.cxx              |  56 ++++++
 26 files changed, 595 insertions(+), 26 deletions(-)

diff --git a/base/inc/LinkDef1.h b/base/inc/LinkDef1.h
index 8c3e0aa522d..c9558c39e63 100644
--- a/base/inc/LinkDef1.h
+++ b/base/inc/LinkDef1.h
@@ -116,6 +116,7 @@
 #pragma link C++ typedef ROOT::DelFunc_t;
 #pragma link C++ typedef ROOT::DelArrFunc_t;
 #pragma link C++ typedef ROOT::DesFunc_t;
+#pragma link C++ typedef Float16_t;
 #pragma link C++ typedef Double32_t;
 
 #pragma link C++ class TApplication;
diff --git a/base/inc/Rtypes.h b/base/inc/Rtypes.h
index ac056e74165..596d7982380 100644
--- a/base/inc/Rtypes.h
+++ b/base/inc/Rtypes.h
@@ -66,6 +66,7 @@ typedef long           Long_t;      //Signed long integer 4 bytes (long)
 typedef unsigned long  ULong_t;     //Unsigned long integer 4 bytes (unsigned long)
 #endif
 typedef float          Float_t;     //Float 4 bytes (float)
+typedef float          Float16_t;   //Float 4 bytes written with a truncated mantissa
 typedef double         Double_t;    //Double 8 bytes
 typedef double         Double32_t;  //Double 8 bytes in memory, written as a 4 bytes float
 typedef char           Text_t;      //General string (char)
diff --git a/base/inc/TBuffer.h b/base/inc/TBuffer.h
index 8a6d0a2faa3..444d55b8b41 100644
--- a/base/inc/TBuffer.h
+++ b/base/inc/TBuffer.h
@@ -140,6 +140,8 @@ public:
    virtual void       SetBufferDisplacement(Int_t skipped) = 0;
 
    // basic types and arrays of basic types
+   virtual   void     ReadFloat16 (Float_t *f, TStreamerElement *ele=0) = 0;
+   virtual   void     WriteFloat16(Float_t *f, TStreamerElement *ele=0) = 0;
    virtual   void     ReadDouble32 (Double_t *d, TStreamerElement *ele=0) = 0;
    virtual   void     WriteDouble32(Double_t *d, TStreamerElement *ele=0) = 0;
 
@@ -156,6 +158,7 @@ public:
    virtual   Int_t    ReadArray(ULong64_t *&l) = 0;
    virtual   Int_t    ReadArray(Float_t   *&f) = 0;
    virtual   Int_t    ReadArray(Double_t  *&d) = 0;
+   virtual   Int_t    ReadArrayFloat16(Float_t *&f, TStreamerElement *ele=0) = 0;
    virtual   Int_t    ReadArrayDouble32(Double_t *&d, TStreamerElement *ele=0) = 0;
 
    virtual   Int_t    ReadStaticArray(Bool_t    *b) = 0;
@@ -171,6 +174,7 @@ public:
    virtual   Int_t    ReadStaticArray(ULong64_t *l) = 0;
    virtual   Int_t    ReadStaticArray(Float_t   *f) = 0;
    virtual   Int_t    ReadStaticArray(Double_t  *d) = 0;
+   virtual   Int_t    ReadStaticArrayFloat16(Float_t  *f, TStreamerElement *ele=0) = 0;
    virtual   Int_t    ReadStaticArrayDouble32(Double_t  *d, TStreamerElement *ele=0) = 0;
 
    virtual   void     ReadFastArray(Bool_t    *b, Int_t n) = 0;
@@ -187,6 +191,7 @@ public:
    virtual   void     ReadFastArray(ULong64_t *l, Int_t n) = 0;
    virtual   void     ReadFastArray(Float_t   *f, Int_t n) = 0;
    virtual   void     ReadFastArray(Double_t  *d, Int_t n) = 0;
+   virtual   void     ReadFastArrayFloat16(Float_t  *f, Int_t n, TStreamerElement *ele=0) = 0;
    virtual   void     ReadFastArrayDouble32(Double_t  *d, Int_t n, TStreamerElement *ele=0) = 0;
    virtual   void     ReadFastArray(void  *start , const TClass *cl, Int_t n=1, TMemberStreamer *s=0) = 0;
    virtual   void     ReadFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0) = 0;
@@ -204,6 +209,7 @@ public:
    virtual   void     WriteArray(const ULong64_t *l, Int_t n) = 0;
    virtual   void     WriteArray(const Float_t   *f, Int_t n) = 0;
    virtual   void     WriteArray(const Double_t  *d, Int_t n) = 0;
+   virtual   void     WriteArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement *ele=0) = 0;
    virtual   void     WriteArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0) = 0;
 
    virtual   void     WriteFastArray(const Bool_t    *b, Int_t n) = 0;
@@ -220,6 +226,7 @@ public:
    virtual   void     WriteFastArray(const ULong64_t *l, Int_t n) = 0;
    virtual   void     WriteFastArray(const Float_t   *f, Int_t n) = 0;
    virtual   void     WriteFastArray(const Double_t  *d, Int_t n) = 0;
+   virtual   void     WriteFastArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement *ele=0) = 0;
    virtual   void     WriteFastArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0) = 0;
    virtual   void     WriteFastArray(void  *start,  const TClass *cl, Int_t n=1, TMemberStreamer *s=0) = 0;
    virtual   Int_t    WriteFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0) = 0;
diff --git a/cint/src/v6_tmplt.cxx b/cint/src/v6_tmplt.cxx
index 9b59b5cb22e..f82deb0d5b3 100644
--- a/cint/src/v6_tmplt.cxx
+++ b/cint/src/v6_tmplt.cxx
@@ -1703,6 +1703,12 @@ static void G__templatemaptypename(char *string)
   else if(strcmp(string,"unsignedshort*")==0||
           strcmp(string,"unsignedshortint*")==0)
     strcpy(string,"unsigned short*");
+  else if (strcmp(string,"Float16_t")==0||
+           strcmp(string,"Float16_t*")==0) 
+    { 
+       /* nothing to do, we want to keep those as is */
+
+    }
   else if (strcmp(string,"Double32_t")==0||
            strcmp(string,"Double32_t*")==0) 
     { 
diff --git a/cint7/src/v6_tmplt.cxx b/cint7/src/v6_tmplt.cxx
index 931c7940c73..13388e948b4 100644
--- a/cint7/src/v6_tmplt.cxx
+++ b/cint7/src/v6_tmplt.cxx
@@ -1683,6 +1683,12 @@ static void G__templatemaptypename(char *string)
   else if(strcmp(string,"unsignedshort*")==0||
           strcmp(string,"unsignedshortint*")==0)
     strcpy(string,"unsigned short*");
+  else if (strcmp(string,"Float16_t")==0||
+           strcmp(string,"Float16_t*")==0) 
+    { 
+       /* nothing to do, we want to keep those as is */
+
+    }
   else if (strcmp(string,"Double32_t")==0||
            strcmp(string,"Double32_t*")==0) 
     { 
diff --git a/io/inc/TBufferFile.h b/io/inc/TBufferFile.h
index 019eac731d1..6e7afc7c65c 100644
--- a/io/inc/TBufferFile.h
+++ b/io/inc/TBufferFile.h
@@ -146,6 +146,8 @@ public:
             { fDisplacement =  (Int_t)(Length() - skipped); }
 
    // basic types and arrays of basic types
+   virtual   void     ReadFloat16 (Float_t *f, TStreamerElement *ele=0);
+   virtual   void     WriteFloat16(Float_t *f, TStreamerElement *ele=0);
    virtual   void     ReadDouble32 (Double_t *d, TStreamerElement *ele=0);
    virtual   void     WriteDouble32(Double_t *d, TStreamerElement *ele=0);
 
@@ -162,6 +164,7 @@ public:
    virtual   Int_t    ReadArray(ULong64_t *&l);
    virtual   Int_t    ReadArray(Float_t   *&f);
    virtual   Int_t    ReadArray(Double_t  *&d);
+   virtual   Int_t    ReadArrayFloat16(Float_t  *&f, TStreamerElement *ele=0);
    virtual   Int_t    ReadArrayDouble32(Double_t  *&d, TStreamerElement *ele=0);
 
    virtual   Int_t    ReadStaticArray(Bool_t    *b);
@@ -177,6 +180,7 @@ public:
    virtual   Int_t    ReadStaticArray(ULong64_t *l);
    virtual   Int_t    ReadStaticArray(Float_t   *f);
    virtual   Int_t    ReadStaticArray(Double_t  *d);
+   virtual   Int_t    ReadStaticArrayFloat16(Float_t  *f, TStreamerElement *ele=0);
    virtual   Int_t    ReadStaticArrayDouble32(Double_t  *d, TStreamerElement *ele=0);
 
    virtual   void     ReadFastArray(Bool_t    *b, Int_t n);
@@ -193,6 +197,7 @@ public:
    virtual   void     ReadFastArray(ULong64_t *l, Int_t n);
    virtual   void     ReadFastArray(Float_t   *f, Int_t n);
    virtual   void     ReadFastArray(Double_t  *d, Int_t n);
+   virtual   void     ReadFastArrayFloat16(Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual   void     ReadFastArrayDouble32(Double_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual   void     ReadFastArray(void  *start , const TClass *cl, Int_t n=1, TMemberStreamer *s=0);
    virtual   void     ReadFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0);
@@ -210,6 +215,7 @@ public:
    virtual   void     WriteArray(const ULong64_t *l, Int_t n);
    virtual   void     WriteArray(const Float_t   *f, Int_t n);
    virtual   void     WriteArray(const Double_t  *d, Int_t n);
+   virtual   void     WriteArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual   void     WriteArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0);
 
    virtual   void     WriteFastArray(const Bool_t    *b, Int_t n);
@@ -226,6 +232,7 @@ public:
    virtual   void     WriteFastArray(const ULong64_t *l, Int_t n);
    virtual   void     WriteFastArray(const Float_t   *f, Int_t n);
    virtual   void     WriteFastArray(const Double_t  *d, Int_t n);
+   virtual   void     WriteFastArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual   void     WriteFastArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual   void     WriteFastArray(void  *start,  const TClass *cl, Int_t n=1, TMemberStreamer *s=0);
    virtual   Int_t    WriteFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0);
diff --git a/io/inc/TStreamerInfo.h b/io/inc/TStreamerInfo.h
index 64686041719..714452be17a 100644
--- a/io/inc/TStreamerInfo.h
+++ b/io/inc/TStreamerInfo.h
@@ -104,7 +104,7 @@ public:
       kChar     =  1,  kShort   =  2,  kInt     =  3,  kLong    =  4,  kFloat    = 5,
       kDouble   =  8,  kDouble32=  9,
       kUChar    = 11,  kUShort  = 12,  kUInt    = 13,  kULong   = 14,  kBits     = 15,
-      kLong64   = 16,  kULong64 = 17,  kBool    = 18,
+      kLong64   = 16,  kULong64 = 17,  kBool    = 18,  kFloat16 = 19,
       kObject   = 61,  kAny     = 62,  kObjectp = 63,  kObjectP = 64,  kTString  = 65,
       kTObject  = 66,  kTNamed  = 67,  kAnyp    = 68,  kAnyP    = 69,  kAnyPnoVT = 70,
       kSTLp     = 71,
diff --git a/io/src/TBufferFile.cxx b/io/src/TBufferFile.cxx
index 45d2cc170b4..b5b03fa2faa 100644
--- a/io/src/TBufferFile.cxx
+++ b/io/src/TBufferFile.cxx
@@ -332,6 +332,44 @@ Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const char *clas
 }
 
 
+//______________________________________________________________________________
+void TBufferFile::ReadFloat16 (Float_t *f, TStreamerElement *ele)
+{
+   // Read a Float16_t from the buffer,
+   // see comments about Float16_t encoding at TBufferFile::WriteFloat16().
+
+   if (ele && ele->GetFactor() != 0) {
+      //a range was specified. We read an integer and convert it back to a double.
+      UInt_t aint; *this >> aint; f[0] = (Float_t)(aint/ele->GetFactor() + ele->GetXmin());
+   } else {
+      Int_t nbits = 0;
+      if (ele) nbits = (UInt_t)ele->GetXmin();
+      if (!nbits) {
+         //we read a float and convert it to double
+         Float_t afloat; 
+         *this >> afloat; 
+         f[0] = afloat;
+      } else {
+         //we read the exponent and the truncated mantissa of the float
+         //and rebuild the float.
+         union {
+            Float_t xx;
+            Int_t ix;
+         };
+         UChar_t  theExp;
+         UShort_t theMan;
+         *this >> theExp;
+         *this >> theMan;
+         ix = theExp;
+         ix <<= 23;
+         ix |= (theMan & ((1<<nbits+1)-1)) <<(23-nbits);
+         if(1<<(nbits+1) & theMan) xx=-xx;
+         f[0] = xx;
+      }
+   }
+}
+
+
 //______________________________________________________________________________
 void TBufferFile::ReadDouble32 (Double_t *d, TStreamerElement *ele)
 {
@@ -369,6 +407,96 @@ void TBufferFile::ReadDouble32 (Double_t *d, TStreamerElement *ele)
    }
 }
 
+//______________________________________________________________________________
+void TBufferFile::WriteFloat16 (Float_t *f, TStreamerElement *ele)
+{
+   // write a Float16_t to the buffer.
+   // The following cases are supported for streaming a Float16_t type
+   // depending on the range declaration in the comment field of the data member:
+   //  A-    Float16_t     fNormal;
+   //  B-    Float16_t     fTemperature; //[0,100]
+   //  C-    Float16_t     fCharge;      //[-1,1,2]
+   //  D-    Float16_t     fVertex[3];   //[-30,30,10]
+   //  E-    Float16_t     fChi2;        //[0,0,6]
+   //  F-    Int_t          fNsp;
+   //        Float16_t*    fPointValue;   //[fNsp][0,3]
+   //
+   // In case A fNormal is converted from a Float_t to a Float_t with mantissa truncated to 12 bits
+   // In case B fTemperature is converted to a 32 bit unsigned integer
+   // In case C fCharge is converted to a 2 bits unsigned integer
+   // In case D the array elements of fVertex are converted to an unsigned 10 bits integer
+   // In case E fChi2 is converted to a Float_t with truncated precision at 6 bits
+   // In case F the fNsp elements of array fPointvalue are converted to an unsigned 32 bit integer
+   //           Note that the range specifier must follow the dimension specifier.
+   // the case B has more precision (9 to 10 significative digits than case A (6 to 7 digits).
+   //
+   // The range specifier has the general format: [xmin,xmax] or [xmin,xmax,nbits]
+   //  [0,1]
+   //  [-10,100];
+   //  [-pi,pi], [-pi/2,pi/4],[-2pi,2*pi]
+   //  [-10,100,16]
+   //  [0,0,8]
+   // if nbits is not specified, or nbits <2 or nbits>16 it is set to 16
+   // if (xmin==0 and xmax==0 and nbits <=16) the float word will have
+   // its mantissa truncated to nbits significative bits.
+   //
+   // IMPORTANT NOTE
+   // --------------
+   // Lets assume an original variable float x:
+   // When using the format [0,0,8] (ie range not specified) you get the best
+   // relative precision when storing and reading back the truncated x, say xt.
+   // The variance of (x-xt)/x will be better than when specifying a range
+   // for the same number of bits. However the precision relative to the 
+   // range (x-xt)/(xmax-xmin) will be worst, and vice-versa.
+   // The format [0,0,8] is also interesting when the range of x is infinite
+   // or unknown.
+   //
+   //  see example of use of the Float16_t data type in tutorial double32.C
+   //
+   //Begin_Html
+   /*
+     <img src="gif/double32.gif">
+   */
+   //End_Html
+
+   if (ele && ele->GetFactor() != 0) {
+      //A range is specified. We normalize the double to the range and
+      //convert it to an integer using a scaling factor that is a function of nbits.
+      //see TStreamerElement::GetRange.
+      Double_t x = f[0];
+      Double_t xmin = ele->GetXmin();
+      Double_t xmax = ele->GetXmax();
+      if (x < xmin) x = xmin;
+      if (x > xmax) x = xmax;
+      UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint;
+   } else {
+      Int_t nbits = 0;
+      //number of bits stored in fXmin (see TStreamerElement::GetRange)
+      if (ele) nbits = (UInt_t)ele->GetXmin();
+      if (!nbits) {
+         //if no range and no bits specified, we convert from double to float
+         Float_t afloat = f[0]; 
+         *this << afloat;
+      } else {
+         //a range is not specified, but nbits is.
+         //In this case we truncate the mantissa to nbits and we stream
+         //the exponent as a UChar_t and the mantissa as a UShort_t.
+         union {
+            Float_t xx;
+            Int_t ix;
+         };
+         xx = f[0];
+         UChar_t  theExp=(UChar_t)(0x000000ff & ((ix<<1)>>24));
+         UShort_t theMan=((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
+         theMan=(++theMan)>>1;
+         if(theMan&1<<nbits) theMan=(1<<nbits)-1;
+         if(xx<0) theMan|=1<<(nbits+1);
+         *this << theExp;
+         *this << theMan;
+      }
+   }
+}
+
 //______________________________________________________________________________
 void TBufferFile::WriteDouble32 (Double_t *d, TStreamerElement *ele)
 {
@@ -691,6 +819,28 @@ Int_t TBufferFile::ReadArray(Double_t *&d)
    return n;
 }
 
+//______________________________________________________________________________
+Int_t TBufferFile::ReadArrayFloat16(Float_t *&f, TStreamerElement *ele)
+{
+   // Read array of floats (written as truncated float) from the I/O buffer.
+   // Returns the number of floats read.
+   // If argument is a 0 pointer then space will be allocated for the array.
+   // see comments about Float16_t encoding at TBufferFile::WriteFloat16
+
+   R__ASSERT(IsReading());
+
+   Int_t n;
+   *this >> n;
+
+   if (n <= 0 || 4*n > fBufSize) return 0;
+
+   if (!f) f = new Float_t[n];
+
+   ReadFastArrayFloat16(f,n,ele);
+
+   return n;
+}
+
 //______________________________________________________________________________
 Int_t TBufferFile::ReadArrayDouble32(Double_t *&d, TStreamerElement *ele)
 {
@@ -937,6 +1087,27 @@ Int_t TBufferFile::ReadStaticArray(Double_t *d)
    return n;
 }
 
+//______________________________________________________________________________
+Int_t TBufferFile::ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele)
+{
+   // Read array of floats (written as truncated float) from the I/O buffer.
+   // Returns the number of floats read.
+   // see comments about Float16_t encoding at TBufferFile::WriteFloat16
+
+   R__ASSERT(IsReading());
+
+   Int_t n;
+   *this >> n;
+
+   if (n <= 0 || 4*n > fBufSize) return 0;
+
+   if (!f) return 0;
+
+   ReadFastArrayFloat16(f,n,ele);
+
+   return n;
+}
+
 //______________________________________________________________________________
 Int_t TBufferFile::ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele)
 {
@@ -1131,6 +1302,54 @@ void TBufferFile::ReadFastArray(Double_t *d, Int_t n)
 #endif
 }
 
+//______________________________________________________________________________
+void TBufferFile::ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele)
+{
+   // Read array of n floats (written as truncated float) from the I/O buffer.
+   // see comments about Float16_t encoding at TBufferFile::WriteFloat16
+
+   if (n <= 0 || 4*n > fBufSize) return;
+
+   if (ele && ele->GetFactor() != 0) {
+      //a range was specified. We read an integer and convert it back to a float
+      Double_t xmin = ele->GetXmin();
+      Double_t factor = ele->GetFactor();
+      for (int j=0;j < n; j++) {
+         UInt_t aint; *this >> aint; f[j] = (Float_t)(aint/factor + xmin);
+      }
+   } else {
+      Int_t i;
+      Int_t nbits = 0;
+      if (ele) nbits = (UInt_t)ele->GetXmin();
+      if (!nbits) {
+         //we read a float and convert it to double
+         Float_t afloat; 
+         for (i = 0; i < n; i++) {
+            *this >> afloat; 
+            f[i] = afloat;
+         }
+      } else {
+         //we read the exponent and the truncated mantissa of the float
+         //and rebuild the new float.
+         union {
+            Float_t xx;
+            Int_t ix;
+         };
+         UChar_t  theExp;
+         UShort_t theMan;
+         for (i = 0; i < n; i++) {
+            *this >> theExp;
+            *this >> theMan;
+            ix = theExp;
+            ix <<= 23;
+            ix |= (theMan & ((1<<nbits+1)-1)) <<(23-nbits);
+            if(1<<(nbits+1) & theMan) xx=-xx;
+            f[i] = xx;
+         }
+      }
+   }
+}
+
 //______________________________________________________________________________
 void TBufferFile::ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele)
 {
@@ -1473,6 +1692,26 @@ void TBufferFile::WriteArray(const Double_t *d, Int_t n)
 #endif
 }
 
+//______________________________________________________________________________
+void TBufferFile::WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele)
+{
+   // Write array of n floats (as truncated float) into the I/O buffer.
+   // see comments about Float16_t encoding at TBufferFile::WriteFloat16
+
+   R__ASSERT(IsWriting());
+
+   *this << n;
+
+   if (n <= 0) return;
+
+   R__ASSERT(f);
+
+   Int_t l = sizeof(Float_t)*n;
+   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+
+   WriteFastArrayFloat16(f,n,ele);
+}
+
 //______________________________________________________________________________
 void TBufferFile::WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele)
 {
@@ -1685,6 +1924,63 @@ void TBufferFile::WriteFastArray(const Double_t *d, Int_t n)
 #endif
 }
 
+//______________________________________________________________________________
+void TBufferFile::WriteFastArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele)
+{
+   // Write array of n floats (as truncated float) into the I/O buffer.
+   // see comments about Float16_t encoding at TBufferFile::WriteFloat16
+
+   if (n <= 0) return;
+
+   Int_t l = sizeof(Float_t)*n;
+   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+
+   if (ele && ele->GetFactor()) {
+      //A range is specified. We normalize the float to the range and
+      //convert it to an integer using a scaling factor that is a function of nbits.
+      //see TStreamerElement::GetRange.
+      Double_t factor = ele->GetFactor();
+      Double_t xmin = ele->GetXmin();
+      Double_t xmax = ele->GetXmax();
+      for (int j = 0; j < n; j++) {
+         Float_t x = f[j];
+         if (x < xmin) x = xmin;
+         if (x > xmax) x = xmax;
+         UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint;
+      }
+   } else {
+      Int_t nbits = 0;
+      //number of bits stored in fXmin (see TStreamerElement::GetRange)
+      if (ele) nbits = (UInt_t)ele->GetXmin();
+      Int_t i;
+      if (!nbits) {
+         //if no range and no bits specified, we convert to truncated float
+         for (i = 0; i < n; i++) {
+            Float_t afloat = f[0]; 
+            *this << afloat;
+         }
+      } else {
+         //a range is not specified, but nbits is.
+         //In this case we truncate the mantissa to nbits and we stream
+         //the exponent as a UChar_t and the mantissa as a UShort_t.
+         union {
+            Float_t xx;
+            Int_t ix;
+         };
+         for (i = 0; i < n; i++) {
+            xx = f[i];
+            UChar_t  theExp=(UChar_t)(0x000000ff & ((ix<<1)>>24));
+            UShort_t theMan=((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
+            theMan=(++theMan)>>1;
+            if(theMan&1<<nbits) theMan=(1<<nbits)-1;
+            if(xx<0) theMan|=1<<(nbits+1);
+            *this << theExp;
+            *this << theMan;
+         }
+      }
+   }
+}
+
 //______________________________________________________________________________
 void TBufferFile::WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele)
 {
diff --git a/io/src/TEmulatedCollectionProxy.cxx b/io/src/TEmulatedCollectionProxy.cxx
index 401cd9ab8cb..fe82ebe4f9c 100644
--- a/io/src/TEmulatedCollectionProxy.cxx
+++ b/io/src/TEmulatedCollectionProxy.cxx
@@ -429,6 +429,7 @@ void TEmulatedCollectionProxy::ReadItems(int nElements, TBuffer &b)
             case kLong_t:    b.ReadFastArray(&itm->s_long    , nElements); break;
             case kLong64_t:  b.ReadFastArray(&itm->s_longlong, nElements); break;
             case kFloat_t:   b.ReadFastArray(&itm->flt       , nElements); break;
+            case kFloat16_t: b.ReadFastArrayFloat16(&itm->flt, nElements); break;
             case kDouble_t:  b.ReadFastArray(&itm->dbl       , nElements); break;
             case kBOOL_t:    b.ReadFastArray(&itm->boolean   , nElements); break;
             case kUChar_t:   b.ReadFastArray(&itm->u_char    , nElements); break;
@@ -478,6 +479,7 @@ void TEmulatedCollectionProxy::WriteItems(int nElements, TBuffer &b)
             case kLong_t:    b.WriteFastArray(&itm->s_long    , nElements); break;
             case kLong64_t:  b.WriteFastArray(&itm->s_longlong, nElements); break;
             case kFloat_t:   b.WriteFastArray(&itm->flt       , nElements); break;
+            case kFloat16_t: b.WriteFastArrayFloat16(&itm->flt, nElements); break;
             case kDouble_t:  b.WriteFastArray(&itm->dbl       , nElements); break;
             case kBOOL_t:    b.WriteFastArray(&itm->boolean   , nElements); break;
             case kUChar_t:   b.WriteFastArray(&itm->u_char    , nElements); break;
diff --git a/io/src/TEmulatedMapProxy.cxx b/io/src/TEmulatedMapProxy.cxx
index 22c353c1caa..b0b725ca94b 100644
--- a/io/src/TEmulatedMapProxy.cxx
+++ b/io/src/TEmulatedMapProxy.cxx
@@ -107,6 +107,8 @@ void TEmulatedMapProxy::ReadMap(int nElements, TBuffer &b)
             case kLong_t:    b >> helper->s_long;      break;
             case kLong64_t:  b >> helper->s_longlong;  break;
             case kFloat_t:   b >> helper->flt;         break;
+            case kFloat16_t: b >> f;
+               helper->flt = float(f);  break;
             case kDouble_t:  b >> helper->dbl;         break;
             case kBOOL_t:    b >> helper->boolean;     break;
             case kUChar_t:   b >> helper->u_char;      break;
@@ -167,6 +169,7 @@ void TEmulatedMapProxy::WriteMap(int nElements, TBuffer &b)
             case kLong_t:    b << i->s_long;      break;
             case kLong64_t:  b << i->s_longlong;  break;
             case kFloat_t:   b << i->flt;         break;
+            case kFloat16_t: b << float(i->flt);  break;
             case kDouble_t:  b << i->dbl;         break;
             case kBOOL_t:    b << i->boolean;     break;
             case kUChar_t:   b << i->u_char;      break;
diff --git a/io/src/TGenCollectionStreamer.cxx b/io/src/TGenCollectionStreamer.cxx
index aee53668446..ee312f80912 100644
--- a/io/src/TGenCollectionStreamer.cxx
+++ b/io/src/TGenCollectionStreamer.cxx
@@ -89,6 +89,7 @@ void TGenCollectionStreamer::ReadPrimitives(int nElements, TBuffer &b)
    case kLong_t:    b.ReadFastArray(&itm->s_long    , nElements); break;
    case kLong64_t:  b.ReadFastArray(&itm->s_longlong, nElements); break;
    case kFloat_t:   b.ReadFastArray(&itm->flt       , nElements); break;
+   case kFloat16_t: b.ReadFastArrayFloat16(&itm->flt, nElements); break;
    case kDouble_t:  b.ReadFastArray(&itm->dbl       , nElements); break;
    case kBOOL_t:    b.ReadFastArray(&itm->boolean   , nElements); break;
    case kUChar_t:   b.ReadFastArray(&itm->u_char    , nElements); break;
@@ -232,6 +233,8 @@ void TGenCollectionStreamer::ReadMap(int nElements, TBuffer &b)
             case kLong_t:    b >> i->s_long;      break;
             case kLong64_t:  b >> i->s_longlong;  break;
             case kFloat_t:   b >> i->flt;         break;
+            case kFloat16_t: b >> f;
+               i->flt = float(f);  break;
             case kDouble_t:  b >> i->dbl;         break;
             case kBOOL_t:    b >> i->boolean;     break;
             case kUChar_t:   b >> i->u_char;      break;
@@ -300,6 +303,7 @@ void TGenCollectionStreamer::WritePrimitives(int nElements, TBuffer &b)
    case kLong_t:    b.WriteFastArray(&itm->s_long    , nElements); break;
    case kLong64_t:  b.WriteFastArray(&itm->s_longlong, nElements); break;
    case kFloat_t:   b.WriteFastArray(&itm->flt       , nElements); break;
+   case kFloat16_t: b.WriteFastArrayFloat16(&itm->flt, nElements); break;
    case kDouble_t:  b.WriteFastArray(&itm->dbl       , nElements); break;
    case kBOOL_t:    b.WriteFastArray(&itm->boolean   , nElements); break;
    case kUChar_t:   b.WriteFastArray(&itm->u_char    , nElements); break;
@@ -395,6 +399,7 @@ void TGenCollectionStreamer::WriteMap(int nElements, TBuffer &b)
             case kLong_t:    b << i->s_long;      break;
             case kLong64_t:  b << i->s_longlong;  break;
             case kFloat_t:   b << i->flt;         break;
+            case kFloat16_t: b << float(i->flt);  break;
             case kDouble_t:  b << i->dbl;         break;
             case kBOOL_t:    b << i->boolean;     break;
             case kUChar_t:   b << i->u_char;      break;
diff --git a/meta/inc/TDataType.h b/meta/inc/TDataType.h
index 3ea7ec33982..2415405da32 100644
--- a/meta/inc/TDataType.h
+++ b/meta/inc/TDataType.h
@@ -35,7 +35,7 @@ enum EDataType {
    kInt_t    = 3,  kUInt_t   = 13, kLong_t     = 4,  kULong_t  = 14,
    kFloat_t  = 5,  kDouble_t =  8, kDouble32_t = 9,  kchar     = 10,
    kBool_t   = 18, kLong64_t = 16, kULong64_t  = 17, kOther_t  = -1,
-   kNoType_t = 0,
+   kNoType_t = 0,  kFloat16_t= 19,
    kCounter =  6,  kCharStar = 7,  kBits     = 15 /* for compatibility with TStreamerInfo */
 };
 
diff --git a/meta/inc/TVirtualStreamerInfo.h b/meta/inc/TVirtualStreamerInfo.h
index a85666cde7e..19819ff4b34 100644
--- a/meta/inc/TVirtualStreamerInfo.h
+++ b/meta/inc/TVirtualStreamerInfo.h
@@ -55,13 +55,13 @@ public:
    };
 
    enum EReadWrite {
-      kBase     =  0,  kOffsetL = 20,  kOffsetP = 40,  kCounter =  6,  kCharStar = 7,
-      kChar     =  1,  kShort   =  2,  kInt     =  3,  kLong    =  4,  kFloat    = 5,
+      kBase     =  0,  kOffsetL = 20,  kOffsetP = 40,  kCounter  =  6,  kCharStar = 7,
+      kChar     =  1,  kShort   =  2,  kInt     =  3,  kLong     =  4,  kFloat    = 5,
       kDouble   =  8,  kDouble32=  9,
-      kUChar    = 11,  kUShort  = 12,  kUInt    = 13,  kULong   = 14,  kBits     = 15,
-      kLong64   = 16,  kULong64 = 17,  kBool    = 18,
-      kObject   = 61,  kAny     = 62,  kObjectp = 63,  kObjectP = 64,  kTString  = 65,
-      kTObject  = 66,  kTNamed  = 67,  kAnyp    = 68,  kAnyP    = 69,  kAnyPnoVT = 70,
+      kUChar    = 11,  kUShort  = 12,  kUInt    = 13,  kULong    = 14,  kBits     = 15,
+      kLong64   = 16,  kULong64 = 17,  kBool    = 18,  kFloat16_t= 19,
+      kObject   = 61,  kAny     = 62,  kObjectp = 63,  kObjectP  = 64,  kTString  = 65,
+      kTObject  = 66,  kTNamed  = 67,  kAnyp    = 68,  kAnyP     = 69,  kAnyPnoVT = 70,
       kSTLp     = 71,
       kSkip     = 100, kSkipL = 120, kSkipP   = 140,
       kConv     = 200, kConvL = 220, kConvP   = 240,
diff --git a/meta/src/TDataType.cxx b/meta/src/TDataType.cxx
index 0f56035f3ba..83a4803ff01 100644
--- a/meta/src/TDataType.cxx
+++ b/meta/src/TDataType.cxx
@@ -116,6 +116,7 @@ const char *TDataType::GetTypeName(EDataType type)
       case 16: return "Long64_t";
       case 17: return "ULong64_t";
       case 18: return "Bool_t";
+      case 19: return "Float16_t";
       case kOther_t:  return "";
       case kNoType_t: return "";
       case kchar:     return "Char_t";
@@ -181,6 +182,8 @@ EDataType TDataType::GetType(const type_info &typeinfo)
       retType = kBool_t;
    } else if (!strcmp(typeid(float).name(), typeinfo.name())) {
       retType = kFloat_t;
+   } else if (!strcmp(typeid(Float16_t).name(), typeinfo.name())) {
+      retType = kFloat16_t;
    } else if (!strcmp(typeid(double).name(), typeinfo.name())) {
       retType = kDouble_t;
    } else if (!strcmp(typeid(Double32_t).name(), typeinfo.name())) {
@@ -304,6 +307,9 @@ void TDataType::SetType(const char *name)
       fSize = sizeof(Double_t);
    }
 
+   if (!strcmp("Float16_t", fName.Data())) {
+      fType = kFloat16_t;
+   }
    if (!strcmp("Double32_t", fName.Data())) {
       fType = kDouble32_t;
    }
diff --git a/meta/src/TStreamerElement.cxx b/meta/src/TStreamerElement.cxx
index 1d7fe6d421f..cfc305a8229 100644
--- a/meta/src/TStreamerElement.cxx
+++ b/meta/src/TStreamerElement.cxx
@@ -188,6 +188,10 @@ TStreamerElement::TStreamerElement(const char *name, const char *title, Int_t of
    fXmin        = 0;
    fXmax        = 0;
    for (Int_t i=0;i<5;i++) fMaxIndex[i] = 0;
+   if (fTypeName == "Float16_t" || fTypeName == "Float16_t*") {
+      GetRange(title,fXmin,fXmax,fFactor);
+      if (fFactor > 0 || fXmin > 0) SetBit(kHasRange);
+   }
    if (fTypeName == "Double32_t" || fTypeName == "Double32_t*") {
       GetRange(title,fXmin,fXmax,fFactor);
       if (fFactor > 0 || fXmin > 0) SetBit(kHasRange);
diff --git a/metautils/src/TClassEdit.cxx b/metautils/src/TClassEdit.cxx
index 98cd0e6efaf..7547d8facd7 100644
--- a/metautils/src/TClassEdit.cxx
+++ b/metautils/src/TClassEdit.cxx
@@ -559,7 +559,7 @@ namespace {
       // a type.
 
       const char *excludelist [] = {"Char_t","Short_t","Int_t","Long_t","Float_t",
-                                    "Int_t","Double_t","Double32_t",
+                                    "Int_t","Double_t","Double32_t","Float16_t",
                                     "UChar_t","UShort_t","UInt_t","ULong_t","UInt_t",
                                     "Long64_t","ULong64_t","Bool_t"};
 
diff --git a/odbc/src/TODBCStatement.cxx b/odbc/src/TODBCStatement.cxx
index 17283aa1861..0e7ccd987d2 100644
--- a/odbc/src/TODBCStatement.cxx
+++ b/odbc/src/TODBCStatement.cxx
@@ -513,6 +513,7 @@ Bool_t TODBCStatement::BindParam(Int_t npar, Int_t roottype, Int_t size)
       case kChar_t:     sqltype = SQL_TINYINT; sqlctype = SQL_C_STINYINT; elemsize = sizeof(signed char); break;
       case kBool_t:     sqltype = SQL_TINYINT; sqlctype = SQL_C_UTINYINT; elemsize = sizeof(unsigned char); break;
       case kFloat_t:    sqltype = SQL_FLOAT;   sqlctype = SQL_C_FLOAT;    elemsize = sizeof(float); break;
+      case kFloat16_t:  sqltype = SQL_FLOAT;   sqlctype = SQL_C_FLOAT;    elemsize = sizeof(float); break;
       case kDouble_t:   sqltype = SQL_DOUBLE;  sqlctype = SQL_C_DOUBLE;   elemsize = sizeof(double); break;
       case kDouble32_t: sqltype = SQL_DOUBLE;  sqlctype = SQL_C_DOUBLE;   elemsize = sizeof(double); break;
       case kCharStar:   sqltype = SQL_CHAR;    sqlctype = SQL_C_CHAR;     elemsize = size; break;
diff --git a/sql/inc/TBufferSQL2.h b/sql/inc/TBufferSQL2.h
index a66c9a2b876..22f56512ffd 100644
--- a/sql/inc/TBufferSQL2.h
+++ b/sql/inc/TBufferSQL2.h
@@ -168,6 +168,8 @@ public:
 
    virtual void     WriteObject(const TObject *obj);
 
+   virtual void     ReadFloat16 (Float_t *f, TStreamerElement *ele=0);
+   virtual void     WriteFloat16(Float_t *f, TStreamerElement *ele=0);
    virtual void     ReadDouble32 (Double_t *d, TStreamerElement *ele=0);
    virtual void     WriteDouble32(Double_t *d, TStreamerElement *ele=0);
 
@@ -184,6 +186,7 @@ public:
    virtual Int_t    ReadArray(ULong64_t *&l);
    virtual Int_t    ReadArray(Float_t   *&f);
    virtual Int_t    ReadArray(Double_t  *&d);
+   virtual Int_t    ReadArrayFloat16(Float_t  *&f, TStreamerElement *ele=0);
    virtual Int_t    ReadArrayDouble32(Double_t  *&d, TStreamerElement *ele=0);
 
    virtual Int_t    ReadStaticArray(Bool_t    *b);
@@ -199,6 +202,7 @@ public:
    virtual Int_t    ReadStaticArray(ULong64_t *l);
    virtual Int_t    ReadStaticArray(Float_t   *f);
    virtual Int_t    ReadStaticArray(Double_t  *d);
+   virtual Int_t    ReadStaticArrayFloat16(Float_t  *f, TStreamerElement *ele=0);
    virtual Int_t    ReadStaticArrayDouble32(Double_t  *d, TStreamerElement *ele=0);
 
    virtual void     ReadFastArray(Bool_t    *b, Int_t n);
@@ -214,6 +218,7 @@ public:
    virtual void     ReadFastArray(ULong64_t *l, Int_t n);
    virtual void     ReadFastArray(Float_t   *f, Int_t n);
    virtual void     ReadFastArray(Double_t  *d, Int_t n);
+   virtual void     ReadFastArrayFloat16(Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual void     ReadFastArrayDouble32(Double_t  *d, Int_t n, TStreamerElement *ele=0);
 
    virtual void     WriteArray(const Bool_t    *b, Int_t n);
@@ -229,6 +234,7 @@ public:
    virtual void     WriteArray(const ULong64_t *l, Int_t n);
    virtual void     WriteArray(const Float_t   *f, Int_t n);
    virtual void     WriteArray(const Double_t  *d, Int_t n);
+   virtual void     WriteArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual void     WriteArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual void     ReadFastArray(void  *start , const TClass *cl, Int_t n=1, TMemberStreamer *s=0);
    virtual void     ReadFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0);
@@ -246,6 +252,7 @@ public:
    virtual void     WriteFastArray(const ULong64_t *l, Int_t n);
    virtual void     WriteFastArray(const Float_t   *f, Int_t n);
    virtual void     WriteFastArray(const Double_t  *d, Int_t n);
+   virtual void     WriteFastArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual void     WriteFastArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual void     WriteFastArray(void  *start,  const TClass *cl, Int_t n=1, TMemberStreamer *s=0);
    virtual Int_t    WriteFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0);
diff --git a/sql/src/TBufferSQL2.cxx b/sql/src/TBufferSQL2.cxx
index 11f60f92972..800718724b8 100644
--- a/sql/src/TBufferSQL2.cxx
+++ b/sql/src/TBufferSQL2.cxx
@@ -1030,18 +1030,34 @@ void TBufferSQL2::WriteObject(const void *actualObjStart, const TClass *actualCl
       return n;                                 \
    }
 
+//______________________________________________________________________________
+void TBufferSQL2::ReadFloat16 (Float_t *f, TStreamerElement * /*ele*/)
+{
+   // Read Float16 value
+
+   SqlReadBasic(*f);
+}
+
 //______________________________________________________________________________
 void TBufferSQL2::ReadDouble32 (Double_t *d, TStreamerElement * /*ele*/)
 {
-   // Read Double_32 value
+   // Read Double32 value
 
    SqlReadBasic(*d);
 }
 
+//______________________________________________________________________________
+void TBufferSQL2::WriteFloat16 (Float_t *f, TStreamerElement * /*ele*/)
+{
+   // Write Float16 value
+
+   SqlWriteBasic(*f);
+}
+
 //______________________________________________________________________________
 void TBufferSQL2::WriteDouble32 (Double_t *d, TStreamerElement * /*ele*/)
 {
-   // Write Double_32 value
+   // Write Double32 value
 
    SqlWriteBasic(*d);
 }
@@ -1150,6 +1166,14 @@ Int_t TBufferSQL2::ReadArray(Double_t  *&d)
    TBufferSQL2_ReadArray(Double_t,d);
 }
 
+//______________________________________________________________________________
+Int_t TBufferSQL2::ReadArrayFloat16(Float_t  *&f, TStreamerElement * /*ele*/)
+{
+   // Read array of Float16_t from buffer
+
+   TBufferSQL2_ReadArray(Float_t,f);
+}
+
 //______________________________________________________________________________
 Int_t TBufferSQL2::ReadArrayDouble32(Double_t  *&d, TStreamerElement * /*ele*/)
 {
@@ -1272,6 +1296,14 @@ Int_t TBufferSQL2::ReadStaticArray(Double_t  *d)
    TBufferSQL2_ReadStaticArray(d);
 }
 
+//______________________________________________________________________________
+Int_t TBufferSQL2::ReadStaticArrayFloat16(Float_t  *f, TStreamerElement * /*ele*/)
+{
+   // Read array of Float16_t from buffer
+
+   TBufferSQL2_ReadStaticArray(f);
+}
+
 //______________________________________________________________________________
 Int_t TBufferSQL2::ReadStaticArrayDouble32(Double_t  *d, TStreamerElement * /*ele*/)
 {
@@ -1426,6 +1458,14 @@ void TBufferSQL2::ReadFastArray(Double_t  *d, Int_t n)
    TBufferSQL2_ReadFastArray(d);
 }
 
+//______________________________________________________________________________
+void TBufferSQL2::ReadFastArrayFloat16(Float_t  *f, Int_t n, TStreamerElement * /*ele*/)
+{
+   // read array of Float16_t from buffer
+
+   TBufferSQL2_ReadFastArray(f);
+}
+
 //______________________________________________________________________________
 void TBufferSQL2::ReadFastArrayDouble32(Double_t  *d, Int_t n, TStreamerElement * /*ele*/)
 {
@@ -1659,6 +1699,14 @@ void TBufferSQL2::WriteArray(const Double_t  *d, Int_t n)
    TBufferSQL2_WriteArray(d);
 }
 
+//______________________________________________________________________________
+void TBufferSQL2::WriteArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement * /*ele*/)
+{
+   // Write array of Float16_t to buffer
+
+   TBufferSQL2_WriteArray(f);
+}
+
 //______________________________________________________________________________
 void TBufferSQL2::WriteArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement * /*ele*/)
 {
@@ -1820,6 +1868,14 @@ void TBufferSQL2::WriteFastArray(const Double_t  *d, Int_t n)
    TBufferSQL2_WriteFastArray(d);
 }
 
+//______________________________________________________________________________
+void TBufferSQL2::WriteFastArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement * /*ele*/)
+{
+   // Write array of Float16_t to buffer
+
+   TBufferSQL2_WriteFastArray(f);
+}
+
 //______________________________________________________________________________
 void TBufferSQL2::WriteFastArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement * /*ele*/)
 {
diff --git a/sql/src/TSQLFile.cxx b/sql/src/TSQLFile.cxx
index e8d9e5cd746..75fe9806c53 100644
--- a/sql/src/TSQLFile.cxx
+++ b/sql/src/TSQLFile.cxx
@@ -86,7 +86,7 @@
 // first write operation. These options are:
 //     SetUseSuffixes() - suffix usage in column names (default - on)
 //     SetArrayLimit()  - defines maximum array size, which can
-//                        has column for each element (default 20)
+//                        has column for each element (default 21)
 //     SetTablesType()  - table type name in MySQL database (default "InnoDB")
 //     SetUseIndexes()  - usage of indexes in database (default kIndexesBasic)
 // Normally these functions should be called immidiately after TSQLFile constructor.
@@ -196,7 +196,7 @@
 
 ClassImp(TSQLFile);
 
-const char* mysql_BasicTypes[20] = {
+const char* mysql_BasicTypes[21] = {
 "VARCHAR(255)",     // kBase     =  0,  used for text
 "TINYINT UNSIGNED", // kChar     =  1,
 "SMALLINT",         // kShort   =  2,
@@ -216,6 +216,7 @@ const char* mysql_BasicTypes[20] = {
 "BIGINT",           // kLong64   = 16,
 "BIGINT UNSIGNED",  // kULong64 = 17,
 "BOOL",             // kBool    = 18,
+"DOUBLE",           // kFloat16 = 19,
 ""
 };
 
@@ -235,7 +236,7 @@ const char* mysql_OtherTypes[13] = {
 "InnoDB"            // default tables types, used only for MySQL tables
 };
 
-const char* oracle_BasicTypes[20] = {
+const char* oracle_BasicTypes[21] = {
 "VARCHAR(255)",     // kBase     =  0,  used for text
 "INT",              // kChar     =  1,
 "INT",              // kShort   =  2,
@@ -255,6 +256,7 @@ const char* oracle_BasicTypes[20] = {
 "INT",              // kLong64   = 16,
 "INT",              // kULong64 = 17,
 "INT",              // kBool    = 18,
+"FLOAT",            // kFloat16 = 19,
 ""
 };
 
@@ -282,7 +284,7 @@ TSQLFile::TSQLFile() :
    fSQLClassInfos(0),
    fUseSuffixes(kTRUE),
    fSQLIOversion(1),
-   fArrayLimit(20),
+   fArrayLimit(21),
    fCanChangeConfig(kFALSE),
    fTablesType(),
    fUseTransactions(0),
@@ -306,7 +308,7 @@ TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const
    fSQLClassInfos(0),
    fUseSuffixes(kTRUE),
    fSQLIOversion(1),
-   fArrayLimit(20),
+   fArrayLimit(21),
    fCanChangeConfig(kFALSE),
    fTablesType(),
    fUseTransactions(0),
@@ -354,7 +356,7 @@ TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const
       fOtherTypes = oracle_OtherTypes;
    }
 
-   fArrayLimit = 20;
+   fArrayLimit = 21;
    fTablesType = SQLDefaultTableType();
    fUseIndexes = 1;
    fUseTransactions = kTransactionsAuto;
@@ -543,7 +545,7 @@ void TSQLFile::SetArrayLimit(Int_t limit)
    // This is usefull to prevent tables with very big number of columns
    // If limit==0, all arrays will be stored in raw format
    // If limit<0, all array values will be stored in column form
-   // Default value is 20
+   // Default value is 21
 
    if (!fCanChangeConfig)
       Error("SetArrayLimit", "Configurations already cannot be changed");
diff --git a/sql/src/TSQLStructure.cxx b/sql/src/TSQLStructure.cxx
index c7e0ebfedc6..d9562c84e21 100644
--- a/sql/src/TSQLStructure.cxx
+++ b/sql/src/TSQLStructure.cxx
@@ -780,6 +780,7 @@ Bool_t TSQLStructure::IsNumericType(Int_t typ)
    case TStreamerInfo::kInt     : return kTRUE;
    case TStreamerInfo::kLong    : return kTRUE;
    case TStreamerInfo::kFloat   : return kTRUE;
+   case TStreamerInfo::kFloat16 : return kTRUE;
    case TStreamerInfo::kCounter : return kTRUE;
    case TStreamerInfo::kDouble  : return kTRUE;
    case TStreamerInfo::kDouble32: return kTRUE;
@@ -807,6 +808,7 @@ const char* TSQLStructure::GetSimpleTypeName(Int_t typ)
    case TStreamerInfo::kInt     : return sqlio::Int;
    case TStreamerInfo::kLong    : return sqlio::Long;
    case TStreamerInfo::kFloat   : return sqlio::Float;
+   case TStreamerInfo::kFloat16 : return sqlio::Float;
    case TStreamerInfo::kCounter : return sqlio::Int;
    case TStreamerInfo::kDouble  : return sqlio::Double;
    case TStreamerInfo::kDouble32: return sqlio::Double;
diff --git a/tree/inc/TBufferSQL.h b/tree/inc/TBufferSQL.h
index 7e04973e8ab..611220509f6 100644
--- a/tree/inc/TBufferSQL.h
+++ b/tree/inc/TBufferSQL.h
@@ -117,6 +117,7 @@ public:
    virtual   void     ReadFastArray(ULong64_t *, Int_t );
    virtual   void     ReadFastArray(Float_t   *, Int_t );
    virtual   void     ReadFastArray(Double_t  *, Int_t );
+   virtual   void     ReadFastArrayFloat16(Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual   void     ReadFastArrayDouble32(Double_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual   void     ReadFastArray(void  *, const TClass *, Int_t n=1, TMemberStreamer *s=0);
    virtual   void     ReadFastArray(void **, const TClass *, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0);
diff --git a/tree/src/TBufferSQL.cxx b/tree/src/TBufferSQL.cxx
index 00d1332cf6f..51c0a1a5e01 100644
--- a/tree/src/TBufferSQL.cxx
+++ b/tree/src/TBufferSQL.cxx
@@ -708,6 +708,13 @@ void TBufferSQL::ReadFastArray(Double_t *d, Int_t n)
    }
 }
 
+//________________________________________________________________________
+void     TBufferSQL::ReadFastArrayFloat16(Float_t  *, Int_t , TStreamerElement *)
+{
+   // ReadFastArray SQL implementation.   
+   Fatal("ReadFastArrayFloat16(Float_t  *, Int_t , TStreamerElement *)","Not implemented yet");
+}
+
 //________________________________________________________________________
 void     TBufferSQL::ReadFastArrayDouble32(Double_t  *, Int_t , TStreamerElement *)
 {
diff --git a/utils/src/rootcint.cxx b/utils/src/rootcint.cxx
index 443432dd206..e12028a5f45 100644
--- a/utils/src/rootcint.cxx
+++ b/utils/src/rootcint.cxx
@@ -1279,6 +1279,65 @@ bool NeedDestructor(G__ClassInfo& cl)
    */
 }
 
+//______________________________________________________________________________
+bool IsTemplateFloat16(G__ClassInfo &cl)
+{
+   // Return true if any of the argument is or contains a Float16.
+   if (!cl.IsTmplt()) return false;
+
+   static G__TypeInfo ti;
+   char arg[2048], *current, *next;
+
+   strcpy(arg, cl.Name());
+   // arg is now is the name of class template instantiation.
+   // We first need to find the start of the list of its template arguments
+   // then we have a comma separated list of type names.  We want to return
+   // the 'count+1'-th element in the list.
+   int len = strlen(arg);
+   int nesting = 0;
+   current = 0;
+   next = &(arg[0]);
+   for (int c = 0; c<len; c++) {
+      switch (arg[c]) {
+      case '<':
+         if (nesting==0) {
+            arg[c]=0;
+            current = next;
+            next = &(arg[c+1]);
+         }
+         nesting++;
+         break;
+      case '>':
+         nesting--;
+         if (nesting==0) {
+            arg[c]=0;
+            current = next;
+            next = &(arg[c+1]);
+            if (current) {
+               if (strcmp(current,"Float16_t")==0) return true;
+               G__ClassInfo subcl(current);
+               if (IsTemplateFloat16(subcl)) return true;
+            }
+         }
+         break;
+      case ',':
+         if (nesting==1) {
+            arg[c]=0;
+            current = next;
+            next = &(arg[c+1]);
+            if (current) {
+               if (strcmp(current,"Float16_t")==0) return true;
+               G__ClassInfo subcl(current);
+               if (IsTemplateFloat16(subcl)) return true;
+            }
+         }
+         break;
+      }
+   }
+
+   return false;
+}
+
 //______________________________________________________________________________
 bool IsTemplateDouble32(G__ClassInfo &cl)
 {
@@ -1338,6 +1397,7 @@ bool IsTemplateDouble32(G__ClassInfo &cl)
    return false;
 }
 
+
 //______________________________________________________________________________
 int IsSTLContainer(G__DataMemberInfo &m)
 {
@@ -2518,7 +2578,7 @@ void WriteClassInit(G__ClassInfo &cl)
    (*dictSrcOut) << "      return &instance;"  << std::endl
                  << "   }" << std::endl;
 
-   if (!stl && !IsTemplateDouble32(cl)) {
+   if (!stl && !IsTemplateDouble32(cl) && !IsTemplateFloat16(cl)) {
       // The GenerateInitInstance for STL are not unique and should not be externally accessible
       (*dictSrcOut) << "   TGenericClassInfo *GenerateInitInstance(const " << csymbol.c_str() << "*)" << std::endl
                     << "   {\n      return GenerateInitInstanceLocal((" <<  csymbol.c_str() << "*)0);\n   }"
@@ -2852,6 +2912,10 @@ void WriteStreamer(G__ClassInfo &cl)
          //  - members with an ! as first character in the title (comment) field
          //  - the member G__virtualinfo inserted by the CINT RTTI system
 
+         //special case for Float16_t
+         int isFloat16=0;
+         if (strstr(m.Type()->Name(),"Float16_t")) isFloat16=1;
+
          //special case for Double32_t
          int isDouble32=0;
          if (strstr(m.Type()->Name(),"Double32_t")) isDouble32=1;
@@ -2893,7 +2957,10 @@ void WriteStreamer(G__ClassInfo &cl)
                         (*dictSrcOut) << "      delete [] " << m.Name() << ";" << std::endl
                             << "      " << GetNonConstMemberName(m) << " = new "
                             << ShortTypeName(m.Type()->Name()) << "[" << indexvar << "];" << std::endl;
-                        if (isDouble32) {
+                        if (isFloat16) {
+                           (*dictSrcOut) << "      R__b.ReadFastArrayFloat16(" <<  GetNonConstMemberName(m)
+                               << "," << indexvar << ");" << std::endl;
+                        } else if (isDouble32) {
                            (*dictSrcOut) << "      R__b.ReadFastArrayDouble32(" <<  GetNonConstMemberName(m)
                                << "," << indexvar << ");" << std::endl;
                         } else {
@@ -2901,7 +2968,10 @@ void WriteStreamer(G__ClassInfo &cl)
                                << "," << indexvar << ");" << std::endl;
                         }
                      } else {
-                        if (isDouble32) {
+                        if (isFloat16) {
+                           (*dictSrcOut) << "      R__b.WriteFastArrayFloat16("
+                               << m.Name() << "," << indexvar << ");" << std::endl;
+                        } else if (isDouble32) {
                            (*dictSrcOut) << "      R__b.WriteFastArrayDouble32("
                                << m.Name() << "," << indexvar << ");" << std::endl;
                         } else {
@@ -2916,7 +2986,10 @@ void WriteStreamer(G__ClassInfo &cl)
                         if ((m.Type())->Property() & G__BIT_ISENUM)
                            (*dictSrcOut) << "      R__b.ReadStaticArray((Int_t*)" << m.Name() << ");" << std::endl;
                         else
-                           if (isDouble32) {
+                           if (isFloat16) {
+                              (*dictSrcOut) << "      R__b.ReadStaticArrayFloat16((" << m.Type()->TrueName()
+                                  << "*)" << m.Name() << ");" << std::endl;
+                           } else if (isDouble32) {
                               (*dictSrcOut) << "      R__b.ReadStaticArrayDouble32((" << m.Type()->TrueName()
                                   << "*)" << m.Name() << ");" << std::endl;
                            } else {
@@ -2927,7 +3000,9 @@ void WriteStreamer(G__ClassInfo &cl)
                         if ((m.Type())->Property() & G__BIT_ISENUM)
                            (*dictSrcOut) << "      R__b.ReadStaticArray((Int_t*)" << m.Name() << ");" << std::endl;
                         else
-                           if (isDouble32) {
+                           if (isFloat16) {
+                              (*dictSrcOut) << "      R__b.ReadStaticArrayFloat16(" << m.Name() << ");" << std::endl;
+                           } else if (isDouble32) {
                               (*dictSrcOut) << "      R__b.ReadStaticArrayDouble32(" << m.Name() << ");" << std::endl;
                            } else {
                               (*dictSrcOut) << "      R__b.ReadStaticArray((" << m.Type()->TrueName()
@@ -2943,7 +3018,10 @@ void WriteStreamer(G__ClassInfo &cl)
                            (*dictSrcOut) << "      R__b.WriteArray((Int_t*)" << m.Name() << ", "
                                << s << ");" << std::endl;
                         else
-                           if (isDouble32) {
+                           if (isFloat16) {
+                              (*dictSrcOut) << "      R__b.WriteArrayFloat16((" << m.Type()->TrueName()
+                                  << "*)" << m.Name() << ", " << s << ");" << std::endl;
+                           } else if (isDouble32) {
                               (*dictSrcOut) << "      R__b.WriteArrayDouble32((" << m.Type()->TrueName()
                                   << "*)" << m.Name() << ", " << s << ");" << std::endl;
                            } else {
@@ -2954,7 +3032,9 @@ void WriteStreamer(G__ClassInfo &cl)
                         if ((m.Type())->Property() & G__BIT_ISENUM)
                            (*dictSrcOut) << "      R__b.WriteArray((Int_t*)" << m.Name() << ", " << s << ");" << std::endl;
                         else
-                           if (isDouble32) {
+                           if (isFloat16) {
+                              (*dictSrcOut) << "      R__b.WriteArrayFloat16(" << m.Name() << ", " << s << ");" << std::endl;
+                           } else if (isDouble32) {
                               (*dictSrcOut) << "      R__b.WriteArrayDouble32(" << m.Name() << ", " << s << ");" << std::endl;
                            } else {
                               (*dictSrcOut) << "      R__b.WriteArray(" << m.Name() << ", " << s << ");" << std::endl;
@@ -2967,7 +3047,13 @@ void WriteStreamer(G__ClassInfo &cl)
                   else
                      (*dictSrcOut) << "      R__b << (Int_t)" << m.Name() << ";" << std::endl;
                } else {
-                  if (isDouble32) {
+                  if (isFloat16) {
+                     if (i == 0)
+                        (*dictSrcOut) << "      {float R_Dummy; R__b >> R_Dummy; " << GetNonConstMemberName(m)
+                            << "=Float16_t(R_Dummy);}" << std::endl;
+                     else
+                        (*dictSrcOut) << "      R__b << float(" << GetNonConstMemberName(m) << ");" << std::endl;
+                  } else if (isDouble32) {
                      if (i == 0)
                         (*dictSrcOut) << "      {float R_Dummy; R__b >> R_Dummy; " << GetNonConstMemberName(m)
                             << "=Double32_t(R_Dummy);}" << std::endl;
diff --git a/xml/inc/TBufferXML.h b/xml/inc/TBufferXML.h
index 6025eec4cbb..e05deaae4e9 100644
--- a/xml/inc/TBufferXML.h
+++ b/xml/inc/TBufferXML.h
@@ -82,6 +82,8 @@ public:
 
    virtual void     WriteObject(const TObject *obj);
 
+   virtual void     ReadFloat16 (Float_t *f, TStreamerElement *ele=0);
+   virtual void     WriteFloat16(Float_t *f, TStreamerElement *ele=0);
    virtual void     ReadDouble32 (Double_t *d, TStreamerElement *ele=0);
    virtual void     WriteDouble32(Double_t *d, TStreamerElement *ele=0);
 
@@ -98,6 +100,7 @@ public:
    virtual Int_t    ReadArray(ULong64_t *&l);
    virtual Int_t    ReadArray(Float_t   *&f);
    virtual Int_t    ReadArray(Double_t  *&d);
+   virtual Int_t    ReadArrayFloat16(Float_t  *&f, TStreamerElement *ele=0);
    virtual Int_t    ReadArrayDouble32(Double_t  *&d, TStreamerElement *ele=0);
 
    virtual Int_t    ReadStaticArray(Bool_t    *b);
@@ -113,6 +116,7 @@ public:
    virtual Int_t    ReadStaticArray(ULong64_t *l);
    virtual Int_t    ReadStaticArray(Float_t   *f);
    virtual Int_t    ReadStaticArray(Double_t  *d);
+   virtual Int_t    ReadStaticArrayFloat16(Float_t  *f, TStreamerElement *ele=0);
    virtual Int_t    ReadStaticArrayDouble32(Double_t  *d, TStreamerElement *ele=0);
 
    virtual void     ReadFastArray(Bool_t    *b, Int_t n);
@@ -128,6 +132,7 @@ public:
    virtual void     ReadFastArray(ULong64_t *l, Int_t n);
    virtual void     ReadFastArray(Float_t   *f, Int_t n);
    virtual void     ReadFastArray(Double_t  *d, Int_t n);
+   virtual void     ReadFastArrayFloat16(Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual void     ReadFastArrayDouble32(Double_t  *d, Int_t n, TStreamerElement *ele=0);
 
    virtual void     WriteArray(const Bool_t    *b, Int_t n);
@@ -143,6 +148,7 @@ public:
    virtual void     WriteArray(const ULong64_t *l, Int_t n);
    virtual void     WriteArray(const Float_t   *f, Int_t n);
    virtual void     WriteArray(const Double_t  *d, Int_t n);
+   virtual void     WriteArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement *ele=0);
    virtual void     WriteArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual void     ReadFastArray(void  *start , const TClass *cl, Int_t n=1, TMemberStreamer *s=0);
    virtual void     ReadFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0);
@@ -160,6 +166,7 @@ public:
    virtual void     WriteFastArray(const ULong64_t *l, Int_t n);
    virtual void     WriteFastArray(const Float_t   *f, Int_t n);
    virtual void     WriteFastArray(const Double_t  *d, Int_t n);
+   virtual void     WriteFastArrayFloat16(const Float_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual void     WriteFastArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement *ele=0);
    virtual void     WriteFastArray(void  *start,  const TClass *cl, Int_t n=1, TMemberStreamer *s=0);
    virtual Int_t    WriteFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0);
diff --git a/xml/src/TBufferXML.cxx b/xml/src/TBufferXML.cxx
index 0160d49dc4a..63ba55726c9 100644
--- a/xml/src/TBufferXML.cxx
+++ b/xml/src/TBufferXML.cxx
@@ -1478,6 +1478,14 @@ void TBufferXML::WriteObject(const void *actualObjStart, const TClass *actualCla
    return n;                                                  \
 }
 
+//______________________________________________________________________________
+void TBufferXML::ReadFloat16 (Float_t *f, TStreamerElement * /*ele*/)
+{
+   // read a Float16_t from the buffer
+   BeforeIOoperation();
+   XmlReadBasic(*f);
+}
+
 //______________________________________________________________________________
 void TBufferXML::ReadDouble32 (Double_t *d, TStreamerElement * /*ele*/)
 {
@@ -1486,6 +1494,14 @@ void TBufferXML::ReadDouble32 (Double_t *d, TStreamerElement * /*ele*/)
    XmlReadBasic(*d);
 }
 
+//______________________________________________________________________________
+void TBufferXML::WriteFloat16 (Float_t *f, TStreamerElement * /*ele*/)
+{
+   // write a Float16_t to the buffer
+   BeforeIOoperation();
+   XmlWriteBasic(*f);
+}
+
 //______________________________________________________________________________
 void TBufferXML::WriteDouble32 (Double_t *d, TStreamerElement * /*ele*/)
 {
@@ -1598,6 +1614,14 @@ Int_t TBufferXML::ReadArray(Double_t  *&d)
    TBufferXML_ReadArray(Double_t,d);
 }
 
+//______________________________________________________________________________
+Int_t TBufferXML::ReadArrayFloat16(Float_t  *&f, TStreamerElement * /*ele*/)
+{
+   // Read array of Float16_t from buffer
+
+   TBufferXML_ReadArray(Float_t,f);
+}
+
 //______________________________________________________________________________
 Int_t TBufferXML::ReadArrayDouble32(Double_t  *&d, TStreamerElement * /*ele*/)
 {
@@ -1725,6 +1749,14 @@ Int_t TBufferXML::ReadStaticArray(Double_t  *d)
    TBufferXML_ReadStaticArray(d);
 }
 
+//______________________________________________________________________________
+Int_t TBufferXML::ReadStaticArrayFloat16(Float_t  *f, TStreamerElement * /*ele*/)
+{
+   // Read array of Float16_t from buffer
+
+   TBufferXML_ReadStaticArray(f);
+}
+
 //______________________________________________________________________________
 Int_t TBufferXML::ReadStaticArrayDouble32(Double_t  *d, TStreamerElement * /*ele*/)
 {
@@ -1887,6 +1919,14 @@ void TBufferXML::ReadFastArray(Double_t  *d, Int_t n)
    TBufferXML_ReadFastArray(d);
 }
 
+//______________________________________________________________________________
+void TBufferXML::ReadFastArrayFloat16(Float_t  *f, Int_t n, TStreamerElement * /*ele*/)
+{
+   // read array of Float16_t from buffer
+
+   TBufferXML_ReadFastArray(f);
+}
+
 //______________________________________________________________________________
 void TBufferXML::ReadFastArrayDouble32(Double_t  *d, Int_t n, TStreamerElement * /*ele*/)
 {
@@ -2055,6 +2095,14 @@ void TBufferXML::WriteArray(const Double_t  *d, Int_t n)
    TBufferXML_WriteArray(d);
 }
 
+//______________________________________________________________________________
+void TBufferXML::WriteArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement * /*ele*/)
+{
+   // Write array of Float16_t to buffer
+
+   TBufferXML_WriteArray(f);
+}
+
 //______________________________________________________________________________
 void TBufferXML::WriteArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement * /*ele*/)
 {
@@ -2225,6 +2273,14 @@ void TBufferXML::WriteFastArray(const Double_t  *d, Int_t n)
    TBufferXML_WriteFastArray(d);
 }
 
+//______________________________________________________________________________
+void TBufferXML::WriteFastArrayFloat16(const Float_t  *f, Int_t n, TStreamerElement * /*ele*/)
+{
+   // Write array of Float16_t to buffer
+
+   TBufferXML_WriteFastArray(f);
+}
+
 //______________________________________________________________________________
 void TBufferXML::WriteFastArrayDouble32(const Double_t  *d, Int_t n, TStreamerElement * /*ele*/)
 {
-- 
GitLab