@@ -192,9 +192,22 @@ public void __init__(CodeContext/*!*/ context, object fmt) {
192192 break ;
193193 case FormatType . Float :
194194 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
195- WriteFloat ( res , _isLittleEndian , ( float ) GetDoubleValue ( context , curObj ++ , values ) ) ;
195+ var d = GetDoubleValue ( context , curObj ++ , values ) ;
196+ var val = ( float ) d ;
197+ if ( float . IsInfinity ( val ) && ! double . IsInfinity ( d ) ) throw PythonOps . OverflowError ( "float too large to pack with f format" ) ;
198+ WriteFloat ( res , _isLittleEndian , val ) ;
196199 }
197200 break ;
201+ #if NET6_0_OR_GREATER
202+ case FormatType . Half:
203+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
204+ var d = GetDoubleValue ( context , curObj ++ , values ) ;
205+ var val = ( Half ) d ;
206+ if ( Half . IsInfinity ( val ) && ! double . IsInfinity ( d ) ) throw PythonOps . OverflowError ( "float too large to pack with e format" ) ;
207+ WriteHalf ( res , _isLittleEndian , val ) ;
208+ }
209+ break ;
210+ #endif
198211 case FormatType . CString :
199212 WriteString ( res , curFormat . Count , GetStringValue ( context , curObj ++ , values ) ) ;
200213 break ;
@@ -273,7 +286,7 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] IBufferProtocol/*!*/ b
273286 break ;
274287 case FormatType . SignedChar :
275288 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
276- res [ res_idx ++ ] = ( int ) ( sbyte ) CreateCharValue ( context , ref curIndex , data ) ;
289+ res [ res_idx ++ ] = ( int ) unchecked ( ( sbyte ) CreateCharValue ( context , ref curIndex , data ) ) ;
277290 }
278291 break ;
279292 case FormatType . UnsignedChar :
@@ -336,7 +349,7 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] IBufferProtocol/*!*/ b
336349 break ;
337350 case FormatType . SizeT :
338351 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
339- res [ res_idx ++ ] = CreateUIntValue ( context , ref curIndex , _isLittleEndian , data ) ;
352+ res [ res_idx ++ ] = BigIntegerOps . __int__ ( CreateUIntValue ( context , ref curIndex , _isLittleEndian , data ) ) ;
340353 }
341354 break ;
342355 case FormatType . LongLong :
@@ -349,9 +362,16 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] IBufferProtocol/*!*/ b
349362 res [ res_idx ++ ] = BigIntegerOps . __int__ ( CreateULongValue ( context , ref curIndex , _isLittleEndian , data ) ) ;
350363 }
351364 break ;
365+ #if NET6_0_OR_GREATER
366+ case FormatType . Half:
367+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
368+ res [ res_idx ++ ] = ( double ) CreateHalfValue ( context , ref curIndex , _isLittleEndian , data ) ;
369+ }
370+ break ;
371+ #endif
352372 case FormatType . Float :
353373 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
354- res [ res_idx ++ ] = CreateFloatValue ( context , ref curIndex , _isLittleEndian , data ) ;
374+ res [ res_idx ++ ] = ( double ) CreateFloatValue ( context , ref curIndex , _isLittleEndian , data ) ;
355375 }
356376 break ;
357377 case FormatType . Double :
@@ -472,6 +492,12 @@ private static Struct CompileAndCache(CodeContext/*!*/ context, string/*!*/ fmt)
472492 res . Add ( new Format ( FormatType . UnsignedLongLong , count ) ) ;
473493 count = 1 ;
474494 break ;
495+ #if NET6_0_OR_GREATER
496+ case 'e' : // half
497+ res . Add ( new Format ( FormatType . Half , count ) ) ;
498+ count = 1 ;
499+ break ;
500+ #endif
475501 case 'f' : // float
476502 res . Add ( new Format ( FormatType . Float , count ) ) ;
477503 count = 1 ;
@@ -697,6 +723,9 @@ private enum FormatType {
697723
698724 Short ,
699725 UnsignedShort ,
726+ #if NET6_0_OR_GREATER
727+ Half ,
728+ #endif
700729
701730 Int,
702731 UnsignedInt ,
@@ -730,6 +759,9 @@ private static int GetNativeSize(FormatType c) {
730759 return 1 ;
731760 case FormatType . Short :
732761 case FormatType . UnsignedShort :
762+ #if NET6_0_OR_GREATER
763+ case FormatType . Half:
764+ #endif
733765 return 2 ;
734766 case FormatType . Int :
735767 case FormatType . UnsignedInt :
@@ -911,6 +943,18 @@ private static void WriteSignedNetPointer(this MemoryStream res, bool fLittleEnd
911943 res . WritePointer ( fLittleEndian , unchecked ( ( ulong ) val . ToInt64 ( ) ) ) ;
912944 }
913945
946+ #if NET6_0_OR_GREATER
947+ private static void WriteHalf ( this MemoryStream res , bool fLittleEndian , Half val ) {
948+ byte [ ] bytes = BitConverter . GetBytes ( val ) ;
949+ if ( BitConverter . IsLittleEndian == fLittleEndian ) {
950+ res . Write ( bytes , 0 , bytes . Length ) ;
951+ } else {
952+ res . WriteByte ( bytes [ 1 ] ) ;
953+ res . WriteByte ( bytes [ 0 ] ) ;
954+ }
955+ }
956+ #endif
957+
914958 private static void WriteFloat ( this MemoryStream res , bool fLittleEndian , float val ) {
915959 byte [ ] bytes = BitConverter . GetBytes ( val ) ;
916960 if ( BitConverter . IsLittleEndian == fLittleEndian ) {
@@ -1134,7 +1178,7 @@ internal static ulong GetULongLongValue(CodeContext/*!*/ context, int index, obj
11341178 internal static double GetDoubleValue ( CodeContext /*!*/ context , int index , object [ ] args ) {
11351179 object val = GetValue ( context , index , args ) ;
11361180 if ( Converter . TryConvertToDouble ( val , out double res ) ) return res ;
1137- throw Error ( context , "expected double value " ) ;
1181+ throw Error ( context , "required argument is not a float " ) ;
11381182 }
11391183
11401184 internal static IList < byte > GetStringValue ( CodeContext /*!*/ context , int index , object [ ] args ) {
@@ -1194,6 +1238,28 @@ internal static ushort CreateUShortValue(CodeContext/*!*/ context, ref int index
11941238 }
11951239 }
11961240
1241+ #if NET6_0_OR_GREATER
1242+ internal static Half CreateHalfValue ( CodeContext /*!*/ context , ref int index , bool fLittleEndian , IList < byte > data ) {
1243+ byte [ ] bytes = new byte [ 2 ] ;
1244+ if ( fLittleEndian == BitConverter . IsLittleEndian ) {
1245+ bytes [ 0 ] = data [ index ++ ] ;
1246+ bytes [ 1 ] = data [ index ++ ] ;
1247+ } else {
1248+ bytes [ 1 ] = data [ index ++ ] ;
1249+ bytes [ 0 ] = data [ index ++ ] ;
1250+ }
1251+ Half res = BitConverter . ToHalf ( bytes , 0 ) ;
1252+
1253+ if ( context . LanguageContext . FloatFormat == FloatFormat . Unknown ) {
1254+ if ( Half . IsNaN ( res ) || Half . IsInfinity ( res ) ) {
1255+ throw PythonOps . ValueError ( "can't unpack IEEE 754 special value on non-IEEE platform" ) ;
1256+ }
1257+ }
1258+
1259+ return res ;
1260+ }
1261+ #endif
1262+
11971263 internal static float CreateFloatValue ( CodeContext /*!*/ context , ref int index , bool fLittleEndian , IList < byte > data ) {
11981264 byte [ ] bytes = new byte [ 4 ] ;
11991265 if ( fLittleEndian == BitConverter . IsLittleEndian ) {
0 commit comments