1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00
v/vlib/strconv/atofq.v

150 lines
18 KiB
V
Raw Normal View History

/*
atof util
Copyright (c) 2019 Dario Deledda. All rights reserved.
Use of this source code is governed by an MIT license
that can be found in the LICENSE file.
This file contains utilities for convert a string in a f64 variable in a very quick way
IEEE 754 standard is used
Know limitation:
- round to 0 approximation
- loos of precision with big exponents
*/
2019-12-27 06:07:09 +03:00
module strconv
union Float64u {
mut:
f f64
2020-04-06 15:53:28 +03:00
u u64
}
// atof_quick return a f64 number from a string in a quick way
pub fn atof_quick(s string) f64 {
mut f := Float64u{} // result
2019-12-20 00:29:37 +03:00
mut sign := f64(1.0) // result sign
mut i := 0 // index
// skip white spaces
for i < s.len && s[i] == ` ` {
i++
}
2019-12-20 00:29:37 +03:00
// check sign
if i < s.len {
if s[i] == `-` {
sign = -1.0
i++
2019-12-20 00:29:37 +03:00
}
else if s[i] == `+` {
i++
}
}
// infinite
2019-12-20 00:29:37 +03:00
if s[i] == `i` && i + 2 < s.len && s[i + 1] == `n` && s[i + 2] == `f` {
if sign > 0.0 {
2020-05-22 18:36:09 +03:00
f.u = double_plus_infinity
2019-12-20 00:29:37 +03:00
}
else {
2020-05-22 18:36:09 +03:00
f.u = double_minus_infinity
}
return f.f
}
// skip zeros
2019-12-20 00:29:37 +03:00
for i < s.len && s[i] == `0` {
i++
// we have a zero, manage it
if i >= s.len {
if sign > 0.0 {
2020-05-22 18:36:09 +03:00
f.u = double_plus_zero
2019-12-20 00:29:37 +03:00
}
else {
2020-05-22 18:36:09 +03:00
f.u = double_minus_zero
}
return f.f
}
}
// integer part
for i < s.len && (s[i] >= `0` && s[i] <= `9`) {
f.f *= f64(10.0)
f.f += f64(s[i] - `0`)
i++
}
// decimal point
if i < s.len && s[i] == `.` {
i++
mut frac_mul := f64(0.1)
for i < s.len && (s[i] >= `0` && s[i] <= `9`) {
f.f += f64(s[i] - `0`) * frac_mul
frac_mul *= f64(0.1)
i++
}
}
2019-12-20 00:29:37 +03:00
// exponent management
if i < s.len && (s[i] == `e` || s[i] == `E`) {
i++
mut exp := 0
mut exp_sign := 1
// negative exponent
if i < s.len {
if s[i] == `-` {
exp_sign = -1
i++
2019-12-20 00:29:37 +03:00
}
else if s[i] == `+` {
i++
}
}
// skip zeros
for i < s.len && s[i] == `0` {
i++
}
for i < s.len && (s[i] >= `0` && s[i] <= `9`) {
exp *= 10
exp += int(s[i] - `0`)
i++
}
if exp_sign == 1 {
if exp > pos_exp.len {
if sign > 0 {
2020-05-22 18:36:09 +03:00
f.u = double_plus_infinity
2019-12-20 00:29:37 +03:00
}
else {
2020-05-22 18:36:09 +03:00
f.u = double_minus_infinity
}
return f.f
}
tmp_mul := Float64u{u: pos_exp[exp]}
2019-12-20 00:29:37 +03:00
// C.printf("exp: %d [0x%016llx] %f,",exp,pos_exp[exp],tmp_mul)
f.f = f.f * tmp_mul.f
2019-12-20 00:29:37 +03:00
}
else {
if exp > neg_exp.len {
if sign > 0 {
2020-05-22 18:36:09 +03:00
f.u = double_plus_zero
2019-12-20 00:29:37 +03:00
}
else {
2020-05-22 18:36:09 +03:00
f.u = double_minus_zero
}
return f.f
}
tmp_mul := Float64u{u: neg_exp[exp]}
2019-12-20 00:29:37 +03:00
// C.printf("exp: %d [0x%016llx] %f,",exp,pos_exp[exp],tmp_mul)
f.f = f.f * tmp_mul.f
}
}
f.f = f.f * sign
return f.f
}
2019-12-20 00:29:37 +03:00
const (
// positive exp of 10 binary form
pos_exp = [u64(0x3ff0000000000000), u64(0x4024000000000000), u64(0x4059000000000000), u64(0x408f400000000000), u64(0x40c3880000000000), u64(0x40f86a0000000000), u64(0x412e848000000000), u64(0x416312d000000000), u64(0x4197d78400000000), u64(0x41cdcd6500000000), u64(0x4202a05f20000000), u64(0x42374876e8000000), u64(0x426d1a94a2000000), u64(0x42a2309ce5400000), u64(0x42d6bcc41e900000), u64(0x430c6bf526340000), u64(0x4341c37937e08000), u64(0x4376345785d8a000), u64(0x43abc16d674ec800), u64(0x43e158e460913d00), u64(0x4415af1d78b58c40), u64(0x444b1ae4d6e2ef50), u64(0x4480f0cf064dd592), u64(0x44b52d02c7e14af6), u64(0x44ea784379d99db4), u64(0x45208b2a2c280291), u64(0x4554adf4b7320335), u64(0x4589d971e4fe8402), u64(0x45c027e72f1f1281), u64(0x45f431e0fae6d721), u64(0x46293e5939a08cea), u64(0x465f8def8808b024), u64(0x4693b8b5b5056e17), u64(0x46c8a6e32246c99c), u64(0x46fed09bead87c03), u64(0x4733426172c74d82), u64(0x476812f9cf7920e3), u64(0x479e17b84357691b), u64(0x47d2ced32a16a1b1), u64(0x48078287f49c4a1d), u64(0x483d6329f1c35ca5), u64(0x48725dfa371a19e7), u64(0x48a6f578c4e0a061), u64(0x48dcb2d6f618c879), u64(0x4911efc659cf7d4c), u64(0x49466bb7f0435c9e), u64(0x497c06a5ec5433c6), u64(0x49b18427b3b4a05c), u64(0x49e5e531a0a1c873), u64(0x4a1b5e7e08ca3a8f), u64(0x4a511b0ec57e649a), u64(0x4a8561d276ddfdc0), u64(0x4ababa4714957d30), u64(0x4af0b46c6cdd6e3e), u64(0x4b24e1878814c9ce), u64(0x4b5a19e96a19fc41), u64(0x4b905031e2503da9), u64(0x4bc4643e5ae44d13), u64(0x4bf97d4df19d6057), u64(0x4c2fdca16e04b86d), u64(0x4c63e9e4e4c2f344), u64(0x4c98e45e1df3b015), u64(0x4ccf1d75a5709c1b), u64(0x4d03726987666191), u64(0x4d384f03e93ff9f5), u64(0x4d6e62c4e38ff872), u64(0x4da2fdbb0e39fb47), u64(0x4dd7bd29d1c87a19), u64(0x4e0dac74463a989f), u64(0x4e428bc8abe49f64), u64(0x4e772ebad6ddc73d), u64(0x4eacfa698c95390c), u64(0x4ee21c81f7dd43a7), u64(0x4f16a3a275d49491), u64(0x4f4c4c8b1349b9b5), u64(0x4f81afd6ec0e1411), u64(0x4fb61bcca7119916), u64(0x4feba2bfd0d5ff5b), u64(0x502145b7e285bf99), u64(0x50559725db272f7f), u64(0x508afcef51f0fb5f), u64(0x50c0de1593369d1b), u64(0x50f5159af8044462), u64(0x512a5b01b605557b), u64(0x516078e111c3556d), u64(0x5194971956342ac8), u64(0x51c9bcdfabc1357a), u64(0x5200160bcb58c16c), u64(0x52341b8ebe2ef1c7), u64(0x526922726dbaae39), u64(0x529f6b0f092959c7), u64(0x52d3a2e965b9d81d), u64(0x53088ba3bf284e24), u64(0x533eae8caef261ad), u64(0x53732d17ed577d0c), u64(0x53a7f85de8ad5c4f), u64(0x53ddf67562d8b363), u64(0x5412ba095dc7701e), u64(0x5447688bb5394c25), u64(0x547d42aea2879f2e), u64(0x54b249ad2594c37d), u64(0x54e6dc186ef9f45c), u64(0x551c931e8ab87173), u64(0x5551dbf316b346e8), u64(0x558652efdc6018a2), u64(0x55bbe7abd3781eca), u64(0x55f170cb642b133f), u64(0x5625ccfe3d35d80e), u64(0x565b403dcc834e12), u64(0x569108269fd210cb), u64(0x56c54a3047c694fe), u64(0x56fa9cbc59b83a3d), u64(0x5730a1f5b8132466), u64(0x5764ca732617ed80), u64(0x5799fd0fef9de8e0), u64(0x57d03e29f5c2b18c), u64(0x58044db473335def), u64(0x583961219000356b), u64(0x586fb969f40042c5), u64(0x58a3d3e2388029bb), u64(0x58d8c8dac6a0342a), u64(0x590efb1178484135), u64(0x59435ceaeb2d28c1), u64(0x59783425a5f872f1), u64(0x59ae412f0f768fad), u64(0x59e2e8bd69aa19cc), u64(0x5a17a2ecc414a03f), u64(0x5a4d8ba7f519c84f), u64(0x5a827748f9301d32), u64(0x5ab7151b377c247e), u64(0x5aecda62055b2d9e), u64(0x5b22087d4358fc82), u64(0x5b568a9c942f3ba3), u64(0x5b8c2d43b93b0a8c), u64(0x5bc19c4a53c4e697), u64(0x5bf6035ce8b6203d), u64(0x5c2b843422e3a84d), u64(0x5c6132a095ce4930), u64(0x5c957f48bb41db7c), u64(0x5ccadf1aea12525b), u64(0x5d00cb70d24b7379), u64(0x5d34fe4d06de5057), u64(0x5d6a3de04895e46d), u64(0x5da066ac2d5daec4), u64(0x5dd4805738b51a75), u64(0x5e09a06d06e26112), u64(0x5e400444244d7cab), u64(0x5e7405552d60dbd6), u64(0x5ea906aa78b912cc), u64(0x5edf485516e7577f), u64(0x5f138d352e5096af), u64(0x5f48708279e4bc5b), u64(0x5f7e8ca3185deb72), u64(0x5fb317e5ef3ab327), u64(0x5fe7dddf6b095ff1), u64(0x601dd55745cbb7ed), u64(0x6052a5568b9f52f4), u64(0x60874eac2e8727b1), u64(0x60bd22573a28f19d), u64(0x60f2357684599702), u64(0x6126c2d4256ffcc3), u64(0x615c73892ecbfbf4), u64(0x6191c835bd3f7d78), u64(0x61
2019-12-20 00:29:37 +03:00
// negative exp of 10 binary form
neg_exp = [u64(0x3ff0000000000000), u64(0x3fb999999999999a), u64(0x3f847ae147ae147b), u64(0x3f50624dd2f1a9fc), u64(0x3f1a36e2eb1c432d), u64(0x3ee4f8b588e368f1), u64(0x3eb0c6f7a0b5ed8d), u64(0x3e7ad7f29abcaf48), u64(0x3e45798ee2308c3a), u64(0x3e112e0be826d695), u64(0x3ddb7cdfd9d7bdbb), u64(0x3da5fd7fe1796495), u64(0x3d719799812dea11), u64(0x3d3c25c268497682), u64(0x3d06849b86a12b9b), u64(0x3cd203af9ee75616), u64(0x3c9cd2b297d889bc), u64(0x3c670ef54646d497), u64(0x3c32725dd1d243ac), u64(0x3bfd83c94fb6d2ac), u64(0x3bc79ca10c924223), u64(0x3b92e3b40a0e9b4f), u64(0x3b5e392010175ee6), u64(0x3b282db34012b251), u64(0x3af357c299a88ea7), u64(0x3abef2d0f5da7dd9), u64(0x3a88c240c4aecb14), u64(0x3a53ce9a36f23c10), u64(0x3a1fb0f6be506019), u64(0x39e95a5efea6b347), u64(0x39b4484bfeebc2a0), u64(0x398039d665896880), u64(0x3949f623d5a8a733), u64(0x3914c4e977ba1f5c), u64(0x38e09d8792fb4c49), u64(0x38aa95a5b7f87a0f), u64(0x38754484932d2e72), u64(0x3841039d428a8b8f), u64(0x380b38fb9daa78e4), u64(0x37d5c72fb1552d83), u64(0x37a16c262777579c), u64(0x376be03d0bf225c7), u64(0x37364cfda3281e39), u64(0x3701d7314f534b61), u64(0x36cc8b8218854567), u64(0x3696d601ad376ab9), u64(0x366244ce242c5561), u64(0x362d3ae36d13bbce), u64(0x35f7624f8a762fd8), u64(0x35c2b50c6ec4f313), u64(0x358dee7a4ad4b81f), u64(0x3557f1fb6f10934c), u64(0x352327fc58da0f70), u64(0x34eea6608e29b24d), u64(0x34b8851a0b548ea4), u64(0x34839dae6f76d883), u64(0x344f62b0b257c0d2), u64(0x34191bc08eac9a41), u64(0x33e41633a556e1ce), u64(0x33b011c2eaabe7d8), u64(0x3379b604aaaca626), u64(0x3344919d5556eb52), u64(0x3310747ddddf22a8), u64(0x32da53fc9631d10d), u64(0x32a50ffd44f4a73d), u64(0x3270d9976a5d5297), u64(0x323af5bf109550f2), u64(0x32059165a6ddda5b), u64(0x31d1411e1f17e1e3), u64(0x319b9b6364f30304), u64(0x316615e91d8f359d), u64(0x3131ab20e472914a), u64(0x30fc45016d841baa), u64(0x30c69d9abe034955), u64(0x309217aefe690777), u64(0x305cf2b1970e7258), u64(0x3027288e1271f513), u64(0x2ff286d80ec190dc), u64(0x2fbda48ce468e7c7), u64(0x2f87b6d71d20b96c), u64(0x2f52f8ac174d6123), u64(0x2f1e5aacf2156838), u64(0x2ee8488a5b445360), u64(0x2eb36d3b7c36a91a), u64(0x2e7f152bf9f10e90), u64(0x2e48ddbcc7f40ba6), u64(0x2e13e497065cd61f), u64(0x2ddfd424d6faf031), u64(0x2da97683df2f268d), u64(0x2d745ecfe5bf520b), u64(0x2d404bd984990e6f), u64(0x2d0a12f5a0f4e3e5), u64(0x2cd4dbf7b3f71cb7), u64(0x2ca0aff95cc5b092), u64(0x2c6ab328946f80ea), u64(0x2c355c2076bf9a55), u64(0x2c0116805effaeaa), u64(0x2bcb5733cb32b111), u64(0x2b95df5ca28ef40d), u64(0x2b617f7d4ed8c33e), u64(0x2b2bff2ee48e0530), u64(0x2af665bf1d3e6a8d), u64(0x2ac1eaff4a98553d), u64(0x2a8cab3210f3bb95), u64(0x2a56ef5b40c2fc77), u64(0x2a225915cd68c9f9), u64(0x29ed5b561574765b), u64(0x29b77c44ddf6c516), u64(0x2982c9d0b1923745), u64(0x294e0fb44f50586e), u64(0x29180c903f7379f2), u64(0x28e33d4032c2c7f5), u64(0x28aec866b79e0cba), u64(0x2878a0522c7e7095), u64(0x2843b374f06526de), u64(0x280f8587e7083e30), u64(0x27d9379fec069826), u64(0x27a42c7ff0054685), u64(0x277023998cd10537), u64(0x2739d28f47b4d525), u64(0x2704a8729fc3ddb7), u64(0x26d086c219697e2c), u64(0x269a71368f0f3047), u64(0x2665275ed8d8f36c), u64(0x2630ec4be0ad8f89), u64(0x25fb13ac9aaf4c0f), u64(0x25c5a956e225d672), u64(0x2591544581b7dec2), u64(0x255bba08cf8c979d), u64(0x25262e6d72d6dfb0), u64(0x24f1bebdf578b2f4), u64(0x24bc6463225ab7ec), u64(0x2486b6b5b5155ff0), u64(0x24522bc490dde65a), u64(0x241d12d41afca3c3), u64(0x23e7424348ca1c9c), u64(0x23b29b69070816e3), u64(0x237dc574d80cf16b), u64(0x2347d12a4670c123), u64(0x23130dbb6b8d674f), u64(0x22de7c5f127bd87e), u64(0x22a8637f41fcad32), u64(0x227382cc34ca2428), u64(0x223f37ad21436d0c), u64(0x2208f9574dcf8a70), u64(0x21d3faac3e3fa1f3), u64(0x219ff779fd329cb9), u64(0x216992c7fdc216fa), u64(0x2134756ccb01abfb), u64(0x21005df0a267bcc9), u64(0x20ca2fe76a3f9475), u64(0x2094f31f8832dd2a), u64(0x2060c27fa028b0ef), u64(0x202ad0cc33744e4b), u64(0x1ff573d68f903ea2), u64(0x1fc1297872d9cbb5), u64(0x1f8b758d848fac55), u64(0x1f55f7a46a0c89dd), u64(0x1f2192e9ee706e4b), u64(0x1eec1e43171a4a11), u64(0x1eb67e9c127b6e74), u64(0x1e81fee341fc585d), u64(0x1e4ccb0536608d61), u64(0x1e
)