Created
May 25, 2021 22:22
-
-
Save timotheecour/b80666a4ba360f3473548db7ad298cfc to your computer and use it in GitHub Desktop.
c2nim --cpp dragonbox.cc
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 = | |
discard | |
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 | |
proc constructDouble*(bits_: bits_type): Double {.constructor.} | |
proc constructDouble*(value: value_type): Double {.constructor.} | |
proc PhysicalSignificand*(this: Double): bits_type {.noSideEffect.} | |
proc PhysicalExponent*(this: Double): bits_type {.noSideEffect.} | |
proc IsFinite*(this: Double): bool {.noSideEffect.} | |
proc IsInf*(this: Double): bool {.noSideEffect.} | |
proc IsNaN*(this: Double): bool {.noSideEffect.} | |
proc IsZero*(this: Double): bool {.noSideEffect.} | |
proc SignBit*(this: Double): bool {.noSideEffect.} | |
## 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 = | |
discard | |
proc FloorLog2Pow10*(e: int32_t): int32_t = | |
discard | |
proc FloorLog10Pow2*(e: int32_t): int32_t = | |
discard | |
proc FloorLog10ThreeQuartersPow2*(e: int32_t): int32_t = | |
discard | |
## ================================================================================================== | |
## | |
## ================================================================================================== | |
type | |
uint64x2* {.bycopy.} = object | |
hi*: uint64_t | |
lo*: uint64_t | |
proc ComputePow10*(k: int32_t): uint64x2 = | |
discard | |
## Returns whether value is divisible by 2^e2 | |
proc MultipleOfPow2*(value: uint64_t; e2: int32_t): bool = | |
discard | |
## Returns whether value is divisible by 5^e5 | |
proc MultipleOfPow5*(value: uint64_t; e5: int32_t): bool = | |
discard | |
type | |
FloatingDecimal64* {.bycopy.} = object | |
significand*: uint64_t | |
exponent*: int32_t | |
proc ToDecimal64_asymmetric_interval*(e2: int32_t): FloatingDecimal64 = | |
discard | |
proc ComputeDelta*(pow10: uint64x2; beta_minus_1: int32_t): uint32_t = | |
discard | |
when defined(__SIZEOF_INT128__): | |
proc Mul128*(x: uint64_t; y: uint64_t): uint64x2 = | |
## 1 mulx | |
discard | |
elif defined(_MSC_VER) and defined(_M_X64): | |
proc Mul128*(x: uint64_t; y: uint64_t): uint64x2 = | |
discard | |
else: | |
proc Lo32*(x: uint64_t): uint32_t = | |
discard | |
proc Hi32*(x: uint64_t): uint32_t = | |
discard | |
proc Mul128*(a: uint64_t; b: uint64_t): uint64x2 = | |
discard | |
## Returns (x * y) / 2^128 | |
proc MulShift*(x: uint64_t; y: uint64x2): uint64_t = | |
## 2 mulx | |
discard | |
proc MulParity*(two_f: uint64_t; pow10: uint64x2; beta_minus_1: int32_t): bool = | |
## 1 mulx, 1 mul | |
discard | |
proc IsIntegralEndpoint*(two_f: uint64_t; e2: int32_t; minus_k: int32_t): bool = | |
discard | |
proc IsIntegralMidpoint*(two_f: uint64_t; e2: int32_t; minus_k: int32_t): bool = | |
discard | |
proc ToDecimal64*(ieee_significand: uint64_t; ieee_exponent: uint64_t): FloatingDecimal64 = | |
discard | |
## ================================================================================================== | |
## ToChars | |
## ================================================================================================== | |
proc Utoa_2Digits*(buf: cstring; digits: uint32_t) = | |
discard | |
proc TrailingZeros_2Digits*(digits: uint32_t): int32_t = | |
discard | |
proc Utoa_8Digits_skip_trailing_zeros*(buf: cstring; digits: uint32_t): int32_t = | |
discard | |
proc PrintDecimalDigitsBackwards*(buf: cstring; output64: uint64_t): int32_t = | |
discard | |
proc DecimalLength*(v: uint64_t): int32_t = | |
discard | |
proc FormatDigits*(buffer: cstring; digits: uint64_t; decimal_exponent: int32_t; | |
force_trailing_dot_zero: bool = false): cstring = | |
discard | |
proc ToChars*(buffer: cstring; value: cdouble; force_trailing_dot_zero: bool = false): cstring = | |
discard | |
## ================================================================================================== | |
## | |
## ================================================================================================== | |
proc Dtoa*(buffer: cstring; value: cdouble): cstring | |
proc nim_dragonbox_Dtoa*(buffer: cstring; value: cdouble): cstring = | |
discard |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment