@@ -5689,6 +5689,73 @@ def test_pickle_scalar_in_list(self):
56895689 assert math .isnan (float (loaded [2 ]))
56905690 assert loaded [3 ] == original [3 ]
56915691
5692+ @staticmethod
5693+ def _raw_bytes (q ):
5694+ """The exact on-the-wire payload used by __reduce__ (bit pattern)."""
5695+ return q .__reduce__ ()[1 ][0 ]
5696+
5697+ def test_pickle_scalar_extreme_values_roundtrip (self ):
5698+ """Subnormals and values near the maximum are exactly where a decimal
5699+ string round-trip would lose bits; the raw-bytes path must preserve
5700+ them exactly."""
5701+ import pickle
5702+ extremes = [
5703+ numpy_quaddtype .smallest_subnormal ,
5704+ numpy_quaddtype .smallest_normal ,
5705+ numpy_quaddtype .smallest_subnormal * QuadPrecision ("13.0" ),
5706+ numpy_quaddtype .max_value ,
5707+ - numpy_quaddtype .max_value ,
5708+ numpy_quaddtype .epsilon ,
5709+ ]
5710+ for original in extremes :
5711+ loaded = pickle .loads (pickle .dumps (original ))
5712+ assert isinstance (loaded , QuadPrecision )
5713+ assert self ._raw_bytes (loaded ) == self ._raw_bytes (original )
5714+ assert loaded == original
5715+
5716+ def test_pickle_scalar_raw_bit_fuzz (self ):
5717+ """Fuzz the entire 128-bit space (subnormals, inf, NaN payloads, values
5718+ near overflow) and assert every value survives a pickle round-trip
5719+ bit-for-bit. Uses the new from_raw_bytes reconstructor to synthesize
5720+ arbitrary bit patterns that decimal fuzzing cannot reach."""
5721+ import pickle
5722+ import random
5723+ from numpy_quaddtype ._quaddtype_main import from_raw_bytes
5724+
5725+ nbytes = len (self ._raw_bytes (QuadPrecision ("1.0" , backend = "sleef" )))
5726+ rng = random .Random (0xC0FFEE )
5727+ for _ in range (4000 ):
5728+ raw = bytes (rng .randrange (256 ) for _ in range (nbytes ))
5729+ original = from_raw_bytes (raw , "sleef" )
5730+ loaded = pickle .loads (pickle .dumps (original ))
5731+ # Compare bit patterns directly so NaNs (which are != themselves)
5732+ # are also checked.
5733+ assert self ._raw_bytes (loaded ) == self ._raw_bytes (original )
5734+
5735+ def test_from_raw_bytes_roundtrip_matches_reduce (self ):
5736+ """from_raw_bytes is the inverse of the __reduce__ payload for both
5737+ backends, including the little-endian canonicalization."""
5738+ from numpy_quaddtype ._quaddtype_main import from_raw_bytes
5739+ for backend in ("sleef" , "longdouble" ):
5740+ original = QuadPrecision ("3.14159265358979323846264338327950288" ,
5741+ backend = backend )
5742+ _ , (data , be ) = original .__reduce__ ()
5743+ assert be == backend
5744+ rebuilt = from_raw_bytes (data , backend )
5745+ assert self ._raw_bytes (rebuilt ) == self ._raw_bytes (original )
5746+ assert rebuilt == original
5747+
5748+ def test_from_raw_bytes_rejects_wrong_length (self ):
5749+ from numpy_quaddtype ._quaddtype_main import from_raw_bytes
5750+ with pytest .raises (ValueError ):
5751+ from_raw_bytes (b"\x00 " * 3 , "sleef" )
5752+
5753+ def test_from_raw_bytes_rejects_bad_backend (self ):
5754+ from numpy_quaddtype ._quaddtype_main import from_raw_bytes
5755+ good = QuadPrecision ("1.0" , backend = "sleef" ).__reduce__ ()[1 ][0 ]
5756+ with pytest .raises (ValueError ):
5757+ from_raw_bytes (good , "float128" )
5758+
56925759
56935760@pytest .mark .parametrize ("dtype" , [
56945761 "bool" ,
0 commit comments