Created
May 26, 2021 03:03
-
-
Save timotheecour/8f45eddc5b3533f5e166b305fde537f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Copyright 2020 Junekey Jeon | |
## Copyright 2020 Alexander Bolz | |
## | |
## Distributed under the Boost Software License, Version 1.0. | |
## (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) | |
## char* output_end = Dtoa(buffer, value); | |
## | |
## Converts the given double-precision number into decimal form and stores the result in the given | |
## buffer. | |
## | |
## The buffer must be large enough, i.e. >= DtoaMinBufferLength. | |
## The output format is similar to printf("%g"). | |
## The output is _not_ null-terminted. | |
## | |
## The output is optimal, i.e. the output string | |
## 1. rounds back to the input number when read in (using round-to-nearest-even) | |
## 2. is as short as possible, | |
## 3. is as close to the input number as possible. | |
## | |
## Note: | |
## This function may temporarily write up to DtoaMinBufferLength characters into the buffer. | |
var DtoaMinBufferLength*: cint = 64 | |
proc Dtoa*(buffer: cstring; value: cdouble): cstring | |
## namespace dragonbox | |
## -------------------------------------------------------------------------------------------------- | |
## This file contains an implementation of Junekey Jeon's Dragonbox algorithm. | |
## | |
## It is a simplified version of the reference implementation found here: | |
## https://github.com/jk-jeon/dragonbox | |
## | |
## The reference implementation also works with single-precision floating-point numbers and | |
## has options to configure the rounding mode. | |
## -------------------------------------------------------------------------------------------------- | |
when defined(_MSC_VER): | |
discard | |
when not defined(DRAGONBOX_ASSERT): | |
template DRAGONBOX_ASSERT*(X: untyped): untyped = | |
assert(X) | |
## ================================================================================================== | |
## | |
## ================================================================================================== | |
proc ReinterpretBits*[Dest; Source](source: Source): Dest {.inline.} = | |
static_assert(sizeof((Dest)) == sizeof((Source)), "size mismatch") | |
var dest: Dest | |
memcpy(addr(dest), addr(source), sizeof((Source))) | |
return dest | |
type | |
Double* {.bycopy.} = object | |
bits*: bits_type ## = p (includes the hidden bit) | |
## static constexpr int32_t MaxExponent = std::numeric_limits<value_type>::max_exponent - 1 - (SignificandSize - 1); | |
## static constexpr int32_t MinExponent = std::numeric_limits<value_type>::min_exponent - 1 - (SignificandSize - 1); | |
## = 2^(p-1) | |
## = 2^(p-1) - 1 | |
## !!!Ignored construct: static_assert ( std :: numeric_limits < double > :: is_iec559 && std :: numeric_limits < double > :: digits == 53 && std :: numeric_limits < double > :: max_exponent == 1024 , IEEE-754 double-precision implementation required ) ; | |
## Error: token expected: ) but got: ::!!! | |
type | |
value_type* = cdouble | |
bits_type* = uint64_t | |
const | |
SignificandSize*: int32_t = digits | |
const | |
ExponentBias*: int32_t = max_exponent - 1 + (SignificandSize - 1) | |
const | |
MaxIeeeExponent*: bits_type = bits_type(2 * max_exponent - 1) | |
const | |
HiddenBit*: bits_type = bits_type(1) shl (SignificandSize - 1) | |
const | |
SignificandMask*: bits_type = HiddenBit - 1 | |
const | |
ExponentMask*: bits_type = MaxIeeeExponent shl (SignificandSize - 1) | |
const | |
SignMask*: bits_type = not (not bits_type(0) shr 1) | |
proc constructDouble*(bits_: bits_type): Double {.constructor.} = | |
discard | |
proc constructDouble*(value: value_type): Double {.constructor.} = | |
discard | |
proc PhysicalSignificand*(this: Double): bits_type {.noSideEffect.} = | |
return bits and SignificandMask | |
proc PhysicalExponent*(this: Double): bits_type {.noSideEffect.} = | |
return (bits and ExponentMask) shr (SignificandSize - 1) | |
proc IsFinite*(this: Double): bool {.noSideEffect.} = | |
return (bits and ExponentMask) != ExponentMask | |
proc IsInf*(this: Double): bool {.noSideEffect.} = | |
return (bits and ExponentMask) == ExponentMask and | |
(bits and SignificandMask) == 0 | |
proc IsNaN*(this: Double): bool {.noSideEffect.} = | |
return (bits and ExponentMask) == ExponentMask and | |
(bits and SignificandMask) != 0 | |
proc IsZero*(this: Double): bool {.noSideEffect.} = | |
return (bits and not SignMask) == 0 | |
proc SignBit*(this: Double): bool {.noSideEffect.} = | |
return (bits and SignMask) != 0 | |
## namespace | |
## ================================================================================================== | |
## | |
## ================================================================================================== | |
## Returns floor(x / 2^n). | |
## | |
## Technically, right-shift of negative integers is implementation defined... | |
## Should easily be optimized into SAR (or equivalent) instruction. | |
proc FloorDivPow2*(x: int32_t; n: int32_t): int32_t {.inline.} = | |
when 0: | |
return if x < 0: not (not x shr n) else: (x shr n) | |
else: | |
return x shr n | |
proc FloorLog2Pow10*(e: int32_t): int32_t {.inline.} = | |
DRAGONBOX_ASSERT(e >= -1233) | |
DRAGONBOX_ASSERT(e <= 1233) | |
return FloorDivPow2(e * 1741647, 19) | |
proc FloorLog10Pow2*(e: int32_t): int32_t {.inline.} = | |
DRAGONBOX_ASSERT(e >= -1500) | |
DRAGONBOX_ASSERT(e <= 1500) | |
return FloorDivPow2(e * 1262611, 22) | |
proc FloorLog10ThreeQuartersPow2*(e: int32_t): int32_t {.inline.} = | |
DRAGONBOX_ASSERT(e >= -1500) | |
DRAGONBOX_ASSERT(e <= 1500) | |
return FloorDivPow2(e * 1262611 - 524031, 22) | |
## ================================================================================================== | |
## | |
## ================================================================================================== | |
type | |
uint64x2* {.bycopy.} = object | |
hi*: uint64_t | |
lo*: uint64_t | |
proc ComputePow10*(k: int32_t): uint64x2 {.inline.} = | |
var kMin: int32_t = -292 | |
var kMax: int32_t = 326 | |
var Pow10: array[kMax - kMin + 1, uint64x2] = [[0xFF77B1FCBEBCDC4F'i64, | |
0x25E8E89C13BB0F7B'i64], [0x9FAACF3DF73609B1'i64, 0x77B191618C54E9AD'i64], [ | |
0xC795830D75038C1D'i64, 0xD59DF5B9EF6A2418'i64], [0xF97AE3D0D2446F25'i64, | |
0x4B0573286B44AD1E'i64], [0x9BECCE62836AC577'i64, 0x4EE367F9430AEC33'i64], [ | |
0xC2E801FB244576D5'i64, 0x229C41F793CDA740'i64], [0xF3A20279ED56D48A'i64, | |
0x6B43527578C11110'i64], [0x9845418C345644D6'i64, 0x830A13896B78AAAA'i64], [ | |
0xBE5691EF416BD60C'i64, 0x23CC986BC656D554'i64], [0xEDEC366B11C6CB8F'i64, | |
0x2CBFBE86B7EC8AA9'i64], [0x94B3A202EB1C3F39'i64, 0x7BF7D71432F3D6AA'i64], [ | |
0xB9E08A83A5E34F07'i64, 0xDAF5CCD93FB0CC54'i64], [0xE858AD248F5C22C9'i64, | |
0xD1B3400F8F9CFF69'i64], [0x91376C36D99995BE'i64, 0x23100809B9C21FA2'i64], [ | |
0xB58547448FFFFB2D'i64, 0xABD40A0C2832A78B'i64], [0xE2E69915B3FFF9F9'i64, | |
0x16C90C8F323F516D'i64], [0x8DD01FAD907FFC3B'i64, 0xAE3DA7D97F6792E4'i64], [ | |
0xB1442798F49FFB4A'i64, 0x99CD11CFDF41779D'i64], [0xDD95317F31C7FA1D'i64, | |
0x40405643D711D584'i64], [0x8A7D3EEF7F1CFC52'i64, 0x482835EA666B2573'i64], [ | |
0xAD1C8EAB5EE43B66'i64, 0xDA3243650005EED0'i64], [0xD863B256369D4A40'i64, | |
0x90BED43E40076A83'i64], [0x873E4F75E2224E68'i64, 0x5A7744A6E804A292'i64], [ | |
0xA90DE3535AAAE202'i64, 0x711515D0A205CB37'i64], [0xD3515C2831559A83'i64, | |
0x0D5A5B44CA873E04'i64], [0x8412D9991ED58091'i64, 0xE858790AFE9486C3'i64], [ | |
0xA5178FFF668AE0B6'i64, 0x626E974DBE39A873'i64], [0xCE5D73FF402D98E3'i64, | |
0xFB0A3D212DC81290'i64], [0x80FA687F881C7F8E'i64, 0x7CE66634BC9D0B9A'i64], [ | |
0xA139029F6A239F72'i64, 0x1C1FFFC1EBC44E81'i64], [0xC987434744AC874E'i64, | |
0xA327FFB266B56221'i64], [0xFBE9141915D7A922'i64, 0x4BF1FF9F0062BAA9'i64], [ | |
0x9D71AC8FADA6C9B5'i64, 0x6F773FC3603DB4AA'i64], [0xC4CE17B399107C22'i64, | |
0xCB550FB4384D21D4'i64], [0xF6019DA07F549B2B'i64, 0x7E2A53A146606A49'i64], [ | |
0x99C102844F94E0FB'i64, 0x2EDA7444CBFC426E'i64], [0xC0314325637A1939'i64, | |
0xFA911155FEFB5309'i64], [0xF03D93EEBC589F88'i64, 0x793555AB7EBA27CB'i64], [ | |
0x96267C7535B763B5'i64, 0x4BC1558B2F3458DF'i64], [0xBBB01B9283253CA2'i64, | |
0x9EB1AAEDFB016F17'i64], [0xEA9C227723EE8BCB'i64, 0x465E15A979C1CADD'i64], [ | |
0x92A1958A7675175F'i64, 0x0BFACD89EC191ECA'i64], [0xB749FAED14125D36'i64, | |
0xCEF980EC671F667C'i64], [0xE51C79A85916F484'i64, 0x82B7E12780E7401B'i64], [ | |
0x8F31CC0937AE58D2'i64, 0xD1B2ECB8B0908811'i64], [0xB2FE3F0B8599EF07'i64, | |
0x861FA7E6DCB4AA16'i64], [0xDFBDCECE67006AC9'i64, 0x67A791E093E1D49B'i64], [ | |
0x8BD6A141006042BD'i64, 0xE0C8BB2C5C6D24E1'i64], [0xAECC49914078536D'i64, | |
0x58FAE9F773886E19'i64], [0xDA7F5BF590966848'i64, 0xAF39A475506A899F'i64], [ | |
0x888F99797A5E012D'i64, 0x6D8406C952429604'i64], [0xAAB37FD7D8F58178'i64, | |
0xC8E5087BA6D33B84'i64], [0xD5605FCDCF32E1D6'i64, 0xFB1E4A9A90880A65'i64], [ | |
0x855C3BE0A17FCD26'i64, 0x5CF2EEA09A550680'i64], [0xA6B34AD8C9DFC06F'i64, | |
0xF42FAA48C0EA481F'i64], [0xD0601D8EFC57B08B'i64, 0xF13B94DAF124DA27'i64], [ | |
0x823C12795DB6CE57'i64, 0x76C53D08D6B70859'i64], [0xA2CB1717B52481ED'i64, | |
0x54768C4B0C64CA6F'i64], [0xCB7DDCDDA26DA268'i64, 0xA9942F5DCF7DFD0A'i64], [ | |
0xFE5D54150B090B02'i64, 0xD3F93B35435D7C4D'i64], [0x9EFA548D26E5A6E1'i64, | |
0xC47BC5014A1A6DB0'i64], [0xC6B8E9B0709F109A'i64, 0x359AB6419CA1091C'i64], [ | |
0xF867241C8CC6D4C0'i64, 0xC30163D203C94B63'i64], [0x9B407691D7FC44F8'i64, | |
0x79E0DE63425DCF1E'i64], [0xC21094364DFB5636'i64, 0x985915FC12F542E5'i64], [ | |
0xF294B943E17A2BC4'i64, 0x3E6F5B7B17B2939E'i64], [0x979CF3CA6CEC5B5A'i64, | |
0xA705992CEECF9C43'i64], [0xBD8430BD08277231'i64, 0x50C6FF782A838354'i64], [ | |
0xECE53CEC4A314EBD'i64, 0xA4F8BF5635246429'i64], [0x940F4613AE5ED136'i64, | |
0x871B7795E136BE9A'i64], [0xB913179899F68584'i64, 0x28E2557B59846E40'i64], [ | |
0xE757DD7EC07426E5'i64, 0x331AEADA2FE589D0'i64], [0x9096EA6F3848984F'i64, | |
0x3FF0D2C85DEF7622'i64], [0xB4BCA50B065ABE63'i64, 0x0FED077A756B53AA'i64], [ | |
0xE1EBCE4DC7F16DFB'i64, 0xD3E8495912C62895'i64], [0x8D3360F09CF6E4BD'i64, | |
0x64712DD7ABBBD95D'i64], [0xB080392CC4349DEC'i64, 0xBD8D794D96AACFB4'i64], [ | |
0xDCA04777F541C567'i64, 0xECF0D7A0FC5583A1'i64], [0x89E42CAAF9491B60'i64, | |
0xF41686C49DB57245'i64], [0xAC5D37D5B79B6239'i64, 0x311C2875C522CED6'i64], [ | |
0xD77485CB25823AC7'i64, 0x7D633293366B828C'i64], [0x86A8D39EF77164BC'i64, | |
0xAE5DFF9C02033198'i64], [0xA8530886B54DBDEB'i64, 0xD9F57F830283FDFD'i64], [ | |
0xD267CAA862A12D66'i64, 0xD072DF63C324FD7C'i64], [0x8380DEA93DA4BC60'i64, | |
0x4247CB9E59F71E6E'i64], [0xA46116538D0DEB78'i64, 0x52D9BE85F074E609'i64], [ | |
0xCD795BE870516656'i64, 0x67902E276C921F8C'i64], [0x806BD9714632DFF6'i64, | |
0x00BA1CD8A3DB53B7'i64], [0xA086CFCD97BF97F3'i64, 0x80E8A40ECCD228A5'i64], [ | |
0xC8A883C0FDAF7DF0'i64, 0x6122CD128006B2CE'i64], [0xFAD2A4B13D1B5D6C'i64, | |
0x796B805720085F82'i64], [0x9CC3A6EEC6311A63'i64, 0xCBE3303674053BB1'i64], [ | |
0xC3F490AA77BD60FC'i64, 0xBEDBFC4411068A9D'i64], [0xF4F1B4D515ACB93B'i64, | |
0xEE92FB5515482D45'i64], [0x991711052D8BF3C5'i64, 0x751BDD152D4D1C4B'i64], [ | |
0xBF5CD54678EEF0B6'i64, 0xD262D45A78A0635E'i64], [0xEF340A98172AACE4'i64, | |
0x86FB897116C87C35'i64], [0x9580869F0E7AAC0E'i64, 0xD45D35E6AE3D4DA1'i64], [ | |
0xBAE0A846D2195712'i64, 0x8974836059CCA10A'i64], [0xE998D258869FACD7'i64, | |
0x2BD1A438703FC94C'i64], [0x91FF83775423CC06'i64, 0x7B6306A34627DDD0'i64], [ | |
0xB67F6455292CBF08'i64, 0x1A3BC84C17B1D543'i64], [0xE41F3D6A7377EECA'i64, | |
0x20CABA5F1D9E4A94'i64], [0x8E938662882AF53E'i64, 0x547EB47B7282EE9D'i64], [ | |
0xB23867FB2A35B28D'i64, 0xE99E619A4F23AA44'i64], [0xDEC681F9F4C31F31'i64, | |
0x6405FA00E2EC94D5'i64], [0x8B3C113C38F9F37E'i64, 0xDE83BC408DD3DD05'i64], [ | |
0xAE0B158B4738705E'i64, 0x9624AB50B148D446'i64], [0xD98DDAEE19068C76'i64, | |
0x3BADD624DD9B0958'i64], [0x87F8A8D4CFA417C9'i64, 0xE54CA5D70A80E5D7'i64], [ | |
0xA9F6D30A038D1DBC'i64, 0x5E9FCF4CCD211F4D'i64], [0xD47487CC8470652B'i64, | |
0x7647C32000696720'i64], [0x84C8D4DFD2C63F3B'i64, 0x29ECD9F40041E074'i64], [ | |
0xA5FB0A17C777CF09'i64, 0xF468107100525891'i64], [0xCF79CC9DB955C2CC'i64, | |
0x7182148D4066EEB5'i64], [0x81AC1FE293D599BF'i64, 0xC6F14CD848405531'i64], [ | |
0xA21727DB38CB002F'i64, 0xB8ADA00E5A506A7D'i64], [0xCA9CF1D206FDC03B'i64, | |
0xA6D90811F0E4851D'i64], [0xFD442E4688BD304A'i64, 0x908F4A166D1DA664'i64], [ | |
0x9E4A9CEC15763E2E'i64, 0x9A598E4E043287FF'i64], [0xC5DD44271AD3CDBA'i64, | |
0x40EFF1E1853F29FE'i64], [0xF7549530E188C128'i64, 0xD12BEE59E68EF47D'i64], [ | |
0x9A94DD3E8CF578B9'i64, 0x82BB74F8301958CF'i64], [0xC13A148E3032D6E7'i64, | |
0xE36A52363C1FAF02'i64], [0xF18899B1BC3F8CA1'i64, 0xDC44E6C3CB279AC2'i64], [ | |
0x96F5600F15A7B7E5'i64, 0x29AB103A5EF8C0BA'i64], [0xBCB2B812DB11A5DE'i64, | |
0x7415D448F6B6F0E8'i64], [0xEBDF661791D60F56'i64, 0x111B495B3464AD22'i64], [ | |
0x936B9FCEBB25C995'i64, 0xCAB10DD900BEEC35'i64], [0xB84687C269EF3BFB'i64, | |
0x3D5D514F40EEA743'i64], [0xE65829B3046B0AFA'i64, 0x0CB4A5A3112A5113'i64], [ | |
0x8FF71A0FE2C2E6DC'i64, 0x47F0E785EABA72AC'i64], [0xB3F4E093DB73A093'i64, | |
0x59ED216765690F57'i64], [0xE0F218B8D25088B8'i64, 0x306869C13EC3532D'i64], [ | |
0x8C974F7383725573'i64, 0x1E414218C73A13FC'i64], [0xAFBD2350644EEACF'i64, | |
0xE5D1929EF90898FB'i64], [0xDBAC6C247D62A583'i64, 0xDF45F746B74ABF3A'i64], [ | |
0x894BC396CE5DA772'i64, 0x6B8BBA8C328EB784'i64], [0xAB9EB47C81F5114F'i64, | |
0x066EA92F3F326565'i64], [0xD686619BA27255A2'i64, 0xC80A537B0EFEFEBE'i64], [ | |
0x8613FD0145877585'i64, 0xBD06742CE95F5F37'i64], [0xA798FC4196E952E7'i64, | |
0x2C48113823B73705'i64], [0xD17F3B51FCA3A7A0'i64, 0xF75A15862CA504C6'i64], [ | |
0x82EF85133DE648C4'i64, 0x9A984D73DBE722FC'i64], [0xA3AB66580D5FDAF5'i64, | |
0xC13E60D0D2E0EBBB'i64], [0xCC963FEE10B7D1B3'i64, 0x318DF905079926A9'i64], [ | |
0xFFBBCFE994E5C61F'i64, 0xFDF17746497F7053'i64], [0x9FD561F1FD0F9BD3'i64, | |
0xFEB6EA8BEDEFA634'i64], [0xC7CABA6E7C5382C8'i64, 0xFE64A52EE96B8FC1'i64], [ | |
0xF9BD690A1B68637B'i64, 0x3DFDCE7AA3C673B1'i64], [0x9C1661A651213E2D'i64, | |
0x06BEA10CA65C084F'i64], [0xC31BFA0FE5698DB8'i64, 0x486E494FCFF30A63'i64], [ | |
0xF3E2F893DEC3F126'i64, 0x5A89DBA3C3EFCCFB'i64], [0x986DDB5C6B3A76B7'i64, | |
0xF89629465A75E01D'i64], [0xBE89523386091465'i64, 0xF6BBB397F1135824'i64], [ | |
0xEE2BA6C0678B597F'i64, 0x746AA07DED582E2D'i64], [0x94DB483840B717EF'i64, | |
0xA8C2A44EB4571CDD'i64], [0xBA121A4650E4DDEB'i64, 0x92F34D62616CE414'i64], [ | |
0xE896A0D7E51E1566'i64, 0x77B020BAF9C81D18'i64], [0x915E2486EF32CD60'i64, | |
0x0ACE1474DC1D122F'i64], [0xB5B5ADA8AAFF80B8'i64, 0x0D819992132456BB'i64], [ | |
0xE3231912D5BF60E6'i64, 0x10E1FFF697ED6C6A'i64], [0x8DF5EFABC5979C8F'i64, | |
0xCA8D3FFA1EF463C2'i64], [0xB1736B96B6FD83B3'i64, 0xBD308FF8A6B17CB3'i64], [ | |
0xDDD0467C64BCE4A0'i64, 0xAC7CB3F6D05DDBDF'i64], [0x8AA22C0DBEF60EE4'i64, | |
0x6BCDF07A423AA96C'i64], [0xAD4AB7112EB3929D'i64, 0x86C16C98D2C953C7'i64], [ | |
0xD89D64D57A607744'i64, 0xE871C7BF077BA8B8'i64], [0x87625F056C7C4A8B'i64, | |
0x11471CD764AD4973'i64], [0xA93AF6C6C79B5D2D'i64, 0xD598E40D3DD89BD0'i64], [ | |
0xD389B47879823479'i64, 0x4AFF1D108D4EC2C4'i64], [0x843610CB4BF160CB'i64, | |
0xCEDF722A585139BB'i64], [0xA54394FE1EEDB8FE'i64, 0xC2974EB4EE658829'i64], [ | |
0xCE947A3DA6A9273E'i64, 0x733D226229FEEA33'i64], [0x811CCC668829B887'i64, | |
0x0806357D5A3F5260'i64], [0xA163FF802A3426A8'i64, 0xCA07C2DCB0CF26F8'i64], [ | |
0xC9BCFF6034C13052'i64, 0xFC89B393DD02F0B6'i64], [0xFC2C3F3841F17C67'i64, | |
0xBBAC2078D443ACE3'i64], [0x9D9BA7832936EDC0'i64, 0xD54B944B84AA4C0E'i64], [ | |
0xC5029163F384A931'i64, 0x0A9E795E65D4DF12'i64], [0xF64335BCF065D37D'i64, | |
0x4D4617B5FF4A16D6'i64], [0x99EA0196163FA42E'i64, 0x504BCED1BF8E4E46'i64], [ | |
0xC06481FB9BCF8D39'i64, 0xE45EC2862F71E1D7'i64], [0xF07DA27A82C37088'i64, | |
0x5D767327BB4E5A4D'i64], [0x964E858C91BA2655'i64, 0x3A6A07F8D510F870'i64], [ | |
0xBBE226EFB628AFEA'i64, 0x890489F70A55368C'i64], [0xEADAB0ABA3B2DBE5'i64, | |
0x2B45AC74CCEA842F'i64], [0x92C8AE6B464FC96F'i64, 0x3B0B8BC90012929E'i64], [ | |
0xB77ADA0617E3BBCB'i64, 0x09CE6EBB40173745'i64], [0xE55990879DDCAABD'i64, | |
0xCC420A6A101D0516'i64], [0x8F57FA54C2A9EAB6'i64, 0x9FA946824A12232E'i64], [ | |
0xB32DF8E9F3546564'i64, 0x47939822DC96ABFA'i64], [0xDFF9772470297EBD'i64, | |
0x59787E2B93BC56F8'i64], [0x8BFBEA76C619EF36'i64, 0x57EB4EDB3C55B65B'i64], [ | |
0xAEFAE51477A06B03'i64, 0xEDE622920B6B23F2'i64], [0xDAB99E59958885C4'i64, | |
0xE95FAB368E45ECEE'i64], [0x88B402F7FD75539B'i64, 0x11DBCB0218EBB415'i64], [ | |
0xAAE103B5FCD2A881'i64, 0xD652BDC29F26A11A'i64], [0xD59944A37C0752A2'i64, | |
0x4BE76D3346F04960'i64], [0x857FCAE62D8493A5'i64, 0x6F70A4400C562DDC'i64], [ | |
0xA6DFBD9FB8E5B88E'i64, 0xCB4CCD500F6BB953'i64], [0xD097AD07A71F26B2'i64, | |
0x7E2000A41346A7A8'i64], [0x825ECC24C873782F'i64, 0x8ED400668C0C28C9'i64], [ | |
0xA2F67F2DFA90563B'i64, 0x728900802F0F32FB'i64], [0xCBB41EF979346BCA'i64, | |
0x4F2B40A03AD2FFBA'i64], [0xFEA126B7D78186BC'i64, 0xE2F610C84987BFA9'i64], [ | |
0x9F24B832E6B0F436'i64, 0x0DD9CA7D2DF4D7CA'i64], [0xC6EDE63FA05D3143'i64, | |
0x91503D1C79720DBC'i64], [0xF8A95FCF88747D94'i64, 0x75A44C6397CE912B'i64], [ | |
0x9B69DBE1B548CE7C'i64, 0xC986AFBE3EE11ABB'i64], [0xC24452DA229B021B'i64, | |
0xFBE85BADCE996169'i64], [0xF2D56790AB41C2A2'i64, 0xFAE27299423FB9C4'i64], [ | |
0x97C560BA6B0919A5'i64, 0xDCCD879FC967D41B'i64], [0xBDB6B8E905CB600F'i64, | |
0x5400E987BBC1C921'i64], [0xED246723473E3813'i64, 0x290123E9AAB23B69'i64], [ | |
0x9436C0760C86E30B'i64, 0xF9A0B6720AAF6522'i64], [0xB94470938FA89BCE'i64, | |
0xF808E40E8D5B3E6A'i64], [0xE7958CB87392C2C2'i64, 0xB60B1D1230B20E05'i64], [ | |
0x90BD77F3483BB9B9'i64, 0xB1C6F22B5E6F48C3'i64], [0xB4ECD5F01A4AA828'i64, | |
0x1E38AEB6360B1AF4'i64], [0xE2280B6C20DD5232'i64, 0x25C6DA63C38DE1B1'i64], [ | |
0x8D590723948A535F'i64, 0x579C487E5A38AD0F'i64], [0xB0AF48EC79ACE837'i64, | |
0x2D835A9DF0C6D852'i64], [0xDCDB1B2798182244'i64, 0xF8E431456CF88E66'i64], [ | |
0x8A08F0F8BF0F156B'i64, 0x1B8E9ECB641B5900'i64], [0xAC8B2D36EED2DAC5'i64, | |
0xE272467E3D222F40'i64], [0xD7ADF884AA879177'i64, 0x5B0ED81DCC6ABB10'i64], [ | |
0x86CCBB52EA94BAEA'i64, 0x98E947129FC2B4EA'i64], [0xA87FEA27A539E9A5'i64, | |
0x3F2398D747B36225'i64], [0xD29FE4B18E88640E'i64, 0x8EEC7F0D19A03AAE'i64], [ | |
0x83A3EEEEF9153E89'i64, 0x1953CF68300424AD'i64], [0xA48CEAAAB75A8E2B'i64, | |
0x5FA8C3423C052DD8'i64], [0xCDB02555653131B6'i64, 0x3792F412CB06794E'i64], [ | |
0x808E17555F3EBF11'i64, 0xE2BBD88BBEE40BD1'i64], [0xA0B19D2AB70E6ED6'i64, | |
0x5B6ACEAEAE9D0EC5'i64], [0xC8DE047564D20A8B'i64, 0xF245825A5A445276'i64], [ | |
0xFB158592BE068D2E'i64, 0xEED6E2F0F0D56713'i64], [0x9CED737BB6C4183D'i64, | |
0x55464DD69685606C'i64], [0xC428D05AA4751E4C'i64, 0xAA97E14C3C26B887'i64], [ | |
0xF53304714D9265DF'i64, 0xD53DD99F4B3066A9'i64], [0x993FE2C6D07B7FAB'i64, | |
0xE546A8038EFE402A'i64], [0xBF8FDB78849A5F96'i64, 0xDE98520472BDD034'i64], [ | |
0xEF73D256A5C0F77C'i64, 0x963E66858F6D4441'i64], [0x95A8637627989AAD'i64, | |
0xDDE7001379A44AA9'i64], [0xBB127C53B17EC159'i64, 0x5560C018580D5D53'i64], [ | |
0xE9D71B689DDE71AF'i64, 0xAAB8F01E6E10B4A7'i64], [0x9226712162AB070D'i64, | |
0xCAB3961304CA70E9'i64], [0xB6B00D69BB55C8D1'i64, 0x3D607B97C5FD0D23'i64], [ | |
0xE45C10C42A2B3B05'i64, 0x8CB89A7DB77C506B'i64], [0x8EB98A7A9A5B04E3'i64, | |
0x77F3608E92ADB243'i64], [0xB267ED1940F1C61C'i64, 0x55F038B237591ED4'i64], [ | |
0xDF01E85F912E37A3'i64, 0x6B6C46DEC52F6689'i64], [0x8B61313BBABCE2C6'i64, | |
0x2323AC4B3B3DA016'i64], [0xAE397D8AA96C1B77'i64, 0xABEC975E0A0D081B'i64], [ | |
0xD9C7DCED53C72255'i64, 0x96E7BD358C904A22'i64], [0x881CEA14545C7575'i64, | |
0x7E50D64177DA2E55'i64], [0xAA242499697392D2'i64, 0xDDE50BD1D5D0B9EA'i64], [ | |
0xD4AD2DBFC3D07787'i64, 0x955E4EC64B44E865'i64], [0x84EC3C97DA624AB4'i64, | |
0xBD5AF13BEF0B113F'i64], [0xA6274BBDD0FADD61'i64, 0xECB1AD8AEACDD58F'i64], [ | |
0xCFB11EAD453994BA'i64, 0x67DE18EDA5814AF3'i64], [0x81CEB32C4B43FCF4'i64, | |
0x80EACF948770CED8'i64], [0xA2425FF75E14FC31'i64, 0xA1258379A94D028E'i64], [ | |
0xCAD2F7F5359A3B3E'i64, 0x096EE45813A04331'i64], [0xFD87B5F28300CA0D'i64, | |
0x8BCA9D6E188853FD'i64], [0x9E74D1B791E07E48'i64, 0x775EA264CF55347E'i64], [ | |
0xC612062576589DDA'i64, 0x95364AFE032A819E'i64], [0xF79687AED3EEC551'i64, | |
0x3A83DDBD83F52205'i64], [0x9ABE14CD44753B52'i64, 0xC4926A9672793543'i64], [ | |
0xC16D9A0095928A27'i64, 0x75B7053C0F178294'i64], [0xF1C90080BAF72CB1'i64, | |
0x5324C68B12DD6339'i64], [0x971DA05074DA7BEE'i64, 0xD3F6FC16EBCA5E04'i64], [ | |
0xBCE5086492111AEA'i64, 0x88F4BB1CA6BCF585'i64], [0xEC1E4A7DB69561A5'i64, | |
0x2B31E9E3D06C32E6'i64], [0x9392EE8E921D5D07'i64, 0x3AFF322E62439FD0'i64], [ | |
0xB877AA3236A4B449'i64, 0x09BEFEB9FAD487C3'i64], [0xE69594BEC44DE15B'i64, | |
0x4C2EBE687989A9B4'i64], [0x901D7CF73AB0ACD9'i64, 0x0F9D37014BF60A11'i64], [ | |
0xB424DC35095CD80F'i64, 0x538484C19EF38C95'i64], [0xE12E13424BB40E13'i64, | |
0x2865A5F206B06FBA'i64], [0x8CBCCC096F5088CB'i64, 0xF93F87B7442E45D4'i64], [ | |
0xAFEBFF0BCB24AAFE'i64, 0xF78F69A51539D749'i64], [0xDBE6FECEBDEDD5BE'i64, | |
0xB573440E5A884D1C'i64], [0x89705F4136B4A597'i64, 0x31680A88F8953031'i64], [ | |
0xABCC77118461CEFC'i64, 0xFDC20D2B36BA7C3E'i64], [0xD6BF94D5E57A42BC'i64, | |
0x3D32907604691B4D'i64], [0x8637BD05AF6C69B5'i64, 0xA63F9A49C2C1B110'i64], [ | |
0xA7C5AC471B478423'i64, 0x0FCF80DC33721D54'i64], [0xD1B71758E219652B'i64, | |
0xD3C36113404EA4A9'i64], [0x83126E978D4FDF3B'i64, 0x645A1CAC083126EA'i64], [ | |
0xA3D70A3D70A3D70A'i64, 0x3D70A3D70A3D70A4'i64], [0xCCCCCCCCCCCCCCCC'i64, | |
0xCCCCCCCCCCCCCCCD'i64], [0x8000000000000000'i64, 0x0000000000000000'i64], [ | |
0xA000000000000000'i64, 0x0000000000000000'i64], [0xC800000000000000'i64, | |
0x0000000000000000'i64], [0xFA00000000000000'i64, 0x0000000000000000'i64], [ | |
0x9C40000000000000'i64, 0x0000000000000000'i64], [0xC350000000000000'i64, | |
0x0000000000000000'i64], [0xF424000000000000'i64, 0x0000000000000000'i64], [ | |
0x9896800000000000'i64, 0x0000000000000000'i64], [0xBEBC200000000000'i64, | |
0x0000000000000000'i64], [0xEE6B280000000000'i64, 0x0000000000000000'i64], [ | |
0x9502F90000000000'i64, 0x0000000000000000'i64], [0xBA43B74000000000'i64, | |
0x0000000000000000'i64], [0xE8D4A51000000000'i64, 0x0000000000000000'i64], [ | |
0x9184E72A00000000'i64, 0x0000000000000000'i64], [0xB5E620F480000000'i64, | |
0x0000000000000000'i64], [0xE35FA931A0000000'i64, 0x0000000000000000'i64], [ | |
0x8E1BC9BF04000000'i64, 0x0000000000000000'i64], [0xB1A2BC2EC5000000'i64, | |
0x0000000000000000'i64], [0xDE0B6B3A76400000'i64, 0x0000000000000000'i64], [ | |
0x8AC7230489E80000'i64, 0x0000000000000000'i64], [0xAD78EBC5AC620000'i64, | |
0x0000000000000000'i64], [0xD8D726B7177A8000'i64, 0x0000000000000000'i64], [ | |
0x878678326EAC9000'i64, 0x0000000000000000'i64], [0xA968163F0A57B400'i64, | |
0x0000000000000000'i64], [0xD3C21BCECCEDA100'i64, 0x0000000000000000'i64], [ | |
0x84595161401484A0'i64, 0x0000000000000000'i64], [0xA56FA5B99019A5C8'i64, | |
0x0000000000000000'i64], [0xCECB8F27F4200F3A'i64, 0x0000000000000000'i64], [ | |
0x813F3978F8940984'i64, 0x4000000000000000'i64], [0xA18F07D736B90BE5'i64, | |
0x5000000000000000'i64], [0xC9F2C9CD04674EDE'i64, 0xA400000000000000'i64], [ | |
0xFC6F7C4045812296'i64, 0x4D00000000000000'i64], [0x9DC5ADA82B70B59D'i64, | |
0xF020000000000000'i64], [0xC5371912364CE305'i64, 0x6C28000000000000'i64], [ | |
0xF684DF56C3E01BC6'i64, 0xC732000000000000'i64], [0x9A130B963A6C115C'i64, | |
0x3C7F400000000000'i64], [0xC097CE7BC90715B3'i64, 0x4B9F100000000000'i64], [ | |
0xF0BDC21ABB48DB20'i64, 0x1E86D40000000000'i64], [0x96769950B50D88F4'i64, | |
0x1314448000000000'i64], [0xBC143FA4E250EB31'i64, 0x17D955A000000000'i64], [ | |
0xEB194F8E1AE525FD'i64, 0x5DCFAB0800000000'i64], [0x92EFD1B8D0CF37BE'i64, | |
0x5AA1CAE500000000'i64], [0xB7ABC627050305AD'i64, 0xF14A3D9E40000000'i64], [ | |
0xE596B7B0C643C719'i64, 0x6D9CCD05D0000000'i64], [0x8F7E32CE7BEA5C6F'i64, | |
0xE4820023A2000000'i64], [0xB35DBF821AE4F38B'i64, 0xDDA2802C8A800000'i64], [ | |
0xE0352F62A19E306E'i64, 0xD50B2037AD200000'i64], [0x8C213D9DA502DE45'i64, | |
0x4526F422CC340000'i64], [0xAF298D050E4395D6'i64, 0x9670B12B7F410000'i64], [ | |
0xDAF3F04651D47B4C'i64, 0x3C0CDD765F114000'i64], [0x88D8762BF324CD0F'i64, | |
0xA5880A69FB6AC800'i64], [0xAB0E93B6EFEE0053'i64, 0x8EEA0D047A457A00'i64], [ | |
0xD5D238A4ABE98068'i64, 0x72A4904598D6D880'i64], [0x85A36366EB71F041'i64, | |
0x47A6DA2B7F864750'i64], [0xA70C3C40A64E6C51'i64, 0x999090B65F67D924'i64], [ | |
0xD0CF4B50CFE20765'i64, 0xFFF4B4E3F741CF6D'i64], [0x82818F1281ED449F'i64, | |
0xBFF8F10E7A8921A4'i64], [0xA321F2D7226895C7'i64, 0xAFF72D52192B6A0D'i64], [ | |
0xCBEA6F8CEB02BB39'i64, 0x9BF4F8A69F764490'i64], [0xFEE50B7025C36A08'i64, | |
0x02F236D04753D5B4'i64], [0x9F4F2726179A2245'i64, 0x01D762422C946590'i64], [ | |
0xC722F0EF9D80AAD6'i64, 0x424D3AD2B7B97EF5'i64], [0xF8EBAD2B84E0D58B'i64, | |
0xD2E0898765A7DEB2'i64], [0x9B934C3B330C8577'i64, 0x63CC55F49F88EB2F'i64], [ | |
0xC2781F49FFCFA6D5'i64, 0x3CBF6B71C76B25FB'i64], [0xF316271C7FC3908A'i64, | |
0x8BEF464E3945EF7A'i64], [0x97EDD871CFDA3A56'i64, 0x97758BF0E3CBB5AC'i64], [ | |
0xBDE94E8E43D0C8EC'i64, 0x3D52EEED1CBEA317'i64], [0xED63A231D4C4FB27'i64, | |
0x4CA7AAA863EE4BDD'i64], [0x945E455F24FB1CF8'i64, 0x8FE8CAA93E74EF6A'i64], [ | |
0xB975D6B6EE39E436'i64, 0xB3E2FD538E122B44'i64], [0xE7D34C64A9C85D44'i64, | |
0x60DBBCA87196B616'i64], [0x90E40FBEEA1D3A4A'i64, 0xBC8955E946FE31CD'i64], [ | |
0xB51D13AEA4A488DD'i64, 0x6BABAB6398BDBE41'i64], [0xE264589A4DCDAB14'i64, | |
0xC696963C7EED2DD1'i64], [0x8D7EB76070A08AEC'i64, 0xFC1E1DE5CF543CA2'i64], [ | |
0xB0DE65388CC8ADA8'i64, 0x3B25A55F43294BCB'i64], [0xDD15FE86AFFAD912'i64, | |
0x49EF0EB713F39EBE'i64], [0x8A2DBF142DFCC7AB'i64, 0x6E3569326C784337'i64], [ | |
0xACB92ED9397BF996'i64, 0x49C2C37F07965404'i64], [0xD7E77A8F87DAF7FB'i64, | |
0xDC33745EC97BE906'i64], [0x86F0AC99B4E8DAFD'i64, 0x69A028BB3DED71A3'i64], [ | |
0xA8ACD7C0222311BC'i64, 0xC40832EA0D68CE0C'i64], [0xD2D80DB02AABD62B'i64, | |
0xF50A3FA490C30190'i64], [0x83C7088E1AAB65DB'i64, 0x792667C6DA79E0FA'i64], [ | |
0xA4B8CAB1A1563F52'i64, 0x577001B891185938'i64], [0xCDE6FD5E09ABCF26'i64, | |
0xED4C0226B55E6F86'i64], [0x80B05E5AC60B6178'i64, 0x544F8158315B05B4'i64], [ | |
0xA0DC75F1778E39D6'i64, 0x696361AE3DB1C721'i64], [0xC913936DD571C84C'i64, | |
0x03BC3A19CD1E38E9'i64], [0xFB5878494ACE3A5F'i64, 0x04AB48A04065C723'i64], [ | |
0x9D174B2DCEC0E47B'i64, 0x62EB0D64283F9C76'i64], [0xC45D1DF942711D9A'i64, | |
0x3BA5D0BD324F8394'i64], [0xF5746577930D6500'i64, 0xCA8F44EC7EE36479'i64], [ | |
0x9968BF6ABBE85F20'i64, 0x7E998B13CF4E1ECB'i64], [0xBFC2EF456AE276E8'i64, | |
0x9E3FEDD8C321A67E'i64], [0xEFB3AB16C59B14A2'i64, 0xC5CFE94EF3EA101E'i64], [ | |
0x95D04AEE3B80ECE5'i64, 0xBBA1F1D158724A12'i64], [0xBB445DA9CA61281F'i64, | |
0x2A8A6E45AE8EDC97'i64], [0xEA1575143CF97226'i64, 0xF52D09D71A3293BD'i64], [ | |
0x924D692CA61BE758'i64, 0x593C2626705F9C56'i64], [0xB6E0C377CFA2E12E'i64, | |
0x6F8B2FB00C77836C'i64], [0xE498F455C38B997A'i64, 0x0B6DFB9C0F956447'i64], [ | |
0x8EDF98B59A373FEC'i64, 0x4724BD4189BD5EAC'i64], [0xB2977EE300C50FE7'i64, | |
0x58EDEC91EC2CB657'i64], [0xDF3D5E9BC0F653E1'i64, 0x2F2967B66737E3ED'i64], [ | |
0x8B865B215899F46C'i64, 0xBD79E0D20082EE74'i64], [0xAE67F1E9AEC07187'i64, | |
0xECD8590680A3AA11'i64], [0xDA01EE641A708DE9'i64, 0xE80E6F4820CC9495'i64], [ | |
0x884134FE908658B2'i64, 0x3109058D147FDCDD'i64], [0xAA51823E34A7EEDE'i64, | |
0xBD4B46F0599FD415'i64], [0xD4E5E2CDC1D1EA96'i64, 0x6C9E18AC7007C91A'i64], [ | |
0x850FADC09923329E'i64, 0x03E2CF6BC604DDB0'i64], [0xA6539930BF6BFF45'i64, | |
0x84DB8346B786151C'i64], [0xCFE87F7CEF46FF16'i64, 0xE612641865679A63'i64], [ | |
0x81F14FAE158C5F6E'i64, 0x4FCB7E8F3F60C07E'i64], [0xA26DA3999AEF7749'i64, | |
0xE3BE5E330F38F09D'i64], [0xCB090C8001AB551C'i64, 0x5CADF5BFD3072CC5'i64], [ | |
0xFDCB4FA002162A63'i64, 0x73D9732FC7C8F7F6'i64], [0x9E9F11C4014DDA7E'i64, | |
0x2867E7FDDCDD9AFA'i64], [0xC646D63501A1511D'i64, 0xB281E1FD541501B8'i64], [ | |
0xF7D88BC24209A565'i64, 0x1F225A7CA91A4226'i64], [0x9AE757596946075F'i64, | |
0x3375788DE9B06958'i64], [0xC1A12D2FC3978937'i64, 0x0052D6B1641C83AE'i64], [ | |
0xF209787BB47D6B84'i64, 0xC0678C5DBD23A49A'i64], [0x9745EB4D50CE6332'i64, | |
0xF840B7BA963646E0'i64], [0xBD176620A501FBFF'i64, 0xB650E5A93BC3D898'i64], [ | |
0xEC5D3FA8CE427AFF'i64, 0xA3E51F138AB4CEBE'i64], [0x93BA47C980E98CDF'i64, | |
0xC66F336C36B10137'i64], [0xB8A8D9BBE123F017'i64, 0xB80B0047445D4184'i64], [ | |
0xE6D3102AD96CEC1D'i64, 0xA60DC059157491E5'i64], [0x9043EA1AC7E41392'i64, | |
0x87C89837AD68DB2F'i64], [0xB454E4A179DD1877'i64, 0x29BABE4598C311FB'i64], [ | |
0xE16A1DC9D8545E94'i64, 0xF4296DD6FEF3D67A'i64], [0x8CE2529E2734BB1D'i64, | |
0x1899E4A65F58660C'i64], [0xB01AE745B101E9E4'i64, 0x5EC05DCFF72E7F8F'i64], [ | |
0xDC21A1171D42645D'i64, 0x76707543F4FA1F73'i64], [0x899504AE72497EBA'i64, | |
0x6A06494A791C53A8'i64], [0xABFA45DA0EDBDE69'i64, 0x0487DB9D17636892'i64], [ | |
0xD6F8D7509292D603'i64, 0x45A9D2845D3C42B6'i64], [0x865B86925B9BC5C2'i64, | |
0x0B8A2392BA45A9B2'i64], [0xA7F26836F282B732'i64, 0x8E6CAC7768D7141E'i64], [ | |
0xD1EF0244AF2364FF'i64, 0x3207D795430CD926'i64], [0x8335616AED761F1F'i64, | |
0x7F44E6BD49E807B8'i64], [0xA402B9C5A8D3A6E7'i64, 0x5F16206C9C6209A6'i64], [ | |
0xCD036837130890A1'i64, 0x36DBA887C37A8C0F'i64], [0x802221226BE55A64'i64, | |
0xC2494954DA2C9789'i64], [0xA02AA96B06DEB0FD'i64, 0xF2DB9BAA10B7BD6C'i64], [ | |
0xC83553C5C8965D3D'i64, 0x6F92829494E5ACC7'i64], [0xFA42A8B73ABBF48C'i64, | |
0xCB772339BA1F17F9'i64], [0x9C69A97284B578D7'i64, 0xFF2A760414536EFB'i64], [ | |
0xC38413CF25E2D70D'i64, 0xFEF5138519684ABA'i64], [0xF46518C2EF5B8CD1'i64, | |
0x7EB258665FC25D69'i64], [0x98BF2F79D5993802'i64, 0xEF2F773FFBD97A61'i64], [ | |
0xBEEEFB584AFF8603'i64, 0xAAFB550FFACFD8FA'i64], [0xEEAABA2E5DBF6784'i64, | |
0x95BA2A53F983CF38'i64], [0x952AB45CFA97A0B2'i64, 0xDD945A747BF26183'i64], [ | |
0xBA756174393D88DF'i64, 0x94F971119AEEF9E4'i64], [0xE912B9D1478CEB17'i64, | |
0x7A37CD5601AAB85D'i64], [0x91ABB422CCB812EE'i64, 0xAC62E055C10AB33A'i64], [ | |
0xB616A12B7FE617AA'i64, 0x577B986B314D6009'i64], [0xE39C49765FDF9D94'i64, | |
0xED5A7E85FDA0B80B'i64], [0x8E41ADE9FBEBC27D'i64, 0x14588F13BE847307'i64], [ | |
0xB1D219647AE6B31C'i64, 0x596EB2D8AE258FC8'i64], [0xDE469FBD99A05FE3'i64, | |
0x6FCA5F8ED9AEF3BB'i64], [0x8AEC23D680043BEE'i64, 0x25DE7BB9480D5854'i64], [ | |
0xADA72CCC20054AE9'i64, 0xAF561AA79A10AE6A'i64], [0xD910F7FF28069DA4'i64, | |
0x1B2BA1518094DA04'i64], [0x87AA9AFF79042286'i64, 0x90FB44D2F05D0842'i64], [ | |
0xA99541BF57452B28'i64, 0x353A1607AC744A53'i64], [0xD3FA922F2D1675F2'i64, | |
0x42889B8997915CE8'i64], [0x847C9B5D7C2E09B7'i64, 0x69956135FEBADA11'i64], [ | |
0xA59BC234DB398C25'i64, 0x43FAB9837E699095'i64], [0xCF02B2C21207EF2E'i64, | |
0x94F967E45E03F4BB'i64], [0x8161AFB94B44F57D'i64, 0x1D1BE0EEBAC278F5'i64], [ | |
0xA1BA1BA79E1632DC'i64, 0x6462D92A69731732'i64], [0xCA28A291859BBF93'i64, | |
0x7D7B8F7503CFDCFE'i64], [0xFCB2CB35E702AF78'i64, 0x5CDA735244C3D43E'i64], [ | |
0x9DEFBF01B061ADAB'i64, 0x3A0888136AFA64A7'i64], [0xC56BAEC21C7A1916'i64, | |
0x088AAA1845B8FDD0'i64], [0xF6C69A72A3989F5B'i64, 0x8AAD549E57273D45'i64], [ | |
0x9A3C2087A63F6399'i64, 0x36AC54E2F678864B'i64], [0xC0CB28A98FCF3C7F'i64, | |
0x84576A1BB416A7DD'i64], [0xF0FDF2D3F3C30B9F'i64, 0x656D44A2A11C51D5'i64], [ | |
0x969EB7C47859E743'i64, 0x9F644AE5A4B1B325'i64], [0xBC4665B596706114'i64, | |
0x873D5D9F0DDE1FEE'i64], [0xEB57FF22FC0C7959'i64, 0xA90CB506D155A7EA'i64], [ | |
0x9316FF75DD87CBD8'i64, 0x09A7F12442D588F2'i64], [0xB7DCBF5354E9BECE'i64, | |
0x0C11ED6D538AEB2F'i64], [0xE5D3EF282A242E81'i64, 0x8F1668C8A86DA5FA'i64], [ | |
0x8FA475791A569D10'i64, 0xF96E017D694487BC'i64], [0xB38D92D760EC4455'i64, | |
0x37C981DCC395A9AC'i64], [0xE070F78D3927556A'i64, 0x85BBE253F47B1417'i64], [ | |
0x8C469AB843B89562'i64, 0x93956D7478CCEC8E'i64], [0xAF58416654A6BABB'i64, | |
0x387AC8D1970027B2'i64], [0xDB2E51BFE9D0696A'i64, 0x06997B05FCC0319E'i64], [ | |
0x88FCF317F22241E2'i64, 0x441FECE3BDF81F03'i64], [0xAB3C2FDDEEAAD25A'i64, | |
0xD527E81CAD7626C3'i64], [0xD60B3BD56A5586F1'i64, 0x8A71E223D8D3B074'i64], [ | |
0x85C7056562757456'i64, 0xF6872D5667844E49'i64], [0xA738C6BEBB12D16C'i64, | |
0xB428F8AC016561DB'i64], [0xD106F86E69D785C7'i64, 0xE13336D701BEBA52'i64], [ | |
0x82A45B450226B39C'i64, 0xECC0024661173473'i64], [0xA34D721642B06084'i64, | |
0x27F002D7F95D0190'i64], [0xCC20CE9BD35C78A5'i64, 0x31EC038DF7B441F4'i64], [ | |
0xFF290242C83396CE'i64, 0x7E67047175A15271'i64], [0x9F79A169BD203E41'i64, | |
0x0F0062C6E984D386'i64], [0xC75809C42C684DD1'i64, 0x52C07B78A3E60868'i64], [ | |
0xF92E0C3537826145'i64, 0xA7709A56CCDF8A82'i64], [0x9BBCC7A142B17CCB'i64, | |
0x88A66076400BB691'i64], [0xC2ABF989935DDBFE'i64, 0x6ACFF893D00EA435'i64], [ | |
0xF356F7EBF83552FE'i64, 0x0583F6B8C4124D43'i64], [0x98165AF37B2153DE'i64, | |
0xC3727A337A8B704A'i64], [0xBE1BF1B059E9A8D6'i64, 0x744F18C0592E4C5C'i64], [ | |
0xEDA2EE1C7064130C'i64, 0x1162DEF06F79DF73'i64], [0x9485D4D1C63E8BE7'i64, | |
0x8ADDCB5645AC2BA8'i64], [0xB9A74A0637CE2EE1'i64, 0x6D953E2BD7173692'i64], [ | |
0xE8111C87C5C1BA99'i64, 0xC8FA8DB6CCDD0437'i64], [0x910AB1D4DB9914A0'i64, | |
0x1D9C9892400A22A2'i64], [0xB54D5E4A127F59C8'i64, 0x2503BEB6D00CAB4B'i64], [ | |
0xE2A0B5DC971F303A'i64, 0x2E44AE64840FD61D'i64], [0x8DA471A9DE737E24'i64, | |
0x5CEAECFED289E5D2'i64], [0xB10D8E1456105DAD'i64, 0x7425A83E872C5F47'i64], [ | |
0xDD50F1996B947518'i64, 0xD12F124E28F77719'i64], [0x8A5296FFE33CC92F'i64, | |
0x82BD6B70D99AAA6F'i64], [0xACE73CBFDC0BFB7B'i64, 0x636CC64D1001550B'i64], [ | |
0xD8210BEFD30EFA5A'i64, 0x3C47F7E05401AA4E'i64], [0x8714A775E3E95C78'i64, | |
0x65ACFAEC34810A71'i64], [0xA8D9D1535CE3B396'i64, 0x7F1839A741A14D0D'i64], [ | |
0xD31045A8341CA07C'i64, 0x1EDE48111209A050'i64], [0x83EA2B892091E44D'i64, | |
0x934AED0AAB460432'i64], [0xA4E4B66B68B65D60'i64, 0xF81DA84D5617853F'i64], [ | |
0xCE1DE40642E3F4B9'i64, 0x36251260AB9D668E'i64], [0x80D2AE83E9CE78F3'i64, | |
0xC1D72B7C6B426019'i64], [0xA1075A24E4421730'i64, 0xB24CF65B8612F81F'i64], [ | |
0xC94930AE1D529CFC'i64, 0xDEE033F26797B627'i64], [0xFB9B7CD9A4A7443C'i64, | |
0x169840EF017DA3B1'i64], [0x9D412E0806E88AA5'i64, 0x8E1F289560EE864E'i64], [ | |
0xC491798A08A2AD4E'i64, 0xF1A6F2BAB92A27E2'i64], [0xF5B5D7EC8ACB58A2'i64, | |
0xAE10AF696774B1DB'i64], [0x9991A6F3D6BF1765'i64, 0xACCA6DA1E0A8EF29'i64], [ | |
0xBFF610B0CC6EDD3F'i64, 0x17FD090A58D32AF3'i64], [0xEFF394DCFF8A948E'i64, | |
0xDDFC4B4CEF07F5B0'i64], [0x95F83D0A1FB69CD9'i64, 0x4ABDAF101564F98E'i64], [ | |
0xBB764C4CA7A4440F'i64, 0x9D6D1AD41ABE37F1'i64], [0xEA53DF5FD18D5513'i64, | |
0x84C86189216DC5ED'i64], [0x92746B9BE2F8552C'i64, 0x32FD3CF5B4E49BB4'i64], [ | |
0xB7118682DBB66A77'i64, 0x3FBC8C33221DC2A1'i64], [0xE4D5E82392A40515'i64, | |
0x0FABAF3FEAA5334A'i64], [0x8F05B1163BA6832D'i64, 0x29CB4D87F2A7400E'i64], [ | |
0xB2C71D5BCA9023F8'i64, 0x743E20E9EF511012'i64], [0xDF78E4B2BD342CF6'i64, | |
0x914DA9246B255416'i64], [0x8BAB8EEFB6409C1A'i64, 0x1AD089B6C2F7548E'i64], [ | |
0xAE9672ABA3D0C320'i64, 0xA184AC2473B529B1'i64], [0xDA3C0F568CC4F3E8'i64, | |
0xC9E5D72D90A2741E'i64], [0x8865899617FB1871'i64, 0x7E2FA67C7A658892'i64], [ | |
0xAA7EEBFB9DF9DE8D'i64, 0xDDBB901B98FEEAB7'i64], [0xD51EA6FA85785631'i64, | |
0x552A74227F3EA565'i64], [0x8533285C936B35DE'i64, 0xD53A88958F87275F'i64], [ | |
0xA67FF273B8460356'i64, 0x8A892ABAF368F137'i64], [0xD01FEF10A657842C'i64, | |
0x2D2B7569B0432D85'i64], [0x8213F56A67F6B29B'i64, 0x9C3B29620E29FC73'i64], [ | |
0xA298F2C501F45F42'i64, 0x8349F3BA91B47B8F'i64], [0xCB3F2F7642717713'i64, | |
0x241C70A936219A73'i64], [0xFE0EFB53D30DD4D7'i64, 0xED238CD383AA0110'i64], [ | |
0x9EC95D1463E8A506'i64, 0xF4363804324A40AA'i64], [0xC67BB4597CE2CE48'i64, | |
0xB143C6053EDCD0D5'i64], [0xF81AA16FDC1B81DA'i64, 0xDD94B7868E94050A'i64], [ | |
0x9B10A4E5E9913128'i64, 0xCA7CF2B4191C8326'i64], [0xC1D4CE1F63F57D72'i64, | |
0xFD1C2F611F63A3F0'i64], [0xF24A01A73CF2DCCF'i64, 0xBC633B39673C8CEC'i64], [ | |
0x976E41088617CA01'i64, 0xD5BE0503E085D813'i64], [0xBD49D14AA79DBC82'i64, | |
0x4B2D8644D8A74E18'i64], [0xEC9C459D51852BA2'i64, 0xDDF8E7D60ED1219E'i64], [ | |
0x93E1AB8252F33B45'i64, 0xCABB90E5C942B503'i64], [0xB8DA1662E7B00A17'i64, | |
0x3D6A751F3B936243'i64], [0xE7109BFBA19C0C9D'i64, 0x0CC512670A783AD4'i64], [ | |
0x906A617D450187E2'i64, 0x27FB2B80668B24C5'i64], [0xB484F9DC9641E9DA'i64, | |
0xB1F9F660802DEDF6'i64], [0xE1A63853BBD26451'i64, 0x5E7873F8A0396973'i64], [ | |
0x8D07E33455637EB2'i64, 0xDB0B487B6423E1E8'i64], [0xB049DC016ABC5E5F'i64, | |
0x91CE1A9A3D2CDA62'i64], [0xDC5C5301C56B75F7'i64, 0x7641A140CC7810FB'i64], [ | |
0x89B9B3E11B6329BA'i64, 0xA9E904C87FCB0A9D'i64], [0xAC2820D9623BF429'i64, | |
0x546345FA9FBDCD44'i64], [0xD732290FBACAF133'i64, 0xA97C177947AD4095'i64], [ | |
0x867F59A9D4BED6C0'i64, 0x49ED8EABCCCC485D'i64], [0xA81F301449EE8C70'i64, | |
0x5C68F256BFFF5A74'i64], [0xD226FC195C6A2F8C'i64, 0x73832EEC6FFF3111'i64], [ | |
0x83585D8FD9C25DB7'i64, 0xC831FD53C5FF7EAB'i64], [0xA42E74F3D032F525'i64, | |
0xBA3E7CA8B77F5E55'i64], [0xCD3A1230C43FB26F'i64, 0x28CE1BD2E55F35EB'i64], [ | |
0x80444B5E7AA7CF85'i64, 0x7980D163CF5B81B3'i64], [0xA0555E361951C366'i64, | |
0xD7E105BCC332621F'i64], [0xC86AB5C39FA63440'i64, 0x8DD9472BF3FEFAA7'i64], [ | |
0xFA856334878FC150'i64, 0xB14F98F6F0FEB951'i64], [0x9C935E00D4B9D8D2'i64, | |
0x6ED1BF9A569F33D3'i64], [0xC3B8358109E84F07'i64, 0x0A862F80EC4700C8'i64], [ | |
0xF4A642E14C6262C8'i64, 0xCD27BB612758C0FA'i64], [0x98E7E9CCCFBD7DBD'i64, | |
0x8038D51CB897789C'i64], [0xBF21E44003ACDD2C'i64, 0xE0470A63E6BD56C3'i64], [ | |
0xEEEA5D5004981478'i64, 0x1858CCFCE06CAC74'i64], [0x95527A5202DF0CCB'i64, | |
0x0F37801E0C43EBC8'i64], [0xBAA718E68396CFFD'i64, 0xD30560258F54E6BA'i64], [ | |
0xE950DF20247C83FD'i64, 0x47C6B82EF32A2069'i64], [0x91D28B7416CDD27E'i64, | |
0x4CDC331D57FA5441'i64], [0xB6472E511C81471D'i64, 0xE0133FE4ADF8E952'i64], [ | |
0xE3D8F9E563A198E5'i64, 0x58180FDDD97723A6'i64], [0x8E679C2F5E44FF8F'i64, | |
0x570F09EAA7EA7648'i64], [0xB201833B35D63F73'i64, 0x2CD2CC6551E513DA'i64], [ | |
0xDE81E40A034BCF4F'i64, 0xF8077F7EA65E58D1'i64], [0x8B112E86420F6191'i64, | |
0xFB04AFAF27FAF782'i64], [0xADD57A27D29339F6'i64, 0x79C5DB9AF1F9B563'i64], [ | |
0xD94AD8B1C7380874'i64, 0x18375281AE7822BC'i64], [0x87CEC76F1C830548'i64, | |
0x8F2293910D0B15B5'i64], [0xA9C2794AE3A3C69A'i64, 0xB2EB3875504DDB22'i64], [ | |
0xD433179D9C8CB841'i64, 0x5FA60692A46151EB'i64], [0x849FEEC281D7F328'i64, | |
0xDBC7C41BA6BCD333'i64], [0xA5C7EA73224DEFF3'i64, 0x12B9B522906C0800'i64], [ | |
0xCF39E50FEAE16BEF'i64, 0xD768226B34870A00'i64], [0x81842F29F2CCE375'i64, | |
0xE6A1158300D46640'i64], [0xA1E53AF46F801C53'i64, 0x60495AE3C1097FD0'i64], [ | |
0xCA5E89B18B602368'i64, 0x385BB19CB14BDFC4'i64], [0xFCF62C1DEE382C42'i64, | |
0x46729E03DD9ED7B5'i64], [0x9E19DB92B4E31BA9'i64, 0x6C07A2C26A8346D1'i64], [ | |
0xC5A05277621BE293'i64, 0xC7098B7305241885'i64], [0xF70867153AA2DB38'i64, | |
0xB8CBEE4FC66D1EA7'i64]] | |
DRAGONBOX_ASSERT(k >= kMin) | |
DRAGONBOX_ASSERT(k <= kMax) | |
return Pow10[static_cast[uint32_t](k - kMin)] | |
## Returns whether value is divisible by 2^e2 | |
proc MultipleOfPow2*(value: uint64_t; e2: int32_t): bool {.inline.} = | |
DRAGONBOX_ASSERT(e2 >= 0) | |
return e2 < 64 and (value and ((uint64_t(1) shl e2) - 1)) == 0 | |
## Returns whether value is divisible by 5^e5 | |
proc MultipleOfPow5*(value: uint64_t; e5: int32_t): bool {.inline.} = | |
type | |
MulCmp {.bycopy.} = object | |
mul: uint64_t | |
cmp: uint64_t | |
var Mod5: UncheckedArray[MulCmp] = [[0x0000000000000001'i64, 0xFFFFFFFFFFFFFFFF'i64], [ | |
0xCCCCCCCCCCCCCCCD'i64, 0x3333333333333333'i64], [0x8F5C28F5C28F5C29'i64, | |
0x0A3D70A3D70A3D70'i64], [0x1CAC083126E978D5'i64, 0x020C49BA5E353F7C'i64], [ | |
0xD288CE703AFB7E91'i64, 0x0068DB8BAC710CB2'i64], [0x5D4E8FB00BCBE61D'i64, | |
0x0014F8B588E368F0'i64], [0x790FB65668C26139'i64, 0x000431BDE82D7B63'i64], [ | |
0xE5032477AE8D46A5'i64, 0x0000D6BF94D5E57A'i64], [0xC767074B22E90E21'i64, | |
0x00002AF31DC46118'i64], [0x8E47CE423A2E9C6D'i64, 0x0000089705F4136B'i64], [ | |
0x4FA7F60D3ED61F49'i64, 0x000001B7CDFD9D7B'i64], [0x0FEE64690C913975'i64, | |
0x00000057F5FF85E5'i64], [0x3662E0E1CF503EB1'i64, 0x000000119799812D'i64], [ | |
0xA47A2CF9F6433FBD'i64, 0x0000000384B84D09'i64], [0x54186F653140A659'i64, | |
0x00000000B424DC35'i64], [0x7738164770402145'i64, 0x0000000024075F3D'i64], [ | |
0xE4A4D1417CD9A041'i64, 0x000000000734ACA5'i64], [0xC75429D9E5C5200D'i64, | |
0x000000000170EF54'i64], [0xC1773B91FAC10669'i64, 0x000000000049C977'i64], [ | |
0x26B172506559CE15'i64, 0x00000000000EC1E4'i64], [0xD489E3A9ADDEC2D1'i64, | |
0x000000000002F394'i64], [0x90E860BB892C8D5D'i64, 0x000000000000971D'i64], [ | |
0x502E79BF1B6F4F79'i64, 0x0000000000001E39'i64], [0xDCD618596BE30FE5'i64, | |
0x000000000000060B'i64], [0x2C2AD1AB7BFA3661'i64, 0x0000000000000135'i64]] | |
DRAGONBOX_ASSERT(e5 >= 0) | |
DRAGONBOX_ASSERT(e5 <= 24) | |
var m5: MulCmp = Mod5[static_cast[cuint](e5)] | |
return value * m5.mul <= m5.cmp | |
type | |
FloatingDecimal64* {.bycopy.} = object | |
significand*: uint64_t | |
exponent*: int32_t | |
proc ToDecimal64_asymmetric_interval*(e2: int32_t): FloatingDecimal64 {.inline.} = | |
## NB: | |
## accept_lower_endpoint = true | |
## accept_upper_endpoint = true | |
var P: int32_t = SignificandSize | |
## Compute k and beta | |
var minus_k: int32_t = FloorLog10ThreeQuartersPow2(e2) | |
var beta_minus_1: int32_t = e2 + FloorLog2Pow10(-minus_k) | |
## Compute xi and zi | |
var pow10: uint64x2 = ComputePow10(-minus_k) | |
var lower_endpoint: uint64_t = (pow10.hi - (pow10.hi shr (P + 1))) shr | |
(64 - P - beta_minus_1) | |
var upper_endpoint: uint64_t = (pow10.hi + (pow10.hi shr (P + 0))) shr | |
(64 - P - beta_minus_1) | |
## If we don't accept the left endpoint (but we do!) or | |
## if the left endpoint is not an integer, increase it | |
var lower_endpoint_is_integer: bool = (2 <= e2 and e2 <= 3) | |
var xi: uint64_t = lower_endpoint + not lower_endpoint_is_integer | |
var zi: uint64_t = upper_endpoint | |
## Try bigger divisor | |
var q: uint64_t = zi div 10 | |
if q * 10 >= xi: | |
return (q, minus_k + 1) | |
q = ((pow10.hi shr (64 - (P + 1) - beta_minus_1)) + 1) div 2 | |
## When tie occurs, choose one of them according to the rule | |
if e2 == -77: | |
dec(q, (q mod 2 != 0)) | |
## Round to even. | |
else: | |
inc(q, (q < xi)) | |
return (q, minus_k) | |
proc ComputeDelta*(pow10: uint64x2; beta_minus_1: int32_t): uint32_t {.inline.} = | |
DRAGONBOX_ASSERT(beta_minus_1 >= 0) | |
DRAGONBOX_ASSERT(beta_minus_1 <= 63) | |
return static_cast[uint32_t](pow10.hi shr (64 - 1 - beta_minus_1)) | |
when defined(__SIZEOF_INT128__): | |
proc Mul128*(x: uint64_t; y: uint64_t): uint64x2 {.inline.} = | |
## 1 mulx | |
## !!!Ignored construct: __extension__ using uint128_t = unsigned __int128 ; | |
## Error: token expected: ; but got: [identifier]!!! | |
var p: uint128_t = uint128_t(x) * y | |
var hi: uint64_t = static_cast[uint64_t](p shr 64) | |
var lo: uint64_t = static_cast[uint64_t](p) | |
return (hi, lo) | |
elif defined(_MSC_VER) and defined(_M_X64): | |
proc Mul128*(x: uint64_t; y: uint64_t): uint64x2 {.inline.} = | |
var hi: uint64_t = 0 | |
var lo: uint64_t = _umul128(x, y, addr(hi)) | |
return (hi, lo) | |
else: | |
proc Lo32*(x: uint64_t): uint32_t {.inline.} = | |
return static_cast[uint32_t](x) | |
proc Hi32*(x: uint64_t): uint32_t {.inline.} = | |
return static_cast[uint32_t](x shr 32) | |
proc Mul128*(a: uint64_t; b: uint64_t): uint64x2 {.inline.} = | |
var b00: uint64_t = uint64_t(Lo32(a)) * Lo32(b) | |
var b01: uint64_t = uint64_t(Lo32(a)) * Hi32(b) | |
var b10: uint64_t = uint64_t(Hi32(a)) * Lo32(b) | |
var b11: uint64_t = uint64_t(Hi32(a)) * Hi32(b) | |
var mid1: uint64_t = b10 + Hi32(b00) | |
var mid2: uint64_t = b01 + Lo32(mid1) | |
var hi: uint64_t = b11 + Hi32(mid1) + Hi32(mid2) | |
var lo: uint64_t = Lo32(b00) or uint64_t(Lo32(mid2)) shl 32 | |
return (hi, lo) | |
## Returns (x * y) / 2^128 | |
proc MulShift*(x: uint64_t; y: uint64x2): uint64_t {.inline.} = | |
## 2 mulx | |
var p1: uint64x2 = Mul128(x, y.hi) | |
var p0: uint64x2 = Mul128(x, y.lo) | |
inc(p1.lo, p0.hi) | |
inc(p1.hi, p1.lo < p0.hi) | |
return p1.hi | |
proc MulParity*(two_f: uint64_t; pow10: uint64x2; beta_minus_1: int32_t): bool {.inline.} = | |
## 1 mulx, 1 mul | |
DRAGONBOX_ASSERT(beta_minus_1 >= 1) | |
DRAGONBOX_ASSERT(beta_minus_1 <= 63) | |
var p01: uint64_t = two_f * pow10.hi | |
var p10: uint64_t = Mul128(two_f, pow10.lo).hi | |
var mid: uint64_t = p01 + p10 | |
return (mid and (uint64_t(1) shl (64 - beta_minus_1))) != 0 | |
proc IsIntegralEndpoint*(two_f: uint64_t; e2: int32_t; minus_k: int32_t): bool {.inline.} = | |
if e2 < -2: | |
return false | |
if e2 <= 9: | |
return true | |
if e2 <= 86: | |
return MultipleOfPow5(two_f, minus_k) | |
return false | |
proc IsIntegralMidpoint*(two_f: uint64_t; e2: int32_t; minus_k: int32_t): bool {.inline.} = | |
if e2 < -4: | |
return MultipleOfPow2(two_f, minus_k - e2 + 1) | |
if e2 <= 9: | |
return true | |
if e2 <= 86: | |
return MultipleOfPow5(two_f, minus_k) | |
return false | |
proc ToDecimal64*(ieee_significand: uint64_t; ieee_exponent: uint64_t): FloatingDecimal64 {. | |
inline.} = | |
var Kappa: int32_t = 2 | |
var BigDivisor: uint32_t = 1000 | |
## 10^(kappa + 1) | |
var SmallDivisor: uint32_t = 100 | |
## 10^(kappa) | |
## | |
## Step 1: | |
## integer promotion & Schubfach multiplier calculation. | |
## | |
var m2: uint64_t | |
var e2: int32_t | |
if ieee_exponent != 0: | |
m2 = HiddenBit or ieee_significand | |
e2 = static_cast[int32_t](ieee_exponent) - ExponentBias | |
if 0 <= -e2 and -e2 < SignificandSize and MultipleOfPow2(m2, -e2): | |
## Small integer. | |
return (m2 shr -e2, 0) | |
if ieee_significand == 0 and ieee_exponent > 1: | |
## Shorter interval case; proceed like Schubfach. | |
return ToDecimal64_asymmetric_interval(e2) | |
else: | |
## Subnormal case; interval is always regular. | |
m2 = ieee_significand | |
e2 = 1 - ExponentBias | |
var is_even: bool = (m2 mod 2 == 0) | |
var accept_lower: bool = is_even | |
var accept_upper: bool = is_even | |
## Compute k and beta. | |
var minus_k: int32_t = FloorLog10Pow2(e2) - Kappa | |
var beta_minus_1: int32_t = e2 + FloorLog2Pow10(-minus_k) | |
DRAGONBOX_ASSERT(beta_minus_1 >= 6) | |
DRAGONBOX_ASSERT(beta_minus_1 <= 9) | |
var pow10: uint64x2 = ComputePow10(-minus_k) | |
## Compute delta | |
## 10^kappa <= delta < 10^(kappa + 1) | |
## 100 <= delta < 1000 | |
var delta: uint32_t = ComputeDelta(pow10, beta_minus_1) | |
DRAGONBOX_ASSERT(delta >= SmallDivisor) | |
DRAGONBOX_ASSERT(delta < BigDivisor) | |
var two_fl: uint64_t = 2 * m2 - 1 | |
var two_fc: uint64_t = 2 * m2 | |
var two_fr: uint64_t = 2 * m2 + 1 | |
## (54 bits) | |
## Compute zi | |
## (54 + 9 = 63 bits) | |
var zi: uint64_t = MulShift(two_fr shl beta_minus_1, pow10) | |
## 2 mulx | |
## | |
## Step 2: | |
## Try larger divisor. | |
## | |
var q: uint64_t = zi div BigDivisor | |
## uint64_t q = Mul128(zi, 0x83126E978D4FDF3Cu).hi >> 9; // 1 mulx | |
var r: uint32_t = static_cast[uint32_t](zi) - | |
BigDivisor * static_cast[uint32_t](q) | |
## r = zi % BigDivisor | |
## 0 <= r < 1000 | |
if r < delta: ## likely ~50% ?! | |
## (r > deltai) | |
## Exclude the right endpoint if necessary | |
if r != 0 or accept_upper or not IsIntegralEndpoint(two_fr, e2, minus_k): | |
return (q, minus_k + Kappa + 1) | |
DRAGONBOX_ASSERT(q != 0) | |
dec(q) | |
r = BigDivisor | |
elif r == delta: ## unlikely | |
## Compare fractional parts. | |
## Check conditions in the order different from the paper | |
## to take advantage of short-circuiting | |
if (accept_lower and IsIntegralEndpoint(two_fl, e2, minus_k)) or | |
MulParity(two_fl, pow10, beta_minus_1): | |
return (q, minus_k + Kappa + 1) | |
else: | |
discard | |
## | |
## Step 3: | |
## Find the significand with the smaller divisor | |
## | |
q = q * 10 | |
## 1 hmul | |
## 0 <= r <= 1000 | |
var dist: uint32_t = r - (delta div 2) + (SmallDivisor div 2) | |
var dist_q: uint32_t = dist div 100 | |
## 1 mul | |
## const uint32_t dist_r = dist % 100; | |
inc(q, dist_q) | |
## if /*likely*/ (dist_r == 0) | |
if dist == dist_q * 100: | |
## const bool approx_y_parity = ((dist ^ (SmallDivisor / 2)) & 1) != 0; | |
var approx_y_parity: bool = (dist and 1) != 0 | |
## Check z^(f) >= epsilon^(f) | |
## We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1, | |
## where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f) | |
## Since there are only 2 possibilities, we only need to care about the | |
## parity. Also, zi and r should have the same parity since the divisor | |
## is an even number | |
if MulParity(two_fc, pow10, beta_minus_1) != approx_y_parity: | |
dec(q) | |
elif q mod 2 != 0 and IsIntegralMidpoint(two_fc, e2, minus_k): | |
dec(q) | |
return (q, minus_k + Kappa) | |
## ================================================================================================== | |
## ToChars | |
## ================================================================================================== | |
proc Utoa_2Digits*(buf: cstring; digits: uint32_t) {.inline.} = | |
var Digits100: array[200, char] = ['0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', | |
'0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', | |
'1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', | |
'1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3', | |
'2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', | |
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', | |
'3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1', | |
'4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', | |
'4', '8', '4', '9', '5', '0', '5', '1', '5', '2', '5', '3', | |
'5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', | |
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', | |
'6', '6', '6', '7', '6', '8', '6', '9', '7', '0', '7', '1', | |
'7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', | |
'7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', | |
'8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', | |
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', | |
'9', '6', '9', '7', '9', '8', '9', '9'] | |
DRAGONBOX_ASSERT(digits <= 99) | |
memcpy(buf, addr(Digits100[2 * digits]), 2 * sizeof((char))) | |
proc TrailingZeros_2Digits*(digits: uint32_t): int32_t {.inline.} = | |
var TrailingZeros100: array[100, int8_t] = [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, | |
0, 0, 0, 0, 0, 0, 0] | |
DRAGONBOX_ASSERT(digits <= 99) | |
return TrailingZeros100[digits] | |
proc Utoa_8Digits_skip_trailing_zeros*(buf: cstring; digits: uint32_t): int32_t {. | |
inline.} = | |
DRAGONBOX_ASSERT(digits >= 1) | |
DRAGONBOX_ASSERT(digits <= 99999999) | |
var q: uint32_t = digits div 10000 | |
var r: uint32_t = digits mod 10000 | |
var qH: uint32_t = q div 100 | |
var qL: uint32_t = q mod 100 | |
Utoa_2Digits(buf + 0, qH) | |
Utoa_2Digits(buf + 2, qL) | |
if r == 0: | |
return TrailingZeros_2Digits(if qL == 0: qH else: qL) + (if qL == 0: 6 else: 4) | |
else: | |
var rH: uint32_t = r div 100 | |
var rL: uint32_t = r mod 100 | |
Utoa_2Digits(buf + 4, rH) | |
Utoa_2Digits(buf + 6, rL) | |
return TrailingZeros_2Digits(if rL == 0: rH else: rL) + (if rL == 0: 2 else: 0) | |
proc PrintDecimalDigitsBackwards*(buf: cstring; output64: uint64_t): int32_t {.inline.} = | |
var tz: int32_t = 0 | |
## number of trailing zeros removed. | |
var nd: int32_t = 0 | |
## number of decimal digits processed. | |
## At most 17 digits remaining | |
if output64 >= 100000000: | |
var q: uint64_t = output64 div 100000000 | |
var r: uint32_t = static_cast[uint32_t](output64 mod 100000000) | |
output64 = q | |
dec(buf, 8) | |
if r != 0: | |
tz = Utoa_8Digits_skip_trailing_zeros(buf, r) | |
DRAGONBOX_ASSERT(tz >= 0) | |
DRAGONBOX_ASSERT(tz <= 7) | |
else: | |
tz = 8 | |
nd = 8 | |
DRAGONBOX_ASSERT(output64 <= UINT32_MAX) | |
var output: uint32_t = static_cast[uint32_t](output64) | |
if output >= 10000: | |
var q: uint32_t = output div 10000 | |
var r: uint32_t = output mod 10000 | |
output = q | |
dec(buf, 4) | |
if r != 0: | |
var rH: uint32_t = r div 100 | |
var rL: uint32_t = r mod 100 | |
Utoa_2Digits(buf + 0, rH) | |
Utoa_2Digits(buf + 2, rL) | |
if tz == nd: | |
inc(tz, TrailingZeros_2Digits(if rL == 0: rH else: rL) + | |
(if rL == 0: 2 else: 0)) | |
else: | |
if tz == nd: | |
inc(tz, 4) | |
else: | |
memset(buf, '0', 4) | |
## (actually not required...) | |
inc(nd, 4) | |
if output >= 100: | |
var q: uint32_t = output div 100 | |
var r: uint32_t = output mod 100 | |
output = q | |
dec(buf, 2) | |
Utoa_2Digits(buf, r) | |
if tz == nd: | |
inc(tz, TrailingZeros_2Digits(r)) | |
inc(nd, 2) | |
if output >= 100: | |
var q2: uint32_t = output div 100 | |
var r2: uint32_t = output mod 100 | |
output = q2 | |
dec(buf, 2) | |
Utoa_2Digits(buf, r2) | |
if tz == nd: | |
inc(tz, TrailingZeros_2Digits(r2)) | |
inc(nd, 2) | |
DRAGONBOX_ASSERT(output >= 1) | |
DRAGONBOX_ASSERT(output <= 99) | |
if output >= 10: | |
var q: uint32_t = output | |
dec(buf, 2) | |
Utoa_2Digits(buf, q) | |
if tz == nd: | |
inc(tz, TrailingZeros_2Digits(q)) | |
else: | |
var q: uint32_t = output | |
DRAGONBOX_ASSERT(q >= 1) | |
DRAGONBOX_ASSERT(q <= 9) | |
dec(buf)[] = static_cast[char]('0' + q) | |
return tz | |
proc DecimalLength*(v: uint64_t): int32_t {.inline.} = | |
DRAGONBOX_ASSERT(v >= 1) | |
DRAGONBOX_ASSERT(v <= 99999999999999999'i64) | |
if static_cast[uint32_t](v shr 32) != 0: | |
if v >= 10000000000000000'i64: | |
return 17 | |
if v >= 1000000000000000'i64: | |
return 16 | |
if v >= 100000000000000'i64: | |
return 15 | |
if v >= 10000000000000'i64: | |
return 14 | |
if v >= 1000000000000'i64: | |
return 13 | |
if v >= 100000000000'i64: | |
return 12 | |
if v >= 10000000000'i64: | |
return 11 | |
return 10 | |
var v32: uint32_t = static_cast[uint32_t](v) | |
if v32 >= 1000000000: | |
return 10 | |
if v32 >= 100000000: | |
return 9 | |
if v32 >= 10000000: | |
return 8 | |
if v32 >= 1000000: | |
return 7 | |
if v32 >= 100000: | |
return 6 | |
if v32 >= 10000: | |
return 5 | |
if v32 >= 1000: | |
return 4 | |
if v32 >= 100: | |
return 3 | |
if v32 >= 10: | |
return 2 | |
return 1 | |
proc FormatDigits*(buffer: cstring; digits: uint64_t; decimal_exponent: int32_t; | |
force_trailing_dot_zero: bool = false): cstring {.inline.} = | |
var MinFixedDecimalPoint: int32_t = -6 | |
var MaxFixedDecimalPoint: int32_t = 17 | |
static_assert(MinFixedDecimalPoint <= -1, "internal error") | |
static_assert(MaxFixedDecimalPoint >= 17, "internal error") | |
DRAGONBOX_ASSERT(digits >= 1) | |
DRAGONBOX_ASSERT(digits <= 99999999999999999'i64) | |
DRAGONBOX_ASSERT(decimal_exponent >= -999) | |
DRAGONBOX_ASSERT(decimal_exponent <= 999) | |
var num_digits: int32_t = DecimalLength(digits) | |
var decimal_point: int32_t = num_digits + decimal_exponent | |
var use_fixed: bool = MinFixedDecimalPoint <= decimal_point and | |
decimal_point <= MaxFixedDecimalPoint | |
## Prepare the buffer. | |
## Avoid calling memset/memcpy with variable arguments below... | |
memset(buffer + 0, '0', 16) | |
memset(buffer + 16, '0', 16) | |
static_assert(MinFixedDecimalPoint >= -30, "internal error") | |
static_assert(MaxFixedDecimalPoint <= 32, "internal error") | |
var decimal_digits_position: int32_t | |
if use_fixed: | |
if decimal_point <= 0: | |
## 0.[000]digits | |
decimal_digits_position = 2 - decimal_point | |
else: | |
## dig.its | |
## digits[000] | |
decimal_digits_position = 0 | |
else: | |
## dE+123 or d.igitsE+123 | |
decimal_digits_position = 1 | |
var digits_end: cstring = buffer + decimal_digits_position + num_digits | |
var tz: int32_t = PrintDecimalDigitsBackwards(digits_end, digits) | |
dec(digits_end, tz) | |
dec(num_digits, tz) | |
## decimal_exponent += tz; // => decimal_point unchanged. | |
if use_fixed: | |
if decimal_point <= 0: | |
## 0.[000]digits | |
buffer[1] = '.' | |
buffer = digits_end | |
elif decimal_point < num_digits: | |
## dig.its | |
when defined(_MSC_VER) and not defined(__clang__): | |
## VC does not inline the memmove call below. (Even if compiled with /arch:AVX2.) | |
## However, memcpy will be inlined. | |
var tmp: array[16, uint8_t] | |
var src: cstring = buffer + decimal_point | |
var dst: cstring = src + 1 | |
memcpy(tmp, src, 16) | |
memcpy(dst, tmp, 16) | |
else: | |
memmove(buffer + decimal_point + 1, buffer + decimal_point, 16) | |
buffer[decimal_point] = '.' | |
buffer = digits_end + 1 | |
else: | |
## digits[000] | |
inc(buffer, decimal_point) | |
if force_trailing_dot_zero: | |
memcpy(buffer, ".0", 2) | |
inc(buffer, 2) | |
else: | |
## Copy the first digit one place to the left. | |
buffer[0] = buffer[1] | |
if num_digits == 1: | |
## dE+123 | |
inc(buffer) | |
else: | |
## d.igitsE+123 | |
buffer[1] = '.' | |
buffer = digits_end | |
var scientific_exponent: int32_t = decimal_point - 1 | |
## SF_ASSERT(scientific_exponent != 0); | |
memcpy(buffer, if scientific_exponent < 0: "e-" else: "e+", 2) | |
inc(buffer, 2) | |
var k: uint32_t = static_cast[uint32_t](if scientific_exponent < 0: -scientific_exponent else: scientific_exponent) | |
if k < 10: | |
inc(buffer)[] = static_cast[char]('0' + k) | |
elif k < 100: | |
Utoa_2Digits(buffer, k) | |
inc(buffer, 2) | |
else: | |
var q: uint32_t = k div 100 | |
var r: uint32_t = k mod 100 | |
inc(buffer)[] = static_cast[char]('0' + q) | |
Utoa_2Digits(buffer, r) | |
inc(buffer, 2) | |
return buffer | |
proc ToChars*(buffer: cstring; value: cdouble; force_trailing_dot_zero: bool = false): cstring {. | |
inline.} = | |
proc v(a1: value): Double | |
var significand: uint64_t = v.PhysicalSignificand() | |
var exponent: uint64_t = v.PhysicalExponent() | |
if exponent != MaxIeeeExponent: | |
## Finite | |
buffer[0] = '-' | |
inc(buffer, v.SignBit()) | |
if exponent != 0 or significand != 0: | |
## != 0 | |
var dec: auto = ToDecimal64(significand, exponent) | |
return FormatDigits(buffer, dec.significand, dec.exponent, | |
force_trailing_dot_zero) | |
else: | |
memcpy(buffer, "0.0 ", 4) | |
inc(buffer, if force_trailing_dot_zero: 3 else: 1) | |
return buffer | |
if significand == 0: | |
buffer[0] = '-' | |
inc(buffer, v.SignBit()) | |
memcpy(buffer, "inf ", 4) | |
return buffer + 3 | |
else: | |
memcpy(buffer, "nan ", 4) | |
return buffer + 3 | |
## ================================================================================================== | |
## | |
## ================================================================================================== | |
proc Dtoa*(buffer: cstring; value: cdouble): cstring = | |
return ToChars(buffer, value) | |
proc nim_dragonbox_Dtoa*(buffer: cstring; value: cdouble): cstring = | |
return ToChars(buffer, value) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment