mod util; #[cfg(feature = "format")] use core::num; use lexical_parse_float::{FromLexical, FromLexicalWithOptions, Options}; #[cfg(feature = "f16")] use lexical_util::bf16::bf16; use lexical_util::error::Error; #[cfg(feature = "f16")] use lexical_util::f16::f16; #[cfg(feature = "format")] use lexical_util::format; #[cfg(any(feature = "format", feature = "power-of-two"))] use lexical_util::format::NumberFormatBuilder; use lexical_util::format::STANDARD; use lexical_util::num::Float; use proptest::prelude::*; use crate::util::default_proptest_config; #[test] fn special_bytes_test() { const FORMAT: u128 = STANDARD; // Test serializing and deserializing special strings. assert!(f32::from_lexical(b"NaN").unwrap().is_nan()); assert!(f32::from_lexical(b"nan").unwrap().is_nan()); assert!(f32::from_lexical(b"NAN").unwrap().is_nan()); assert!(f32::from_lexical(b"inf").unwrap().is_infinite()); assert!(f32::from_lexical(b"INF").unwrap().is_infinite()); assert!(f32::from_lexical(b"Infinity").unwrap().is_infinite()); let options = Options::builder().nan_string(Some(b"nan")).inf_string(Some(b"Infinity")).build().unwrap(); // The error message depends on whether the radix feature is enabled. assert!(f32::from_lexical_with_options::(b"inf", &options).is_err()); assert!(f32::from_lexical_with_options::(b"Infinity", &options).unwrap().is_infinite()); } #[test] #[cfg(feature = "power-of-two")] fn invalid_format_test() { const FORMAT: u128 = NumberFormatBuilder::from_radix(40); let options = Options::new(); let res = f32::from_lexical_with_options::(b"inf", &options); assert!(res.is_err()); assert_eq!(res, Err(Error::InvalidMantissaRadix)); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn invalid_punctuation_test() { const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'h')) .base_prefix(num::NonZeroU8::new(b'h')) .integer_internal_digit_separator(true) .build(); let options = Options::new(); let res = f32::from_lexical_with_options::(b"inf", &options); assert!(res.is_err()); assert_eq!(res, Err(Error::InvalidPunctuation)); } #[test] fn f32_decimal_test() { // integer test assert_eq!(0.0, f32::from_lexical(b"0").unwrap()); assert_eq!(1.0, f32::from_lexical(b"1").unwrap()); assert_eq!(12.0, f32::from_lexical(b"12").unwrap()); assert_eq!(123.0, f32::from_lexical(b"123").unwrap()); assert_eq!(1234.0, f32::from_lexical(b"1234").unwrap()); assert_eq!(12345.0, f32::from_lexical(b"12345").unwrap()); assert_eq!(123456.0, f32::from_lexical(b"123456").unwrap()); assert_eq!(1234567.0, f32::from_lexical(b"1234567").unwrap()); assert_eq!(12345678.0, f32::from_lexical(b"12345678").unwrap()); // No fraction after decimal point test assert_eq!(1.0, f32::from_lexical(b"1.").unwrap()); assert_eq!(12.0, f32::from_lexical(b"12.").unwrap()); assert_eq!(1234567.0, f32::from_lexical(b"1234567.").unwrap()); // No integer before decimal point test assert_eq!(0.1, f32::from_lexical(b".1").unwrap()); assert_eq!(0.12, f32::from_lexical(b".12").unwrap()); assert_eq!(0.1234567, f32::from_lexical(b".1234567").unwrap()); // decimal test assert_eq!(123.1, f32::from_lexical(b"123.1").unwrap()); assert_eq!(123.12, f32::from_lexical(b"123.12").unwrap()); assert_eq!(123.123, f32::from_lexical(b"123.123").unwrap()); assert_eq!(123.1234, f32::from_lexical(b"123.1234").unwrap()); assert_eq!(123.12345, f32::from_lexical(b"123.12345").unwrap()); // rounding test assert_eq!(123456790.0, f32::from_lexical(b"123456789").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.1").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.12").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.123").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.1234").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.12345").unwrap()); // exponent test assert_eq!(123456789.12345, f32::from_lexical(b"1.2345678912345e8").unwrap()); assert_eq!(123450000.0, f32::from_lexical(b"1.2345e+8").unwrap()); assert_eq!(1.2345e+11, f32::from_lexical(b"1.2345e+11").unwrap()); assert_eq!(1.2345e+11, f32::from_lexical(b"123450000000").unwrap()); assert_eq!(1.2345e+38, f32::from_lexical(b"1.2345e+38").unwrap()); assert_eq!(1.2345e+38, f32::from_lexical(b"123450000000000000000000000000000000000").unwrap()); assert_eq!(1.2345e-8, f32::from_lexical(b"1.2345e-8").unwrap()); assert_eq!(1.2345e-8, f32::from_lexical(b"0.000000012345").unwrap()); assert_eq!(1.2345e-38, f32::from_lexical(b"1.2345e-38").unwrap()); assert_eq!( 1.2345e-38, f32::from_lexical(b"0.000000000000000000000000000000000000012345").unwrap() ); assert!(f32::from_lexical(b"NaN").unwrap().is_nan()); assert!(f32::from_lexical(b"nan").unwrap().is_nan()); assert!(f32::from_lexical(b"NAN").unwrap().is_nan()); assert!(f32::from_lexical(b"inf").unwrap().is_infinite()); assert!(f32::from_lexical(b"INF").unwrap().is_infinite()); assert!(f32::from_lexical(b"+inf").unwrap().is_infinite()); assert!(f32::from_lexical(b"-inf").unwrap().is_infinite()); // Check various expected failures. assert_eq!(Err(Error::Empty(0)), f32::from_lexical(b"")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"e")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"E")); assert_eq!(Err(Error::EmptyMantissa(1)), f32::from_lexical(b".e1")); assert_eq!(Err(Error::EmptyMantissa(1)), f32::from_lexical(b".e-1")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"e1")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"e-1")); assert_eq!(Err(Error::Empty(1)), f32::from_lexical(b"+")); assert_eq!(Err(Error::Empty(1)), f32::from_lexical(b"-")); // Bug fix for Issue #8 assert_eq!(Ok(5.002868148396374), f32::from_lexical(b"5.002868148396374")); // Other bug fixes assert_eq!(Ok(7.2625224e+37), f32::from_lexical(b"72625224000000000000000000000000000000")); assert_eq!(Ok(7.2625224e+37), f32::from_lexical(b"72625224000000000000000000000000000000.0")); assert_eq!(Ok(-7.2625224e+37), f32::from_lexical(b"-72625224000000000000000000000000000000")); assert_eq!(Ok(-7.2625224e+37), f32::from_lexical(b"-72625224000000000000000000000000000000.0")); } #[test] #[cfg(feature = "radix")] fn f32_radix_test() { const BASE36: u128 = NumberFormatBuilder::from_radix(36); let options = Options::builder().exponent(b'^').build().unwrap(); assert_eq!(1234.0, f32::from_lexical_with_options::(b"YA", &options).unwrap()); let options = options.rebuild().lossy(true).build().unwrap(); assert_eq!(1234.0, f32::from_lexical_with_options::(b"YA", &options).unwrap()); const BASE21: u128 = NumberFormatBuilder::from_radix(21); assert_eq!( 2879628700000000000000000.0, f32::from_lexical_with_options::(b"4.BHJ97^I", &options).unwrap() ); assert_eq!( 48205230000000000000000000000000000000.0, f32::from_lexical_with_options::(b"4.C4407^17", &options).unwrap() ); assert_eq!( 105861930000000000000000000000000000000.0, f32::from_lexical_with_options::(b"A.15A^17", &options).unwrap() ); assert_eq!( 63900540000000000000000000000000000000.0, f32::from_lexical_with_options::(b"6.1AK^17", &options).unwrap() ); assert_eq!( 48205210000000000000000000000000000000.0, f32::from_lexical_with_options::(b"4.C44^17", &options).unwrap() ); assert_eq!( 48205230000000000000000000000000000000.0, f32::from_lexical_with_options::(b"4C440700000000000000000000000.0", &options) .unwrap() ); } #[test] fn parse_f32_test() { let parse = move |x| f32::from_lexical_partial(x); assert_eq!(Ok((0.0, 1)), parse(b"0")); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); assert_eq!(Ok((1.2345e-38, 10)), parse(b"1.2345e-38")); // Check expected rounding, using borderline cases. // Round-down, halfway assert_eq!(Ok((16777216.0, 8)), parse(b"16777216")); assert_eq!(Ok((16777216.0, 8)), parse(b"16777217")); assert_eq!(Ok((16777218.0, 8)), parse(b"16777218")); assert_eq!(Ok((33554432.0, 8)), parse(b"33554432")); assert_eq!(Ok((33554432.0, 8)), parse(b"33554434")); assert_eq!(Ok((33554436.0, 8)), parse(b"33554436")); assert_eq!(Ok((17179869184.0, 11)), parse(b"17179869184")); assert_eq!(Ok((17179869184.0, 11)), parse(b"17179870208")); assert_eq!(Ok((17179871232.0, 11)), parse(b"17179871232")); // Round-up, halfway assert_eq!(Ok((16777218.0, 8)), parse(b"16777218")); assert_eq!(Ok((16777220.0, 8)), parse(b"16777219")); assert_eq!(Ok((16777220.0, 8)), parse(b"16777220")); assert_eq!(Ok((33554436.0, 8)), parse(b"33554436")); assert_eq!(Ok((33554440.0, 8)), parse(b"33554438")); assert_eq!(Ok((33554440.0, 8)), parse(b"33554440")); assert_eq!(Ok((17179871232.0, 11)), parse(b"17179871232")); assert_eq!(Ok((17179873280.0, 11)), parse(b"17179872256")); assert_eq!(Ok((17179873280.0, 11)), parse(b"17179873280")); // Round-up, above halfway assert_eq!(Ok((33554436.0, 8)), parse(b"33554435")); assert_eq!(Ok((17179871232.0, 11)), parse(b"17179870209")); // Check exactly halfway, round-up at halfway assert_eq!(Ok((1.0000001, 28)), parse(b"1.00000017881393432617187499")); assert_eq!(Ok((1.0000002, 26)), parse(b"1.000000178813934326171875")); assert_eq!(Ok((1.0000002, 28)), parse(b"1.00000017881393432617187501")); // Invalid or partially-parsed assert_eq!(Err(Error::EmptyMantissa(0)), parse(b"e10")); assert_eq!(Err(Error::EmptyMantissa(1)), parse(b".")); assert_eq!(Err(Error::EmptyMantissa(1)), parse(b".e10")); assert_eq!(Err(Error::EmptyExponent(2)), parse(b"0e")); assert_eq!(Ok((1.23, 4)), parse(b"1.23/")); // Errors identified via test-parse-random. assert_eq!(Ok((0.0, 21)), parse(b"1.565385248817619e-82")); assert_eq!(Ok((5.483634359675252e34, 20)), parse(b"5.483634359675252e34")); // Test a case from fast_float basictest. assert_eq!(Ok((1.1754941e-38, 1118)), parse(b"1.17549414062751785924617589866280818433124586473279624003138594271817467598606476997247227700427174568176269531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-38")); assert_eq!(Ok((f32::INFINITY, 6)), parse(b"1e1000")); // Errors identified via test-parse-golang. assert_eq!(Ok((0, 25)), parse(b"1.00000000001e-2147483638").map(|(x, y)| (x.to_bits(), y))); } #[test] fn parse_f64_test() { let parse = move |x| f64::from_lexical_partial(x); #[cfg(feature = "power-of-two")] let parse_binary = move |x| { const BINARY: u128 = NumberFormatBuilder::from_radix(2); let options = Options::builder().exponent(b'^').build().unwrap(); f64::from_lexical_partial_with_options::(x, &options) }; assert_eq!(Ok((0.0, 1)), parse(b"0")); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); assert_eq!(Ok((1e-323, 6)), parse(b"1e-323")); assert_eq!(Ok((1.2345e-308, 11)), parse(b"1.2345e-308")); // Check expected rounding, using borderline cases. // Round-down, halfway assert_eq!(Ok((9007199254740992.0, 16)), parse(b"9007199254740992")); assert_eq!(Ok((9007199254740992.0, 16)), parse(b"9007199254740993")); assert_eq!(Ok((9007199254740994.0, 16)), parse(b"9007199254740994")); assert_eq!(Ok((18014398509481984.0, 17)), parse(b"18014398509481984")); assert_eq!(Ok((18014398509481984.0, 17)), parse(b"18014398509481986")); assert_eq!(Ok((18014398509481988.0, 17)), parse(b"18014398509481988")); assert_eq!(Ok((9223372036854775808.0, 19)), parse(b"9223372036854775808")); assert_eq!(Ok((9223372036854775808.0, 19)), parse(b"9223372036854776832")); assert_eq!(Ok((9223372036854777856.0, 19)), parse(b"9223372036854777856")); assert_eq!( Ok((11417981541647679048466287755595961091061972992.0, 47)), parse(b"11417981541647679048466287755595961091061972992") ); assert_eq!( Ok((11417981541647679048466287755595961091061972992.0, 47)), parse(b"11417981541647680316116887983825362587765178368") ); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 47)), parse(b"11417981541647681583767488212054764084468383744") ); // Round-up, halfway assert_eq!(Ok((9007199254740994.0, 16)), parse(b"9007199254740994")); assert_eq!(Ok((9007199254740996.0, 16)), parse(b"9007199254740995")); assert_eq!(Ok((9007199254740996.0, 16)), parse(b"9007199254740996")); assert_eq!(Ok((18014398509481988.0, 17)), parse(b"18014398509481988")); assert_eq!(Ok((18014398509481992.0, 17)), parse(b"18014398509481990")); assert_eq!(Ok((18014398509481992.0, 17)), parse(b"18014398509481992")); assert_eq!(Ok((9223372036854777856.0, 19)), parse(b"9223372036854777856")); assert_eq!(Ok((9223372036854779904.0, 19)), parse(b"9223372036854778880")); assert_eq!(Ok((9223372036854779904.0, 19)), parse(b"9223372036854779904")); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 47)), parse(b"11417981541647681583767488212054764084468383744") ); assert_eq!( Ok((11417981541647684119068688668513567077874794496.0, 47)), parse(b"11417981541647682851418088440284165581171589120") ); assert_eq!( Ok((11417981541647684119068688668513567077874794496.0, 47)), parse(b"11417981541647684119068688668513567077874794496") ); // Round-up, above halfway assert_eq!(Ok((9223372036854777856.0, 19)), parse(b"9223372036854776833")); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 47)), parse(b"11417981541647680316116887983825362587765178369") ); // Rounding error // Adapted from failures in strtod. assert_eq!(Ok((2.2250738585072014e-308, 23)), parse(b"2.2250738585072014e-308")); assert_eq!(Ok((2.225073858507201e-308, 776)), parse(b"2.2250738585072011360574097967091319759348195463516456480234261097248222220210769455165295239081350879141491589130396211068700864386945946455276572074078206217433799881410632673292535522868813721490129811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306666559949382757725720157630626906633326475653000092458883164330377797918696120494973903778297049050510806099407302629371289589500035837999672072543043602840788957717961509455167482434710307026091446215722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844239002654981983854879482922068947216898310996983658468140228542433306603398508864458040010349339704275671864433837704860378616227717385456230658746790140867233276367187499e-308")); assert_eq!(Ok((2.2250738585072014e-308, 774)), parse(b"2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901298112245145188984905722230728525513315575501591439747639798341180199932396254828901710708185069063066665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462157228988025818254518032570701886087211312807951223342628836862232150377566662250398253433597456888442390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042756718644338377048603786162277173854562306587467901408672332763671875e-308")); assert_eq!(Ok((2.2250738585072014e-308, 776)), parse(b"2.2250738585072011360574097967091319759348195463516456480234261097248222220210769455165295239081350879141491589130396211068700864386945946455276572074078206217433799881410632673292535522868813721490129811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306666559949382757725720157630626906633326475653000092458883164330377797918696120494973903778297049050510806099407302629371289589500035837999672072543043602840788957717961509455167482434710307026091446215722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844239002654981983854879482922068947216898310996983658468140228542433306603398508864458040010349339704275671864433837704860378616227717385456230658746790140867233276367187501e-308")); assert_eq!(Ok((1.7976931348623157e+308, 380)), parse(b"179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999999999999999999999999999999999999999999999999999999999999")); assert_eq!(Ok((5e-324, 761)), parse(b"7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324")); assert_eq!(Ok((1e-323, 758)), parse(b"7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324")); assert_eq!(Ok((1e-323, 761)), parse(b"7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324")); assert_eq!(Ok((1e-320, 6)), parse(b"1e-320")); // Highest denormal float. assert_eq!(Ok((2.2250738585072009e-308, 23)), parse(b"2.2250738585072009e-308")); // Rounding error // Adapted from: // https://www.exploringbinary.com/glibc-strtod-incorrectly-converts-2-to-the-negative-1075/ #[cfg(feature = "power-of-two")] assert_eq!(Ok((5e-324, 14)), parse_binary(b"1^-10000110010")); #[cfg(feature = "power-of-two")] assert_eq!(Ok((0.0, 14)), parse_binary(b"1^-10000110011")); assert_eq!(Ok((0.0, 1077)), parse(b"0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125")); assert_eq!(Ok((5e-324, 1081)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281250001")); assert_eq!(Ok((5e-324, 1078)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251")); // Check with trailing zeros too, before the max number. assert_eq!(Ok((0.0, 1024)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210200000000")); assert_eq!(Ok((5e-324, 1024)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210300000000")); assert_eq!(Ok((5e-324, 1024)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210310000000")); assert_eq!(Ok((0.0, 705)), parse(b"2.47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210200000000e-324")); assert_eq!(Ok((5e-324, 705)), parse(b"2.47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210300000000e-324")); assert_eq!(Ok((5e-324, 705)), parse(b"2.47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210310000000e-324")); // Rounding error // Adapted from: // https://www.exploringbinary.com/how-glibc-strtod-works/ assert_eq!(Ok((2.2250738585072011e-308, 1076)), parse(b"0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375")); // Rounding error // Adapted from test-parse-random failures. assert_eq!(Ok((1.009e-28, 8)), parse(b"1009e-31")); assert_eq!(Ok((f64::INFINITY, 9)), parse(b"18294e304")); // Rounding error // Adapted from a @dangrabcad's issue #20. assert_eq!(Ok((7.689539722041643e164, 21)), parse(b"7.689539722041643e164")); assert_eq!(Ok((7.689539722041643e164, 165)), parse(b"768953972204164300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); assert_eq!(Ok((7.689539722041643e164, 167)), parse(b"768953972204164300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); // Check other cases similar to @dangrabcad's issue #20. assert_eq!(Ok((9223372036854777856.0, 21)), parse(b"9223372036854776833.0")); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 49)), parse(b"11417981541647680316116887983825362587765178369.0") ); assert_eq!(Ok((9007199254740996.0, 18)), parse(b"9007199254740995.0")); assert_eq!(Ok((18014398509481992.0, 19)), parse(b"18014398509481990.0")); assert_eq!(Ok((9223372036854779904.0, 21)), parse(b"9223372036854778880.0")); assert_eq!( Ok((11417981541647684119068688668513567077874794496.0, 49)), parse(b"11417981541647682851418088440284165581171589120.0") ); // Check other cases ostensibly identified via proptest. assert_eq!(Ok((71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 310)), parse(b"71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); assert_eq!(Ok((126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 311)), parse(b"126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); assert_eq!(Ok((38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 310)), parse(b"38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); // Round-trip for base2. #[cfg(feature = "power-of-two")] { assert_eq!( Ok((f64::from_bits(0x3bcd261840000000), 33)), parse_binary(b"1.1101001001100001100001^-1000011") ); } // Check other bugs in Golang. assert_eq!(Ok((1.0905441441816094e+30, 31)), parse(b"1090544144181609348835077142190")); // Errors identified via test-parse-random. assert_eq!(Ok((-7.014172639932773e-283, 23)), parse(b"-7.014172639932773e-283")); assert_eq!(Ok((1.565385248817619e-82, 21)), parse(b"1.565385248817619e-82")); // Errors identified in fast_float assert_eq!(Ok((1.0905441441816094e+30, 31)), parse(b"1090544144181609348835077142190")); assert_eq!(Ok((f64::INFINITY, 6)), parse(b"1e1000")); assert_eq!( Ok((-2.2400841322710136e+18, 57)), parse(b"-2240084132271013504.131248280843119943687942846658579428") ); // Errors identified via test-parse-golang. assert_eq!(Ok((0.0, 25)), parse(b"1.00000000001e-2147483638")); assert_eq!(Ok((0, 25)), parse(b"1.00000000001e-2147483638").map(|(x, y)| (x.to_bits(), y))); } #[test] fn f64_decimal_test() { // integer test assert_eq!(0.0, f64::from_lexical(b"0").unwrap()); assert_eq!(1.0, f64::from_lexical(b"1").unwrap()); assert_eq!(12.0, f64::from_lexical(b"12").unwrap()); assert_eq!(123.0, f64::from_lexical(b"123").unwrap()); assert_eq!(1234.0, f64::from_lexical(b"1234").unwrap()); assert_eq!(12345.0, f64::from_lexical(b"12345").unwrap()); assert_eq!(123456.0, f64::from_lexical(b"123456").unwrap()); assert_eq!(1234567.0, f64::from_lexical(b"1234567").unwrap()); assert_eq!(12345678.0, f64::from_lexical(b"12345678").unwrap()); // No fraction after decimal point test assert_eq!(1.0, f64::from_lexical(b"1.").unwrap()); assert_eq!(12.0, f64::from_lexical(b"12.").unwrap()); assert_eq!(1234567.0, f64::from_lexical(b"1234567.").unwrap()); // No integer before decimal point test assert_eq!(0.1, f64::from_lexical(b".1").unwrap()); assert_eq!(0.12, f64::from_lexical(b".12").unwrap()); assert_eq!(0.1234567, f64::from_lexical(b".1234567").unwrap()); // decimal test assert_eq!(123456789.0, f64::from_lexical(b"123456789").unwrap()); assert_eq!(123456789.1, f64::from_lexical(b"123456789.1").unwrap()); assert_eq!(123456789.12, f64::from_lexical(b"123456789.12").unwrap()); assert_eq!(123456789.123, f64::from_lexical(b"123456789.123").unwrap()); assert_eq!(123456789.1234, f64::from_lexical(b"123456789.1234").unwrap()); assert_eq!(123456789.12345, f64::from_lexical(b"123456789.12345").unwrap()); assert_eq!(123456789.123456, f64::from_lexical(b"123456789.123456").unwrap()); assert_eq!(123456789.1234567, f64::from_lexical(b"123456789.1234567").unwrap()); assert_eq!(123456789.12345678, f64::from_lexical(b"123456789.12345678").unwrap()); // rounding test assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.123456789").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.1234567890").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.123456789012").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.1234567890123").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.12345678901234").unwrap()); // exponent test assert_eq!(123456789.12345, f64::from_lexical(b"1.2345678912345e8").unwrap()); assert_eq!(123450000.0, f64::from_lexical(b"1.2345e+8").unwrap()); assert_eq!(1.2345e+11, f64::from_lexical(b"123450000000").unwrap()); assert_eq!(1.2345e+11, f64::from_lexical(b"1.2345e+11").unwrap()); assert_eq!(1.2345e+38, f64::from_lexical(b"1.2345e+38").unwrap()); assert_eq!(1.2345e+38, f64::from_lexical(b"123450000000000000000000000000000000000").unwrap()); assert_eq!(1.2345e+308, f64::from_lexical(b"1.2345e+308").unwrap()); assert_eq!(1.2345e+308, f64::from_lexical(b"123450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()); assert_eq!(0.000000012345, f64::from_lexical(b"1.2345e-8").unwrap()); assert_eq!(1.2345e-8, f64::from_lexical(b"0.000000012345").unwrap()); assert_eq!(1.2345e-38, f64::from_lexical(b"1.2345e-38").unwrap()); assert_eq!( 1.2345e-38, f64::from_lexical(b"0.000000000000000000000000000000000000012345").unwrap() ); // denormalized (try extremely low values) assert_eq!(1.2345e-308, f64::from_lexical(b"1.2345e-308").unwrap()); // due to issues in how the data is parsed, manually extracting // non-exponents of 1.(b"YA", &options).unwrap()); let options = options.rebuild().lossy(true).build().unwrap(); assert_eq!(1234.0, f64::from_lexical_with_options::(b"YA", &options).unwrap()); } #[test] fn parse_f64_large_zeros_test() { // Test numbers with a massive number of 0s in the integer component. let parse = move |x| f64::from_lexical_partial(x); assert_eq!(Ok((71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 308)), parse(b"71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); assert_eq!(Ok((126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 309)), parse(b"126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); assert_eq!(Ok((38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 308)), parse(b"38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); } #[test] #[cfg(feature = "power-of-two")] fn parse_binary_f64_test() { #[cfg(feature = "power-of-two")] let parse_binary = move |x| { const BINARY: u128 = NumberFormatBuilder::from_radix(2); let options = Options::builder().exponent(b'^').build().unwrap(); f64::from_lexical_partial_with_options::(x, &options) }; // Test a wide variety of denormal floats here. // Halfway, round-up. assert_eq!( Ok((2.2250738585072009e-308, 65)), parse_binary(b"1111111111111111111111111111111111111111111111111111^-10000110010") ); assert_eq!( Ok((2.2250738585072014e-308, 66)), parse_binary(b"10000000000000000000000000000000000000000000000000000^-10000110010") ); assert_eq!( Ok((2.2250738585072009e-308, 66)), parse_binary(b"11111111111111111111111111111111111111111111111111110^-10000110011") ); assert_eq!( Ok((2.2250738585072014e-308, 66)), parse_binary(b"11111111111111111111111111111111111111111111111111111^-10000110011") ); // Halfway, round-down. assert_eq!( Ok((2.2250738585072004e-308, 65)), parse_binary(b"1111111111111111111111111111111111111111111111111110^-10000110010") ); assert_eq!( Ok((2.2250738585072004e-308, 66)), parse_binary(b"11111111111111111111111111111111111111111111111111101^-10000110011") ); // Force the moderate path (round-up). assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111100000^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111101000^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111101111^-10000110111") ); assert_eq!( Ok((2.2250738585072014e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111110000^-10000110111") ); assert_eq!( Ok((2.2250738585072014e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111111111^-10000110111") ); assert_eq!( Ok((2.2250738585072014e-308, 70)), parse_binary(b"100000000000000000000000000000000000000000000000000000000^-10000110110") ); // Force the moderate path (round-down). assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111000000^-10000110111") ); assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111001000^-10000110111") ); assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111001111^-10000110111") ); assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111010000^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111010001^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111011111^-10000110111") ); // Let's test comically long digits (round-up). assert_eq!(Ok((2.225073858507201e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000^-10010011011")); assert_eq!(Ok((2.225073858507201e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111^-10010011011")); assert_eq!(Ok((2.2250738585072014e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000^-10010011011")); assert_eq!(Ok((2.2250738585072014e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000^-10010011011")); } #[test] fn parse_f32_lossy_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); let parse = move |x| f32::from_lexical_partial_with_options::(x, &options); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); } #[test] fn parse_f64_lossy_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); let parse = move |x| f64::from_lexical_partial_with_options::(x, &options); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); } #[test] fn f32_lossy_decimal_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); assert_eq!( Err(Error::EmptyMantissa(1)), f32::from_lexical_with_options::(b".", &options) ); assert_eq!(Err(Error::Empty(0)), f32::from_lexical_with_options::(b"", &options)); assert_eq!(Ok(0.0), f32::from_lexical_with_options::(b"0.0", &options)); assert_eq!( Err((Error::InvalidDigit(1)).into()), f32::from_lexical_with_options::(b"1a", &options) ); // Bug fix for Issue #8 assert_eq!( Ok(5.002868148396374), f32::from_lexical_with_options::(b"5.002868148396374", &options) ); } #[test] fn f64_lossy_decimal_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); assert_eq!( Err(Error::EmptyMantissa(1)), f64::from_lexical_with_options::(b".", &options) ); assert_eq!(Err(Error::Empty(0)), f64::from_lexical_with_options::(b"", &options)); assert_eq!(Ok(0.0), f64::from_lexical_with_options::(b"0.0", &options)); assert_eq!( Err((Error::InvalidDigit(1)).into()), f64::from_lexical_with_options::(b"1a", &options) ); // Bug fix for Issue #8 assert_eq!( Ok(5.002868148396374), f64::from_lexical_with_options::(b"5.002868148396374", &options) ); } #[cfg(feature = "format")] const fn rebuild(format: u128) -> NumberFormatBuilder { NumberFormatBuilder::rebuild(format) } #[test] #[cfg(feature = "format")] fn f64_special_test() { // Comments match (no_special, case_sensitive, has_sep) const F1: u128 = STANDARD; const F2: u128 = format::IGNORE; const F3: u128 = rebuild(F1).no_special(true).build(); const F4: u128 = rebuild(F1).case_sensitive_special(true).build(); const F5: u128 = rebuild(F2).case_sensitive_special(true).build(); let opts = Options::new(); // Easy NaN assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); // Case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"nan", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"nan", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"nan", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"nan", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"nan", &opts).is_err()); // Digit-separator NaN. assert!(f64::from_lexical_with_options::(b"N_aN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).unwrap().is_nan()); // Digit-separator + case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); // Leading digit separator + case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); // Trailing digit separator + case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); } #[test] #[cfg(feature = "format")] fn case_sensitive_exponent_test() { const FORMAT: u128 = NumberFormatBuilder::new().case_sensitive_exponent(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0E+300", &options).is_err()); assert!(f64::from_lexical(b"+3.0e+300").is_ok()); assert!(f64::from_lexical(b"+3.0E+300").is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_integer_digits_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_integer_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b".0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_required_fraction_digits_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_fraction_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_digits_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3", &options).is_ok()); assert!(f64::from_lexical_with_options::(b".0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_no_positive_mantissa_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_positive_mantissa_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"-3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_mantissa_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_mantissa_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"-3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_no_exponent_notation_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_exponent_notation(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0e-7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3e", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3e-", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_optional_exponent_test() { const FORMAT: u128 = format::PERMISSIVE; let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e-7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e-", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_exponent_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_exponent_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e-7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0e-", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_no_positive_exponent_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_positive_exponent_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0e+7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3.0e-7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_exponent_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_exponent_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3.0e+7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0e-7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_no_exponent_without_fraction_test() { const F1: u128 = rebuild(format::PERMISSIVE).no_exponent_without_fraction(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3e7", &options).is_err()); const F2: u128 = rebuild(F1).required_fraction_digits(true).build(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_no_leading_zeros_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_float_leading_zeros(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"1.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"0.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"01.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"10.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"010.0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_required_exponent_notation_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .required_exponent_digits(false) .required_exponent_notation(true) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3.0e", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"0.e", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_integer_internal_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_internal_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3_1.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_fraction_internal_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_internal_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0_1e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_exponent_internal_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_internal_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7_1", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_integer_leading_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_leading_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3_1.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_fraction_leading_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_leading_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0_1e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_exponent_leading_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_leading_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7_1", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_integer_trailing_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_trailing_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3_1.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_fraction_trailing_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_trailing_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0_1e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_exponent_trailing_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_trailing_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7_1", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_integer_consecutive_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_internal_digit_separator(true) .integer_consecutive_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3__1.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_fraction_consecutive_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_internal_digit_separator(true) .fraction_consecutive_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0__1e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_exponent_consecutive_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_internal_digit_separator(true) .exponent_consecutive_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7__1", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_json_exponent_without_dot() { // Tests courtesy of @ijl: // https://github.com/Alexhuszagh/rust-lexical/issues/24#issuecomment-578153783 const FORMAT: u128 = format::JSON; let options = Options::new(); // JSONTestSuite/test_parsing/y_number_0e1.json assert!(f64::from_lexical_with_options::(b"0e1", &options).is_ok()); // JSONTestSuite/test_parsing/y_number_int_with_exp.json assert!(f64::from_lexical_with_options::(b"20e1", &options).is_ok()); // JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.json assert!(f64::from_lexical_with_options::(b"1E+2", &options).is_ok()); // JSONTestSuite/test_transform/number_1e-999.json assert!(f64::from_lexical_with_options::(b"1E-999", &options).is_ok()); // nativejson-benchmark/data/jsonchecker/pass01.json assert!(f64::from_lexical_with_options::(b"23456789012E66", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_json_exponent_requires_digit() { // Tests courtesy of @ijl: // https://github.com/Alexhuszagh/rust-lexical/issues/24#issuecomment-578153783 const FORMAT: u128 = format::JSON; let options = Options::new(); assert!(f64::from_lexical_with_options::(b"1e", &options).is_err()); // JSONTestSuite/test_parsing/n_number_9.e+.json assert!(f64::from_lexical_with_options::(b"9.e+", &options).is_err()); // JSONTestSuite/test_parsing/n_number_2.e-3.json assert!(f64::from_lexical_with_options::(b"2.e-3", &options).is_err()); // JSONTestSuite/test_parsing/n_number_real_without_fractional_part.json assert!(f64::from_lexical_with_options::(b"1.", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_json_no_leading_zero() { const FORMAT: u128 = format::JSON; let options = Options::new(); assert!(f64::from_lexical_with_options::(b"12.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"-12.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"012.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"-012.0", &options).is_err()); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn base_prefix_test() { const FORMAT: u128 = NumberFormatBuilder::new().base_prefix(num::NonZeroU8::new(b'x')).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+0x", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+0x ", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+0x3", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300 ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+0x", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+0x ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+0x3", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+0x3.0e+300 ", &options).is_ok()); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn base_suffix_test() { const FORMAT: u128 = NumberFormatBuilder::new().base_suffix(num::NonZeroU8::new(b'h')).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"h", &options).is_err()); assert!(f64::from_lexical_with_options::(b"-h ", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+h ", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300h ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+h", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+h ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+3h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0e+300h ", &options).is_ok()); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn base_prefix_and_suffix_test() { const FORMAT: u128 = NumberFormatBuilder::new() .base_prefix(num::NonZeroU8::new(b'x')) .base_suffix(num::NonZeroU8::new(b'h')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0xh", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300h ", &options).is_err()); } #[test] #[cfg(feature = "format")] fn issue66_test() { const RUST: u128 = format::RUST_LITERAL; const JSON: u128 = format::JSON; const CXX: u128 = format::CXX17_LITERAL; let options = Options::new(); assert_eq!(f64::from_lexical_with_options::(b"42.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"42.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"4_2.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"42.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"4'2.0", &options), Ok(42.0)); } #[test] #[cfg(feature = "power-of-two")] fn issue68_test() { const FORMAT: u128 = NumberFormatBuilder::from_radix(16); let options = Options::builder().exponent(b'^').build().unwrap(); // Roughly 2^1375, 15 1s. let hex = b"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; assert_eq!(f32::INFINITY, f32::from_lexical_with_options::(hex, &options).unwrap()); assert_eq!(f64::INFINITY, f64::from_lexical_with_options::(hex, &options).unwrap()); } fn float_equal(x: F, y: F) -> bool { if x.is_nan() { y.is_nan() } else { y == x } } default_quickcheck! { fn f32_roundtrip_quickcheck(x: f32) -> bool { let string = x.to_string(); let result = f32::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } fn f32_short_decimal_quickcheck(x: f32) -> bool { let string = format!("{:.4}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } fn f32_long_decimal_quickcheck(x: f32) -> bool { let string = format!("{:.100}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } fn f32_short_exponent_quickcheck(x: f32) -> bool { let string = format!("{:.4e}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } fn f32_long_exponent_quickcheck(x: f32) -> bool { let string = format!("{:.100e}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } fn f64_roundtrip_quickcheck(x: f64) -> bool { let string = x.to_string(); let result = f64::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } fn f64_short_decimal_quickcheck(x: f64) -> bool { let string = format!("{:.4}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } fn f64_long_decimal_quickcheck(x: f64) -> bool { let string = format!("{:.100}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } fn f64_short_exponent_quickcheck(x: f64) -> bool { let string = format!("{:.4e}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } fn f64_long_exponent_quickcheck(x: f64) -> bool { let string = format!("{:.100e}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg(feature = "f16")] fn f16_roundtrip_quickcheck(bits: u16) -> bool { let x = f16::from_bits(bits); let string = x.as_f32().to_string(); let result = f16::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } #[cfg(feature = "f16")] fn bf16_roundtrip_quickcheck(bits: u16) -> bool { let x = bf16::from_bits(bits); let string = x.as_f32().to_string(); let result = bf16::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } } proptest! { #![proptest_config(default_proptest_config())] #[test] fn f32_invalid_proptest(i in r"[+-]?[0-9]{2}[^\deE]?\.[^\deE]?[0-9]{2}[^\deE]?e[+-]?[0-9]+[^\deE]") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_invalid_digit()); } #[test] fn f32_double_sign_proptest(i in r"[+-]{2}[0-9]{2}\.[0-9]{2}e[+-]?[0-9]+") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_invalid_digit() || res.err().unwrap().is_empty_mantissa() ); } #[test] fn f32_sign_or_dot_only_proptest(i in r"[+-]?\.?") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_empty() || res.err().unwrap().is_empty_mantissa() ); } #[test] fn f32_double_exponent_sign_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]{2}[0-9]+") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] fn f32_missing_exponent_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]?") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] fn f32_roundtrip_display_proptest(i in f32::MIN..f32::MAX) { let input: String = format!("{}", i); prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap()); } #[test] fn f32_roundtrip_debug_proptest(i in f32::MIN..f32::MAX) { let input: String = format!("{:?}", i); prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap()); } #[test] fn f32_roundtrip_scientific_proptest(i in f32::MIN..f32::MAX) { let input: String = format!("{:e}", i); prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap()); } #[test] fn f64_invalid_proptest(i in r"[+-]?[0-9]{2}[^\deE]?\.[^\deE]?[0-9]{2}[^\deE]?e[+-]?[0-9]+[^\deE]") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_invalid_digit()); } #[test] fn f64_double_sign_proptest(i in r"[+-]{2}[0-9]{2}\.[0-9]{2}e[+-]?[0-9]+") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_invalid_digit() || res.err().unwrap().is_empty_mantissa() ); } #[test] fn f64_sign_or_dot_only_proptest(i in r"[+-]?\.?") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_empty() || res.err().unwrap().is_empty_mantissa() ); } #[test] fn f64_double_exponent_sign_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]{2}[0-9]+") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] fn f64_missing_exponent_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]?") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] fn f64_roundtrip_display_proptest(i in f64::MIN..f64::MAX) { let input: String = format!("{}", i); prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap()); } #[test] fn f64_roundtrip_debug_proptest(i in f64::MIN..f64::MAX) { let input: String = format!("{:?}", i); prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap()); } #[test] fn f64_roundtrip_scientific_proptest(i in f64::MIN..f64::MAX) { let input: String = format!("{:e}", i); prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap()); } }