Skip to content

Commit b6bfe38

Browse files
authored
move formatfloat out of system (#20195)
* move formatfloat out of system * fixes doc * Update changelog.md * careless * fixes * deprecate system/formatfloat * better handling
1 parent 12f23d5 commit b6bfe38

23 files changed

+201
-176
lines changed

changelog.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
- `addr` is now available for all addressable locations,
77
`unsafeAddr` is now deprecated and an alias for `addr`.
88

9-
- `io` and `assertions` are about to move out of the `system` module.
10-
You may instead import `std/syncio` and `std/assertions`.
9+
- `io`, `assertions`, `formatfloat` are about to move out of the `system` module. You may instead import `std/syncio`, `std/assertions` and `std/formatfloat`.
1110
The `-d:nimPreviewSlimSystem` option makes these imports required.
1211

1312
- The `gc:v2` option is removed.

compiler/ic/ic.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import ".." / [ast, idents, lineinfos, msgs, ropes, options,
1515
from os import removeFile, isAbsolute
1616

1717
when defined(nimPreviewSlimSystem):
18-
import std/[syncio, assertions]
18+
import std/[syncio, assertions, formatfloat]
1919

2020
type
2121
PackedConfig* = object

compiler/lexer.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import
2020
wordrecg, lineinfos, pathutils, parseutils
2121

2222
when defined(nimPreviewSlimSystem):
23-
import std/assertions
23+
import std/[assertions, formatfloat]
2424

2525
const
2626
MaxLineLength* = 80 # lines longer than this lead to a warning

compiler/renderer.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import
1818
lexer, options, idents, strutils, ast, msgs, lineinfos
1919

2020
when defined(nimPreviewSlimSystem):
21-
import std/[syncio, assertions]
21+
import std/[syncio, assertions, formatfloat]
2222

2323
type
2424
TRenderFlag* = enum

compiler/rodutils.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ when not declared(signbit):
4242
proc signbit*(x: SomeFloat): bool {.inline.} =
4343
result = c_signbit(x) != 0
4444

45-
import system/formatfloat
45+
import std/formatfloat
4646

4747
proc toStrMaxPrecision*(f: BiggestFloat | float32): string =
4848
const literalPostfix = when f is float32: "f" else: ""

compiler/ropes.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ import
6161
from pathutils import AbsoluteFile
6262

6363
when defined(nimPreviewSlimSystem):
64-
import std/[assertions, syncio]
64+
import std/[assertions, syncio, formatfloat]
6565

6666

6767
type

compiler/sem.nim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ when defined(nimfix):
2525
when not defined(leanCompiler):
2626
import spawn
2727

28+
when defined(nimPreviewSlimSystem):
29+
import std/formatfloat
30+
2831
# implementation
2932

3033
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode

compiler/semfold.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import
1818
from system/memory import nimCStrLen
1919

2020
when defined(nimPreviewSlimSystem):
21-
import std/assertions
21+
import std/[assertions, formatfloat]
2222

2323
proc errorType*(g: ModuleGraph): PType =
2424
## creates a type representing an error state

compiler/types.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import
1414
lineinfos, int128, modulegraphs, astmsgs
1515

1616
when defined(nimPreviewSlimSystem):
17-
import std/assertions
17+
import std/[assertions, formatfloat]
1818

1919
type
2020
TPreferedDesc* = enum

compiler/vm.nim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import
1818
gorgeimpl, lineinfos, btrees, macrocacheimpl,
1919
modulegraphs, sighashes, int128, vmprofiler
2020

21+
when defined(nimPreviewSlimSystem):
22+
import std/formatfloat
23+
2124
import ast except getstr
2225
from semfold import leValueConv, ordinalValToString
2326
from evaltempl import evalTemplate

compiler/vmmarshal.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import streams, json, intsets, tables, ast, astalgo, idents, types, msgs,
1313
options, lineinfos
1414

1515
when defined(nimPreviewSlimSystem):
16-
import std/assertions
16+
import std/[assertions, formatfloat]
1717

1818
proc ptrToInt(x: PNode): int {.inline.} =
1919
result = cast[int](x) # don't skip alignment

compiler/vmops.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ from std/os import getEnv, existsEnv, delEnv, putEnv, envPairs,
2828
from std/times import cpuTime
2929
from std/hashes import hash
3030
from std/osproc import nil
31-
from system/formatfloat import addFloatRoundtrip, addFloatSprintf
3231

3332

3433
when defined(nimPreviewSlimSystem):
3534
import std/syncio
36-
35+
else:
36+
from std/formatfloat import addFloatRoundtrip, addFloatSprintf
3737

3838
# There are some useful procs in vmconv.
3939
import vmconv, vmmarshal

lib/core/macros.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ include "system/inclrtl"
1111
import std/private/since
1212

1313
when defined(nimPreviewSlimSystem):
14-
import std/assertions
14+
import std/[assertions, formatfloat]
1515

1616

1717
## This module contains the interface to the compiler's abstract syntax

lib/packages/docutils/rstgen.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils,
4444

4545

4646
when defined(nimPreviewSlimSystem):
47-
import std/[assertions, syncio]
47+
import std/[assertions, syncio, formatfloat]
4848

4949

5050
import ../../std/private/since

lib/pure/json.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ import options # xxx remove this dependency using same approach as https://githu
165165
import std/private/since
166166

167167
when defined(nimPreviewSlimSystem):
168-
import std/[syncio, assertions]
168+
import std/[syncio, assertions, formatfloat]
169169

170170
export
171171
tables.`$`

lib/std/formatfloat.nim

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#
2+
#
3+
# Nim's Runtime Library
4+
# (c) Copyright 2022 Nim contributors
5+
#
6+
# See the file "copying.txt", included in this
7+
# distribution, for details about the copyright.
8+
#
9+
10+
when defined(nimPreviewSlimSystem):
11+
import std/assertions
12+
else:
13+
{.deprecated: "formatfloat is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/formatfloat`".}
14+
15+
proc c_memcpy(a, b: pointer, size: csize_t): pointer {.importc: "memcpy", header: "<string.h>", discardable.}
16+
17+
proc addCstringN(result: var string, buf: cstring; buflen: int) =
18+
# no nimvm support needed, so it doesn't need to be fast here either
19+
let oldLen = result.len
20+
let newLen = oldLen + buflen
21+
result.setLen newLen
22+
c_memcpy(result[oldLen].addr, buf, buflen.csize_t)
23+
24+
import std/private/[dragonbox, schubfach]
25+
26+
proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: BiggestFloat): int =
27+
## This is the implementation to format floats.
28+
##
29+
## returns the amount of bytes written to `buf` not counting the
30+
## terminating '\0' character.
31+
result = toChars(buf, value, forceTrailingDotZero=true)
32+
buf[result] = '\0'
33+
34+
proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int =
35+
result = float32ToChars(buf, value, forceTrailingDotZero=true)
36+
buf[result] = '\0'
37+
38+
proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
39+
importc: "sprintf", varargs, noSideEffect.}
40+
41+
proc writeToBuffer(buf: var array[65, char]; value: cstring) =
42+
var i = 0
43+
while value[i] != '\0':
44+
buf[i] = value[i]
45+
inc i
46+
47+
proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat): int =
48+
## This is the implementation to format floats.
49+
##
50+
## returns the amount of bytes written to `buf` not counting the
51+
## terminating '\0' character.
52+
var n: int = c_sprintf(addr buf, "%.16g", value)
53+
var hasDot = false
54+
for i in 0..n-1:
55+
if buf[i] == ',':
56+
buf[i] = '.'
57+
hasDot = true
58+
elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
59+
hasDot = true
60+
if not hasDot:
61+
buf[n] = '.'
62+
buf[n+1] = '0'
63+
buf[n+2] = '\0'
64+
result = n + 2
65+
else:
66+
result = n
67+
# On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' or 'nan(ind)'
68+
# of '-1.#IND' are produced.
69+
# We want to get rid of these here:
70+
if buf[n-1] in {'n', 'N', 'D', 'd', ')'}:
71+
writeToBuffer(buf, "nan")
72+
result = 3
73+
elif buf[n-1] == 'F':
74+
if buf[0] == '-':
75+
writeToBuffer(buf, "-inf")
76+
result = 4
77+
else:
78+
writeToBuffer(buf, "inf")
79+
result = 3
80+
81+
proc writeFloatToBuffer*(buf: var array[65, char]; value: BiggestFloat | float32): int {.inline.} =
82+
when defined(nimPreviewFloatRoundtrip) or defined(nimPreviewSlimSystem):
83+
writeFloatToBufferRoundtrip(buf, value)
84+
else:
85+
writeFloatToBufferSprintf(buf, value)
86+
87+
proc addFloatRoundtrip*(result: var string; x: float | float32) =
88+
when nimvm:
89+
doAssert false
90+
else:
91+
var buffer {.noinit.}: array[65, char]
92+
let n = writeFloatToBufferRoundtrip(buffer, x)
93+
result.addCstringN(cstring(buffer[0].addr), n)
94+
95+
proc addFloatSprintf*(result: var string; x: float) =
96+
when nimvm:
97+
doAssert false
98+
else:
99+
var buffer {.noinit.}: array[65, char]
100+
let n = writeFloatToBufferSprintf(buffer, x)
101+
result.addCstringN(cstring(buffer[0].addr), n)
102+
103+
proc nimFloatToString(a: float): cstring =
104+
## ensures the result doesn't print like an integer, i.e. return 2.0, not 2
105+
# print `-0.0` properly
106+
asm """
107+
function nimOnlyDigitsOrMinus(n) {
108+
return n.toString().match(/^-?\d+$/);
109+
}
110+
if (Number.isSafeInteger(`a`))
111+
`result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0"
112+
else {
113+
`result` = `a`+""
114+
if(nimOnlyDigitsOrMinus(`result`)){
115+
`result` = `a`+".0"
116+
}
117+
}
118+
"""
119+
120+
proc addFloat*(result: var string; x: float | float32) {.inline.} =
121+
## Converts float to its string representation and appends it to `result`.
122+
runnableExamples:
123+
var
124+
s = "foo:"
125+
b = 45.67
126+
s.addFloat(45.67)
127+
assert s == "foo:45.67"
128+
template impl =
129+
when defined(nimPreviewFloatRoundtrip) or defined(nimPreviewSlimSystem):
130+
addFloatRoundtrip(result, x)
131+
else:
132+
addFloatSprintf(result, x)
133+
when defined(js):
134+
when nimvm: impl()
135+
else:
136+
result.add nimFloatToString(x)
137+
else: impl()
138+
139+
when defined(nimPreviewSlimSystem):
140+
func `$`*(x: float | float32): string =
141+
## Outplace version of `addFloat`.
142+
result.addFloat(x)

lib/system/dragonbox.nim renamed to lib/std/private/dragonbox.nim

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,20 @@ when defined(nimPreviewSlimSystem):
3030
const
3131
dtoaMinBufferLength*: cint = 64
3232

33-
## --------------------------------------------------------------------------------------------------
3433
## This file contains an implementation of Junekey Jeon's Dragonbox algorithm.
3534
##
3635
## It is a simplified version of the reference implementation found here:
3736
## https://github.com/jk-jeon/dragonbox
3837
##
3938
## The reference implementation also works with single-precision floating-point numbers and
4039
## has options to configure the rounding mode.
41-
## --------------------------------------------------------------------------------------------------
4240

4341
template dragonbox_Assert*(x: untyped): untyped =
4442
assert(x)
4543

46-
## ==================================================================================================
47-
##
48-
## ==================================================================================================
44+
# ==================================================================================================
45+
#
46+
# ==================================================================================================
4947

5048
type
5149
ValueType* = float
@@ -106,10 +104,11 @@ proc isZero*(this: Double): bool {.noSideEffect.} =
106104
proc signBit*(this: Double): int {.noSideEffect.} =
107105
return ord((this.bits and signMask) != 0)
108106

107+
108+
# ==================================================================================================
109+
#
110+
# ==================================================================================================
109111
## namespace
110-
## ==================================================================================================
111-
##
112-
## ==================================================================================================
113112
## Returns floor(x / 2^n).
114113
##
115114
## Technically, right-shift of negative integers is implementation defined...
@@ -133,9 +132,9 @@ proc floorLog10ThreeQuartersPow2*(e: int32): int32 {.inline.} =
133132
dragonbox_Assert(e <= 1500)
134133
return floorDivPow2(e * 1262611 - 524031, 22)
135134

136-
## ==================================================================================================
137-
##
138-
## ==================================================================================================
135+
# ==================================================================================================
136+
#
137+
# ==================================================================================================
139138

140139
type
141140
uint64x2* {.bycopy.} = object
@@ -1040,9 +1039,9 @@ proc toDecimal64*(ieeeSignificand: uint64; ieeeExponent: uint64): FloatingDecima
10401039
dec(q)
10411040
return FloatingDecimal64(significand: q, exponent: minusK + kappa)
10421041

1043-
## ==================================================================================================
1044-
## ToChars
1045-
## ==================================================================================================
1042+
# ==================================================================================================
1043+
# ToChars
1044+
# ==================================================================================================
10461045

10471046
when false:
10481047
template `+!`(x: cstring; offset: int): cstring = cast[cstring](cast[uint](x) + uint(offset))

lib/system/schubfach.nim renamed to lib/std/private/schubfach.nim

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
## Distributed under the Boost Software License, Version 1.0.
44
## (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
55

6-
## --------------------------------------------------------------------------------------------------
6+
# --------------------------------------------------------------------------------------------------
77
## This file contains an implementation of the Schubfach algorithm as described in
88
##
99
## [1] Raffaello Giulietti, "The Schubfach way to render doubles",
1010
## https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
11-
## --------------------------------------------------------------------------------------------------
11+
# --------------------------------------------------------------------------------------------------
1212

1313
import std/private/digitsutils
1414

@@ -19,9 +19,9 @@ when defined(nimPreviewSlimSystem):
1919
template sf_Assert(x: untyped): untyped =
2020
assert(x)
2121

22-
## ==================================================================================================
23-
##
24-
## ==================================================================================================
22+
# ==================================================================================================
23+
#
24+
# ==================================================================================================
2525

2626
type
2727
ValueType = float32
@@ -68,7 +68,7 @@ proc isZero(this: Single): bool {.noSideEffect.} =
6868
proc signBit(this: Single): int {.noSideEffect.} =
6969
return int((this.bits and signMask) != 0)
7070

71-
## ==================================================================================================
71+
# ==================================================================================================
7272
## Returns floor(x / 2^n).
7373
##
7474
## Technically, right-shift of negative integers is implementation defined...

lib/std/syncio.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
include system/inclrtl
1313
import std/private/since
14-
import system/formatfloat
14+
import std/formatfloat
1515

1616
# ----------------- IO Part ------------------------------------------------
1717
type

0 commit comments

Comments
 (0)