Skip to content

Commit

Permalink
add schubfach_64, schubfach_32
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed May 15, 2021
1 parent 2ea8423 commit 097fc18
Show file tree
Hide file tree
Showing 11 changed files with 2,240 additions and 68 deletions.
24 changes: 13 additions & 11 deletions compiler/builddeps.nim
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,14 @@ proc addDependencyImpl(conf: ConfigRef, name: string, info: TLineInfo, jobs: seq
for job in jobs:
let objFile = dir / ("$1_$2_$3.o" % [prefix, name, job.input.splitFile.name])
if optForceFullMake in conf.globalOptions or not objFile.fileExists:
# xxx
# let cppExe = getCompilerExe(c.config; compiler: TSystemCC; cfile: AbsoluteFile): string =
# compilePattern = getCompilerExe(conf, c, cfile.cname)
# xxx use `getCompilerExe`
when defined(osx):
let cppExe = "clang++"
else:
let cppExe = "g++"
when defined(linux):
# PRTEMP: avoids:
# /usr/bin/ld: /home/runner/work/Nim/Nim/nimcache/r_linux_amd64/nimdragonbox.o: relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE
# xxx: avoids linker errors:
# relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE
let options = "-fPIE"
else:
let options = ""
Expand All @@ -49,19 +47,23 @@ proc addDependencyImpl(conf: ConfigRef, name: string, info: TLineInfo, jobs: seq
localError(conf, info, "building '$#' failed: cmd: $#\noutput:\n$#" % [name, cmd, outp])
conf.addExternalFileToLink(objFile.AbsoluteFile)
if linkerFlags.len > 0:
# conf.addExternalFileToLink(linkerFlags)
conf.addLinkOption(linkerFlags)

proc addDependency*(conf: ConfigRef, name: string, info: TLineInfo) =
case name
of "drachennest_dragonbox":
addDependencyImpl(conf, name, info, jobs = @[Job(input: "vendor/drachennest/dragonbox.cc", copts: "-std=c++11")])
let copts = "-std=c++11"
var jobs: seq[Job]
for file in "impl.cc dragonbox.cc schubfach_32.cc schubfach_64.cc".split:
jobs.add Job(input: "vendor/drachennest" / file, copts: copts)
addDependencyImpl(conf, name, info, jobs = jobs)
of "dragonbox_dragonbox":
let includeDir = conf.libpath.string / "vendor/dragonbox/include"
let dir = "vendor/dragonbox"
let includeDir = conf.libpath.string / dir / "include"
let copts = "-std=c++17 -I $#" % includeDir.quoteShell
let jobs = @[
Job(input: "vendor/dragonbox/impl.cc", copts: copts),
Job(input: "vendor/dragonbox/dragonbox_to_chars.cpp", copts: copts)]
var jobs: seq[Job]
for file in "impl.cc dragonbox_to_chars.cpp".split:
jobs.add Job(input: dir / file, copts: copts)
addDependencyImpl(conf, name, info, jobs = jobs, linkerFlags = "-lc++")
else:
localError(conf, info, "expected: 'dragonbox', got: '$1'" % name)
21 changes: 15 additions & 6 deletions lib/std/strfloats.nim
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,35 @@ when useDragonbox:
proc nimtoStringDragonbox0Impl(buf: ptr char, value: cfloat): ptr char {.importc: "nimtoStringDragonbox0ImplFloat".}

addDependency("drachennest_dragonbox")
proc toStringDragonboxImpl(buf: ptr char, value: cdouble): ptr char {.importc: "nim_dragonbox_Dtoa".}
proc toStringDragonboxImpl(buf: ptr char, value: cdouble): ptr char {.importc: "nimtoStringDragonboxImplDouble".}
proc toStringDragonboxImpl(buf: ptr char, value: cfloat): ptr char {.importc: "nimSchubfachFtoa".} # note: using schubfach here because drachennest dragonbox doesn't yet support float32

proc nimSchubfachToString(buf: ptr char, value: cfloat): ptr char {.importc: "nimSchubfachFtoa".}
proc nimSchubfachToString(buf: ptr char, value: cdouble): ptr char {.importc: "nimSchubfachDtoa".}

proc toStringDragonbox0*(buf: var array[strFloatBufLen, char]; value: float|float32): int {.inline.} =
let first = buf[0].addr
let ret = nimtoStringDragonbox0Impl(first, value)
fixup(buf, ret, first, result)

proc toStringDragonbox*(buf: var array[strFloatBufLen, char]; value: BiggestFloat): int {.inline.} =
proc toStringSchubfach*(buf: var array[strFloatBufLen, char]; value: float|float32): int {.inline.} =
let first = buf[0].addr
let ret = nimSchubfachToString(first, value)
fixup(buf, ret, first, result)

proc toStringDragonbox*(buf: var array[strFloatBufLen, char]; value: float|float32): int {.inline.} =
let first = buf[0].addr
let ret = toStringDragonboxImpl(first, value)
fixup(buf, ret, first, result)

template toString*(buf: var array[strFloatBufLen, char]; value: BiggestFloat): int =
# toStringDragonbox(buf, value)
toStringDragonbox0(buf, value)
template toString*(buf: var array[strFloatBufLen, char]; value: float|float32): int =
toStringDragonbox(buf, value)
# toStringDragonbox0(buf, value)
else:
template toString*(buf: var array[strFloatBufLen, char]; value: BiggestFloat): int =
toStringSprintf(buf, value)

proc addFloat*(result: var string; x: float) =
proc addFloat*(result: var string; x: float | float32) =
## Converts `x` to its string representation and appends it to `result`.
##
## The algorithm is implementation defined, but currently uses dragonbox algorithm,
Expand Down
31 changes: 2 additions & 29 deletions lib/vendor/drachennest/dragonbox.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,7 @@
// 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)

namespace dragonbox {

// 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.

constexpr int DtoaMinBufferLength = 64;

char* Dtoa(char* buffer, double value);

} // namespace dragonbox
#include "dragonbox.h"

//--------------------------------------------------------------------------------------------------
// This file contains an implementation of Junekey Jeon's Dragonbox algorithm.
Expand Down Expand Up @@ -878,7 +855,7 @@ static inline FloatingDecimal64 ToDecimal64_asymmetric_interval(int32_t e2)
const uint64_t upper_endpoint = (pow10.hi + (pow10.hi >> (P + 0))) >> (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
// if the left endpoint is not an integer, increase it
const bool lower_endpoint_is_integer = (2 <= e2 && e2 <= 3);

const uint64_t xi = lower_endpoint + !lower_endpoint_is_integer;
Expand Down Expand Up @@ -1547,7 +1524,3 @@ char* dragonbox::Dtoa(char* buffer, double value)
{
return ToChars(buffer, value);
}

extern "C" char* nim_dragonbox_Dtoa(char* buffer, double value){
return ToChars(buffer, value);
}
31 changes: 31 additions & 0 deletions lib/vendor/drachennest/dragonbox.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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)

#pragma once

namespace dragonbox {

// 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.

constexpr int DtoaMinBufferLength = 64;

char* Dtoa(char* buffer, double value);

} // namespace dragonbox
15 changes: 15 additions & 0 deletions lib/vendor/drachennest/impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "schubfach_32.h"
#include "schubfach_64.h"
#include "dragonbox.h"

extern "C" char* nimtoStringDragonboxImplDouble(char* buffer, double value){
return dragonbox::Dtoa(buffer, value);
}

extern "C" char* nimSchubfachFtoa(char* buffer, float value){
return schubfach::Ftoa(buffer, value);
}

extern "C" char* nimSchubfachDtoa(char* buffer, double value){
return schubfach::Dtoa(buffer, value);
}
2 changes: 1 addition & 1 deletion lib/vendor/drachennest/readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# files
dragonbox.cc: adapted from https://github.com/abolz/Drachennest/blob/master/src/dragonbox.cc
LICENSE.txt: copied from https://github.com/abolz/Drachennest/blob/master/LICENSE
dragonbox.*,schubfach_32.*: adapted from https://github.com/abolz/Drachennest/blob/master/src/dragonbox.cc
Loading

0 comments on commit 097fc18

Please sign in to comment.