-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move formatfloat out of system (#20195)
* move formatfloat out of system * fixes doc * Update changelog.md * careless * fixes * deprecate system/formatfloat * better handling
- Loading branch information
Showing
23 changed files
with
201 additions
and
176 deletions.
There are no files selected for viewing
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
# | ||
# | ||
# Nim's Runtime Library | ||
# (c) Copyright 2022 Nim contributors | ||
# | ||
# See the file "copying.txt", included in this | ||
# distribution, for details about the copyright. | ||
# | ||
|
||
when defined(nimPreviewSlimSystem): | ||
import std/assertions | ||
else: | ||
{.deprecated: "formatfloat is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/formatfloat`".} | ||
|
||
proc c_memcpy(a, b: pointer, size: csize_t): pointer {.importc: "memcpy", header: "<string.h>", discardable.} | ||
|
||
proc addCstringN(result: var string, buf: cstring; buflen: int) = | ||
# no nimvm support needed, so it doesn't need to be fast here either | ||
let oldLen = result.len | ||
let newLen = oldLen + buflen | ||
result.setLen newLen | ||
c_memcpy(result[oldLen].addr, buf, buflen.csize_t) | ||
|
||
import std/private/[dragonbox, schubfach] | ||
|
||
proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: BiggestFloat): int = | ||
## This is the implementation to format floats. | ||
## | ||
## returns the amount of bytes written to `buf` not counting the | ||
## terminating '\0' character. | ||
result = toChars(buf, value, forceTrailingDotZero=true) | ||
buf[result] = '\0' | ||
|
||
proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int = | ||
result = float32ToChars(buf, value, forceTrailingDotZero=true) | ||
buf[result] = '\0' | ||
|
||
proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", | ||
importc: "sprintf", varargs, noSideEffect.} | ||
|
||
proc writeToBuffer(buf: var array[65, char]; value: cstring) = | ||
var i = 0 | ||
while value[i] != '\0': | ||
buf[i] = value[i] | ||
inc i | ||
|
||
proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat): int = | ||
## This is the implementation to format floats. | ||
## | ||
## returns the amount of bytes written to `buf` not counting the | ||
## terminating '\0' character. | ||
var n: int = c_sprintf(addr buf, "%.16g", value) | ||
var hasDot = false | ||
for i in 0..n-1: | ||
if buf[i] == ',': | ||
buf[i] = '.' | ||
hasDot = true | ||
elif buf[i] in {'a'..'z', 'A'..'Z', '.'}: | ||
hasDot = true | ||
if not hasDot: | ||
buf[n] = '.' | ||
buf[n+1] = '0' | ||
buf[n+2] = '\0' | ||
result = n + 2 | ||
else: | ||
result = n | ||
# On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' or 'nan(ind)' | ||
# of '-1.#IND' are produced. | ||
# We want to get rid of these here: | ||
if buf[n-1] in {'n', 'N', 'D', 'd', ')'}: | ||
writeToBuffer(buf, "nan") | ||
result = 3 | ||
elif buf[n-1] == 'F': | ||
if buf[0] == '-': | ||
writeToBuffer(buf, "-inf") | ||
result = 4 | ||
else: | ||
writeToBuffer(buf, "inf") | ||
result = 3 | ||
|
||
proc writeFloatToBuffer*(buf: var array[65, char]; value: BiggestFloat | float32): int {.inline.} = | ||
when defined(nimPreviewFloatRoundtrip) or defined(nimPreviewSlimSystem): | ||
writeFloatToBufferRoundtrip(buf, value) | ||
else: | ||
writeFloatToBufferSprintf(buf, value) | ||
|
||
proc addFloatRoundtrip*(result: var string; x: float | float32) = | ||
when nimvm: | ||
doAssert false | ||
else: | ||
var buffer {.noinit.}: array[65, char] | ||
let n = writeFloatToBufferRoundtrip(buffer, x) | ||
result.addCstringN(cstring(buffer[0].addr), n) | ||
|
||
proc addFloatSprintf*(result: var string; x: float) = | ||
when nimvm: | ||
doAssert false | ||
else: | ||
var buffer {.noinit.}: array[65, char] | ||
let n = writeFloatToBufferSprintf(buffer, x) | ||
result.addCstringN(cstring(buffer[0].addr), n) | ||
|
||
proc nimFloatToString(a: float): cstring = | ||
## ensures the result doesn't print like an integer, i.e. return 2.0, not 2 | ||
# print `-0.0` properly | ||
asm """ | ||
function nimOnlyDigitsOrMinus(n) { | ||
return n.toString().match(/^-?\d+$/); | ||
} | ||
if (Number.isSafeInteger(`a`)) | ||
`result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0" | ||
else { | ||
`result` = `a`+"" | ||
if(nimOnlyDigitsOrMinus(`result`)){ | ||
`result` = `a`+".0" | ||
} | ||
} | ||
""" | ||
|
||
proc addFloat*(result: var string; x: float | float32) {.inline.} = | ||
## Converts float to its string representation and appends it to `result`. | ||
runnableExamples: | ||
var | ||
s = "foo:" | ||
b = 45.67 | ||
s.addFloat(45.67) | ||
assert s == "foo:45.67" | ||
template impl = | ||
when defined(nimPreviewFloatRoundtrip) or defined(nimPreviewSlimSystem): | ||
addFloatRoundtrip(result, x) | ||
else: | ||
addFloatSprintf(result, x) | ||
when defined(js): | ||
when nimvm: impl() | ||
else: | ||
result.add nimFloatToString(x) | ||
else: impl() | ||
|
||
when defined(nimPreviewSlimSystem): | ||
func `$`*(x: float | float32): string = | ||
## Outplace version of `addFloat`. | ||
result.addFloat(x) |
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
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
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
Oops, something went wrong.