@@ -308,6 +308,134 @@ def test_string_roundtrip():
308308 )
309309
310310
311+ class TestBytesSupport :
312+ """Test suite for QuadPrecision bytes input support."""
313+
314+ @pytest .mark .parametrize ("original" , [
315+ QuadPrecision ("0.417022004702574000667425480060047" ), # Random value
316+ QuadPrecision ("1.23456789012345678901234567890123456789" ), # Many digits
317+ pytest .param (numpy_quaddtype .pi , id = "pi" ), # Mathematical constant
318+ pytest .param (numpy_quaddtype .e , id = "e" ),
319+ QuadPrecision ("1e-100" ), # Very small
320+ QuadPrecision ("1e100" ), # Very large
321+ QuadPrecision ("-3.14159265358979323846264338327950288419" ), # Negative pi
322+ QuadPrecision ("0.0" ), # Zero
323+ QuadPrecision ("-0.0" ), # Negative zero
324+ QuadPrecision ("1.0" ), # One
325+ QuadPrecision ("-1.0" ), # Negative one
326+ ])
327+ def test_bytes_roundtrip (self , original ):
328+ """Test that bytes representations of quad precision values roundtrip correctly."""
329+ string_repr = str (original )
330+ bytes_repr = string_repr .encode ("ascii" )
331+ reconstructed = QuadPrecision (bytes_repr )
332+
333+ # Values should be exactly equal (bit-for-bit identical)
334+ assert reconstructed == original , (
335+ f"Bytes round-trip failed for { repr (original )} :\n "
336+ f" Original: { repr (original )} \n "
337+ f" Bytes: { bytes_repr } \n "
338+ f" Reconstructed: { repr (reconstructed )} "
339+ )
340+
341+ @pytest .mark .parametrize ("bytes_val,expected_str" , [
342+ # Simple numeric values
343+ (b"1.0" , "1.0" ),
344+ (b"-1.0" , "-1.0" ),
345+ (b"0.0" , "0.0" ),
346+ (b"3.14159" , "3.14159" ),
347+ # Scientific notation
348+ (b"1e10" , "1e10" ),
349+ (b"1e-10" , "1e-10" ),
350+ (b"2.5e100" , "2.5e100" ),
351+ (b"-3.7e-50" , "-3.7e-50" ),
352+ ])
353+ def test_bytes_creation_basic (self , bytes_val , expected_str ):
354+ """Test basic creation of QuadPrecision from bytes objects."""
355+ assert QuadPrecision (bytes_val ) == QuadPrecision (expected_str )
356+
357+ @pytest .mark .parametrize ("bytes_val,check_func" , [
358+ # Very large and very small numbers
359+ (b"1e308" , lambda x : x == QuadPrecision ("1e308" )),
360+ (b"1e-308" , lambda x : x == QuadPrecision ("1e-308" )),
361+ # Special values
362+ (b"inf" , lambda x : np .isinf (x )),
363+ (b"-inf" , lambda x : np .isinf (x ) and x < 0 ),
364+ (b"nan" , lambda x : np .isnan (x )),
365+ ])
366+ def test_bytes_creation_edge_cases (self , bytes_val , check_func ):
367+ """Test edge cases for QuadPrecision creation from bytes."""
368+ val = QuadPrecision (bytes_val )
369+ assert check_func (val )
370+
371+ @pytest .mark .parametrize ("invalid_bytes" , [
372+ b"" , # Empty bytes
373+ b"not_a_number" , # Invalid format
374+ b"1.23abc" , # Trailing garbage
375+ b"abc1.23" , # Leading garbage
376+ ])
377+ def test_bytes_invalid_input (self , invalid_bytes ):
378+ """Test that invalid bytes input raises appropriate errors."""
379+ with pytest .raises (ValueError , match = "Unable to parse bytes to QuadPrecision" ):
380+ QuadPrecision (invalid_bytes )
381+
382+ @pytest .mark .parametrize ("backend" , ["sleef" , "longdouble" ])
383+ @pytest .mark .parametrize ("bytes_val" , [
384+ b"1.0" ,
385+ b"-1.0" ,
386+ b"3.141592653589793238462643383279502884197" ,
387+ b"1e100" ,
388+ b"1e-100" ,
389+ b"0.0" ,
390+ ])
391+ def test_bytes_backend_consistency (self , backend , bytes_val ):
392+ """Test that bytes parsing works consistently across backends."""
393+ quad_val = QuadPrecision (bytes_val , backend = backend )
394+ str_val = QuadPrecision (bytes_val .decode ("ascii" ), backend = backend )
395+
396+ # Bytes and string should produce identical results
397+ assert quad_val == str_val , (
398+ f"Backend { backend } : bytes and string parsing differ for { bytes_val } \n "
399+ f" From bytes: { repr (quad_val )} \n "
400+ f" From string: { repr (str_val )} "
401+ )
402+
403+ @pytest .mark .parametrize ("bytes_val,expected_str" , [
404+ # Leading whitespace is OK (consumed by parser)
405+ (b" 1.0" , "1.0" ),
406+ (b" 3.14" , "3.14" ),
407+ ])
408+ def test_bytes_whitespace_valid (self , bytes_val , expected_str ):
409+ """Test handling of valid whitespace in bytes input."""
410+ assert QuadPrecision (bytes_val ) == QuadPrecision (expected_str )
411+
412+ @pytest .mark .parametrize ("invalid_bytes" , [
413+ b"1.0 " , # Trailing whitespace
414+ b"1.0 " , # Multiple trailing spaces
415+ b"1 .0" , # Internal whitespace
416+ b"1. 0" , # Internal whitespace
417+ ])
418+ def test_bytes_whitespace_invalid (self , invalid_bytes ):
419+ """Test that invalid whitespace in bytes input raises errors."""
420+ with pytest .raises (ValueError , match = "Unable to parse bytes to QuadPrecision" ):
421+ QuadPrecision (invalid_bytes )
422+
423+ @pytest .mark .parametrize ("test_str" , [
424+ "1.0" ,
425+ "-3.14159265358979323846264338327950288419" ,
426+ "1e100" ,
427+ "2.71828182845904523536028747135266249775" ,
428+ ])
429+ def test_bytes_encoding_compatibility (self , test_str ):
430+ """Test that bytes created from different encodings work correctly."""
431+ from_string = QuadPrecision (test_str )
432+ from_bytes = QuadPrecision (test_str .encode ("ascii" ))
433+ from_bytes_utf8 = QuadPrecision (test_str .encode ("utf-8" ))
434+
435+ assert from_string == from_bytes
436+ assert from_string == from_bytes_utf8
437+
438+
311439def test_string_subclass_parsing ():
312440 """Test that QuadPrecision handles string subclasses correctly.
313441
0 commit comments