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

158 lines
15 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 atofq
// same used in atof, here only for references
const(
DOUBLE_PLUS_ZERO = u64(0x0000000000000000)
DOUBLE_MINUS_ZERO = 0x8000000000000000
DOUBLE_PLUS_INFINITY = 0x7FF0000000000000
DOUBLE_MINUS_INFINITY = 0xFFF0000000000000
)
union Float64u {
mut:
f f64
u u64 = u64(0)
}
// 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 {
f.u = DOUBLE_PLUS_INFINITY
2019-12-20 00:29:37 +03:00
}
else {
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 {
f.u = DOUBLE_PLUS_ZERO
2019-12-20 00:29:37 +03:00
}
else {
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 {
f.u = DOUBLE_PLUS_INFINITY
2019-12-20 00:29:37 +03:00
}
else {
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) {
f.u = DOUBLE_PLUS_ZERO
2019-12-20 00:29:37 +03:00
}
else {
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
2019-12-20 00:29:37 +03:00
pos_exp = [0x3ff0000000000000, 0x4024000000000000, 0x4059000000000000, 0x408f400000000000, 0x40c3880000000000, 0x40f86a0000000000, 0x412e848000000000, 0x416312d000000000, 0x4197d78400000000, 0x41cdcd6500000000, 0x4202a05f20000000, 0x42374876e8000000, 0x426d1a94a2000000, 0x42a2309ce5400000, 0x42d6bcc41e900000, 0x430c6bf526340000, 0x4341c37937e08000, 0x4376345785d8a000, 0x43abc16d674ec800, 0x43e158e460913d00, 0x4415af1d78b58c40, 0x444b1ae4d6e2ef50, 0x4480f0cf064dd592, 0x44b52d02c7e14af6, 0x44ea784379d99db4, 0x45208b2a2c280291, 0x4554adf4b7320335, 0x4589d971e4fe8402, 0x45c027e72f1f1281, 0x45f431e0fae6d721, 0x46293e5939a08cea, 0x465f8def8808b024, 0x4693b8b5b5056e17, 0x46c8a6e32246c99c, 0x46fed09bead87c03, 0x4733426172c74d82, 0x476812f9cf7920e3, 0x479e17b84357691b, 0x47d2ced32a16a1b1, 0x48078287f49c4a1d, 0x483d6329f1c35ca5, 0x48725dfa371a19e7, 0x48a6f578c4e0a061, 0x48dcb2d6f618c879, 0x4911efc659cf7d4c, 0x49466bb7f0435c9e, 0x497c06a5ec5433c6, 0x49b18427b3b4a05c, 0x49e5e531a0a1c873, 0x4a1b5e7e08ca3a8f, 0x4a511b0ec57e649a, 0x4a8561d276ddfdc0, 0x4ababa4714957d30, 0x4af0b46c6cdd6e3e, 0x4b24e1878814c9ce, 0x4b5a19e96a19fc41, 0x4b905031e2503da9, 0x4bc4643e5ae44d13, 0x4bf97d4df19d6057, 0x4c2fdca16e04b86d, 0x4c63e9e4e4c2f344, 0x4c98e45e1df3b015, 0x4ccf1d75a5709c1b, 0x4d03726987666191, 0x4d384f03e93ff9f5, 0x4d6e62c4e38ff872, 0x4da2fdbb0e39fb47, 0x4dd7bd29d1c87a19, 0x4e0dac74463a989f, 0x4e428bc8abe49f64, 0x4e772ebad6ddc73d, 0x4eacfa698c95390c, 0x4ee21c81f7dd43a7, 0x4f16a3a275d49491, 0x4f4c4c8b1349b9b5, 0x4f81afd6ec0e1411, 0x4fb61bcca7119916, 0x4feba2bfd0d5ff5b, 0x502145b7e285bf99, 0x50559725db272f7f, 0x508afcef51f0fb5f, 0x50c0de1593369d1b, 0x50f5159af8044462, 0x512a5b01b605557b, 0x516078e111c3556d, 0x5194971956342ac8, 0x51c9bcdfabc1357a, 0x5200160bcb58c16c, 0x52341b8ebe2ef1c7, 0x526922726dbaae39, 0x529f6b0f092959c7, 0x52d3a2e965b9d81d, 0x53088ba3bf284e24, 0x533eae8caef261ad, 0x53732d17ed577d0c, 0x53a7f85de8ad5c4f, 0x53ddf67562d8b363, 0x5412ba095dc7701e, 0x5447688bb5394c25, 0x547d42aea2879f2e, 0x54b249ad2594c37d, 0x54e6dc186ef9f45c, 0x551c931e8ab87173, 0x5551dbf316b346e8, 0x558652efdc6018a2, 0x55bbe7abd3781eca, 0x55f170cb642b133f, 0x5625ccfe3d35d80e, 0x565b403dcc834e12, 0x569108269fd210cb, 0x56c54a3047c694fe, 0x56fa9cbc59b83a3d, 0x5730a1f5b8132466, 0x5764ca732617ed80, 0x5799fd0fef9de8e0, 0x57d03e29f5c2b18c, 0x58044db473335def, 0x583961219000356b, 0x586fb969f40042c5, 0x58a3d3e2388029bb, 0x58d8c8dac6a0342a, 0x590efb1178484135, 0x59435ceaeb2d28c1, 0x59783425a5f872f1, 0x59ae412f0f768fad, 0x59e2e8bd69aa19cc, 0x5a17a2ecc414a03f, 0x5a4d8ba7f519c84f, 0x5a827748f9301d32, 0x5ab7151b377c247e, 0x5aecda62055b2d9e, 0x5b22087d4358fc82, 0x5b568a9c942f3ba3, 0x5b8c2d43b93b0a8c, 0x5bc19c4a53c4e697, 0x5bf6035ce8b6203d, 0x5c2b843422e3a84d, 0x5c6132a095ce4930, 0x5c957f48bb41db7c, 0x5ccadf1aea12525b, 0x5d00cb70d24b7379, 0x5d34fe4d06de5057, 0x5d6a3de04895e46d, 0x5da066ac2d5daec4, 0x5dd4805738b51a75, 0x5e09a06d06e26112, 0x5e400444244d7cab, 0x5e7405552d60dbd6, 0x5ea906aa78b912cc, 0x5edf485516e7577f, 0x5f138d352e5096af, 0x5f48708279e4bc5b, 0x5f7e8ca3185deb72, 0x5fb317e5ef3ab327, 0x5fe7dddf6b095ff1, 0x601dd55745cbb7ed, 0x6052a5568b9f52f4, 0x60874eac2e8727b1, 0x60bd22573a28f19d, 0x60f2357684599702, 0x6126c2d4256ffcc3, 0x615c73892ecbfbf4, 0x6191c835bd3f7d78, 0x61c63a432c8f5cd6, 0x61fbc8d3f7b3340c, 0x62315d847ad00087, 0x6265b4e5998400a9, 0x629b221effe500d4, 0x62d0f5535fef2084, 0x630532a837eae8a5, 0x633a7f5245e5a2cf, 0x63708f936baf85c1, 0x63a4b378469b6732, 0x63d9e056584240fe, 0x64102c35f729689f, 0x6444374374f3c2c6, 0x647945145230b378, 0x64af965966bce056, 0x64e3bdf7e0360c36, 0x6518ad75d8438f43, 0x654ed8d34e547314, 0x6583478410f4c7ec, 0x65b819651531f9e8, 0x65ee1fbe5a7e7861, 0x6622d3d6f88f0b3d, 0x665788ccb6b2ce0c, 0x668d6affe45f818f, 0x66c262dfeebbb0f9, 0x66f6fb97ea6a9d38, 0x672cba7de5054486, 0x6761f48eaf234ad4, 0x679671b25aec1d89, 0x67cc0e1ef1a724eb, 0x680188d357087713, 0x6835eb082cca94d7, 0x686b65ca37fd3a0d, 0x68a11f9e62fe4448, 0x68d56785fbbdd55a, 0x690ac1677aad4ab1, 0x6940b8e0acac4eaf, 0x6974e718d7d7625a, 0x69aa20df0dcd3af1, 0x69e0548b68a044d6, 0x6a1469ae42c8560c, 0x6
// negative exp of 10 binary form
neg_exp = [0x3ff0000000000000, 0x3fb999999999999a, 0x3f847ae147ae147b, 0x3f50624dd2f1a9fc, 0x3f1a36e2eb1c432d, 0x3ee4f8b588e368f1, 0x3eb0c6f7a0b5ed8d, 0x3e7ad7f29abcaf48, 0x3e45798ee2308c3a, 0x3e112e0be826d695, 0x3ddb7cdfd9d7bdbb, 0x3da5fd7fe1796495, 0x3d719799812dea11, 0x3d3c25c268497682, 0x3d06849b86a12b9b, 0x3cd203af9ee75616, 0x3c9cd2b297d889bc, 0x3c670ef54646d497, 0x3c32725dd1d243ac, 0x3bfd83c94fb6d2ac, 0x3bc79ca10c924223, 0x3b92e3b40a0e9b4f, 0x3b5e392010175ee6, 0x3b282db34012b251, 0x3af357c299a88ea7, 0x3abef2d0f5da7dd9, 0x3a88c240c4aecb14, 0x3a53ce9a36f23c10, 0x3a1fb0f6be506019, 0x39e95a5efea6b347, 0x39b4484bfeebc2a0, 0x398039d665896880, 0x3949f623d5a8a733, 0x3914c4e977ba1f5c, 0x38e09d8792fb4c49, 0x38aa95a5b7f87a0f, 0x38754484932d2e72, 0x3841039d428a8b8f, 0x380b38fb9daa78e4, 0x37d5c72fb1552d83, 0x37a16c262777579c, 0x376be03d0bf225c7, 0x37364cfda3281e39, 0x3701d7314f534b61, 0x36cc8b8218854567, 0x3696d601ad376ab9, 0x366244ce242c5561, 0x362d3ae36d13bbce, 0x35f7624f8a762fd8, 0x35c2b50c6ec4f313, 0x358dee7a4ad4b81f, 0x3557f1fb6f10934c, 0x352327fc58da0f70, 0x34eea6608e29b24d, 0x34b8851a0b548ea4, 0x34839dae6f76d883, 0x344f62b0b257c0d2, 0x34191bc08eac9a41, 0x33e41633a556e1ce, 0x33b011c2eaabe7d8, 0x3379b604aaaca626, 0x3344919d5556eb52, 0x3310747ddddf22a8, 0x32da53fc9631d10d, 0x32a50ffd44f4a73d, 0x3270d9976a5d5297, 0x323af5bf109550f2, 0x32059165a6ddda5b, 0x31d1411e1f17e1e3, 0x319b9b6364f30304, 0x316615e91d8f359d, 0x3131ab20e472914a, 0x30fc45016d841baa, 0x30c69d9abe034955, 0x309217aefe690777, 0x305cf2b1970e7258, 0x3027288e1271f513, 0x2ff286d80ec190dc, 0x2fbda48ce468e7c7, 0x2f87b6d71d20b96c, 0x2f52f8ac174d6123, 0x2f1e5aacf2156838, 0x2ee8488a5b445360, 0x2eb36d3b7c36a91a, 0x2e7f152bf9f10e90, 0x2e48ddbcc7f40ba6, 0x2e13e497065cd61f, 0x2ddfd424d6faf031, 0x2da97683df2f268d, 0x2d745ecfe5bf520b, 0x2d404bd984990e6f, 0x2d0a12f5a0f4e3e5, 0x2cd4dbf7b3f71cb7, 0x2ca0aff95cc5b092, 0x2c6ab328946f80ea, 0x2c355c2076bf9a55, 0x2c0116805effaeaa, 0x2bcb5733cb32b111, 0x2b95df5ca28ef40d, 0x2b617f7d4ed8c33e, 0x2b2bff2ee48e0530, 0x2af665bf1d3e6a8d, 0x2ac1eaff4a98553d, 0x2a8cab3210f3bb95, 0x2a56ef5b40c2fc77, 0x2a225915cd68c9f9, 0x29ed5b561574765b, 0x29b77c44ddf6c516, 0x2982c9d0b1923745, 0x294e0fb44f50586e, 0x29180c903f7379f2, 0x28e33d4032c2c7f5, 0x28aec866b79e0cba, 0x2878a0522c7e7095, 0x2843b374f06526de, 0x280f8587e7083e30, 0x27d9379fec069826, 0x27a42c7ff0054685, 0x277023998cd10537, 0x2739d28f47b4d525, 0x2704a8729fc3ddb7, 0x26d086c219697e2c, 0x269a71368f0f3047, 0x2665275ed8d8f36c, 0x2630ec4be0ad8f89, 0x25fb13ac9aaf4c0f, 0x25c5a956e225d672, 0x2591544581b7dec2, 0x255bba08cf8c979d, 0x25262e6d72d6dfb0, 0x24f1bebdf578b2f4, 0x24bc6463225ab7ec, 0x2486b6b5b5155ff0, 0x24522bc490dde65a, 0x241d12d41afca3c3, 0x23e7424348ca1c9c, 0x23b29b69070816e3, 0x237dc574d80cf16b, 0x2347d12a4670c123, 0x23130dbb6b8d674f, 0x22de7c5f127bd87e, 0x22a8637f41fcad32, 0x227382cc34ca2428, 0x223f37ad21436d0c, 0x2208f9574dcf8a70, 0x21d3faac3e3fa1f3, 0x219ff779fd329cb9, 0x216992c7fdc216fa, 0x2134756ccb01abfb, 0x21005df0a267bcc9, 0x20ca2fe76a3f9475, 0x2094f31f8832dd2a, 0x2060c27fa028b0ef, 0x202ad0cc33744e4b, 0x1ff573d68f903ea2, 0x1fc1297872d9cbb5, 0x1f8b758d848fac55, 0x1f55f7a46a0c89dd, 0x1f2192e9ee706e4b, 0x1eec1e43171a4a11, 0x1eb67e9c127b6e74, 0x1e81fee341fc585d, 0x1e4ccb0536608d61, 0x1e1708d0f84d3de7, 0x1de26d73f9d764b9, 0x1dad7becc2f23ac2, 0x1d779657025b6235, 0x1d42deac01e2b4f7, 0x1d0e3113363787f2, 0x1cd8274291c6065b, 0x1ca3529ba7d19eaf, 0x1c6eea92a61c3118, 0x1c38bba884e35a7a, 0x1c03c9539d82aec8, 0x1bcfa885c8d117a6, 0x1b99539e3a40dfb8, 0x1b6442e4fb671960, 0x1b303583fc527ab3, 0x1af9ef3993b72ab8, 0x1ac4bf6142f8eefa, 0x1a90991a9bfa58c8, 0x1a5a8e90f9908e0d, 0x1a253eda614071a4, 0x19f0ff151a99f483, 0x19bb31bb5dc320d2, 0x1985c162b168e70e, 0x1951678227871f3e, 0x191bd8d03f3e9864, 0x18e6470cff6546b6, 0x18b1d270cc51055f, 0x187c83e7ad4e6efe, 0x1846cfec8aa52598, 0x18123ff06eea847a, 0x17dd331a4b10d3f6, 0x17a75c1508da432b, 0x1772b010d3e1cf56, 0x173de6815302e556, 0x1707eb9aa8cf1dde, 0x16d322e220a5b17e, 0x169e9e369aa2b597, 0x16687e92154ef7ac, 0x16339874ddd8c623, 0x15ff5a549627a36c, 0x15c91510781fb5f0, 0x1
)