1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-28 19:19:53 +00:00

Add number test.

This commit is contained in:
Calvin Rose 2018-12-29 01:16:54 -05:00
parent 2bcedd5920
commit b06f7226c4
2 changed files with 70 additions and 19 deletions

57
ctest/number_test.c Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2018 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.
*/
#include <janet/janet.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
/* Compare valid c numbers to system implementation. */
static void test_valid_str(const char *str) {
int err = 0;
double cnum, jnum;
cnum = atof(str);
jnum = janet_scan_number((const uint8_t *) str, strlen(str), &err);
assert(!err);
assert(cnum == jnum);
}
int main() {
janet_init();
test_valid_str("1.0");
test_valid_str("1");
test_valid_str("2.1");
test_valid_str("1e10");
test_valid_str("2e10");
test_valid_str("1e-10");
test_valid_str("2e-10");
test_valid_str("1.123123e10");
test_valid_str("1.123123e-10");
test_valid_str("-1.23e2");
test_valid_str("-4.5e15");
janet_deinit();
return 0;
}

View File

@ -77,15 +77,6 @@ struct Mant {
uint32_t *digits; /* Each digit is base (2 ^ 31). Digits are least significant first. */ uint32_t *digits; /* Each digit is base (2 ^ 31). Digits are least significant first. */
}; };
/* Print number */
static void mant_debug(struct Mant *mant) {
printf("<bigint: 0x%x", mant->first_digit);
for (int i = 0; i < mant->n; i++) {
printf(" 0x%x", mant->digits[i]);
}
printf(">\n");
}
/* Allocate n more digits for mant. Return a pointer to these digits. */ /* Allocate n more digits for mant. Return a pointer to these digits. */
static uint32_t *mant_extra(struct Mant *mant, int32_t n) { static uint32_t *mant_extra(struct Mant *mant, int32_t n) {
int32_t oldn = mant->n; int32_t oldn = mant->n;
@ -206,15 +197,21 @@ static double mant_extract(struct Mant *mant, int32_t exponent2) {
uint64_t d3 = (n > 2) ? mant->digits[n - 3] : (n == 2) ? mant->first_digit : 0; uint64_t d3 = (n > 2) ? mant->digits[n - 3] : (n == 2) ? mant->first_digit : 0;
int lz = clz(d1); int lz = clz(d1);
int nbits = 32 - lz; int nbits = 32 - lz;
top53 = (d2 << (53 - MANT_NBIT)) + (d3 >> (2 * MANT_NBIT - 53)); top53 = (d2 << (54 - MANT_NBIT)) + (d3 >> (2 * MANT_NBIT - 54));
top53 >>= nbits; top53 >>= nbits;
top53 |= (d1 << (53 - nbits)); top53 |= (d1 << (54 - nbits));
if (top53 & 1) top53++;
top53 >>= 1;
if (top53 > 0x1FffffFFFFffffUL) {
top53 >>= 1;
exponent2++;
}
exponent2 += (nbits - 53) + MANT_NBIT * n; exponent2 += (nbits - 53) + MANT_NBIT * n;
} else { } else {
/* One digit */ /* One digit */
top53 = mant->first_digit; top53 = mant->first_digit;
} }
return ldexp((double) top53, exponent2); return ldexp(top53, exponent2);
} }
/* Read in a mantissa and exponent of a certain base, and give /* Read in a mantissa and exponent of a certain base, and give
@ -231,7 +228,7 @@ static double convert(
/* Short circuit zero and huge numbers */ /* Short circuit zero and huge numbers */
if (mant->n == 0 && mant->first_digit == 0) if (mant->n == 0 && mant->first_digit == 0)
return 0.0; return 0.0;
if (exponent > 1022) if (exponent > 1023)
return negative ? -INFINITY : INFINITY; return negative ? -INFINITY : INFINITY;
/* Final value is X = mant * base ^ exponent * 2 ^ exponent2 /* Final value is X = mant * base ^ exponent * 2 ^ exponent2
@ -246,12 +243,8 @@ static double convert(
/* Negative exponents are tricky - we don't want to loose bits /* Negative exponents are tricky - we don't want to loose bits
* from integer division, so we need to premultiply. */ * from integer division, so we need to premultiply. */
if (exponent < 0) { if (exponent < 0) {
mant_lshift_n(mant, 10 - exponent); mant_lshift_n(mant, 20 - exponent);
exponent2 -= (10 - exponent) * MANT_NBIT; exponent2 -= (20 - exponent) * MANT_NBIT;
while (exponent < -3) {
mant_div(mant, (base * base) * (base * base));
exponent += 4;
}
while (exponent < 0) { while (exponent < 0) {
mant_div(mant, base); mant_div(mant, base);
exponent++; exponent++;
@ -381,6 +374,7 @@ double janet_scan_number(
double result = convert(neg, &mant, base, ex); double result = convert(neg, &mant, base, ex);
free(mant.digits); free(mant.digits);
*err = 0;
return result; return result;
error: error: