summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Wadman <mattias.wadman@gmail.com>2023-11-29 09:36:33 +0100
committerGitHub <noreply@github.com>2023-11-29 09:36:33 +0100
commit98a206964d59143c6ed9189b91cdb34af1ae5071 (patch)
treee8055db585b3fa602b289b1fc2e725e293600a17
parent16170910332b51f1ff497ef566d6a525acdb5b43 (diff)
Convert decnum to binary64 (double) instead of decimal64
This is what the JSON spec suggests and will also be less confusing compared to other jq implementations and langauges. Related to #2939
-rw-r--r--src/jv.c23
-rw-r--r--tests/jq.test9
2 files changed, 16 insertions, 16 deletions
diff --git a/src/jv.c b/src/jv.c
index ada15fed..4031dc62 100644
--- a/src/jv.c
+++ b/src/jv.c
@@ -213,7 +213,7 @@ enum {
#define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))
// the decimal precision of binary double
-#define DEC_NUBMER_DOUBLE_PRECISION (16)
+#define DEC_NUBMER_DOUBLE_PRECISION (17)
#define DEC_NUMBER_STRING_GUARD (14)
#define DEC_NUBMER_DOUBLE_EXTRA_UNITS ((DEC_NUBMER_DOUBLE_PRECISION - DECNUMDIGITS + DECDPUN - 1)/DECDPUN)
@@ -489,19 +489,15 @@ pthread_getspecific(pthread_key_t key)
#endif
static pthread_key_t dec_ctx_key;
-static pthread_key_t dec_ctx_dbl_key;
static pthread_once_t dec_ctx_once = PTHREAD_ONCE_INIT;
#define DEC_CONTEXT() tsd_dec_ctx_get(&dec_ctx_key)
-#define DEC_CONTEXT_TO_DOUBLE() tsd_dec_ctx_get(&dec_ctx_dbl_key)
// atexit finalizer to clean up the tsd dec contexts if main() exits
// without having called pthread_exit()
void jv_tsd_dec_ctx_fini() {
jv_mem_free(pthread_getspecific(dec_ctx_key));
- jv_mem_free(pthread_getspecific(dec_ctx_dbl_key));
pthread_setspecific(dec_ctx_key, NULL);
- pthread_setspecific(dec_ctx_dbl_key, NULL);
}
void jv_tsd_dec_ctx_init() {
@@ -509,10 +505,6 @@ void jv_tsd_dec_ctx_init() {
fprintf(stderr, "error: cannot create thread specific key");
abort();
}
- if (pthread_key_create(&dec_ctx_dbl_key, jv_mem_free) != 0) {
- fprintf(stderr, "error: cannot create thread specific key");
- abort();
- }
atexit(jv_tsd_dec_ctx_fini);
}
@@ -533,12 +525,6 @@ static decContext* tsd_dec_ctx_get(pthread_key_t *key) {
INT32_MAX - (DECDPUN - 1) - (ctx->emax - ctx->emin - 1));
ctx->traps = 0; /*no errors*/
}
- else if (key == &dec_ctx_dbl_key)
- {
- decContextDefault(ctx, DEC_INIT_DECIMAL64);
- // just to make sure we got this right
- assert(ctx->digits <= DEC_NUBMER_DOUBLE_PRECISION);
- }
if (pthread_setspecific(*key, ctx) != 0) {
fprintf(stderr, "error: cannot store thread specific data");
abort();
@@ -610,6 +596,11 @@ static jv jvp_literal_number_new(const char * literal) {
static double jvp_literal_number_to_double(jv j) {
assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL));
+ decContext dblCtx;
+
+ // init as decimal64 but change digits to allow conversion to binary64 (double)
+ decContextDefault(&dblCtx, DEC_INIT_DECIMAL64);
+ dblCtx.digits = DEC_NUBMER_DOUBLE_PRECISION;
decNumber *p_dec_number = jvp_dec_number_ptr(j);
decNumberDoublePrecision dec_double;
@@ -617,7 +608,7 @@ static double jvp_literal_number_to_double(jv j) {
// reduce the number to the shortest possible form
// that fits into the 64 bit floating point representation
- decNumberReduce(&dec_double.number, p_dec_number, DEC_CONTEXT_TO_DOUBLE());
+ decNumberReduce(&dec_double.number, p_dec_number, &dblCtx);
decNumberToString(&dec_double.number, literal);
diff --git a/tests/jq.test b/tests/jq.test
index 9d0b5928..c5c8cf06 100644
--- a/tests/jq.test
+++ b/tests/jq.test
@@ -1867,6 +1867,15 @@ false
1
1
+# decnum to double conversion
+.[] as $n | $n+0 | [., tostring, . == $n]
+[-9007199254740993, -9007199254740992, 9007199254740992, 9007199254740993, 13911860366432393]
+[-9007199254740992,"-9007199254740992",true]
+[-9007199254740992,"-9007199254740992",true]
+[9007199254740992,"9007199254740992",true]
+[9007199254740992,"9007199254740992",true]
+[13911860366432392,"13911860366432392",true]
+
# abs, fabs, length
abs
"abc"