@@ -266,6 +266,33 @@ get_size_t(PyObject *v, size_t *p)
266266
267267/* Floating point helpers */
268268
269+ static PyObject *
270+ unpack_halffloat (const char * p , /* start of 2-byte string */
271+ int le ) /* true for little-endian, false for big-endian */
272+ {
273+ double x ;
274+
275+ x = _PyFloat_Unpack2 ((unsigned char * )p , le );
276+ if (x == -1.0 && PyErr_Occurred ()) {
277+ return NULL ;
278+ }
279+ return PyFloat_FromDouble (x );
280+ }
281+
282+ static int
283+ pack_halffloat (char * p , /* start of 2-byte string */
284+ PyObject * v , /* value to pack */
285+ int le ) /* true for little-endian, false for big-endian */
286+ {
287+ double x = PyFloat_AsDouble (v );
288+ if (x == -1.0 && PyErr_Occurred ()) {
289+ PyErr_SetString (StructError ,
290+ "required argument is not a float" );
291+ return -1 ;
292+ }
293+ return _PyFloat_Pack2 (x , (unsigned char * )p , le );
294+ }
295+
269296static PyObject *
270297unpack_float (const char * p , /* start of 4-byte string */
271298 int le ) /* true for little-endian, false for big-endian */
@@ -469,6 +496,16 @@ nu_bool(const char *p, const formatdef *f)
469496}
470497
471498
499+ static PyObject *
500+ nu_halffloat (const char * p , const formatdef * f )
501+ {
502+ #if PY_LITTLE_ENDIAN
503+ return unpack_halffloat (p , 1 );
504+ #else
505+ return unpack_halffloat (p , 0 );
506+ #endif
507+ }
508+
472509static PyObject *
473510nu_float (const char * p , const formatdef * f )
474511{
@@ -680,6 +717,16 @@ np_bool(char *p, PyObject *v, const formatdef *f)
680717 return 0 ;
681718}
682719
720+ static int
721+ np_halffloat (char * p , PyObject * v , const formatdef * f )
722+ {
723+ #if PY_LITTLE_ENDIAN
724+ return pack_halffloat (p , v , 1 );
725+ #else
726+ return pack_halffloat (p , v , 0 );
727+ #endif
728+ }
729+
683730static int
684731np_float (char * p , PyObject * v , const formatdef * f )
685732{
@@ -743,6 +790,7 @@ static const formatdef native_table[] = {
743790 {'Q' , sizeof (PY_LONG_LONG ), LONG_LONG_ALIGN , nu_ulonglong ,np_ulonglong },
744791#endif
745792 {'?' , sizeof (BOOL_TYPE ), BOOL_ALIGN , nu_bool , np_bool },
793+ {'e' , sizeof (short ), SHORT_ALIGN , nu_halffloat , np_halffloat },
746794 {'f' , sizeof (float ), FLOAT_ALIGN , nu_float , np_float },
747795 {'d' , sizeof (double ), DOUBLE_ALIGN , nu_double , np_double },
748796 {'P' , sizeof (void * ), VOID_P_ALIGN , nu_void_p , np_void_p },
@@ -825,6 +873,12 @@ bu_ulonglong(const char *p, const formatdef *f)
825873#endif
826874}
827875
876+ static PyObject *
877+ bu_halffloat (const char * p , const formatdef * f )
878+ {
879+ return unpack_halffloat (p , 0 );
880+ }
881+
828882static PyObject *
829883bu_float (const char * p , const formatdef * f )
830884{
@@ -921,6 +975,12 @@ bp_ulonglong(char *p, PyObject *v, const formatdef *f)
921975 return res ;
922976}
923977
978+ static int
979+ bp_halffloat (char * p , PyObject * v , const formatdef * f )
980+ {
981+ return pack_halffloat (p , v , 0 );
982+ }
983+
924984static int
925985bp_float (char * p , PyObject * v , const formatdef * f )
926986{
@@ -972,6 +1032,7 @@ static formatdef bigendian_table[] = {
9721032 {'q' , 8 , 0 , bu_longlong , bp_longlong },
9731033 {'Q' , 8 , 0 , bu_ulonglong , bp_ulonglong },
9741034 {'?' , 1 , 0 , bu_bool , bp_bool },
1035+ {'e' , 2 , 0 , bu_halffloat , bp_halffloat },
9751036 {'f' , 4 , 0 , bu_float , bp_float },
9761037 {'d' , 8 , 0 , bu_double , bp_double },
9771038 {0 }
@@ -1053,6 +1114,12 @@ lu_ulonglong(const char *p, const formatdef *f)
10531114#endif
10541115}
10551116
1117+ static PyObject *
1118+ lu_halffloat (const char * p , const formatdef * f )
1119+ {
1120+ return unpack_halffloat (p , 1 );
1121+ }
1122+
10561123static PyObject *
10571124lu_float (const char * p , const formatdef * f )
10581125{
@@ -1141,6 +1208,12 @@ lp_ulonglong(char *p, PyObject *v, const formatdef *f)
11411208 return res ;
11421209}
11431210
1211+ static int
1212+ lp_halffloat (char * p , PyObject * v , const formatdef * f )
1213+ {
1214+ return pack_halffloat (p , v , 1 );
1215+ }
1216+
11441217static int
11451218lp_float (char * p , PyObject * v , const formatdef * f )
11461219{
@@ -1182,6 +1255,7 @@ static formatdef lilendian_table[] = {
11821255 {'Q' , 8 , 0 , lu_ulonglong , lp_ulonglong },
11831256 {'?' , 1 , 0 , bu_bool , bp_bool }, /* Std rep not endian dep,
11841257 but potentially different from native rep -- reuse bx_bool funcs. */
1258+ {'e' , 2 , 0 , lu_halffloat , lp_halffloat },
11851259 {'f' , 4 , 0 , lu_float , lp_float },
11861260 {'d' , 8 , 0 , lu_double , lp_double },
11871261 {0 }
@@ -2239,7 +2313,7 @@ these can be preceded by a decimal repeat count:\n\
22392313 x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
22402314 ?: _Bool (requires C99; if not available, char is used instead)\n\
22412315 h:short; H:unsigned short; i:int; I:unsigned int;\n\
2242- l:long; L:unsigned long; f:float; d:double.\n\
2316+ l:long; L:unsigned long; f:float; d:double; e:half-float .\n\
22432317Special cases (preceding decimal count indicates length):\n\
22442318 s:string (array of char); p: pascal string (with count byte).\n\
22452319Special cases (only available in native format):\n\
0 commit comments