move formatfloat out of system (#20195)
* move formatfloat out of system * fixes doc * Update changelog.md * careless * fixes * deprecate system/formatfloat * better handling
This commit is contained in:
parent
12f23d5ae8
commit
b6bfe38ff5
23 changed files with 201 additions and 176 deletions
|
|
@ -6,8 +6,7 @@
|
||||||
- `addr` is now available for all addressable locations,
|
- `addr` is now available for all addressable locations,
|
||||||
`unsafeAddr` is now deprecated and an alias for `addr`.
|
`unsafeAddr` is now deprecated and an alias for `addr`.
|
||||||
|
|
||||||
- `io` and `assertions` are about to move out of the `system` module.
|
- `io`, `assertions`, `formatfloat` are about to move out of the `system` module. You may instead import `std/syncio`, `std/assertions` and `std/formatfloat`.
|
||||||
You may instead import `std/syncio` and `std/assertions`.
|
|
||||||
The `-d:nimPreviewSlimSystem` option makes these imports required.
|
The `-d:nimPreviewSlimSystem` option makes these imports required.
|
||||||
|
|
||||||
- The `gc:v2` option is removed.
|
- The `gc:v2` option is removed.
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import ".." / [ast, idents, lineinfos, msgs, ropes, options,
|
||||||
from os import removeFile, isAbsolute
|
from os import removeFile, isAbsolute
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[syncio, assertions]
|
import std/[syncio, assertions, formatfloat]
|
||||||
|
|
||||||
type
|
type
|
||||||
PackedConfig* = object
|
PackedConfig* = object
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import
|
||||||
wordrecg, lineinfos, pathutils, parseutils
|
wordrecg, lineinfos, pathutils, parseutils
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/assertions
|
import std/[assertions, formatfloat]
|
||||||
|
|
||||||
const
|
const
|
||||||
MaxLineLength* = 80 # lines longer than this lead to a warning
|
MaxLineLength* = 80 # lines longer than this lead to a warning
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import
|
||||||
lexer, options, idents, strutils, ast, msgs, lineinfos
|
lexer, options, idents, strutils, ast, msgs, lineinfos
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[syncio, assertions]
|
import std/[syncio, assertions, formatfloat]
|
||||||
|
|
||||||
type
|
type
|
||||||
TRenderFlag* = enum
|
TRenderFlag* = enum
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ when not declared(signbit):
|
||||||
proc signbit*(x: SomeFloat): bool {.inline.} =
|
proc signbit*(x: SomeFloat): bool {.inline.} =
|
||||||
result = c_signbit(x) != 0
|
result = c_signbit(x) != 0
|
||||||
|
|
||||||
import system/formatfloat
|
import std/formatfloat
|
||||||
|
|
||||||
proc toStrMaxPrecision*(f: BiggestFloat | float32): string =
|
proc toStrMaxPrecision*(f: BiggestFloat | float32): string =
|
||||||
const literalPostfix = when f is float32: "f" else: ""
|
const literalPostfix = when f is float32: "f" else: ""
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ import
|
||||||
from pathutils import AbsoluteFile
|
from pathutils import AbsoluteFile
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[assertions, syncio]
|
import std/[assertions, syncio, formatfloat]
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ when defined(nimfix):
|
||||||
when not defined(leanCompiler):
|
when not defined(leanCompiler):
|
||||||
import spawn
|
import spawn
|
||||||
|
|
||||||
|
when defined(nimPreviewSlimSystem):
|
||||||
|
import std/formatfloat
|
||||||
|
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode
|
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import
|
||||||
from system/memory import nimCStrLen
|
from system/memory import nimCStrLen
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/assertions
|
import std/[assertions, formatfloat]
|
||||||
|
|
||||||
proc errorType*(g: ModuleGraph): PType =
|
proc errorType*(g: ModuleGraph): PType =
|
||||||
## creates a type representing an error state
|
## creates a type representing an error state
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import
|
||||||
lineinfos, int128, modulegraphs, astmsgs
|
lineinfos, int128, modulegraphs, astmsgs
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/assertions
|
import std/[assertions, formatfloat]
|
||||||
|
|
||||||
type
|
type
|
||||||
TPreferedDesc* = enum
|
TPreferedDesc* = enum
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ import
|
||||||
gorgeimpl, lineinfos, btrees, macrocacheimpl,
|
gorgeimpl, lineinfos, btrees, macrocacheimpl,
|
||||||
modulegraphs, sighashes, int128, vmprofiler
|
modulegraphs, sighashes, int128, vmprofiler
|
||||||
|
|
||||||
|
when defined(nimPreviewSlimSystem):
|
||||||
|
import std/formatfloat
|
||||||
|
|
||||||
import ast except getstr
|
import ast except getstr
|
||||||
from semfold import leValueConv, ordinalValToString
|
from semfold import leValueConv, ordinalValToString
|
||||||
from evaltempl import evalTemplate
|
from evaltempl import evalTemplate
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import streams, json, intsets, tables, ast, astalgo, idents, types, msgs,
|
||||||
options, lineinfos
|
options, lineinfos
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/assertions
|
import std/[assertions, formatfloat]
|
||||||
|
|
||||||
proc ptrToInt(x: PNode): int {.inline.} =
|
proc ptrToInt(x: PNode): int {.inline.} =
|
||||||
result = cast[int](x) # don't skip alignment
|
result = cast[int](x) # don't skip alignment
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ from std/os import getEnv, existsEnv, delEnv, putEnv, envPairs,
|
||||||
from std/times import cpuTime
|
from std/times import cpuTime
|
||||||
from std/hashes import hash
|
from std/hashes import hash
|
||||||
from std/osproc import nil
|
from std/osproc import nil
|
||||||
from system/formatfloat import addFloatRoundtrip, addFloatSprintf
|
|
||||||
|
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/syncio
|
import std/syncio
|
||||||
|
else:
|
||||||
|
from std/formatfloat import addFloatRoundtrip, addFloatSprintf
|
||||||
|
|
||||||
# There are some useful procs in vmconv.
|
# There are some useful procs in vmconv.
|
||||||
import vmconv, vmmarshal
|
import vmconv, vmmarshal
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ include "system/inclrtl"
|
||||||
import std/private/since
|
import std/private/since
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/assertions
|
import std/[assertions, formatfloat]
|
||||||
|
|
||||||
|
|
||||||
## This module contains the interface to the compiler's abstract syntax
|
## This module contains the interface to the compiler's abstract syntax
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils,
|
||||||
|
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[assertions, syncio]
|
import std/[assertions, syncio, formatfloat]
|
||||||
|
|
||||||
|
|
||||||
import ../../std/private/since
|
import ../../std/private/since
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ import options # xxx remove this dependency using same approach as https://githu
|
||||||
import std/private/since
|
import std/private/since
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[syncio, assertions]
|
import std/[syncio, assertions, formatfloat]
|
||||||
|
|
||||||
export
|
export
|
||||||
tables.`$`
|
tables.`$`
|
||||||
|
|
|
||||||
142
lib/std/formatfloat.nim
Normal file
142
lib/std/formatfloat.nim
Normal file
|
|
@ -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)
|
||||||
|
|
@ -30,7 +30,6 @@ when defined(nimPreviewSlimSystem):
|
||||||
const
|
const
|
||||||
dtoaMinBufferLength*: cint = 64
|
dtoaMinBufferLength*: cint = 64
|
||||||
|
|
||||||
## --------------------------------------------------------------------------------------------------
|
|
||||||
## This file contains an implementation of Junekey Jeon's Dragonbox algorithm.
|
## This file contains an implementation of Junekey Jeon's Dragonbox algorithm.
|
||||||
##
|
##
|
||||||
## It is a simplified version of the reference implementation found here:
|
## It is a simplified version of the reference implementation found here:
|
||||||
|
|
@ -38,14 +37,13 @@ const
|
||||||
##
|
##
|
||||||
## The reference implementation also works with single-precision floating-point numbers and
|
## The reference implementation also works with single-precision floating-point numbers and
|
||||||
## has options to configure the rounding mode.
|
## has options to configure the rounding mode.
|
||||||
## --------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template dragonbox_Assert*(x: untyped): untyped =
|
template dragonbox_Assert*(x: untyped): untyped =
|
||||||
assert(x)
|
assert(x)
|
||||||
|
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
##
|
#
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
|
|
||||||
type
|
type
|
||||||
ValueType* = float
|
ValueType* = float
|
||||||
|
|
@ -106,10 +104,11 @@ proc isZero*(this: Double): bool {.noSideEffect.} =
|
||||||
proc signBit*(this: Double): int {.noSideEffect.} =
|
proc signBit*(this: Double): int {.noSideEffect.} =
|
||||||
return ord((this.bits and signMask) != 0)
|
return ord((this.bits and signMask) != 0)
|
||||||
|
|
||||||
|
|
||||||
|
# ==================================================================================================
|
||||||
|
#
|
||||||
|
# ==================================================================================================
|
||||||
## namespace
|
## namespace
|
||||||
## ==================================================================================================
|
|
||||||
##
|
|
||||||
## ==================================================================================================
|
|
||||||
## Returns floor(x / 2^n).
|
## Returns floor(x / 2^n).
|
||||||
##
|
##
|
||||||
## Technically, right-shift of negative integers is implementation defined...
|
## Technically, right-shift of negative integers is implementation defined...
|
||||||
|
|
@ -133,9 +132,9 @@ proc floorLog10ThreeQuartersPow2*(e: int32): int32 {.inline.} =
|
||||||
dragonbox_Assert(e <= 1500)
|
dragonbox_Assert(e <= 1500)
|
||||||
return floorDivPow2(e * 1262611 - 524031, 22)
|
return floorDivPow2(e * 1262611 - 524031, 22)
|
||||||
|
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
##
|
#
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
|
|
||||||
type
|
type
|
||||||
uint64x2* {.bycopy.} = object
|
uint64x2* {.bycopy.} = object
|
||||||
|
|
@ -1040,9 +1039,9 @@ proc toDecimal64*(ieeeSignificand: uint64; ieeeExponent: uint64): FloatingDecima
|
||||||
dec(q)
|
dec(q)
|
||||||
return FloatingDecimal64(significand: q, exponent: minusK + kappa)
|
return FloatingDecimal64(significand: q, exponent: minusK + kappa)
|
||||||
|
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
## ToChars
|
# ToChars
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
template `+!`(x: cstring; offset: int): cstring = cast[cstring](cast[uint](x) + uint(offset))
|
template `+!`(x: cstring; offset: int): cstring = cast[cstring](cast[uint](x) + uint(offset))
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
## Distributed under the Boost Software License, Version 1.0.
|
## 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)
|
## (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
## --------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------
|
||||||
## This file contains an implementation of the Schubfach algorithm as described in
|
## This file contains an implementation of the Schubfach algorithm as described in
|
||||||
##
|
##
|
||||||
## [1] Raffaello Giulietti, "The Schubfach way to render doubles",
|
## [1] Raffaello Giulietti, "The Schubfach way to render doubles",
|
||||||
## https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
|
## https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
|
||||||
## --------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
import std/private/digitsutils
|
import std/private/digitsutils
|
||||||
|
|
||||||
|
|
@ -19,9 +19,9 @@ when defined(nimPreviewSlimSystem):
|
||||||
template sf_Assert(x: untyped): untyped =
|
template sf_Assert(x: untyped): untyped =
|
||||||
assert(x)
|
assert(x)
|
||||||
|
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
##
|
#
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
|
|
||||||
type
|
type
|
||||||
ValueType = float32
|
ValueType = float32
|
||||||
|
|
@ -68,7 +68,7 @@ proc isZero(this: Single): bool {.noSideEffect.} =
|
||||||
proc signBit(this: Single): int {.noSideEffect.} =
|
proc signBit(this: Single): int {.noSideEffect.} =
|
||||||
return int((this.bits and signMask) != 0)
|
return int((this.bits and signMask) != 0)
|
||||||
|
|
||||||
## ==================================================================================================
|
# ==================================================================================================
|
||||||
## Returns floor(x / 2^n).
|
## Returns floor(x / 2^n).
|
||||||
##
|
##
|
||||||
## Technically, right-shift of negative integers is implementation defined...
|
## Technically, right-shift of negative integers is implementation defined...
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
include system/inclrtl
|
include system/inclrtl
|
||||||
import std/private/since
|
import std/private/since
|
||||||
import system/formatfloat
|
import std/formatfloat
|
||||||
|
|
||||||
# ----------------- IO Part ------------------------------------------------
|
# ----------------- IO Part ------------------------------------------------
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
# Implementation of some runtime checks.
|
# Implementation of some runtime checks.
|
||||||
include system/indexerrors
|
include system/indexerrors
|
||||||
|
when defined(nimPreviewSlimSystem):
|
||||||
|
import std/formatfloat
|
||||||
|
|
||||||
proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
|
proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
|
||||||
when hostOS == "standalone":
|
when hostOS == "standalone":
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,14 @@ runnableExamples:
|
||||||
assert $(-2*3) == "-6"
|
assert $(-2*3) == "-6"
|
||||||
|
|
||||||
import std/private/[digitsutils, miscdollars]
|
import std/private/[digitsutils, miscdollars]
|
||||||
import system/formatfloat
|
|
||||||
export addFloat
|
when not defined(nimPreviewSlimSystem):
|
||||||
|
import std/formatfloat
|
||||||
|
export addFloat
|
||||||
|
|
||||||
|
func `$`*(x: float | float32): string =
|
||||||
|
## Outplace version of `addFloat`.
|
||||||
|
result.addFloat(x)
|
||||||
|
|
||||||
proc `$`*(x: int): string {.raises: [].} =
|
proc `$`*(x: int): string {.raises: [].} =
|
||||||
## Outplace version of `addInt`.
|
## Outplace version of `addInt`.
|
||||||
|
|
@ -27,9 +33,6 @@ gen(int)
|
||||||
gen(uint64)
|
gen(uint64)
|
||||||
gen(int64)
|
gen(int64)
|
||||||
|
|
||||||
func `$`*(x: float | float32): string =
|
|
||||||
## Outplace version of `addFloat`.
|
|
||||||
result.addFloat(x)
|
|
||||||
|
|
||||||
proc `$`*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
|
proc `$`*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
|
||||||
## The stringify operator for a boolean argument. Returns `x`
|
## The stringify operator for a boolean argument. Returns `x`
|
||||||
|
|
|
||||||
|
|
@ -1,135 +1,6 @@
|
||||||
#
|
when not defined(nimPreviewSlimSystem):
|
||||||
#
|
import std/formatfloat
|
||||||
# Nim's Runtime Library
|
export formatfloat
|
||||||
# (c) Copyright 2019 Nim contributors
|
{.deprecated: "use `std/formatfloat`".}
|
||||||
#
|
else:
|
||||||
# See the file "copying.txt", included in this
|
{.error: "use `std/formatfloat`".}
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
|
||||||
import std/assertions
|
|
||||||
|
|
||||||
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 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):
|
|
||||||
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):
|
|
||||||
addFloatRoundtrip(result, x)
|
|
||||||
else:
|
|
||||||
addFloatSprintf(result, x)
|
|
||||||
when defined(js):
|
|
||||||
when nimvm: impl()
|
|
||||||
else:
|
|
||||||
result.add nimFloatToString(x)
|
|
||||||
else: impl()
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
include system/inclrtl
|
include system/inclrtl
|
||||||
|
|
||||||
|
when defined(nimPreviewSlimSystem):
|
||||||
|
import std/formatfloat
|
||||||
|
|
||||||
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
||||||
## imported from typetraits
|
## imported from typetraits
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue