mirror of
https://github.com/janet-lang/janet
synced 2025-10-29 14:47:42 +00:00
New custom strtod implementation.
This commit is contained in:
@@ -26,21 +26,20 @@ int main() {
|
||||
free(string);
|
||||
|
||||
if (pres.status == DST_PARSE_ERROR) {
|
||||
dst_puts(dst_formatc("parse error at %d: %s\n", pres.bytes_read, pres.result.error));
|
||||
dst_puts(dst_formatc("parse error at %d: %S\n", pres.bytes_read, pres.result.error));
|
||||
return 1;
|
||||
}
|
||||
assert(pres.status == DST_PARSE_OK);
|
||||
dst_puts(dst_formatc("\nparse result: %v\n\n", pres.result.value));
|
||||
dst_puts(dst_formatc("\nparse map result: %v\n\n", pres.map));
|
||||
|
||||
/*
|
||||
opts.flags = 0;
|
||||
opts.source = pres.result.value;
|
||||
opts.parsemap = dst_wrap_nil();
|
||||
opts.sourcemap = pres.map;
|
||||
|
||||
ares = dst_asm(opts);
|
||||
if (ares.status == DST_ASSEMBLE_ERROR) {
|
||||
dst_puts(dst_formatc("assembly error: %s\n", ares.result.error));
|
||||
dst_puts(dst_formatc("assembly error: %S\n", ares.result.error));
|
||||
dst_puts(dst_formatc("error location: %d, %d\n", ares.error_start, ares.error_end));
|
||||
return 1;
|
||||
}
|
||||
assert(ares.status == DST_ASSEMBLE_OK);
|
||||
@@ -49,7 +48,6 @@ int main() {
|
||||
|
||||
dst_run(dst_wrap_function(func));
|
||||
dst_puts(dst_formatc("result: %v\n", dst_vm_fiber->ret));
|
||||
*/
|
||||
|
||||
dst_deinit();
|
||||
|
||||
|
||||
122
unittests/strtod_test.c
Normal file
122
unittests/strtod_test.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Calvin Rose
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Use a custom double parser instead of libc's strtod for better portability
|
||||
* and control. Also, uses a less strict rounding method than ieee to not incur
|
||||
* the cost of 4000 loc and dependence on arbitary precision arithmetic. There
|
||||
* is no plan to use arbitrary precision arithmetic for parsing numbers, and a
|
||||
* formal rounding mode has yet to be chosen (round towards 0 seems
|
||||
* reasonable).
|
||||
*
|
||||
* This version has been modified for much greater flexibility in parsing, such
|
||||
* as choosing the radix, supporting integer output, and returning DstValues
|
||||
* directly.
|
||||
*
|
||||
* Numbers are of the form [-+]R[rR]I.F[eE&][-+]X where R is the radix, I is
|
||||
* the integer part, F is the fractional part, and X is the exponent. All
|
||||
* signs, radix, decimal point, fractional part, and exponent can be ommited.
|
||||
* The number will be considered and integer if the there is no decimal point
|
||||
* and no exponent. Any number greater the 2^32-1 or less than -(2^32) will be
|
||||
* coerced to a double. If there is an error, the function dst_scan_number will
|
||||
* return a dst nil. The radix is assumed to be 10 if omitted, and the E
|
||||
* separator for the exponent can only be used when the radix is 10. This is
|
||||
* because E is a vaid digit in bases 15 or greater. For bases greater than 10,
|
||||
* the letters are used as digitis. A through Z correspond to the digits 10
|
||||
* through 35, and the lowercase letters have the same values. The radix number
|
||||
* is always in base 10. For example, a hexidecimal number could be written
|
||||
* '16rdeadbeef'. dst_scan_number also supports some c style syntax for
|
||||
* hexidecimal literals. The previous number could also be written
|
||||
* '0xdeadbeef'. Note that in this case, the number will actually be a double
|
||||
* as it will not fit in the range for a signed 32 bit integer. The string
|
||||
* '0xbeef' would parse to an integer as it is in the range of an int32_t. */
|
||||
|
||||
#include "unit.h"
|
||||
#include <dst/dst.h>
|
||||
#include <math.h>
|
||||
|
||||
DstValue dst_scan_number(const uint8_t *str, int32_t len);
|
||||
|
||||
const char *valid_test_strs[] = {
|
||||
"0",
|
||||
"-0.0",
|
||||
"+0",
|
||||
"123",
|
||||
"-123",
|
||||
"aaaaaa",
|
||||
"+a123",
|
||||
"0.12312",
|
||||
"89.12312",
|
||||
"-123.01231",
|
||||
"123e10",
|
||||
"1203412347981232379183.13013248723478932478923478e12",
|
||||
"120341234798123237918313013248723478932478923478",
|
||||
"999_999_999_999",
|
||||
"8r777",
|
||||
"",
|
||||
"----",
|
||||
" ",
|
||||
"--123",
|
||||
"0xff",
|
||||
"0xff.f",
|
||||
"0xff&-1",
|
||||
"0xfefefe",
|
||||
"1926.4823e11",
|
||||
"0xff_ff_ff_ff",
|
||||
"0xff_ff_ff_ff_ff_ff",
|
||||
"2r1010",
|
||||
"2r10101010001101",
|
||||
"123a",
|
||||
"0.1e510",
|
||||
"4.123123e-308",
|
||||
"4.123123e-320",
|
||||
"1e-308",
|
||||
"1e-309",
|
||||
"9e-308",
|
||||
"9e-309",
|
||||
"919283691283e-309",
|
||||
"9999e302",
|
||||
"123.12312.123",
|
||||
"90.e0.1",
|
||||
"90.e1",
|
||||
".e1"
|
||||
};
|
||||
|
||||
int main() {
|
||||
dst_init();
|
||||
unsigned i;
|
||||
for (i = 0; i < (sizeof(valid_test_strs) / sizeof(void *)); i++) {
|
||||
DstValue out;
|
||||
double refout;
|
||||
const uint8_t *str = (const uint8_t *) valid_test_strs[i];
|
||||
int32_t len = 0; while (str[len]) len++;
|
||||
|
||||
refout = strtod(valid_test_strs[i], NULL);
|
||||
out = dst_scan_number(str, len);
|
||||
dst_puts(dst_formatc("literal: %s, out: %v, refout: %v\n",
|
||||
valid_test_strs[i], out, dst_wrap_real(refout)));
|
||||
|
||||
}
|
||||
uint64_t x = 0x07FFFFFFFFFFFFFF;
|
||||
uint64_t y = 36;
|
||||
|
||||
printf("%llu, %llu\n", x, (x * y) / y);
|
||||
}
|
||||
Reference in New Issue
Block a user