mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
These were mostly bugs with code of the following form: ``` if uint64Value < (... literal expression ...) ``` Swift's comparison operators allow their left- and right-hand sides to be of different widths. This in turn means that the literal expression above typically gets typechecked by default as a plain `Int` or `UInt` expression. In a number of cases, this led to truncation on platforms where `Int` is not 64 bits. In particular, this seems to fix tests on wasm32.
373 lines
22 KiB
Swift
373 lines
22 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift -g %s -o %t/a.out -enable-experimental-feature Extern
|
|
// RUN: %target-codesign %t/a.out
|
|
// RUN: %target-run %t/a.out
|
|
|
|
// REQUIRES: executable_test
|
|
|
|
// Needed to declare the ABI entry point
|
|
// REQUIRES: swift_feature_Extern
|
|
|
|
import StdlibUnittest
|
|
|
|
let tests = TestSuite("FloatingPointParsing")
|
|
|
|
fileprivate func expectRoundTrip(
|
|
_ value: Float64,
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
let text = value.debugDescription
|
|
let roundTrip = Float64(Substring(text))
|
|
expectNotNil(roundTrip, text, stackTrace: stackTrace, showFrame: showFrame, file: file, line: line)
|
|
if let roundTrip {
|
|
if value.isNaN {
|
|
// We cannot in general guarantee perfect round-tripping for NaN values,
|
|
// but we can verify that printing/parsing a NaN does result in another
|
|
// NaN.
|
|
expectTrue(roundTrip.isNaN, text, stackTrace: stackTrace, showFrame: showFrame, file: file, line: line)
|
|
} else {
|
|
expectEqual(roundTrip.bitPattern, value.bitPattern, text, stackTrace: stackTrace, showFrame: showFrame, file: file, line: line)
|
|
}
|
|
}
|
|
}
|
|
|
|
fileprivate func expectParse(
|
|
_ input: String,
|
|
_ expected: Float64,
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
let parsed = Float64(Substring(input))
|
|
let msg = "\(input) did not parse to \(expected)"
|
|
expectNotNil(parsed, msg, stackTrace: stackTrace, showFrame: showFrame, file: file, line: line)
|
|
if let parsed {
|
|
expectEqual(parsed.bitPattern, expected.bitPattern, msg, stackTrace: stackTrace, showFrame: showFrame, file: file, line: line)
|
|
}
|
|
}
|
|
|
|
func expectParseFails(
|
|
_ input: String,
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
let parsed = Float64(Substring(input))
|
|
expectNil(parsed, stackTrace: stackTrace, showFrame: showFrame, file: file, line: line)
|
|
}
|
|
|
|
tests.test("Invalids") {
|
|
expectParseFails("")
|
|
expectParseFails(".")
|
|
expectParseFails("e0")
|
|
expectParseFails(".e0")
|
|
expectParseFails("1e+")
|
|
expectParseFails("-")
|
|
expectParseFails("+")
|
|
expectParseFails("&")
|
|
expectParseFails("+x")
|
|
expectParseFails("x")
|
|
}
|
|
|
|
tests.test("Infinities") {
|
|
expectParse("inf", Float64.infinity)
|
|
expectParse("+inf", Float64.infinity)
|
|
expectParse("-inf", -Float64.infinity)
|
|
expectParse("INF", Float64.infinity)
|
|
expectParse("InF", Float64.infinity)
|
|
expectParse("iNf", Float64.infinity)
|
|
expectParse("infinity", Float64.infinity)
|
|
expectParse("INFINITY", Float64.infinity)
|
|
expectParse("+infinity", Float64.infinity)
|
|
expectParse("-infinity", -Float64.infinity)
|
|
|
|
expectParseFails("i")
|
|
expectParseFails("in")
|
|
expectParseFails(" inf")
|
|
expectParseFails("- inf")
|
|
expectParseFails("--inf")
|
|
expectParseFails("-+inf")
|
|
expectParseFails("++inf")
|
|
expectParseFails("inf ")
|
|
expectParseFails("inx")
|
|
expectParseFails("-inx")
|
|
expectParseFails("infi")
|
|
expectParseFails("infin")
|
|
expectParseFails("infini")
|
|
expectParseFails("infinit")
|
|
expectParseFails("infinite")
|
|
expectParseFails("infinityandbeyond")
|
|
|
|
expectRoundTrip(Float64.infinity)
|
|
expectRoundTrip(-Float64.infinity)
|
|
}
|
|
|
|
tests.test("NaNs") {
|
|
// Note: Previous Swift runtime used libc strtof and then
|
|
// truncated to Float64, which is why some of these are
|
|
// wrong when testing previous runtimes.
|
|
expectRoundTrip(Float64.nan)
|
|
expectRoundTrip(-Float64.nan)
|
|
expectRoundTrip(Float64(nan:73, signaling:false))
|
|
expectRoundTrip(Float64(nan:73, signaling:true))
|
|
expectParse("nan", Float64.nan)
|
|
expectParse("NAN", Float64.nan)
|
|
expectParse("NaN", Float64.nan)
|
|
expectParse("-nan", -Float64.nan)
|
|
expectParse("nan()", Float64.nan)
|
|
expectParse("nan(0)", Float64.nan)
|
|
expectParse("nan(000000000000000000000000000000000000000)", Float64.nan)
|
|
expectParse("nan(0x00000000000000000000000000000000000000)", Float64.nan)
|
|
expectParse("nan(10)", Float64(nan:10, signaling:false))
|
|
expectParse("nan(1234567890)", Float64(nan:1234567890, signaling:false))
|
|
expectParse("nan(0x10)", Float64(nan:16, signaling:false))
|
|
expectParse("nan(0x12345678)", Float64(nan:0x12345678, signaling:false))
|
|
expectParse("nan(0x9abcdef)", Float64(nan:0x9abcdef, signaling:false))
|
|
expectParse("nan(010)", Float64(nan:8, signaling:false))
|
|
expectParse("nan(01234567)", Float64(nan:0o1234567, signaling:false))
|
|
expectParse("nan(9)", Float64(nan:9, signaling:false))
|
|
expectParse("nan(99)", Float64(nan:99, signaling:false))
|
|
expectParse("nan(255)", Float64(nan:255, signaling:false))
|
|
expectParse("nan(256)", Float64(nan:256, signaling:false))
|
|
expectParse("nan(511)", Float64(nan:511, signaling:false))
|
|
expectParse("nan(999999)", Float64(nan:999999, signaling:false))
|
|
expectParse("nan(999999999999999)", Float64(nan:0x38d7ea4c67fff, signaling:false))
|
|
expectParse("nan(0xfffffffffffff)", Float64(nan:0x3ffffffffffff, signaling:false))
|
|
expectParseFails("n")
|
|
expectParseFails("na")
|
|
expectParseFails("nann")
|
|
expectParseFails("nananananana")
|
|
expectParseFails("nan(xyz)")
|
|
expectParseFails("nan(01238)")
|
|
expectParseFails("nan(01239)")
|
|
expectParseFails("nan(0123a)")
|
|
expectParseFails("nan(0123b)")
|
|
expectParseFails("nan(0123c)")
|
|
expectParseFails("nan(0123d)")
|
|
expectParseFails("nan(0123e)")
|
|
expectParseFails("nan(0123f)")
|
|
expectParseFails("nan(0123g)")
|
|
expectParseFails("nan(123a)")
|
|
expectParseFails("nan(123b)")
|
|
expectParseFails("nan(123c)")
|
|
expectParseFails("nan(123d)")
|
|
expectParseFails("nan(123e)")
|
|
expectParseFails("nan(123f)")
|
|
expectParseFails("nan(123g)")
|
|
expectParseFails("nan(0x123g)")
|
|
}
|
|
|
|
tests.test("HexFloats") {
|
|
expectParseFails("0x")
|
|
expectParseFails("0x.")
|
|
expectParseFails("0x😀")
|
|
expectParseFails("0x1😀p2")
|
|
expectParseFails("0x1.07😀p2")
|
|
expectParseFails("0x1p😀")
|
|
expectParseFails("0x1p+😀")
|
|
expectParseFails("0x1p")
|
|
expectParseFails("0x1p+")
|
|
expectParseFails("0xp+7")
|
|
expectParseFails("0x.p1")
|
|
expectParseFails("0x..p1")
|
|
expectParseFails("0x0p1.0")
|
|
expectParse("0x0p0", 0.0)
|
|
expectParse("0x0p1", 0.0)
|
|
expectParse("-0x0p0", -0.0)
|
|
expectParse("0x0p999999999", 0.0)
|
|
expectParse("0x0.0p999999999", 0.0)
|
|
expectParse("0x.0p-999999999", 0.0)
|
|
expectParse("0x0p-999999999", 0.0)
|
|
|
|
expectParse("0x.000001", 0x0.000001p0)
|
|
expectParse("0x1p-1074", Float64.leastNonzeroMagnitude)
|
|
expectParse("0x1p-1074", Float64(bitPattern:1))
|
|
expectParse("0x1p-1073", Float64(bitPattern:2))
|
|
expectParse("0x1p-1072", Float64(bitPattern:4))
|
|
expectParse("0x1p-1071", Float64(bitPattern:8))
|
|
expectParse("0x1p-1070", Float64(bitPattern:16))
|
|
|
|
// Test the tricky rounding of values between the largest subnormal and least normal
|
|
expectParse("0x0.fffffffffffffp-1022", Float64.leastNormalMagnitude.nextDown) // Largest subnormal
|
|
expectParse("0x1.ffffffffffffep-1023", Float64.leastNormalMagnitude.nextDown) // Largest subnormal
|
|
expectParse("0x1.ffffffffffffefffffffffffffffffffffp-1023", Float64.leastNormalMagnitude.nextDown) // Largest subnormal
|
|
expectParse("0x1.fffffffffffffp-1023", Float64.leastNormalMagnitude) // Halfway
|
|
expectParse("0x1.fffffffffffff00000000000000001p-1023", Float64.leastNormalMagnitude) // just above Halfway
|
|
|
|
expectParse("0x1p-1022", Float64.leastNormalMagnitude) // Smallest normal
|
|
|
|
expectParse("0x1.5555555555555p-2", 1.0/3.0)
|
|
expectParse("0x0.fffffffffffff8", Float64(1.0).nextDown) // Exactly
|
|
expectParse("0x0.fffffffffffffc", 1.0) // Halfway
|
|
expectParse("0x1p0", 1.0)
|
|
|
|
expectParse("0x1.00000000000008p0", 1.0) // Halfway, rounds even
|
|
expectParse("0x1.0000000000000800000000000000000000000000000000000000000000001p0", Float64(1.0).nextUp) // Halfway + epsilon
|
|
expectParse("0x1.0000000000001p0", Float64(1.0).nextUp) // Exactly
|
|
expectParse("0x1.000000000000100000000001", Float64(1.0).nextUp) // Bigger than above
|
|
expectParse("0x1000000000000100000000000000001p-120", (Float64(1.0)).nextUp)
|
|
expectParse("0x00000000.0000000000000000000000000000010000000000001000000000000000000001p120", Float64(1.0).nextUp)
|
|
expectParse("0x1p+1", 2.0)
|
|
expectParse("0x1p+0000000000000000000000000000000000001", 2.0)
|
|
expectParse("0x12", 18.0)
|
|
expectParse("0xab", 171.0)
|
|
expectParse("0x1p+10", 1024.0)
|
|
expectParse("0x1p+0000000000000000000000000010", 1024.0)
|
|
expectParse("0x1.921fb54442d18p+1", Float64.pi)
|
|
|
|
// Rationale for the four assertions below:
|
|
// * Float64.greatestFiniteMagnitude has an odd significand
|
|
// * Let epsilon = the difference between Float64.greatestFiniteMagnitude and its immediate predecessor
|
|
// * Define a synthetic finite successor to Float64.gFM as Float64.gFM + epsilon
|
|
// * Assertion: the value above should round to infinity
|
|
// * Assertion: the value above should be treated as having an even significand
|
|
// * Conclusion: Exact halfway between Float64.gFM and the value above is the smallest magnitude that should round to infinity
|
|
expectParse("0x1.fffffffffffffp+1023", Float64.greatestFiniteMagnitude) // Exact
|
|
expectParse("0x1.fffffffffffff7fffffffffffffffffffffp+1023", Float64.greatestFiniteMagnitude) // .gFM + less than 1/2 epsilon
|
|
expectParse("0x1.fffffffffffff8p+1023", Float64.infinity) // .gFM + 1/2 epsilon
|
|
expectParse("0x2.0000000000000p+1023", Float64.infinity) // .gFM + epsilon above
|
|
|
|
expectParse("0x123456789abcdefp123456789", Float64.infinity)
|
|
}
|
|
|
|
tests.test("Decimal Floats") {
|
|
expectParse("1e-163", 1e-163)
|
|
expectParse("9007199254740992.0", 9007199254740992.0)
|
|
expectParse("-9007199254740992.0", -9007199254740992.0)
|
|
expectParse("4503599627370496.0", 4503599627370496.0)
|
|
expectParse("7.888609052210118e-31", 7.888609052210118e-31)
|
|
expectParse("3.944304526105059e-31", 3.944304526105059e-31)
|
|
expectParse(".0", 0.0)
|
|
expectParse("0", 0.0)
|
|
expectParse("0.", 0.0)
|
|
expectParse("0.0", 0.0)
|
|
expectParse("000000000000000000000000000000", 0.0)
|
|
expectParse(".000000000000000000000000000000", 0.0)
|
|
expectParse("000000000000000000000000000000.0000000000000000000000000000", 0.0)
|
|
expectParse("0000000000000000.000000000000000e9999999999", 0.0)
|
|
expectParse("0e9999999999", 0.0)
|
|
expectParse("1", 1.0)
|
|
expectParse("2", 2.0)
|
|
expectParse("1e0", 1.0)
|
|
expectParse("3.7e1", 37.0)
|
|
expectParse("12.34e3", 12340.0)
|
|
expectParse("-00.0047e5", -470.0)
|
|
expectParse("2e0", 2.0)
|
|
expectParse("1e1", 10.0)
|
|
expectParse("7e1", 70.0)
|
|
expectParse("1e2", 100.0)
|
|
expectParse("1e3", 1000.0)
|
|
expectParse("1e4", 10000.0)
|
|
expectParse("1e0000000000000000000000000000000001", 10.0)
|
|
expectParse("1", 1.0)
|
|
expectParse("1.0", 1.0)
|
|
expectParse("1.00000000", 1.0)
|
|
expectParse("2.0", 2.0)
|
|
|
|
expectParse("0.000001", 1e-6)
|
|
expectParse("0.0000001", 1e-7)
|
|
expectParse("0.00000001", 1e-8)
|
|
expectParse("0.000000001", 1e-9)
|
|
expectParse("0.0000000001", 1e-10)
|
|
expectParse("0.00000000001", 1e-11)
|
|
expectParse("0.000000000001", 1e-12)
|
|
expectParse("0.0000000000001", 1e-13)
|
|
expectParse("0.00000000000001", 1e-14)
|
|
|
|
expectParse("5e-324", Float64.leastNonzeroMagnitude)
|
|
// Exact decimal form of 2^-1074 (which is exactly Float64.leastNonzeroMagnitude)
|
|
expectParse("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625", Float64.leastNonzeroMagnitude)
|
|
// Exact decimal form of 2^-1075 (halfway between Float64.lNM and 0)
|
|
// Ties round even, so this rounds down to zero
|
|
expectParse("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125", 0.0)
|
|
// Increment the last digit, this should round up
|
|
expectParse("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328126", Float64.leastNonzeroMagnitude)
|
|
|
|
// Even a teeny-tiny bit larger than 2^-1075 should round up
|
|
expectParse("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002470328229206232720882843964341106861825299013071623822127928412503377536351043759326499181808179961898982823477228588654633283551779698981993873980053909390631503565951557022639229085839244910518443593180284993653615250031937045767824921936562366986365848075700158576926990370631192827955855133292783433840935197801553124659726357957462276646527282722005637400648549997709659947045402082816622623785739345073633900796776193057750674017632467360096895134053553745851666113422376667860416215968046191446729184030053005753084904876539171138659164623952491262365388187963623937328042389101867234849766823508986338858792562830275599565752445550725518931369083625477918694866799496832404970582102851318545139621383772282614543769341253209859132766723632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", Float64.leastNonzeroMagnitude)
|
|
|
|
expectParse("2.2250738585072009e-308", Float64.leastNormalMagnitude.nextDown)
|
|
expectParse("2.2250738585072014e-308", Float64.leastNormalMagnitude)
|
|
expectParse("1.7976931348623157e+308", Float64.greatestFiniteMagnitude)
|
|
expectParse("-1.7976931348623157e+308", -Float64.greatestFiniteMagnitude)
|
|
|
|
expectParse("179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858367", Float64.greatestFiniteMagnitude) // Exact - 1
|
|
expectParse("179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368", Float64.greatestFiniteMagnitude) // Exact
|
|
expectParse("179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369", Float64.greatestFiniteMagnitude) // Exact + 1
|
|
|
|
// exact gFM + 1 ULP
|
|
expectParse("179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216", Float64.infinity)
|
|
|
|
// 1 less than exact midpoint between gFM and gFM + 1 ULP
|
|
// (Largest integer that rounds to gFM)
|
|
expectParse("179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791", Float64.greatestFiniteMagnitude)
|
|
// Even closer to (but still less than) the exact midpoint
|
|
expectParse("179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", Float64.greatestFiniteMagnitude)
|
|
|
|
// Exact midpoint between gFM and gFM + 1 ULP
|
|
// (Rounds even to gFM + 1 ULP, which we treat as infinite
|
|
expectParse("179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792", Float64.infinity)
|
|
|
|
expectParse("1.7976931348623157e+308", Float64.greatestFiniteMagnitude)
|
|
expectParse("1.7976931348623159e+308", Float64.infinity)
|
|
expectParse("1.797693134862316e+308", Float64.infinity)
|
|
expectParse("1.79769313486232e+308", Float64.infinity)
|
|
expectParse("1.79769313487e+308", Float64.infinity)
|
|
expectParse("1.79769314e+308", Float64.infinity)
|
|
expectParse("1.7977e+308", Float64.infinity)
|
|
expectParse("1.798e+308", Float64.infinity)
|
|
expectParse("1.8e+308", Float64.infinity)
|
|
expectParse("2e+308", Float64.infinity)
|
|
expectParse("1e309", Float64.infinity)
|
|
expectParse("1e9999999999999999999999999999999999", Float64.infinity)
|
|
expectParse("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999.999999999999999999999999999", Float64.infinity)
|
|
}
|
|
|
|
@_extern(c, "_swift_stdlib_strtod_clocale")
|
|
func _swift_stdlib_strtod_clocale(
|
|
_: Optional<UnsafePointer<CChar>>,
|
|
_: Optional<UnsafeMutablePointer<Double>>
|
|
) -> Optional<UnsafePointer<CChar>>
|
|
|
|
func viaLegacy(_ text: String) -> Double? {
|
|
return text.withCString { strptr -> Double? in
|
|
var result = Double()
|
|
let succeeded = withUnsafeMutablePointer(to: &result) { dptr in
|
|
let endptr = _swift_stdlib_strtod_clocale(strptr, dptr)
|
|
return endptr == strptr + text.utf8.count
|
|
}
|
|
if succeeded {
|
|
return Double?.some(result)
|
|
} else {
|
|
return Double?.none
|
|
}
|
|
}
|
|
}
|
|
|
|
tests.test("Legacy ABI") {
|
|
expectEqual(viaLegacy("1.0"), 1.0 as Double)
|
|
expectEqual(viaLegacy("1.7976931348623157e+308"), Double.greatestFiniteMagnitude)
|
|
}
|
|
|
|
/*
|
|
// Checking 100 million random doubles takes only a fraction of a second on a
|
|
// release build, but is _PAINFULLY SLOW_ in debug builds, so only enable this
|
|
// locally!
|
|
tests.test("Random Float64") {
|
|
let blocks = 100_000
|
|
let blocksize = 1_000
|
|
for _ in 0..<blocks {
|
|
var raw = UInt64.random(in: 0...UInt64.max)
|
|
for _ in 0..<blocksize {
|
|
raw &+= 1
|
|
let d = Float64(bitPattern: raw)
|
|
expectRoundTrip(d)
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
runAllTests()
|