From 65429b4f102b86c4939cf3bc33877f40ad9768b3 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sun, 27 Dec 2015 23:47:29 -0500 Subject: [PATCH 1/8] Check for valid indices in substring and string-copy. --- extlib/benz/string.c | 874 ++++++++++++++++++++++--------------------- 1 file changed, 446 insertions(+), 428 deletions(-) diff --git a/extlib/benz/string.c b/extlib/benz/string.c index de023afa..7d09eea5 100644 --- a/extlib/benz/string.c +++ b/extlib/benz/string.c @@ -5,509 +5,509 @@ #include "picrin.h" struct pic_chunk { - char *str; - int refcnt; - size_t len; - char buf[1]; + char *str; + int refcnt; + size_t len; + char buf[1]; }; struct pic_rope { - int refcnt; - size_t weight; - struct pic_chunk *chunk; - size_t offset; - struct pic_rope *left, *right; + int refcnt; + size_t weight; + struct pic_chunk *chunk; + size_t offset; + struct pic_rope *left, *right; }; #define CHUNK_INCREF(c) do { \ - (c)->refcnt++; \ - } while (0) + (c)->refcnt++; \ + } while (0) #define CHUNK_DECREF(c) do { \ - struct pic_chunk *c_ = (c); \ - if (! --c_->refcnt) { \ - if (c_->str != c_->buf) \ - pic_free(pic, c_->str); \ - pic_free(pic, c_); \ - } \ - } while (0) + struct pic_chunk *c_ = (c); \ + if (! --c_->refcnt) { \ + if (c_->str != c_->buf) \ + pic_free(pic, c_->str); \ + pic_free(pic, c_); \ + } \ + } while (0) void pic_rope_incref(pic_state PIC_UNUSED(*pic), struct pic_rope *x) { - x->refcnt++; + x->refcnt++; } void pic_rope_decref(pic_state *pic, struct pic_rope *x) { - if (! --x->refcnt) { - if (x->chunk) { - CHUNK_DECREF(x->chunk); - pic_free(pic, x); - return; - } - pic_rope_decref(pic, x->left); - pic_rope_decref(pic, x->right); - pic_free(pic, x); - } + if (! --x->refcnt) { + if (x->chunk) { + CHUNK_DECREF(x->chunk); + pic_free(pic, x); + return; + } + pic_rope_decref(pic, x->left); + pic_rope_decref(pic, x->right); + pic_free(pic, x); + } } static struct pic_chunk * pic_make_chunk(pic_state *pic, const char *str, size_t len) { - struct pic_chunk *c; + struct pic_chunk *c; - c = pic_malloc(pic, sizeof(struct pic_chunk) + len); - c->refcnt = 1; - c->str = c->buf; - c->len = len; - c->buf[len] = 0; - memcpy(c->buf, str, len); + c = pic_malloc(pic, sizeof(struct pic_chunk) + len); + c->refcnt = 1; + c->str = c->buf; + c->len = len; + c->buf[len] = 0; + memcpy(c->buf, str, len); - return c; + return c; } static struct pic_rope * pic_make_rope(pic_state *pic, struct pic_chunk *c) { - struct pic_rope *x; + struct pic_rope *x; - x = pic_malloc(pic, sizeof(struct pic_rope)); - x->refcnt = 1; - x->left = NULL; - x->right = NULL; - x->weight = c->len; - x->offset = 0; - x->chunk = c; /* delegate ownership */ + x = pic_malloc(pic, sizeof(struct pic_rope)); + x->refcnt = 1; + x->left = NULL; + x->right = NULL; + x->weight = c->len; + x->offset = 0; + x->chunk = c; /* delegate ownership */ - return x; + return x; } static pic_str * pic_make_string(pic_state *pic, struct pic_rope *rope) { - pic_str *str; + pic_str *str; - str = (pic_str *)pic_obj_alloc(pic, sizeof(pic_str), PIC_TT_STRING); - str->rope = rope; /* delegate ownership */ - return str; + str = (pic_str *)pic_obj_alloc(pic, sizeof(pic_str), PIC_TT_STRING); + str->rope = rope; /* delegate ownership */ + return str; } static size_t rope_len(struct pic_rope *x) { - return x->weight; + return x->weight; } static char rope_at(struct pic_rope *x, size_t i) { - while (i < x->weight) { - if (x->chunk) { - return x->chunk->str[x->offset + i]; - } - if (i < x->left->weight) { - x = x->left; - } else { - x = x->right; - i -= x->left->weight; - } - } - return -1; + while (i < x->weight) { + if (x->chunk) { + return x->chunk->str[x->offset + i]; + } + if (i < x->left->weight) { + x = x->left; + } else { + x = x->right; + i -= x->left->weight; + } + } + return -1; } static struct pic_rope * rope_cat(pic_state *pic, struct pic_rope *x, struct pic_rope *y) { - struct pic_rope *z; + struct pic_rope *z; - z = pic_malloc(pic, sizeof(struct pic_rope)); - z->refcnt = 1; - z->left = x; - z->right = y; - z->weight = x->weight + y->weight; - z->offset = 0; - z->chunk = NULL; + z = pic_malloc(pic, sizeof(struct pic_rope)); + z->refcnt = 1; + z->left = x; + z->right = y; + z->weight = x->weight + y->weight; + z->offset = 0; + z->chunk = NULL; - pic_rope_incref(pic, x); - pic_rope_incref(pic, y); + pic_rope_incref(pic, x); + pic_rope_incref(pic, y); - return z; + return z; } static struct pic_rope * rope_sub(pic_state *pic, struct pic_rope *x, size_t i, size_t j) { - assert(i <= j); - assert(j <= x->weight); + assert(i <= j); + assert(j <= x->weight); - if (i == 0 && x->weight == j) { - pic_rope_incref(pic, x); - return x; - } + if (i == 0 && x->weight == j) { + pic_rope_incref(pic, x); + return x; + } - if (x->chunk) { - struct pic_rope *y; + if (x->chunk) { + struct pic_rope *y; - y = pic_malloc(pic, sizeof(struct pic_rope)); - y->refcnt = 1; - y->left = NULL; - y->right = NULL; - y->weight = j - i; - y->offset = x->offset + i; - y->chunk = x->chunk; + y = pic_malloc(pic, sizeof(struct pic_rope)); + y->refcnt = 1; + y->left = NULL; + y->right = NULL; + y->weight = j - i; + y->offset = x->offset + i; + y->chunk = x->chunk; - CHUNK_INCREF(x->chunk); + CHUNK_INCREF(x->chunk); - return y; - } + return y; + } - if (j <= x->left->weight) { - return rope_sub(pic, x->left, i, j); - } - else if (x->left->weight <= i) { - return rope_sub(pic, x->right, i - x->left->weight, j - x->left->weight); - } - else { - struct pic_rope *r, *l; + if (j <= x->left->weight) { + return rope_sub(pic, x->left, i, j); + } + else if (x->left->weight <= i) { + return rope_sub(pic, x->right, i - x->left->weight, j - x->left->weight); + } + else { + struct pic_rope *r, *l; - l = rope_sub(pic, x->left, i, x->left->weight); - r = rope_sub(pic, x->right, 0, j - x->left->weight); - x = rope_cat(pic, l, r); + l = rope_sub(pic, x->left, i, x->left->weight); + r = rope_sub(pic, x->right, 0, j - x->left->weight); + x = rope_cat(pic, l, r); - pic_rope_decref(pic, l); - pic_rope_decref(pic, r); + pic_rope_decref(pic, l); + pic_rope_decref(pic, r); - return x; - } + return x; + } } static void flatten(pic_state *pic, struct pic_rope *x, struct pic_chunk *c, size_t offset) { - if (x->chunk) { - memcpy(c->str + offset, x->chunk->str + x->offset, x->weight); - CHUNK_DECREF(x->chunk); + if (x->chunk) { + memcpy(c->str + offset, x->chunk->str + x->offset, x->weight); + CHUNK_DECREF(x->chunk); - x->chunk = c; - x->offset = offset; - CHUNK_INCREF(c); - return; - } - flatten(pic, x->left, c, offset); - flatten(pic, x->right, c, offset + x->left->weight); + x->chunk = c; + x->offset = offset; + CHUNK_INCREF(c); + return; + } + flatten(pic, x->left, c, offset); + flatten(pic, x->right, c, offset + x->left->weight); - pic_rope_decref(pic, x->left); - pic_rope_decref(pic, x->right); - x->left = x->right = NULL; - x->chunk = c; - x->offset = offset; - CHUNK_INCREF(c); + pic_rope_decref(pic, x->left); + pic_rope_decref(pic, x->right); + x->left = x->right = NULL; + x->chunk = c; + x->offset = offset; + CHUNK_INCREF(c); } static const char * rope_cstr(pic_state *pic, struct pic_rope *x) { - struct pic_chunk *c; + struct pic_chunk *c; - if (x->chunk && x->offset == 0 && x->weight == x->chunk->len) { - return x->chunk->str; /* reuse cached chunk */ - } + if (x->chunk && x->offset == 0 && x->weight == x->chunk->len) { + return x->chunk->str; /* reuse cached chunk */ + } - c = pic_malloc(pic, sizeof(struct pic_chunk) + x->weight); - c->refcnt = 1; - c->len = x->weight; - c->str = c->buf; - c->str[c->len] = '\0'; + c = pic_malloc(pic, sizeof(struct pic_chunk) + x->weight); + c->refcnt = 1; + c->len = x->weight; + c->str = c->buf; + c->str[c->len] = '\0'; - flatten(pic, x, c, 0); + flatten(pic, x, c, 0); - CHUNK_DECREF(c); - return c->str; + CHUNK_DECREF(c); + return c->str; } pic_str * pic_make_str(pic_state *pic, const char *str, int len) { - if (str == NULL && len > 0) { - pic_errorf(pic, "zero length specified against NULL ptr"); - } - return pic_make_string(pic, pic_make_rope(pic, pic_make_chunk(pic, str, len))); + if (str == NULL && len > 0) { + pic_errorf(pic, "zero length specified against NULL ptr"); + } + return pic_make_string(pic, pic_make_rope(pic, pic_make_chunk(pic, str, len))); } pic_str * pic_make_str_cstr(pic_state *pic, const char *cstr) { - return pic_make_str(pic, cstr, strlen(cstr)); + return pic_make_str(pic, cstr, strlen(cstr)); } int pic_str_len(pic_str *str) { - return rope_len(str->rope); + return rope_len(str->rope); } char pic_str_ref(pic_state *pic, pic_str *str, int i) { - int c; + int c; - c = rope_at(str->rope, i); - if (c == -1) { - pic_errorf(pic, "index out of range %d", i); - } - return (char)c; + c = rope_at(str->rope, i); + if (c == -1) { + pic_errorf(pic, "index out of range %d", i); + } + return (char)c; } pic_str * pic_str_cat(pic_state *pic, pic_str *a, pic_str *b) { - return pic_make_string(pic, rope_cat(pic, a->rope, b->rope)); + return pic_make_string(pic, rope_cat(pic, a->rope, b->rope)); } pic_str * pic_str_sub(pic_state *pic, pic_str *str, int s, int e) { - return pic_make_string(pic, rope_sub(pic, str->rope, s, e)); + return pic_make_string(pic, rope_sub(pic, str->rope, s, e)); } int pic_str_cmp(pic_state *pic, pic_str *str1, pic_str *str2) { - return strcmp(pic_str_cstr(pic, str1), pic_str_cstr(pic, str2)); + return strcmp(pic_str_cstr(pic, str1), pic_str_cstr(pic, str2)); } const char * pic_str_cstr(pic_state *pic, pic_str *str) { - return rope_cstr(pic, str->rope); + return rope_cstr(pic, str->rope); } pic_value pic_xvfformat(pic_state *pic, xFILE *file, const char *fmt, va_list ap) { - char c; - pic_value irrs = pic_nil_value(); + char c; + pic_value irrs = pic_nil_value(); - while ((c = *fmt++)) { - switch (c) { - default: - xfputc(pic, c, file); - break; - case '%': - c = *fmt++; - if (! c) - goto exit; - switch (c) { - default: - xfputc(pic, c, file); - break; - case '%': - xfputc(pic, '%', file); - break; - case 'c': - xfprintf(pic, file, "%c", va_arg(ap, int)); - break; - case 's': - xfprintf(pic, file, "%s", va_arg(ap, const char *)); - break; - case 'd': - xfprintf(pic, file, "%d", va_arg(ap, int)); - break; - case 'p': - xfprintf(pic, file, "%p", va_arg(ap, void *)); - break; - case 'f': - xfprintf(pic, file, "%f", va_arg(ap, double)); - break; - } - break; - case '~': - c = *fmt++; - if (! c) - goto exit; - switch (c) { - default: - xfputc(pic, c, file); - break; - case '~': - xfputc(pic, '~', file); - break; - case '%': - xfputc(pic, '\n', file); - break; - case 'a': - irrs = pic_cons(pic, pic_fdisplay(pic, va_arg(ap, pic_value), file), irrs); - break; - case 's': - irrs = pic_cons(pic, pic_fwrite(pic, va_arg(ap, pic_value), file), irrs); - break; - } - break; - } - } + while ((c = *fmt++)) { + switch (c) { + default: + xfputc(pic, c, file); + break; + case '%': + c = *fmt++; + if (! c) + goto exit; + switch (c) { + default: + xfputc(pic, c, file); + break; + case '%': + xfputc(pic, '%', file); + break; + case 'c': + xfprintf(pic, file, "%c", va_arg(ap, int)); + break; + case 's': + xfprintf(pic, file, "%s", va_arg(ap, const char *)); + break; + case 'd': + xfprintf(pic, file, "%d", va_arg(ap, int)); + break; + case 'p': + xfprintf(pic, file, "%p", va_arg(ap, void *)); + break; + case 'f': + xfprintf(pic, file, "%f", va_arg(ap, double)); + break; + } + break; + case '~': + c = *fmt++; + if (! c) + goto exit; + switch (c) { + default: + xfputc(pic, c, file); + break; + case '~': + xfputc(pic, '~', file); + break; + case '%': + xfputc(pic, '\n', file); + break; + case 'a': + irrs = pic_cons(pic, pic_fdisplay(pic, va_arg(ap, pic_value), file), irrs); + break; + case 's': + irrs = pic_cons(pic, pic_fwrite(pic, va_arg(ap, pic_value), file), irrs); + break; + } + break; + } + } exit: - return pic_reverse(pic, irrs); + return pic_reverse(pic, irrs); } pic_value pic_xvformat(pic_state *pic, const char *fmt, va_list ap) { - struct pic_port *port; - pic_value irrs; + struct pic_port *port; + pic_value irrs; - port = pic_open_output_string(pic); + port = pic_open_output_string(pic); - irrs = pic_xvfformat(pic, port->file, fmt, ap); - irrs = pic_cons(pic, pic_obj_value(pic_get_output_string(pic, port)), irrs); + irrs = pic_xvfformat(pic, port->file, fmt, ap); + irrs = pic_cons(pic, pic_obj_value(pic_get_output_string(pic, port)), irrs); - pic_close_port(pic, port); - return irrs; + pic_close_port(pic, port); + return irrs; } pic_value pic_xformat(pic_state *pic, const char *fmt, ...) { - va_list ap; - pic_value objs; + va_list ap; + pic_value objs; - va_start(ap, fmt); - objs = pic_xvformat(pic, fmt, ap); - va_end(ap); + va_start(ap, fmt); + objs = pic_xvformat(pic, fmt, ap); + va_end(ap); - return objs; + return objs; } void pic_vfformat(pic_state *pic, xFILE *file, const char *fmt, va_list ap) { - pic_xvfformat(pic, file, fmt, ap); + pic_xvfformat(pic, file, fmt, ap); } pic_str * pic_vformat(pic_state *pic, const char *fmt, va_list ap) { - struct pic_port *port; - pic_str *str; + struct pic_port *port; + pic_str *str; - port = pic_open_output_string(pic); + port = pic_open_output_string(pic); - pic_vfformat(pic, port->file, fmt, ap); - str = pic_get_output_string(pic, port); + pic_vfformat(pic, port->file, fmt, ap); + str = pic_get_output_string(pic, port); - pic_close_port(pic, port); - return str; + pic_close_port(pic, port); + return str; } pic_str * pic_format(pic_state *pic, const char *fmt, ...) { - va_list ap; - pic_str *str; + va_list ap; + pic_str *str; - va_start(ap, fmt); - str = pic_vformat(pic, fmt, ap); - va_end(ap); + va_start(ap, fmt); + str = pic_vformat(pic, fmt, ap); + va_end(ap); - return str; + return str; } static pic_value pic_str_string_p(pic_state *pic) { - pic_value v; + pic_value v; - pic_get_args(pic, "o", &v); + pic_get_args(pic, "o", &v); - return pic_bool_value(pic_str_p(v)); + return pic_bool_value(pic_str_p(v)); } static pic_value pic_str_string(pic_state *pic) { - int argc, i; - pic_value *argv; - pic_str *str; - char *buf; + int argc, i; + pic_value *argv; + pic_str *str; + char *buf; - pic_get_args(pic, "*", &argc, &argv); + pic_get_args(pic, "*", &argc, &argv); - buf = pic_malloc(pic, argc); + buf = pic_malloc(pic, argc); - for (i = 0; i < argc; ++i) { - pic_assert_type(pic, argv[i], char); - buf[i] = pic_char(argv[i]); - } + for (i = 0; i < argc; ++i) { + pic_assert_type(pic, argv[i], char); + buf[i] = pic_char(argv[i]); + } - str = pic_make_str(pic, buf, argc); - pic_free(pic, buf); + str = pic_make_str(pic, buf, argc); + pic_free(pic, buf); - return pic_obj_value(str); + return pic_obj_value(str); } static pic_value pic_str_make_string(pic_state *pic) { - int len; - char c = ' '; - char *buf; - pic_value ret; + int len; + char c = ' '; + char *buf; + pic_value ret; - pic_get_args(pic, "i|c", &len, &c); + pic_get_args(pic, "i|c", &len, &c); - buf = pic_malloc(pic, len); - memset(buf, c, len); + buf = pic_malloc(pic, len); + memset(buf, c, len); - ret = pic_obj_value(pic_make_str(pic, buf, len)); + ret = pic_obj_value(pic_make_str(pic, buf, len)); - pic_free(pic, buf); - return ret; + pic_free(pic, buf); + return ret; } static pic_value pic_str_string_length(pic_state *pic) { - pic_str *str; + pic_str *str; - pic_get_args(pic, "s", &str); + pic_get_args(pic, "s", &str); - return pic_int_value(pic_str_len(str)); + return pic_int_value(pic_str_len(str)); } static pic_value pic_str_string_ref(pic_state *pic) { - pic_str *str; - int k; + pic_str *str; + int k; - pic_get_args(pic, "si", &str, &k); + pic_get_args(pic, "si", &str, &k); - return pic_char_value(pic_str_ref(pic, str, k)); + return pic_char_value(pic_str_ref(pic, str, k)); } #define DEFINE_STRING_CMP(name, op) \ - static pic_value \ - pic_str_string_##name(pic_state *pic) \ - { \ - int argc, i; \ - pic_value *argv; \ - \ - pic_get_args(pic, "*", &argc, &argv); \ - \ - if (argc < 1 || ! pic_str_p(argv[0])) { \ - return pic_false_value(); \ - } \ - \ - for (i = 1; i < argc; ++i) { \ - if (! pic_str_p(argv[i])) { \ + static pic_value \ + pic_str_string_##name(pic_state *pic) \ + { \ + int argc, i; \ + pic_value *argv; \ + \ + pic_get_args(pic, "*", &argc, &argv); \ + \ + if (argc < 1 || ! pic_str_p(argv[0])) { \ + return pic_false_value(); \ + } \ + \ + for (i = 1; i < argc; ++i) { \ + if (! pic_str_p(argv[i])) { \ return pic_false_value(); \ - } \ - if (! (pic_str_cmp(pic, pic_str_ptr(argv[i-1]), pic_str_ptr(argv[i])) op 0)) { \ + } \ + if (! (pic_str_cmp(pic, pic_str_ptr(argv[i-1]), pic_str_ptr(argv[i])) op 0)) { \ return pic_false_value(); \ - } \ - } \ - return pic_true_value(); \ - } + } \ + } \ + return pic_true_value(); \ + } DEFINE_STRING_CMP(eq, ==) DEFINE_STRING_CMP(lt, <) @@ -518,200 +518,218 @@ DEFINE_STRING_CMP(ge, >=) static pic_value pic_str_string_copy(pic_state *pic) { - pic_str *str; - int n, start, end; + pic_str *str; + int n, start, end, len; - n = pic_get_args(pic, "s|ii", &str, &start, &end); + n = pic_get_args(pic, "s|ii", &str, &start, &end); - switch (n) { - case 1: - start = 0; - case 2: - end = pic_str_len(str); - } + len = pic_str_len(str); - return pic_obj_value(pic_str_sub(pic, str, start, end)); + switch (n) { + case 1: + start = 0; + case 2: + end = len; + } + +#if 0 +#if 0 + if (start < 0) start = 0; /* should an error be reported? */ + if (end > len) end = len; /* should an error be reported? */ +#else + if ((start < 0) || (end < 0) || (start > len) || (end > len)) + pic_errorf(pic, "string-copy: invalid index"); +#endif + if (end < start) /* surely this is an error!? */ + pic_errorf(pic, "string-copy: start index > end index"); +#else + /* simplest version to catch all cases as errors */ + if ((start < 0) || (end > len) || (end < start)) + pic_errorf(pic, "string-copy: invalid index"); +#endif + + return pic_obj_value(pic_str_sub(pic, str, start, end)); } static pic_value pic_str_string_append(pic_state *pic) { - int argc, i; - pic_value *argv; - pic_str *str; + int argc, i; + pic_value *argv; + pic_str *str; - pic_get_args(pic, "*", &argc, &argv); + pic_get_args(pic, "*", &argc, &argv); - str = pic_make_str(pic, NULL, 0); - for (i = 0; i < argc; ++i) { - if (! pic_str_p(argv[i])) { - pic_errorf(pic, "type error"); - } - str = pic_str_cat(pic, str, pic_str_ptr(argv[i])); - } - return pic_obj_value(str); + str = pic_make_str(pic, NULL, 0); + for (i = 0; i < argc; ++i) { + if (! pic_str_p(argv[i])) { + pic_errorf(pic, "type error"); + } + str = pic_str_cat(pic, str, pic_str_ptr(argv[i])); + } + return pic_obj_value(str); } static pic_value pic_str_string_map(pic_state *pic) { - struct pic_proc *proc; - pic_value *argv, vals, val; - int argc, i, len, j; - pic_str *str; - char *buf; + struct pic_proc *proc; + pic_value *argv, vals, val; + int argc, i, len, j; + pic_str *str; + char *buf; - pic_get_args(pic, "l*", &proc, &argc, &argv); + pic_get_args(pic, "l*", &proc, &argc, &argv); - if (argc == 0) { - pic_errorf(pic, "string-map: one or more strings expected, but got zero"); - } else { - pic_assert_type(pic, argv[0], str); - len = pic_str_len(pic_str_ptr(argv[0])); - } - for (i = 1; i < argc; ++i) { - pic_assert_type(pic, argv[i], str); + if (argc == 0) { + pic_errorf(pic, "string-map: one or more strings expected, but got zero"); + } else { + pic_assert_type(pic, argv[0], str); + len = pic_str_len(pic_str_ptr(argv[0])); + } + for (i = 1; i < argc; ++i) { + pic_assert_type(pic, argv[i], str); - len = len < pic_str_len(pic_str_ptr(argv[i])) - ? len - : pic_str_len(pic_str_ptr(argv[i])); - } - buf = pic_malloc(pic, len); + len = len < pic_str_len(pic_str_ptr(argv[i])) + ? len + : pic_str_len(pic_str_ptr(argv[i])); + } + buf = pic_malloc(pic, len); - pic_try { - for (i = 0; i < len; ++i) { - vals = pic_nil_value(); - for (j = 0; j < argc; ++j) { - pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); - } - val = pic_apply_list(pic, proc, vals); + pic_try { + for (i = 0; i < len; ++i) { + vals = pic_nil_value(); + for (j = 0; j < argc; ++j) { + pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); + } + val = pic_apply_list(pic, proc, vals); - pic_assert_type(pic, val, char); - buf[i] = pic_char(val); - } - str = pic_make_str(pic, buf, len); - } - pic_catch { - pic_free(pic, buf); - pic_raise(pic, pic->err); - } + pic_assert_type(pic, val, char); + buf[i] = pic_char(val); + } + str = pic_make_str(pic, buf, len); + } + pic_catch { + pic_free(pic, buf); + pic_raise(pic, pic->err); + } - pic_free(pic, buf); + pic_free(pic, buf); - return pic_obj_value(str); + return pic_obj_value(str); } static pic_value pic_str_string_for_each(pic_state *pic) { - struct pic_proc *proc; - int argc, len, i, j; - pic_value *argv, vals; + struct pic_proc *proc; + int argc, len, i, j; + pic_value *argv, vals; - pic_get_args(pic, "l*", &proc, &argc, &argv); + pic_get_args(pic, "l*", &proc, &argc, &argv); - if (argc == 0) { - pic_errorf(pic, "string-map: one or more strings expected, but got zero"); - } else { - pic_assert_type(pic, argv[0], str); - len = pic_str_len(pic_str_ptr(argv[0])); - } - for (i = 1; i < argc; ++i) { - pic_assert_type(pic, argv[i], str); + if (argc == 0) { + pic_errorf(pic, "string-map: one or more strings expected, but got zero"); + } else { + pic_assert_type(pic, argv[0], str); + len = pic_str_len(pic_str_ptr(argv[0])); + } + for (i = 1; i < argc; ++i) { + pic_assert_type(pic, argv[i], str); - len = len < pic_str_len(pic_str_ptr(argv[i])) - ? len - : pic_str_len(pic_str_ptr(argv[i])); - } + len = len < pic_str_len(pic_str_ptr(argv[i])) + ? len + : pic_str_len(pic_str_ptr(argv[i])); + } - for (i = 0; i < len; ++i) { - vals = pic_nil_value(); - for (j = 0; j < argc; ++j) { - pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); - } - pic_apply_list(pic, proc, vals); - } + for (i = 0; i < len; ++i) { + vals = pic_nil_value(); + for (j = 0; j < argc; ++j) { + pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); + } + pic_apply_list(pic, proc, vals); + } - return pic_undef_value(); + return pic_undef_value(); } static pic_value pic_str_list_to_string(pic_state *pic) { - pic_str *str; - pic_value list, e, it; - int i; - char *buf; + pic_str *str; + pic_value list, e, it; + int i; + char *buf; - pic_get_args(pic, "o", &list); + pic_get_args(pic, "o", &list); - if (pic_length(pic, list) == 0) { - return pic_obj_value(pic_make_str(pic, NULL, 0)); - } + if (pic_length(pic, list) == 0) { + return pic_obj_value(pic_make_str(pic, NULL, 0)); + } - buf = pic_malloc(pic, pic_length(pic, list)); + buf = pic_malloc(pic, pic_length(pic, list)); - pic_try { - i = 0; - pic_for_each (e, list, it) { - pic_assert_type(pic, e, char); + pic_try { + i = 0; + pic_for_each (e, list, it) { + pic_assert_type(pic, e, char); - buf[i++] = pic_char(e); - } + buf[i++] = pic_char(e); + } - str = pic_make_str(pic, buf, i); - } - pic_catch { - pic_free(pic, buf); - pic_raise(pic, pic->err); - } - pic_free(pic, buf); + str = pic_make_str(pic, buf, i); + } + pic_catch { + pic_free(pic, buf); + pic_raise(pic, pic->err); + } + pic_free(pic, buf); - return pic_obj_value(str); + return pic_obj_value(str); } static pic_value pic_str_string_to_list(pic_state *pic) { - pic_str *str; - pic_value list; - int n, start, end, i; + pic_str *str; + pic_value list; + int n, start, end, i; - n = pic_get_args(pic, "s|ii", &str, &start, &end); + n = pic_get_args(pic, "s|ii", &str, &start, &end); - switch (n) { - case 1: - start = 0; - case 2: - end = pic_str_len(str); - } + switch (n) { + case 1: + start = 0; + case 2: + end = pic_str_len(str); + } - list = pic_nil_value(); + list = pic_nil_value(); - for (i = start; i < end; ++i) { - pic_push(pic, pic_char_value(pic_str_ref(pic, str, i)), list); - } - return pic_reverse(pic, list); + for (i = start; i < end; ++i) { + pic_push(pic, pic_char_value(pic_str_ref(pic, str, i)), list); + } + return pic_reverse(pic, list); } void pic_init_str(pic_state *pic) { - pic_defun(pic, "string?", pic_str_string_p); - pic_defun(pic, "string", pic_str_string); - pic_defun(pic, "make-string", pic_str_make_string); - pic_defun(pic, "string-length", pic_str_string_length); - pic_defun(pic, "string-ref", pic_str_string_ref); - pic_defun(pic, "string-copy", pic_str_string_copy); - pic_defun(pic, "string-append", pic_str_string_append); - pic_defun(pic, "string-map", pic_str_string_map); - pic_defun(pic, "string-for-each", pic_str_string_for_each); - pic_defun(pic, "list->string", pic_str_list_to_string); - pic_defun(pic, "string->list", pic_str_string_to_list); + pic_defun(pic, "string?", pic_str_string_p); + pic_defun(pic, "string", pic_str_string); + pic_defun(pic, "make-string", pic_str_make_string); + pic_defun(pic, "string-length", pic_str_string_length); + pic_defun(pic, "string-ref", pic_str_string_ref); + pic_defun(pic, "string-copy", pic_str_string_copy); + pic_defun(pic, "string-append", pic_str_string_append); + pic_defun(pic, "string-map", pic_str_string_map); + pic_defun(pic, "string-for-each", pic_str_string_for_each); + pic_defun(pic, "list->string", pic_str_list_to_string); + pic_defun(pic, "string->list", pic_str_string_to_list); - pic_defun(pic, "string=?", pic_str_string_eq); - pic_defun(pic, "string?", pic_str_string_gt); - pic_defun(pic, "string<=?", pic_str_string_le); - pic_defun(pic, "string>=?", pic_str_string_ge); + pic_defun(pic, "string=?", pic_str_string_eq); + pic_defun(pic, "string?", pic_str_string_gt); + pic_defun(pic, "string<=?", pic_str_string_le); + pic_defun(pic, "string>=?", pic_str_string_ge); } From be33d016e91c042725583f03d23bda65fa10c216 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Fri, 8 Jan 2016 15:55:00 -0500 Subject: [PATCH 2/8] Refactor read_unsigned to prepare for pluggable atod --- .gitignore | 1 + extlib/benz/include/picrin/compat.h | 63 +++++++++++++ extlib/benz/read.c | 136 +++++++++------------------- 3 files changed, 109 insertions(+), 91 deletions(-) diff --git a/.gitignore b/.gitignore index c799dc45..d31d791a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ GTAGS _build _static _template +.DS_Store diff --git a/extlib/benz/include/picrin/compat.h b/extlib/benz/include/picrin/compat.h index 30af63b9..4794b717 100644 --- a/extlib/benz/include/picrin/compat.h +++ b/extlib/benz/include/picrin/compat.h @@ -213,6 +213,69 @@ strcpy(char *dst, const char *src) return d; } +PIC_INLINE double +atof(const char *nptr) +{ + int c; + double f, g, h; + int exp, s, i, e; + unsigned u; + + /* note that picrin_read always assures that *nptr is a digit, never a '+' or '-' */ + /* in other words, the result of atof will always be positive */ + + /* mantissa */ + /* pre '.' */ + u = *nptr++ - '0'; + while (isdigit(c = *nptr)) { + u = u * 10 + (*nptr++ - '0'); + } + if (c == '.') { + /* after '.' */ + g = 0, e = 0; + while (isdigit(c = *nptr)) { + g = g * 10 + (*nptr++ - '0'); + e++; + } + h = 1.0; + while (e-- > 0) { + h /= 10; + } + f = u + g * h; + } + else { + f = u; + } + /* suffix, i.e., exponent */ + s = 0; + exp = 0; + c = *nptr; + + if (c == 'e' && c == 'E') { + nptr++; + switch ((c = *nptr++)) { + case '-': + s = 1; + case '+': + c = *nptr++; + default: + exp = c - '0'; + while (isdigit(c = *nptr)) { + exp = exp * 10 + (*nptr++ - '0'); + } + } + } + e = 10; + for (i = 0; exp; ++i) { + if ((exp & 1) != 0) { + f = s ? f / e : (f * e); + } + e *= e; + exp >>= 1; + } + return f; +} + #endif #if PIC_ENABLE_STDIO diff --git a/extlib/benz/read.c b/extlib/benz/read.c index 618317c9..5299e540 100644 --- a/extlib/benz/read.c +++ b/extlib/benz/read.c @@ -237,104 +237,58 @@ read_uinteger(pic_state *pic, struct pic_port *port, int c) return u; } -static int -read_suffix(pic_state *pic, struct pic_port *port) -{ - int c, s = 1; - - c = peek(pic, port); - - if (c != 'e' && c != 'E') { - return 0; - } - - next(pic, port); - - switch ((c = next(pic, port))) { - case '-': - s = -1; - case '+': - c = next(pic, port); - default: - return s * read_uinteger(pic, port, c); - } -} - static pic_value read_unsigned(pic_state *pic, struct pic_port *port, int c) { - unsigned u; - int exp, s, i, e; +#define ATOF_BUF_SIZE (64) + char buf[ATOF_BUF_SIZE]; + double flt; + int idx = 0; /* index into buffer */ + int dpe = 0; /* the number of '.' or 'e' characters seen */ - u = read_uinteger(pic, port, c); - - switch (peek(pic, port)) { -#if PIC_ENABLE_LIBC - case '.': { - char buf[256]; - i = sprintf(buf, "%d", u); - buf[i++] = next(pic, port); - while (isdigit(c = peek(pic, port))) { - buf[i++] = next(pic, port); - } - sprintf(buf + i, "e%d", read_suffix(pic, port)); - return pic_float_value(atof(buf)); + if (! isdigit(c)) { + read_error(pic, "expected one or more digits", pic_list1(pic, pic_char_value(c))); } -#else - case '.': { - double f, g, h; - next(pic, port); - g = 0, e = 0; - while (isdigit(c = peek(pic, port))) { - g = g * 10 + (next(pic, port) - '0'); - e++; - } - h = 1.0; - while (e-- > 0) { - h /= 10; - } - f = u + g * h; - - exp = read_suffix(pic, port); - if (exp >= 0) { - s = 0; - } else { - exp = -exp; - s = 1; - } - - e = 10; - for (i = 0; exp; ++i) { - if ((exp & 1) != 0) { - f = s ? f / e : (f * e); - } - e *= e; - exp >>= 1; - } - return pic_float_value(f); + buf[idx++] = (char )c; + while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) { + buf[idx++] = (char )next(pic, port); } -#endif - - default: - exp = read_suffix(pic, port); - if (exp >= 0) { - s = 0; - } else { - exp = -exp; - s = 1; + if ('.' == peek(pic, port) && idx < ATOF_BUF_SIZE) { + dpe++; + buf[idx++] = (char )next(pic, port); + while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) { + buf[idx++] = (char )next(pic, port); } - - e = 10; - for (i = 0; exp; ++i) { - if ((exp & 1) != 0) { - u = s ? u / e : (u * e); - } - e *= e; - exp >>= 1; - } - - return pic_int_value(u); } + c = peek(pic, port); + + if ((c == 'e' || c == 'E') && idx < (ATOF_BUF_SIZE - 2)) { + dpe++; + buf[idx++] = (char )next(pic, port); + switch ((c = peek(pic, port))) { + case '-': + case '+': + buf[idx++] = (char )next(pic, port); + break; + default: + break; + } + if (! isdigit(peek(pic, port))) { + read_error(pic, "expected one or more digits", pic_list1(pic, pic_char_value(c))); + } + while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) { + buf[idx++] = (char )next(pic, port); + } + } + if (idx >= ATOF_BUF_SIZE) + read_error(pic, "number too large", + pic_obj_value(pic_make_str(pic, (const char *)buf, ATOF_BUF_SIZE))); + buf[idx] = 0; + flt = atof(buf); + + if (dpe == 0 && pic_valid_int(flt)) + return pic_int_value((int )flt); + return pic_float_value(flt); } static pic_value @@ -346,7 +300,7 @@ read_number(pic_state *pic, struct pic_port *port, int c) static pic_value negate(pic_value n) { - if (pic_int_p(n)) { + if (pic_int_p(n) && (INT_MIN != pic_int(n))) { return pic_int_value(-pic_int(n)); } else { return pic_float_value(-pic_float(n)); From 4ef9394c0bf324b5c064fc6e72ff5e9d6734dcbf Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Fri, 8 Jan 2016 17:30:21 -0500 Subject: [PATCH 3/8] Refactor xvfprintf to prepare for pluggable dtoa --- extlib/benz/file.c | 31 +--------------- extlib/benz/include/picrin/compat.h | 57 +++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/extlib/benz/file.c b/extlib/benz/file.c index c0b2a243..e2d1cd67 100644 --- a/extlib/benz/file.c +++ b/extlib/benz/file.c @@ -345,39 +345,12 @@ int xvfprintf(pic_state *pic, xFILE *stream, const char *fmt, va_list ap) { ival = va_arg(ap, int); cnt += print_int(pic, stream, ival, 10); break; -#if PIC_ENABLE_LIBC case 'f': { - char buf[100]; - sprintf(buf, "%g", va_arg(ap, double)); + char buf[64]; + pic_dtoa(va_arg(ap, double), buf); cnt += xfputs(pic, buf, stream); break; } -#else -# define fabs(x) ((x) >= 0 ? (x) : -(x)) - case 'f': { - double dval = va_arg(ap, double); - long lval; - if (dval < 0) { - dval = -dval; - xputc(pic, '-', stream); - cnt++; - } - lval = (long)dval; - cnt += print_int(pic, stream, lval, 10); - xputc(pic, '.', stream); - cnt++; - dval -= lval; - if ((ival = fabs(dval) * 1e4 + 0.5) == 0) { - cnt += xfputs(pic, "0000", stream); - } else { - if (ival < 1000) xputc(pic, '0', stream); cnt++; - if (ival < 100) xputc(pic, '0', stream); cnt++; - if (ival < 10) xputc(pic, '0', stream); cnt++; - cnt += print_int(pic, stream, ival, 10); - } - break; - } -#endif case 'c': ival = va_arg(ap, int); cnt += xfputc(pic, ival, stream); diff --git a/extlib/benz/include/picrin/compat.h b/extlib/benz/include/picrin/compat.h index 4794b717..95c3a46d 100644 --- a/extlib/benz/include/picrin/compat.h +++ b/extlib/benz/include/picrin/compat.h @@ -231,6 +231,7 @@ atof(const char *nptr) u = u * 10 + (*nptr++ - '0'); } if (c == '.') { + nptr++; /* after '.' */ g = 0, e = 0; while (isdigit(c = *nptr)) { @@ -280,6 +281,62 @@ atof(const char *nptr) #if PIC_ENABLE_STDIO # include + +PIC_INLINE void +pic_dtoa(double dval, char *buf) +{ + sprintf(buf, "%g", dval); +} + +#else + +PIC_INLINE void +pic_dtoa(double dval, char *buf) +{ +# define fabs(x) ((x) >= 0 ? (x) : -(x)) + long lval, tlval; + int ival; + int scnt, ecnt, cnt = 0; + if (dval < 0) { + dval = -dval; + buf[cnt++] = '-'; + } + lval = tlval = (long)dval; + scnt = cnt; + do { + buf[cnt++] = '0' + (tlval % 10); + } while ((tlval /= 10) != 0); + ecnt = cnt; + while (scnt < ecnt) { + char c = buf[scnt]; + buf[scnt++] = buf[--ecnt]; + buf[ecnt] = c; + } + buf[cnt++] = '.'; + dval -= lval; + if ((ival = fabs(dval) * 1e4 + 0.5) == 0) { + buf[cnt++] = '0'; + buf[cnt++] = '0'; + buf[cnt++] = '0'; + buf[cnt++] = '0'; + } else { + if (ival < 1000) buf[cnt++] = '0'; + if (ival < 100) buf[cnt++] = '0'; + if (ival < 10) buf[cnt++] = '0'; + scnt = cnt; + do { + buf[cnt++] = '0' + (ival % 10); + } while ((ival /= 10) != 0); + ecnt = cnt; + while (scnt < ecnt) { + char c = buf[scnt]; + buf[scnt++] = buf[--ecnt]; + buf[ecnt] = c; + } + } + buf[cnt] = 0; +} + #endif #if defined(__cplusplus) From bfe1db8d16ba6bf38951faccb7b0543db676fba8 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Fri, 8 Jan 2016 23:06:14 -0500 Subject: [PATCH 4/8] Add benz compile time hooks PIC_DOUBLE_TO_CSTRING and PIC_CSTRING_TO_DOUBLE --- extlib/benz/file.c | 2 +- extlib/benz/include/picrin/compat.h | 18 ++++++++++++++---- extlib/benz/read.c | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/extlib/benz/file.c b/extlib/benz/file.c index e2d1cd67..334a4315 100644 --- a/extlib/benz/file.c +++ b/extlib/benz/file.c @@ -347,7 +347,7 @@ int xvfprintf(pic_state *pic, xFILE *stream, const char *fmt, va_list ap) { break; case 'f': { char buf[64]; - pic_dtoa(va_arg(ap, double), buf); + PIC_DOUBLE_TO_CSTRING(va_arg(ap, double), buf); cnt += xfputs(pic, buf, stream); break; } diff --git a/extlib/benz/include/picrin/compat.h b/extlib/benz/include/picrin/compat.h index 95c3a46d..4d53379c 100644 --- a/extlib/benz/include/picrin/compat.h +++ b/extlib/benz/include/picrin/compat.h @@ -282,16 +282,16 @@ atof(const char *nptr) #if PIC_ENABLE_STDIO # include -PIC_INLINE void -pic_dtoa(double dval, char *buf) +void +PIC_INLINE pic_dtoa(double dval, char *buf) { sprintf(buf, "%g", dval); } #else -PIC_INLINE void -pic_dtoa(double dval, char *buf) +void +PIC_INLINE pic_dtoa(double dval, char *buf) { # define fabs(x) ((x) >= 0 ? (x) : -(x)) long lval, tlval; @@ -339,6 +339,16 @@ pic_dtoa(double dval, char *buf) #endif +#ifndef PIC_DOUBLE_TO_CSTRING +#define PIC_DOUBLE_TO_CSTRING pic_dtoa +#endif +void PIC_DOUBLE_TO_CSTRING(double, char *); + +#ifndef PIC_CSTRING_TO_DOUBLE +#define PIC_CSTRING_TO_DOUBLE atof +#endif +double PIC_CSTRING_TO_DOUBLE(const char *); + #if defined(__cplusplus) } #endif diff --git a/extlib/benz/read.c b/extlib/benz/read.c index 5299e540..eeca5485 100644 --- a/extlib/benz/read.c +++ b/extlib/benz/read.c @@ -284,7 +284,7 @@ read_unsigned(pic_state *pic, struct pic_port *port, int c) read_error(pic, "number too large", pic_obj_value(pic_make_str(pic, (const char *)buf, ATOF_BUF_SIZE))); buf[idx] = 0; - flt = atof(buf); + flt = PIC_CSTRING_TO_DOUBLE(buf); if (dpe == 0 && pic_valid_int(flt)) return pic_int_value((int )flt); From 5fd8f8287f4841bd8e1c5b69bded3d5aac09a2e6 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Fri, 8 Jan 2016 23:34:51 -0500 Subject: [PATCH 5/8] Plug in emyg_dtoa and emyg_atod for round trip double conversion --- Makefile | 3 +- contrib/10.roundtrip/emyg_atod.c | 761 +++++++++++++++++++++++++++++++ contrib/10.roundtrip/emyg_atod.h | 12 + contrib/10.roundtrip/emyg_dtoa.c | 441 ++++++++++++++++++ contrib/10.roundtrip/emyg_dtoa.h | 12 + contrib/10.roundtrip/emyg_pow5.h | 735 +++++++++++++++++++++++++++++ contrib/10.roundtrip/nitro.mk | 4 + 7 files changed, 1967 insertions(+), 1 deletion(-) create mode 100644 contrib/10.roundtrip/emyg_atod.c create mode 100644 contrib/10.roundtrip/emyg_atod.h create mode 100644 contrib/10.roundtrip/emyg_dtoa.c create mode 100644 contrib/10.roundtrip/emyg_dtoa.h create mode 100644 contrib/10.roundtrip/emyg_pow5.h create mode 100644 contrib/10.roundtrip/nitro.mk diff --git a/Makefile b/Makefile index b8aa1b35..58eadf39 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ PICRIN_OBJS = \ CONTRIB_SRCS = CONTRIB_OBJS = $(CONTRIB_SRCS:.c=.o) CONTRIB_LIBS = +CONTRIB_DEFS = CONTRIB_INITS = CONTRIB_TESTS = CONTRIB_DOCS = $(wildcard contrib/*/docs/*.rst) @@ -19,7 +20,7 @@ REPL_ISSUE_TESTS = $(wildcard t/issue/*.sh) TEST_RUNNER = bin/picrin -CFLAGS += -I./extlib/benz/include -Wall -Wextra +CFLAGS += -I./extlib/benz/include -Wall -Wextra $(CONTRIB_DEFS) LDFLAGS += -lm prefix ?= /usr/local diff --git a/contrib/10.roundtrip/emyg_atod.c b/contrib/10.roundtrip/emyg_atod.c new file mode 100644 index 00000000..321d80e9 --- /dev/null +++ b/contrib/10.roundtrip/emyg_atod.c @@ -0,0 +1,761 @@ +/* emyg_atod.c +** +** Copyright (C) 2015 Doug Currie, Londonderry, NH, USA +** +** 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. +*/ + +/* This code is an implementation of strtod() to accompany emyg_dtoa.c +** It is based on an algorithm described by Aubrey Jaffer, January 2015, +** "Easy Accurate Reading and Writing of Floating-Point Numbers" +** arXiv:1310.8121v6 -- http://arxiv.org/abs/1310.8121v6 +*/ +/* This implementation, besides the obvious translation from Java to C, has +** some differences/improvements: +** 1. All memory allocations are on the stack, no heap allocations +** 2. We don't shift numerator right for the case: negative dpoint, positive bex +** This can happen for an input like -139745422447689500.0 that has... +** mant: 1397454224476895000 dp: -1 bex: 5. Shifting the mantissa right would +** lose information; instead we shift the scale factor left. +** 3. We use a roundQuotient function (quornd) optimized for atod; it adjusts +** the result to be 53 bits if it is 54 before rounding by appropriate use +** of the quotient LSB and remainder; this avoids doing the divide twice. +*/ + +#include +#include +#include +#include // used by emyg_strtod +#include // scalb() + +#include "emyg_pow5.h" // in separate file to support alternate implementations, and it's big + +#ifdef TESTING_QUOREM +#include +#include +#define QUODBG(x) x +#else +#define QUODBG(x) +#endif + +#define OPTIMIZE_FOR_ATOD + +#define BIGNUM_JUMBO_SIZE_UINT32 (30) /* 960 bits > (64 + 54 + (log (expt 5 345) 2) = 919) */ +#define BIGNUM_NORMAL_SIZE_UINT32 (28) /* when we don't need the extra space for multiply */ +#define BIGNUM_QUOTIENT_SIZE_UINT32 (4) /* difference twixt dividend - divisor; see m - n + 1 */ + +static const int doubleMantissaBits = 53; + +static inline int nlz32 (uint32_t x) +{ +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long bitno; + uint8_t s = _BitScanReverse(&bitno, (unsigned long )x); + return s ? (31 - (int )bitno) : 32; +#elif defined(__GNUC__) && (UINT_MAX == 0xFFFFFFFFUL) + return (x == 0u) ? 32 : __builtin_clz((unsigned int )x); +#elif defined(__GNUC__) && (ULONG_MAX == 0xFFFFFFFFUL) + return (x == 0u) ? 32 : __builtin_clzl((unsigned long )x); +#else + int n; + if (x == 0) return(32); + n = 0; + if (x <= 0x0000FFFF) { n = n +16; x = x <<16; } + if (x <= 0x00FFFFFF) { n = n + 8; x = x << 8; } + if (x <= 0x0FFFFFFF) { n = n + 4; x = x << 4; } + if (x <= 0x3FFFFFFF) { n = n + 2; x = x << 2; } + if (x <= 0x7FFFFFFF) { n = n + 1; } + return n; +#endif +} + +static inline int nlz64 (uint64_t x) +{ +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long bitno; + uint8_t s = _BitScanReverse64(&bitno, x); + return s ? (63 - (int )bitno) : 64; +#elif defined(__GNUC__) && (ULONG_MAX > 0xFFFFFFFFFFFFFFF5ULL) + return (x == 0u) ? 64 : __builtin_clzl((unsigned long )x); +#elif defined(__GNUC__) && (ULONGLONG_MAX > 0xFFFFFFFFFFFFFFF5ULL) + return (x == 0u) ? 64 : __builtin_clzll((unsigned long long )x); +#else + int s = nlz32(x >> 32); + return (s == 32) ? (32 + nlz32(x & UINT32_MAX)) : s; +#endif +} + +/* Divide code divmnu.c adapted from Hacker's Delight; here are the changes: +** 1. Eliminated signed arithmetic (shift left and conversions) since +** these are undefined behavior for C; adapted similar solution from +** David Ireland's BigDigits library. +** 2. Removed the option to return the remainder, and added the rounding +** feature needed for IEEE conversion. +** 3. Eliminated the alloca() calls; we know that for IEEE doubles none +** of our bignums will be larger than 112 bits. +** 4. Added code specific to emyg_atod() to force result size to 53 bits +** and returning a -1 to indicate the scaling by /2 +** Hacker's Delight web site has a permission statement, incuding: you are +** free to use, copy, and distribute any of the code on this web site, +** whether modified by you or not. You need not give attribution. +*/ + +/* This divides an n-word dividend by an m-word divisor, giving an +** n-m+1-word quotient and m-word remainder. The bignums are in arrays of +** words. Here a "word" is 32 bits. This routine is designed for a 64-bit +** machine which has a 64/64 division instruction. */ + +/* q[0], u[0], and v[0] contain the LEAST significant words. +** (The sequence is in little-endian order). +** +** This is a fairly precise implementation of Knuth's Algorithm D, for a +** binary computer with base b = 2**32. The caller supplies: +** 1. Space q for the quotient, m - n + 1 words (at least one). +** 2. The dividend u, m words, m >= 1. +** 3. The divisor v, n words, n >= 1. +** The most significant digit of the divisor, v[n-1], must be nonzero. The +** dividend u may have leading zeros; this just makes the algorithm take +** longer and makes the quotient contain more leading zeros. +** The program does not alter the input parameters u and v. +** The quotient returned may have leading zeros. The +** function itself returns a value of 0 for success and 1 for invalid +** parameters (e.g., division by 0). +** For now, we must have m >= n. Knuth's Algorithm D also requires +** that the dividend be at least as long as the divisor. (In his terms, +** m >= 0 (unstated). Therefore m+n >= n.) +*/ + +int quornd (uint32_t q[], const uint32_t u[], const uint32_t v[], int m, int n) +{ + const uint64_t b = 4294967296ULL; // Number base (2**32). + uint32_t un[BIGNUM_JUMBO_SIZE_UINT32]; // Normalized form of u, v. + uint32_t vn[BIGNUM_JUMBO_SIZE_UINT32]; + uint64_t qhat; // Estimated quotient digit. + uint64_t rhat; // A remainder. + uint64_t p; // Product of two digits. + uint64_t t, k; + int s, i, j; + int res = 0; + + if (m < n || n <= 0 || v[n-1] == 0) + return 1; // Return if invalid param. + + if (n == 1) + { + k = 0; // Take care of the case of a + for (j = m - 1; j >= 0; j--) // single-digit divisor here. + { + q[j] = (k*b + u[j]) / v[0]; + k = (k*b + u[j]) - (q[j] * v[0]); + } +#ifdef OPTIMIZE_FOR_ATOD + if ((64 - nlz32(q[1])) > doubleMantissaBits) + { + // we need to divide quotient by 2 to make it fit + res = -1; // let caller know we made this adjustment + uint32_t saved_q0 = q[0]; + q[0] = (q[0] >> 1) | (q[1] << 31); + q[1] = q[1] >> 1; + + if (0 == (saved_q0 & 1)) + return res; // no need to round + // now the remainder is >= 0.5 + // if un is 0, then the remainder is 0.5 + // otherwise it is > 0.5 + if ((k & UINT32_MAX) != 0) + goto round_up; // (2 * remainder) > divisor, round + // continue with check for round_even + if ((q[0] & 1) == 1) + goto round_up; // round to even + return res; + } +#endif + // rounding + k = (k & UINT32_MAX) * 2; // k is now 2 * remainder + if ((k > v[0]) || ((k == v[0]) && ((q[0] & 1) == 1))) + { +round_up: + i = 0; + do + { + t = (uint64_t)q[i] + 1; + q[i++] = t; + } while ((t > UINT32_MAX) && (i < (m - n + 1))); + } + return res; + } + + /* Normalize by shifting v left just enough so that its high-order + bit is on, and shift u left the same amount. We may have to append a + high-order digit on the dividend; we do that unconditionally. */ + + s = nlz32(v[n-1]); // 0 <= s <= 31. + + if (n > BIGNUM_JUMBO_SIZE_UINT32) return 1; + for (i = n - 1; i > 0; i--) + vn[i] = (v[i] << s) | ((uint64_t)v[i-1] >> (32-s)); + vn[0] = v[0] << s; + + if ((m + 1) > BIGNUM_JUMBO_SIZE_UINT32) return 1; + un[m] = (uint64_t)u[m-1] >> (32-s); + for (i = m - 1; i > 0; i--) + un[i] = (u[i] << s) | ((uint64_t)u[i-1] >> (32-s)); + un[0] = u[0] << s; + + for (j = m - n; j >= 0; j--) // Main loop. + { + // Compute estimate qhat of q[j]. + qhat = (un[j+n]*b + un[j+n-1]) / vn[n-1]; + rhat = (un[j+n]*b + un[j+n-1]) - qhat*vn[n-1]; +again: + if (qhat >= b || qhat*vn[n-2] > b*rhat + un[j+n-2]) + { + qhat = qhat - 1; + rhat = rhat + vn[n-1]; + if (rhat < b) goto again; + } + + // Multiply and subtract. + k = 0; + for (i = 0; i < n; i++) + { + p = qhat * vn[i]; + un[i+j] -= k; + k = (un[i+j] > (UINT32_MAX - k)) ? 1 : 0; + un[i+j] -= (p & UINT32_MAX); + if (un[i+j] > (UINT32_MAX - (p & UINT32_MAX))) k++; + k += (p >> 32); + } + un[j+n] -= k; + + q[j] = qhat; // Store quotient digit. + if (un[j+n]) // If we subtracted too + { + q[j] = q[j] - 1; // much, add back. + k = 0; + for (i = 0; i < n; i++) + { + t = (uint64_t)un[i+j] + vn[i] + k; + un[i+j] = t; + k = t >> 32; + } + un[j+n] = un[j+n] + k; + } + } // End j. + +#ifdef OPTIMIZE_FOR_ATOD + if ((64 - nlz32(q[1])) > doubleMantissaBits) + { + // we need to divide quotient by 2 to make it fit + res = -1; // let caller know we made this adjustment + uint32_t saved_q0 = q[0]; + q[0] = (q[0] >> 1) | (q[1] << 31); + q[1] = q[1] >> 1; + + if (0 == (saved_q0 & 1)) + return -1; // no need to round + // now the remainder is >= 0.5 + // if un is 0, then the remainder is 0.5 + // otherwise it is > 0.5 + for (i = n-1; i >= 0; i--) + { + if (un[i] != 0) + goto round_up; // (2 * remainder) > divisor, round + } + // continue with check for round_even + } + else +#endif + { + // Rounding: multiply the remainder by 2 and compare with the divisor + // + if (un[n-1] > (UINT32_MAX / 2u)) + goto round_up; + + for (i = n-1; i > 0; i--) + { + uint32_t ud = (un[i] << 1) | (un[i-1] >> 31); + if (ud > vn[i]) + goto round_up; // (2 * remainder) > divisor, round + if (ud < vn[i]) + return 0; // (2 * remainder) < divisor, done + } + if ((un[0] << 1) > vn[0]) + goto round_up; // (2 * remainder) > divisor, round + if ((un[0] << 1) < vn[0]) + return 0; // (2 * remainder) < divisor, done + } + // Check for round to even + // (2 * remainder) == divisor + if ((q[0] & 1) == 1) goto round_up; // round to even + return res; +} + +#if TESTING_QUOREM +void print_bigint (const char *nm, const uint32_t num[], const int n) +{ + int i; + printf("%s: ", nm); + for (i = 0; i < n; i++) + printf("%u ", num[i]); + printf("\n"); +} +#endif + +static inline void one_shiftLeft (uint32_t v[], int s) +{ + int x = 0; + while (s >= 32) { v[x++] = 0; s -= 32; } + v[x] = 1u << s; +} + +static inline void scl_shift_left_by (uint32_t v[], const uint32_t x[], int sz, int s) +{ + // v and x may be identical + int w = s / 32; // words to shift + int b = s % 32; // bits to shift + int i; + + QUODBG(printf("scl_shift_left_by sz %d shift %d (%d %d)\n", sz, s, w, b)); + + // sz is the size of the result, v + // x is guaranteed to be appropriately sized to provide enough data + // this is a dumb api but works for now + + // first copy words + v[sz - 1] = 0u; + for (i = sz - 2; i >= 0; i--) + { + v[i] = ((i - w) >= 0) ? x[i - w] : 0u; + } + + // then shift bits + for (i = sz - 1; i > 0; i--) + { + v[i] = (v[i] << b) | (v[i - 1] >> (32 - b)); + } + v[0] = (v[0] << b); +} + +static inline void u64_shiftLeft (uint32_t v[], uint64_t n, int sz, int s) +{ + uint64_t ns; + int x = 0; + + if (s >= 0) + { + while (s >= 32) { v[x++] = 0; s -= 32; } + ns = n << s; + v[x++] = (ns & UINT32_MAX); + if (x < sz) // -- don't write past end of v[], caller determined size needed + { + v[x++] = (ns >> 32); + if (x < sz && s != 0) // no more data if s == 0 + v[x] = n >> (64 - s); + } + } +} + +static inline double doubleValue (uint32_t v[]) +{ + // only the fist 64-bits of v[] are used; caller has determined that's all that's needed + return (double )((uint64_t )v[0] + ((uint64_t )v[1] << 32)); +} + +static inline int bitLength (const uint32_t v[], int sz_in_32bit_words) +{ + int x = sz_in_32bit_words - 1; + + while ((v[x] == 0) && (x > 0)) x = x - 1; + return (x * 32) + (32 - nlz32(v[x])); +} + +static inline void mulbyu64 (uint32_t p[], const uint64_t u64mant, const uint32_t m[], int z) +{ + // p is z+2 32-bit words + // m is z 32-bit words + + // TODO: could this be optimized to use 128 bit math on platforms that support it? + + uint64_t lo = u64mant & UINT32_MAX; + uint64_t hi = u64mant >> 32; + uint64_t a = 0; + int i; + + for (i = 0; i < z; i++) + { + a += lo * m[i]; + p[i] = a & UINT32_MAX; + a = a >> 32; + } + p[z] = a; + //p[z+1] = 0; + a = 0; + if (hi > 0) for (i = 0; i < z; i++) + { + a += (hi * m[i]) + p[i+1]; // this always (just) fits in 64 bits + p[i+1] = (a & UINT32_MAX); + a = a >> 32; + } + p[z+1] = a; +} + +/* atod_guts +** input: u64mant dpoint +** result: u64mant * 10**dpoint +** +** case dpoint >= 0: +** reframe as: u64mant * 5**dpoint * 2**dpoint +** if (u64mant * 5**dpoint) is less than 53 bits +** then the answer is just scalb(u64mant * 5**dpoint, dpoint) +** else +** calculate bex = the bit length of (u64mant * 5**dpoint) +** divide and round: (u64mant * 5**dpoint) / 2**bex +** the answer is scalb(u64mant * 5**dpoint, bex + dpoint) +** case dpoint < 0 +** reframe as: (u64mant / (5**(-dpoint)) / 2**(-dpoint) +*/ +double atod_guts (uint64_t u64mant, int dpoint) +{ + const uint32_t *pow5p; + uint32_t num[BIGNUM_JUMBO_SIZE_UINT32]; // up to (log (expt 5 325) 2) = 755 bits => ~104 bytes + uint32_t scl[BIGNUM_NORMAL_SIZE_UINT32]; + uint32_t quo[BIGNUM_QUOTIENT_SIZE_UINT32]; + int n, m; // as per quornd: n is size of divisor, m is size of dividend in 32-bit words + int z; // z is size of pow5p in 32-bit words + int bex; // binary exponentish + + QUODBG(fprintf(stderr, "mant: %llu dp: %d\n", u64mant, dpoint)); + + if (dpoint >= 0) + { + int r = get_pow5(dpoint, &pow5p, &z); + if (r) return 0.0/0.0; // NaN for bad input -- TODO: use inf for excessive +exponents? + m = z + 2; // size is sum of lengths of multiplicands + if (m > BIGNUM_JUMBO_SIZE_UINT32) { n = 0; goto atod_fail; } + mulbyu64(num, u64mant, pow5p, z); // num = pow5 * u64mant + bex = bitLength(num, m) - doubleMantissaBits; + if (bex <= 0) return scalb(doubleValue(num), dpoint); + QUODBG(fprintf(stderr, "+ bex: %d z: %d m: %d\n", bex, z, m)); + n = (bex / 32) + 1; // 32-bit words needed to hold 1 << bex + m = (bex + doubleMantissaBits + 31) / 32; // we may be able to shrink by a word + if (n > BIGNUM_NORMAL_SIZE_UINT32) goto atod_fail; + one_shiftLeft(scl, bex); + if ((m - n + 1) > BIGNUM_QUOTIENT_SIZE_UINT32) goto atod_fail; + QUODBG(fprintf(stderr, "+ n: %d m: %d q: %d\n", n, m, m - n + 1)); + if (quornd(quo, num, scl, m, n)) + { + QUODBG(fprintf(stderr, "+ quornd returned error\n")); + return 0.0/0.0; // NaN for bad input or software error + } + QUODBG(print_bigint("num", num, m)); + QUODBG(print_bigint("scl", scl, n)); + QUODBG(print_bigint("quo", quo, m - n + 1)); + return scalb(doubleValue(quo), bex + dpoint); + } + else + { + int bma = 64 - nlz64(u64mant); // bits in mantissa + int r = get_pow5(-dpoint, &pow5p, &z); + if (r) return 0.0/0.0; // NaN for bad input -- TODO: use 0.0 for excessive -exponents? + bex = bma - bitLength(pow5p, z) - doubleMantissaBits; + if (bex > 0) + { + // to avoid losing significant bits, which could occur in the u64_shiftLeft below + // instead of shifting num right, let's shift pow5 left + // DANGER Will Robinson! We are aliasing pow5p and scl -- this is OK since + // the only place below they are both used in the same statement or call is + // scl_shift_left_by(), which is designed to handle aliased pointers + // and which doesn't happen at all if OPTIMIZE_FOR_ATOD is defined + // + m = 2; + if (m > BIGNUM_JUMBO_SIZE_UINT32) { n = 0; goto atod_fail; } + num[0] = u64mant & UINT32_MAX; + num[1] = u64mant >> 32; + // use z+1 because scl_shift_left_by my shift by as many as 10 bits (64 - 1 - 53) + if ((z + 1) > BIGNUM_NORMAL_SIZE_UINT32) { n = 0; goto atod_fail; } + scl_shift_left_by(scl, pow5p, z + 1, bex); + QUODBG(print_bigint("scl", scl, z + 1)); + n = (bitLength(scl, z + 1) + 31) / 32; + pow5p = scl; // DANGER Will Robinson! -- see above + QUODBG(fprintf(stderr, "- bma %d bex: %d z: %d m: %d n: %d\n", bma, bex, z, m, n)); + } + else + { + m = (((bma - bex) + 31) / 32); // u64mant << -bex + if (m > BIGNUM_JUMBO_SIZE_UINT32) { n = 0; goto atod_fail; } + QUODBG(fprintf(stderr, "- bma %d bex: %d z: %d m: %d\n", bma, bex, z, m)); + u64_shiftLeft(num, u64mant, m, -bex); + n = z; + } + if ((m - n + 1) > BIGNUM_QUOTIENT_SIZE_UINT32) goto atod_fail; + QUODBG(fprintf(stderr, "- n: %d m: %d q: %d\n", n, m, m - n + 1)); + r = quornd(quo, num, pow5p, m, n); + if (r > 0) + { + QUODBG(fprintf(stderr, "- quornd returned error\n")); + return 0.0/0.0; // NaN for bad input + } + QUODBG(print_bigint("num", num, m)); + QUODBG(print_bigint("pow5p", pow5p, n)); + QUODBG(print_bigint("quo", quo, m - n + 1)); +#ifdef OPTIMIZE_FOR_ATOD + QUODBG(fprintf(stderr, "- r: %d\n", r)); + if (r < 0) + { + bex++; + } +#else + bma = 64 - nlz64(doubleValue(quo)); + if (bma > doubleMantissaBits) + { + bex++; + n = (pow5p[z-1] > (UINT32_MAX / 2u)) ? z + 1 : z; + // use z+2 because mulbyu64 will set those words even though they may be zero + if ((z + 2) > BIGNUM_NORMAL_SIZE_UINT32) goto atod_fail; + QUODBG(fprintf(stderr, "- n: %d m: %d q: %d bma: %d\n", n, m, m - n + 1, bma)); + scl_shift_left_by(scl, pow5p, z + 1, 1); + if (quornd(quo, num, scl, m, n)) + { + QUODBG(fprintf(stderr, "- quornd returned error; v[n-1]: %u\n", scl[n-1])); + return 0.0/0.0; // NaN for bad input + } + QUODBG(print_bigint("num", num, m)); + QUODBG(print_bigint("scl", scl, n)); + QUODBG(print_bigint("quo", quo, m - n + 1)); + } +#endif + return scalb(doubleValue(quo), bex + dpoint); + } +atod_fail: + QUODBG(fprintf(stderr, "atod_guts undersized bignum n: %d m: %d\n", n, m)); + return 0.0/0.0; // NaN for bad input +} + +/* +double strtod(const char *nptr, char **endptr); + The expected form of the (initial portion of the) string is optional + leading white space as recognized by isspace(3), an optional plus + ('+') or minus sign ('-') and then either (i) a decimal number, or + (ii) a hexadecimal number, or (iii) an infinity, or (iv) a NAN (not- + a-number). + + A decimal number consists of a nonempty sequence of decimal digits + possibly containing a radix character (decimal point, locale- + dependent, usually '.'), optionally followed by a decimal exponent. + A decimal exponent consists of an 'E' or 'e', followed by an optional + plus or minus sign, followed by a nonempty sequence of decimal + digits, and indicates multiplication by a power of 10. + + A hexadecimal number consists of a "0x" or "0X" followed by a + nonempty sequence of hexadecimal digits possibly containing a radix + character, optionally followed by a binary exponent. A binary + exponent consists of a 'P' or 'p', followed by an optional plus or + minus sign, followed by a nonempty sequence of decimal digits, and + indicates multiplication by a power of 2. At least one of radix + character and binary exponent must be present. + + An infinity is either "INF" or "INFINITY", disregarding case. + + A NAN is "NAN" (disregarding case) optionally followed by a string, + (n-char-sequence), where n-char-sequence specifies in an + implementation-dependent way the type of NAN (see NOTES). + + These functions return the converted value, if any. + + If endptr is not NULL, a pointer to the character after the last + character used in the conversion is stored in the location referenced + by endptr. + + If no conversion is performed, zero is returned and the value of nptr + is stored in the location referenced by endptr. + + If the correct value would cause overflow, plus or minus HUGE_VAL + (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the + value), and ERANGE is stored in errno. If the correct value would + cause underflow, zero is returned and ERANGE is stored in errno. +*/ + +double emyg_strtod(const char *nptr, char **endptr) +{ + const char *cp = nptr; + double res; + uint64_t mant; // mantissa + int minus = 0; // mantissa minus + int dadp = 0; // digits after decimal point + int expt = 0; // explicit exponent + int expm = 0; // exponent minus + char c; + + while (isspace(c = *cp++)) /*skip*/; + + if ('-' == c) { minus = 1; c = *cp++; } + else if ('+' == c) { c = *cp++; } + else {} + + if (('n' == c || 'N' == c) + && ('a' == cp[0] || 'A' == cp[0]) + && ('n' == cp[1] || 'N' == cp[1])) + { + // for Scheme allow (require?) ".0" + if ('.' == cp[2] && '0' == cp[3]) cp = &cp[4]; + else cp = &cp[2]; + res = 0.0/0.0; + } + else + if (('i' == c || 'I' == c) + && ('n' == cp[0] || 'N' == cp[0]) + && ('f' == cp[1] || 'F' == cp[1])) + { + // for Scheme allow (require?) ".0" + if ('.' == cp[2] && '0' == cp[3]) cp = &cp[4]; + else cp = &cp[2]; + res = 1.0/0.0; + // TODO: allow "INITY" + } + else if ('.' == c) + { + mant = 0; + goto after_dp; + } + else if (isdigit(c)) + { + mant = c - '0'; // mantissa + while (isdigit(c = *cp++)) + { + uint8_t d = c - '0'; + if (mant <= (UINT64_MAX / 10)) mant *= 10; + else + { + if (0 == d) expt += 1; + else + { + QUODBG(fprintf(stderr, "- overlow in emyg_strtod 1\n")); + goto no_conv; + } + } + if (mant <= (UINT64_MAX - d)) mant += d; + else + { + QUODBG(fprintf(stderr, "- overlow in emyg_strtod 2\n")); + goto no_conv; + } + } + if ('.' == c) + { + after_dp: + while (isdigit(c = *cp++)) + { + uint8_t d = c - '0'; + if (mant <= (UINT64_MAX / 10)) mant *= 10; + else + { + if (0 == d) + { + /* ignore trailing zeroes by not scaling nor bumping dadp */ + continue; + } + else + { + QUODBG(fprintf(stderr, "- overlow in emyg_strtod 3\n")); + //goto no_conv; + continue; // ignore extra digits + } + } + if (mant <= (UINT64_MAX - d)) mant += d; + else + { + QUODBG(fprintf(stderr, "- overlow in emyg_strtod 4\n")); + //goto no_conv; + continue; // ignore extra digits + } + dadp++; + } + } + if ('e' == c || 'E' == c) + { + c = *cp++; + if ('-' == c) { expm = 1; c = *cp++; } + else if ('+' == c) { c = *cp++; } + else {} + + if (isdigit(c)) + { + expt += c - '0'; + while (isdigit(c = *cp++)) + { + uint8_t d = c - '0'; + if (expt <= (INT_MAX / 10)) expt *= 10; + else + { + QUODBG(fprintf(stderr, "- overlow in emyg_strtod\n")); + goto no_conv; + } + if (expt <= (INT_MAX - d)) expt += d; + else + { + QUODBG(fprintf(stderr, "- overlow in emyg_strtod\n")); + goto no_conv; + } + } + } + else + { + // oops, not an exp at all + c = *--cp; + if (('-' == c) || ('+' == c)) --cp; + res = 0.0; + } + } + if (expm) expt = -expt; + res = atod_guts(mant, expt - dadp); + } + else // no conversion + { +no_conv: + cp = nptr + 1; + res = 0.0; + } + if (NULL != endptr) *endptr = (char *)--cp; + return minus ? -res : res; +} + +#ifdef TESTING_QUOREM + +int main (int argc, char **argv) +{ + if ((argc == 4) && (0 == strcmp(argv[1], "-p"))) + { + char *p; + double d = atod_guts(strtoull(argv[2], &p, 10), strtol(argv[3], &p, 10)); + printf("%.17g %a\n", d, d); + return 0; + } + + if ((argc == 3) && (0 == strcmp(argv[1], "-s"))) + { + char *p; + double d = emyg_strtod(argv[2], &p); + printf("%.17g %a\n", d, d); + return 0; + } + return 0; +} + +#endif diff --git a/contrib/10.roundtrip/emyg_atod.h b/contrib/10.roundtrip/emyg_atod.h new file mode 100644 index 00000000..7857a36e --- /dev/null +++ b/contrib/10.roundtrip/emyg_atod.h @@ -0,0 +1,12 @@ +/* emyg_atod.h */ + + +#ifdef __cplusplus +extern "C" { +#endif + +double emyg_strtod (const char *nptr, char **endptr); + +#ifdef __cplusplus +} +#endif diff --git a/contrib/10.roundtrip/emyg_dtoa.c b/contrib/10.roundtrip/emyg_dtoa.c new file mode 100644 index 00000000..9315c5f5 --- /dev/null +++ b/contrib/10.roundtrip/emyg_dtoa.c @@ -0,0 +1,441 @@ +/* emyg_dtoa.c +** Copyright (C) 2015 Doug Currie +** based on dtoa_milo.h +** Copyright (C) 2014 Milo Yip +** +** 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. +*/ + +/* This code is a mostly mechanical translation of Milo Yip's C++ version of +** Grisu2 to C. For algorithm information, see Loitsch, Florian. "Printing +** floating-point numbers quickly and accurately with integers." ACM Sigplan +** Notices 45.6 (2010): 233-243. +*/ + +#include +#include + +#if defined(_MSC_VER) +#include "msinttypes/stdint.h" +#include +#else +#include +#endif + +#include + +#include "emyg_dtoa.h" + +#define UINT64_C2(h, l) (((uint64_t )(h) << 32) | (uint64_t )(l)) + +typedef struct DiyFp_s { + uint64_t f; + int e; +} DiyFp; + +static const int kDiySignificandSize = 64; +static const int kDpSignificandSize = 52; +static const int kDpExponentBias = 0x3FF + kDpSignificandSize; +static const int kDpMinExponent = -kDpExponentBias; +static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000); +static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF); +static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000); + +static inline DiyFp DiyFp_from_parts (uint64_t f, int e) { + DiyFp fp; + fp.f = f; + fp.e = e; + return fp; +} + +DiyFp DiyFp_from_double (double d) { + union { + double d; + uint64_t u64; + } u = { d }; + DiyFp res; + + int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize; + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + res.f = significand + kDpHiddenBit; + res.e = biased_e - kDpExponentBias; + } + else { + res.f = significand; + res.e = kDpMinExponent + 1; + } + return res; +} + +static inline DiyFp DiyFp_subtract (const DiyFp lhs, const DiyFp rhs) { + assert(lhs.e == rhs.e); + assert(lhs.f >= rhs.f); + return DiyFp_from_parts(lhs.f - rhs.f, lhs.e); +} + +static inline DiyFp DiyFp_multiply (const DiyFp lhs, const DiyFp rhs) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(lhs.f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp_fro_parts(h, e + rhs.e + 64); +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + unsigned __int128 p = (unsigned __int128 )(lhs.f) * (unsigned __int128 )(rhs.f); + uint64_t h = p >> 64; + uint64_t l = (uint64_t )(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp_from_parts(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = lhs.f >> 32; + const uint64_t b = lhs.f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp_from_parts(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), lhs.e + rhs.e + 64); +#endif +} + +static inline DiyFp Normalize (const DiyFp lhs) { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, lhs.f); + return DiyFp_from_parts(lhs.f << (63 - index), lhs.e - (63 - index)); +#elif defined(__GNUC__) + int s = __builtin_clzll(lhs.f); + return DiyFp_from_parts(lhs.f << s, lhs.e - s); +#else + DiyFp res = lhs; + while (!(res.f & kDpHiddenBit)) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 1); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1); + return res; +#endif +} + +static inline DiyFp NormalizeBoundary (const DiyFp lhs) { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, lhs.f); + return DiyFp_from_parts(lhs.f << (63 - index), lhs.e - (63 - index)); +#else + DiyFp res = lhs; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; +#endif +} + +static inline void NormalizedBoundaries (DiyFp lhs, DiyFp* minus, DiyFp* plus) { + DiyFp pl = NormalizeBoundary(DiyFp_from_parts((lhs.f << 1) + 1, lhs.e - 1)); + DiyFp mi = (lhs.f == kDpHiddenBit) + ? DiyFp_from_parts((lhs.f << 2) - 1, lhs.e - 2) + : DiyFp_from_parts((lhs.f << 1) - 1, lhs.e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; +} + +static inline DiyFp GetCachedPower (int e, int* K) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76), + UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea), + UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df), + UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f), + UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c), + UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5), + UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d), + UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637), + UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7), + UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5), + UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b), + UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996), + UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8), + UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053), + UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd), + UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94), + UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b), + UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac), + UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3), + UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb), + UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c), + UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000), + UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984), + UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70), + UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245), + UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8), + UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a), + UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea), + UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85), + UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2), + UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3), + UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25), + UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece), + UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5), + UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a), + UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a), + UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129), + UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429), + UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d), + UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841), + UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9), + UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + + //int k = (int )(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = (int )(dk); + if (k != dk) + k++; + + unsigned index = (unsigned )((k >> 3) + 1); + *K = -(-348 + (int )(index << 3)); // decimal exponent no need lookup table + + assert(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0])); + return DiyFp_from_parts(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +static inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +static inline unsigned CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + if (n < 1000000000) return 9; + return 10; +} + +static inline void DigitGen(const DiyFp W, const DiyFp Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + const DiyFp one = DiyFp_from_parts((uint64_t )(1) << -Mp.e, Mp.e); + const DiyFp wp_w = DiyFp_subtract(Mp, W); + uint32_t p1 = (uint32_t )(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int kappa = (int )(CountDecimalDigit32(p1)); + *len = 0; + + while (kappa > 0) { + uint32_t d; + switch (kappa) { + case 10: d = p1 / 1000000000; p1 %= 1000000000; break; + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default: +#if defined(_MSC_VER) + __assume(0); +#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + __builtin_unreachable(); +#else + d = 0; +#endif + } + if (d || *len) + buffer[(*len)++] = '0' + (char )(d); + kappa--; + uint64_t tmp = ((uint64_t )(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, (uint64_t )(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = (char )(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = '0' + d; + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); + return; + } + } +} + +static inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v = DiyFp_from_double(value); + DiyFp w_m, w_p; + NormalizedBoundaries(v, &w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = DiyFp_multiply(Normalize(v), c_mk); + DiyFp Wp = DiyFp_multiply(w_p, c_mk); + DiyFp Wm = DiyFp_multiply(w_m, c_mk); + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +static inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', + '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', + '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', + '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', + '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', + '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', + '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', + '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', + '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', + '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' + }; + return cDigitsLut; +} + +static inline void WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = '0' + (char )(K / 100); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = '0' + (char )(K); + + *buffer = '\0'; +} + +static inline void Prettify(char* buffer, int length, int k) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (length <= kk && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + buffer[kk + 2] = '\0'; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + memmove(&buffer[kk + 1], &buffer[kk], length - kk); + buffer[kk] = '.'; + buffer[length + 1] = '\0'; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + memmove(&buffer[offset], &buffer[0], length); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + buffer[length + offset] = '\0'; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + memmove(&buffer[2], &buffer[1], length - 1); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +void emyg_dtoa (double value, char* buffer) { + // Not handling NaN and inf + assert(!isnan(value)); + assert(!isinf(value)); + + if (value == 0) { + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + buffer[3] = '\0'; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + Prettify(buffer, length, K); + } +} diff --git a/contrib/10.roundtrip/emyg_dtoa.h b/contrib/10.roundtrip/emyg_dtoa.h new file mode 100644 index 00000000..a353a700 --- /dev/null +++ b/contrib/10.roundtrip/emyg_dtoa.h @@ -0,0 +1,12 @@ +/* emyg_dtoa.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +void emyg_dtoa (double value, char *buffer); + +#ifdef __cplusplus +} +#endif + diff --git a/contrib/10.roundtrip/emyg_pow5.h b/contrib/10.roundtrip/emyg_pow5.h new file mode 100644 index 00000000..a827539c --- /dev/null +++ b/contrib/10.roundtrip/emyg_pow5.h @@ -0,0 +1,735 @@ +/* emyg_pow5.h */ + +/* This isn't really a header file, but we keep it in a separate file +** to support alternate implementations, and because it's big. +** It has be a .h (rather than a .c) file to avoid fooling premake4 +** into building into the image twice. +*/ + +#ifndef MAX_POW5_IN_TABLE + +#define MAX_POW5_IN_TABLE 345u + +/* These are powers of 5 with 32-bit digits in little endian format */ +/* generated using (pow5c 345) from testgen.scm */ +static const uint32_t pow5[] = { +1u, +5u, +25u, +125u, +625u, +3125u, +15625u, +78125u, +390625u, +1953125u, +9765625u, +48828125u, +244140625u, +1220703125u, +1808548329u, 1u, +452807053u, 7u, +2264035265u, 35u, +2730241733u, 177u, +766306777u, 888u, +3831533885u, 4440u, +1977800241u, 22204u, +1299066613u, 111022u, +2200365769u, 555111u, +2411894253u, 2775557u, +3469536673u, 13877787u, +167814181u, 69388939u, +839070905u, 346944695u, +4195354525u, 1734723475u, +3796903441u, 83682787u, 2u, +1804648021u, 418413939u, 10u, +433305513u, 2092069697u, 50u, +2166527565u, 1870413893u, 252u, +2242703233u, 762134875u, 1262u, +2623581573u, 3810674377u, 6310u, +233005977u, 1873502704u, 31554u, +1165029885u, 777578928u, 157772u, +1530182129u, 3887894641u, 788860u, +3355943349u, 2259604022u, 3944304u, +3894814857u, 2708085521u, 19721522u, +2294205101u, 655525721u, 98607613u, +2881090913u, 3277628607u, 493038065u, +1520552677u, 3503241150u, 2465190328u, +3307796089u, 336336567u, 3736017052u, 2u, +3654078557u, 1681682838u, 1500216076u, 14u, +1090523601u, 4113446898u, 3206113085u, 71u, +1157650709u, 3387365307u, 3145663541u, 358u, +1493286249u, 4051924648u, 2843415820u, 1793u, +3171463949u, 3079754057u, 1332177216u, 8968u, +2972417857u, 2513868400u, 2365918787u, 44841u, +1977187397u, 3979407411u, 3239659345u, 224207u, +1296002393u, 2717167873u, 3313394841u, 1121038u, +2185044669u, 700937478u, 3682072320u, 5605193u, +2335288753u, 3504687392u, 1230492416u, 28025969u, +3086509173u, 343567778u, 1857494788u, 140129846u, +2547643977u, 1717838893u, 697539348u, 700649232u, +4148285293u, 4294227171u, 3487696741u, 3503246160u, +3561557281u, 4291266675u, 258614525u, 336361620u, 4u, +627917221u, 4276464195u, 1293072629u, 1681808100u, 20u, +3139586105u, 4202451791u, 2170395853u, 4114073205u, 101u, +2813028637u, 3832389774u, 2262044677u, 3390496843u, 509u, +1180241297u, 1982079689u, 2720288797u, 4067582329u, 2548u, +1606239189u, 1320463854u, 716542099u, 3158042464u, 12744u, +3736228649u, 2307351975u, 3582710496u, 2905310432u, 63723u, +1501274061u, 2946825287u, 733683298u, 1641650276u, 318618u, +3211403009u, 1849224548u, 3668416493u, 3913284084u, 1593091u, +3172113157u, 656188151u, 1162213283u, 2386551240u, 7965459u, +2975663897u, 3280940758u, 1516099119u, 3342821609u, 39827297u, +1993417597u, 3519801905u, 3285528302u, 3829206158u, 199136488u, +1377153393u, 419140343u, 3542739626u, 1966161609u, 995682444u, +2590799669u, 2095701716u, 533828946u, 1240873457u, 683444926u, 1u, +69096457u, 1888573991u, 2669144732u, 1909399989u, 3417224631u, 5u, +345482285u, 852935363u, 460821774u, 957065356u, 4201221269u, 28u, +1727411425u, 4264676815u, 2304108870u, 490359484u, 3826237162u, 144u, +47122533u, 4143514893u, 2930609762u, 2451797422u, 1951316626u, 724u, +235612665u, 3537705281u, 1768146926u, 3669052521u, 1166648540u, 3622u, +1178063325u, 508657221u, 250800042u, 1165393423u, 1538275408u, 18111u, +1595349329u, 2543286106u, 1254000210u, 1531999819u, 3396409745u, 90556u, +3681779349u, 4126495939u, 1975033756u, 3365031800u, 4097146838u, 452783u, +1229027561u, 3452610515u, 1285234192u, 3940257114u, 3305865009u, 2263919u, +1850170509u, 83183392u, 2131203668u, 2521416387u, 3644423161u, 11319598u, +660917953u, 415916962u, 2066083748u, 4017147345u, 1042246623u, 56597994u, +3304589765u, 2079584810u, 1740484148u, 2905867543u, 916265823u, 282989971u, +3638046937u, 1807989461u, 112486150u, 1644435829u, 286361822u, 1414949856u, +1010365501u, 450012717u, 562430752u, 3927211849u, 1431809111u, 2779781984u, 1u, +756860209u, 2250063586u, 2812153760u, 2456190061u, 2864078263u, 1014008033u, 8u, +3784301045u, 2660383338u, 1175866914u, 3691015716u, 1435489429u, 775072872u, 41u, +1741636041u, 417014806u, 1584367277u, 1275209397u, 2882479853u, 3875364361u, 205u, +118245613u, 2085074032u, 3626869089u, 2081079690u, 1527497378u, 2196952624u, 1029u, +591228065u, 1835435568u, 954476263u, 1815463862u, 3342519596u, 2394828529u, 5147u, +2956140325u, 587243248u, 477414021u, 487384719u, 3827696094u, 3384208056u, 25737u, +1895799737u, 2936216243u, 2387070105u, 2436923595u, 1958611286u, 4036138396u, 128688u, +889064093u, 1796179329u, 3345415936u, 3594683385u, 1203121840u, 3000822798u, 643444u, +150353169u, 390962054u, 3842177794u, 793547744u, 1720641908u, 2119212103u, 3217223u, +751765845u, 1954810270u, 2031019786u, 3967738724u, 13274948u, 2006125925u, 16086117u, +3758829225u, 1184116758u, 1565164340u, 2658824438u, 66374744u, 1440695033u, 80430587u, +1614276941u, 1625616498u, 3530854405u, 409220303u, 331873723u, 2908507869u, 402152936u, +3776417409u, 3833115195u, 474402842u, 2046101519u, 1659368615u, 1657637457u, 2010764683u, +1702217861u, 1985706795u, 2372014214u, 1640573003u, 4001875781u, 3993219990u, 1463888824u, 2u, +4216122009u, 1338599384u, 3270136480u, 3907897721u, 2829509722u, 2786230770u, 3024476828u, 11u, +3900740861u, 2398029628u, 3465780513u, 2359619424u, 1262646726u, 1046251965u, 2237482255u, 58u, +2323835121u, 3400213552u, 149033383u, 3208162532u, 2018266336u, 936292530u, 2597476684u, 292u, +3029241013u, 4116165874u, 745166918u, 3155910772u, 1501397091u, 386495356u, 102481533u, 1463u, +2261303177u, 3400960189u, 3725834594u, 2894651972u, 3212018162u, 1932476781u, 512407665u, 7315u, +2716581293u, 4119899059u, 1449303789u, 1588357976u, 3175188925u, 1072449316u, 2562038327u, 36575u, +698004577u, 3419626114u, 2951551653u, 3646822585u, 2991042738u, 1067279287u, 4220257044u, 182877u, +3490022885u, 4213228682u, 1872856380u, 1054243744u, 2070311806u, 1041429142u, 3921416037u, 914389u, +270245241u, 3886274230u, 774347312u, 976251426u, 1761624439u, 912178416u, 2427211002u, 4571949u, +1351226205u, 2251501966u, 3871736564u, 586289834u, 218187604u, 265924786u, 3546120419u, 22859747u, +2461163729u, 2667575239u, 2178813638u, 2931449174u, 1090938020u, 1329623930u, 550732911u, 114298739u, +3715884053u, 452974309u, 2304133601u, 1772343984u, 1159722807u, 2353152355u, 2753664556u, 571493695u, +1399551081u, 2264871549u, 2930733413u, 271785330u, 1503646741u, 3175827184u, 883420894u, 2857468478u, +2702788109u, 2734423154u, 1768765179u, 1358926653u, 3223266409u, 2994234033u, 122137177u, 1402440503u, 3u, +629038657u, 787213885u, 253891306u, 2499665971u, 3231430158u, 2086268280u, 610685888u, 2717235219u, 16u, +3145193285u, 3936069425u, 1269456530u, 3908395263u, 3272248904u, 1841406811u, 3053429442u, 701274207u, 83u, +2841064537u, 2500477944u, 2052315358u, 2362107132u, 3476342636u, 617099466u, 2382245324u, 3506371038u, 415u, +1320420797u, 3912455131u, 1671642200u, 3220601070u, 201843998u, 3085497334u, 3321292028u, 351986008u, 2079u, +2307136689u, 2382406472u, 4063243708u, 3218103463u, 1009219993u, 2542584782u, 3721558255u, 1759930043u, 10395u, +2945748853u, 3322097770u, 3136349358u, 3205615431u, 751132672u, 4122989319u, 1427922093u, 209715627u, 51977u, +1843842377u, 3725586965u, 2796844905u, 3143175270u, 3755663363u, 3435077411u, 2844643173u, 1048578136u, 259885u, +629277293u, 1448065643u, 1099322641u, 2830974465u, 1598447634u, 4290485171u, 1338313980u, 947923387u, 1299426u, +3146386465u, 2945360919u, 1201645910u, 1269970438u, 3697270877u, 4272556672u, 2396602608u, 444649640u, 6497131u, +2847030437u, 1841902710u, 1713262257u, 2054884895u, 1306485202u, 4182914180u, 3393078452u, 2223248202u, 32485655u, +1350250297u, 619578961u, 4271343991u, 1684489884u, 2237458716u, 3734701717u, 4080490376u, 2526306421u, 162428277u, +2456284189u, 3097894806u, 4176850771u, 4127482128u, 2597358989u, 1493639403u, 3222582700u, 4041597517u, 812141387u, +3691486353u, 2604572144u, 3704384674u, 3457541460u, 101893061u, 3173229722u, 3228011613u, 3028118404u, 4060706939u, +1277562581u, 137958836u, 1342054189u, 107838120u, 509465309u, 2981246722u, 3255156180u, 2255690135u, 3123665514u, 4u, +2092845609u, 689794181u, 2415303649u, 539190601u, 2547326545u, 2021331722u, 3390879015u, 2688516086u, 2733425684u, 23u, +1874293453u, 3448970907u, 3486583653u, 2695953007u, 4146698133u, 1516724020u, 4069493189u, 557678545u, 782226535u, 118u, +781532673u, 64985353u, 253049085u, 594863151u, 3553621484u, 3288652808u, 3167596762u, 2788392729u, 3911132675u, 590u, +3907663365u, 324926765u, 1265245425u, 2974315755u, 588238236u, 3558362156u, 2953081925u, 1057061760u, 2375794194u, 2954u, +2358447641u, 1624633829u, 2031259829u, 1986676888u, 2941191183u, 611941596u, 1880507741u, 990341507u, 3289036379u, 14772u, +3202303613u, 3828201851u, 1566364554u, 1343449850u, 1821054029u, 3059707983u, 812604113u, 656740241u, 3560280008u, 73863u, +3126616177u, 1961140074u, 3536855478u, 2422281955u, 515335554u, 2413638029u, 4063020568u, 3283701205u, 621530856u, 369319u, +2748178997u, 1215765781u, 504408208u, 3521475187u, 2576677772u, 3478255553u, 3135233658u, 3533604141u, 3107654283u, 1846595u, +855993097u, 1783861612u, 2522041041u, 427506751u, 4293454272u, 211408583u, 2791266406u, 488151524u, 2653369531u, 9232978u, +4279965485u, 329373468u, 4020270615u, 2137533757u, 4287402176u, 1057042919u, 1071430142u, 2440757623u, 381945767u, 46164893u, +4219958241u, 1646867344u, 2921483891u, 2097734197u, 4257141698u, 990247303u, 1062183415u, 3613853524u, 1909728837u, 230824465u, +3919922021u, 3939369428u, 1722517568u, 1898736396u, 4105839308u, 656269223u, 1015949780u, 889398437u, 958709597u, 1154122327u, +2419740921u, 2516977960u, 22653252u, 903747390u, 3349327358u, 3281346119u, 784781604u, 152024890u, 498580690u, 1475644340u, 1u, +3508770013u, 3994955210u, 113266262u, 223769654u, 3861734903u, 3521828710u, 3923908023u, 760124450u, 2492903450u, 3083254404u, 6u, +363980881u, 2794906870u, 566331314u, 1118848270u, 2128805331u, 429274370u, 2439670935u, 3800622254u, 3874582658u, 2531370134u, 33u, +1819904405u, 1089632462u, 2831656573u, 1299274054u, 2054092064u, 2146371852u, 3608420083u, 1823242088u, 2193044110u, 4066916082u, 167u, +509587433u, 1153195016u, 1273380978u, 2201402977u, 1680525729u, 2141924670u, 862231233u, 526275852u, 2375285960u, 3154711228u, 839u, +2547937165u, 1471007784u, 2071937595u, 2417080294u, 4107661351u, 2119688759u, 16188871u, 2631379261u, 3286495208u, 2888654254u, 4198u, +4149751233u, 3060071626u, 1769753384u, 3495466880u, 3358437573u, 2008509207u, 80944357u, 271994417u, 3547574155u, 1558369385u, 20993u, +3568886981u, 2415456246u, 258832331u, 297465218u, 3907285981u, 1452611446u, 404721787u, 1359972085u, 558001591u, 3496879633u, 104966u, +664565721u, 3487346642u, 1294161657u, 1487326090u, 2356560721u, 2968089938u, 2023608936u, 2504893129u, 2790007956u, 304528981u, 524834u, +3322828605u, 256864026u, 2175840993u, 3141663155u, 3192869014u, 1955547804u, 1528110091u, 3934531055u, 1065137894u, 1522644908u, 2624170u, +3729241137u, 1284320133u, 2289270373u, 2823413889u, 3079443185u, 1187804431u, 3345583161u, 2492786092u, 1030722178u, 3318257245u, 13120851u, +1466336501u, 2126633373u, 2856417274u, 1232167559u, 2512314040u, 1644054862u, 3843013918u, 3873995871u, 858643596u, 3706384338u, 65604258u, +3036715209u, 2043232274u, 1397184484u, 1865870502u, 3971635609u, 3925307016u, 2035200407u, 2190110175u, 4293217984u, 1352052506u, 328021294u, +2298674157u, 1626226781u, 2690955126u, 739417919u, 2678308863u, 2446665900u, 1586067447u, 2360616285u, 4286220738u, 2465295238u, 1640106471u, +2903436193u, 3836166611u, 569873743u, 3697089598u, 506642427u, 3643394911u, 3635369941u, 3213146834u, 4251234508u, 3736541602u, 3905565061u, 1u, +1632279077u, 2000963874u, 2849368719u, 1305578806u, 2533212139u, 1037105371u, 996980525u, 3180832286u, 4076303359u, 1502838830u, 2347956125u, 9u, +3866428089u, 1414884779u, 1361941709u, 2232926737u, 4076126104u, 890559561u, 689935330u, 3019259543u, 3201647614u, 3219226858u, 3149846034u, 47u, +2152271261u, 2779456603u, 2514741250u, 2574699094u, 3200761338u, 157830513u, 3449676651u, 2211395827u, 3123336185u, 3211232405u, 2864328285u, 238u, +2171421713u, 1012381129u, 3983771661u, 4283560880u, 3118904804u, 789152568u, 68514071u, 2467044547u, 2731779039u, 3171260140u, 1436739540u, 1193u, +2267173973u, 766938351u, 2738989122u, 4237935220u, 2709622136u, 3945762843u, 342570355u, 3745288143u, 773993309u, 2971398815u, 2888730407u, 5966u, +2745935273u, 3834691757u, 810043722u, 4009806919u, 663208796u, 2548945034u, 1712851779u, 1546571531u, 3869966549u, 1972092187u, 1558750150u, 29833u, +844774477u, 1993589604u, 4050218614u, 2869165411u, 3316043984u, 4154790578u, 4269291601u, 3437890360u, 2169963562u, 1270526347u, 3498783456u, 149166u, +4223872385u, 1378013428u, 3071223888u, 1460925171u, 3695318035u, 3594083709u, 4166588825u, 9582620u, 2259883222u, 2057664441u, 314048097u, 745834u, +3939492741u, 2595099848u, 2471217553u, 3009658562u, 1296720992u, 790549365u, 3653074945u, 47913104u, 2709481518u, 1698387615u, 1570240487u, 3729170u, +2517594521u, 90597356u, 3766153176u, 2163390924u, 2188637667u, 3952746826u, 1085505541u, 239565524u, 662505702u, 4196970782u, 3556235140u, 18645851u, +3998038013u, 452986782u, 1650896696u, 2227020032u, 2353253745u, 2583864948u, 1132560413u, 1197827621u, 3312528510u, 3804984726u, 601306520u, 93229259u, +2810320881u, 2264933914u, 3959516184u, 2545165569u, 3176334135u, 34422854u, 1367834772u, 1694170810u, 3677740663u, 1845054449u, 3006532604u, 466146295u, +1166702517u, 2734734981u, 2617711738u, 4135893257u, 2996768789u, 172114273u, 2544206564u, 4175886755u, 1208834132u, 635337657u, 2147761134u, 2330731478u, +1538545289u, 788773018u, 203656805u, 3499597104u, 2098942061u, 860571368u, 4131098228u, 3699564593u, 1749203368u, 3176688286u, 2148871078u, 3063722800u, 2u, +3397759149u, 3943865091u, 1018284025u, 318116336u, 1904775717u, 7889546u, 3475621957u, 1317953785u, 156082252u, 2998539544u, 2154420801u, 2433712114u, 13u, +4103893857u, 2539456274u, 796452833u, 1590581681u, 933943993u, 39447732u, 198240601u, 2294801633u, 780411261u, 2107795832u, 2182169416u, 3578625980u, 67u, +3339600101u, 4107346782u, 3982264167u, 3657941109u, 374752670u, 197238661u, 991203005u, 2884073573u, 3902056307u, 1949044568u, 2320912490u, 713260718u, 339u, +3813098617u, 3356864729u, 2731451655u, 1109836365u, 1873763354u, 986193305u, 661047729u, 1535465978u, 2330412354u, 1155288252u, 3014627860u, 3566303592u, 1695u, +1885623901u, 3899421761u, 772356390u, 1254214532u, 778882179u, 635999231u, 3305238646u, 3382362594u, 3062127179u, 1481473966u, 2188237413u, 651648779u, 8479u, +838184913u, 2317239623u, 3861781954u, 1976105364u, 3894410896u, 3179996155u, 3641291342u, 4026911085u, 2425734010u, 3112402537u, 2351252474u, 3258243897u, 42395u, +4190924565u, 2996263523u, 2129040588u, 1290592232u, 2292185298u, 3015078891u, 1026587529u, 2954686245u, 3538735462u, 2677110799u, 3166327781u, 3406317599u, 211978u, +3774753641u, 2096415731u, 2055268351u, 2157993866u, 2870991899u, 2190492569u, 837970352u, 1888529338u, 513808129u, 500652111u, 2946737020u, 4146686110u, 1059893u, +1693899021u, 1892144067u, 1686407165u, 2200034740u, 1470057609u, 2362528256u, 4189851762u, 852712098u, 2569040647u, 2503260555u, 1848783212u, 3553561369u, 5299469u, +4174527809u, 870785744u, 4137068531u, 2410239109u, 3055320751u, 3222706689u, 3769389628u, 4263560494u, 4255268643u, 3926368185u, 653981470u, 587937663u, 26497349u, +3692769861u, 58961428u, 3505473472u, 3461260957u, 2391701869u, 3228631560u, 1667078959u, 4137933290u, 4096474035u, 2451971745u, 3269907354u, 2939688315u, 132486745u, +1283980121u, 294807144u, 347498176u, 126435605u, 3368574757u, 3258255914u, 4040427502u, 3509797267u, 3302500995u, 3669924137u, 3464634884u, 1813539690u, 662433728u, +2124933309u, 1474035721u, 1737490880u, 632178025u, 3957971897u, 3406377685u, 3022268329u, 369117155u, 3627603091u, 1169751504u, 143305240u, 477763862u, 3312168642u, +2034731953u, 3075211311u, 97519809u, 3160890127u, 2609990301u, 4146986541u, 2226439760u, 1845585778u, 958146271u, 1553790228u, 716526201u, 2388819310u, 3675941322u, 3u, +1583725173u, 2491154669u, 487599048u, 2919548747u, 165049620u, 3555063524u, 2542264212u, 637994300u, 495764061u, 3473983845u, 3582631006u, 3354161958u, 1199837428u, 19u, +3623658569u, 3865838754u, 2437995242u, 1712841847u, 825248103u, 595448436u, 4121386472u, 3189971502u, 2478820305u, 190050041u, 733285850u, 3885907906u, 1704219847u, 96u, +938423661u, 2149324590u, 3600041622u, 4269241941u, 4126240516u, 2977242180u, 3427063176u, 3064955626u, 3804166936u, 950250207u, 3666429250u, 2249670346u, 4226131943u, 481u, +397151009u, 2156688359u, 820338928u, 4166340525u, 3451333400u, 2001309016u, 4250413995u, 2439876245u, 1840965499u, 456283743u, 1152277067u, 2658417142u, 3950790533u, 2409u, +1985755045u, 2193507203u, 4101694642u, 3651833441u, 76797820u, 1416610492u, 4072200793u, 3609446637u, 614892905u, 2281418717u, 1466418039u, 407183823u, 2574083484u, 12049u, +1338840633u, 2377601425u, 3328604028u, 1079298025u, 383989104u, 2788085164u, 3181134782u, 867364005u, 3074464529u, 2817158993u, 3037122901u, 2035919116u, 4280482828u, 60247u, +2399235869u, 3298072534u, 3758118254u, 1101522832u, 1919945521u, 1055523932u, 3020772025u, 41852732u, 2487420758u, 1200893080u, 2300712620u, 1589660991u, 4222544958u, 301239u, +3406244753u, 3605460784u, 1610722089u, 1212646868u, 1009793014u, 982652366u, 2218958238u, 209263663u, 3847169198u, 1709498106u, 2913628509u, 3653337661u, 3932855607u, 1506199u, +4146321877u, 847434739u, 3758643153u, 1768267045u, 753997775u, 618294535u, 2504856599u, 1046318317u, 2055976806u, 4252523238u, 1683240658u, 1086819124u, 2484408855u, 7530999u, +3551740201u, 4237173699u, 1613346581u, 251400637u, 3769988877u, 3091472675u, 3934348403u, 936624291u, 1689949439u, 4082747008u, 4121235998u, 1139128325u, 3832109684u, 37654997u, +578831821u, 4005999315u, 3771765613u, 1257003186u, 1670075201u, 2572461491u, 2491872834u, 388154163u, 4154779900u, 3233865857u, 3426310810u, 1400674333u, 1980679237u, 188274989u, +2894159105u, 2850127391u, 1678958885u, 1990048638u, 4055408710u, 4272372864u, 3869429580u, 1940770817u, 3594030316u, 3284427401u, 4246652165u, 2708404372u, 1313461594u, 941374947u, +1585893637u, 1365735070u, 4099827132u, 1360308599u, 3097174368u, 4181995140u, 2167278720u, 1113919497u, 790282398u, 3537235121u, 4053391644u, 657119976u, 2272340677u, 411907440u, 1u, +3634500889u, 2533708055u, 3319266477u, 2506575703u, 2600969953u, 3730106519u, 2246459012u, 1274630191u, 3951411991u, 506306421u, 3087089040u, 3285599884u, 2771768793u, 2059537202u, 5u, +992635261u, 4078605687u, 3711430499u, 3942943926u, 119947879u, 1470663414u, 2642360472u, 2078183661u, 2577190772u, 2531532109u, 2550543312u, 3543097535u, 973942080u, 1707751421u, 27u, +668209009u, 3213159252u, 1377283315u, 2534850450u, 599739399u, 3058349774u, 326900473u, 1800983716u, 1051974u, 4067725956u, 4162781970u, 535618493u, 574743108u, 4243789810u, 136u, +3341045045u, 3180894372u, 2591449282u, 4084317659u, 2998696997u, 2406846982u, 1634502368u, 414983988u, 5259872u, 3158760596u, 3634040670u, 2678092469u, 2873715540u, 4039079866u, 684u, +3820323337u, 3019569975u, 72344525u, 3241719114u, 2108583101u, 3444300321u, 3877544546u, 2074919941u, 26299360u, 2908901092u, 990334169u, 505560461u, 1483675815u, 3015530149u, 3424u, +1921747501u, 2212947991u, 361722628u, 3323693682u, 1952980916u, 41632423u, 2207853550u, 1784665117u, 131496802u, 1659603572u, 656703552u, 2527802306u, 3123411779u, 2192748858u, 17123u, +1018802913u, 2474805365u, 1808613142u, 3733566522u, 1174969991u, 208162117u, 2449333158u, 333390995u, 657484012u, 4003050564u, 3283517761u, 4049076938u, 2732157009u, 2373809701u, 85617u, +799047269u, 3784092234u, 453131120u, 1487963428u, 1579882663u, 1040810586u, 3656731198u, 1666954977u, 3287420060u, 2835383636u, 3532686921u, 3065515509u, 775883161u, 3279113916u, 428087u, +3995236345u, 1740591986u, 2265655604u, 3144849844u, 3604446020u, 909085635u, 1103786807u, 4039807593u, 3552198413u, 1292016295u, 483565424u, 2442675661u, 3879415808u, 3510667692u, 2140438u, +2796312541u, 113025342u, 2738343430u, 2839347334u, 842360919u, 250460883u, 1223966740u, 3019168782u, 581122885u, 2165114183u, 2417827121u, 3623443713u, 2217209858u, 373469280u, 10702194u, +1096660817u, 565126713u, 806815262u, 1311834785u, 4211804598u, 1252304415u, 1824866404u, 2210942023u, 2905614428u, 2235636323u, 3499201015u, 937349383u, 2496114702u, 1867346402u, 53510970u, +1188336789u, 2825633566u, 4034076310u, 2264206629u, 3879153807u, 1966554783u, 534397429u, 2464775525u, 1643170254u, 2588247026u, 316135893u, 391779623u, 3890638919u, 746797420u, 267554852u, +1646716649u, 1243265943u, 2990512369u, 2731098557u, 2215899853u, 1242839327u, 2671987147u, 3733943033u, 3920883976u, 56333243u, 1580679468u, 1958898115u, 2273325411u, 3733987104u, 1337774260u, +3938615949u, 1921362420u, 2067659958u, 770590900u, 2489564676u, 1919229341u, 475033848u, 1489845984u, 2424550700u, 281666219u, 3608430044u, 1204555984u, 2776692465u, 1490066338u, 2393904008u, 1u, +2513210561u, 1016877512u, 1748365200u, 3852954502u, 3857888788u, 1006212115u, 2375169242u, 3154262624u, 3532818909u, 1408331097u, 862281036u, 1727812628u, 998560438u, 3155364397u, 3379585449u, 7u, +3976118213u, 789420266u, 151891409u, 2084903328u, 2109574760u, 736093283u, 3285911619u, 2886411234u, 484225364u, 2746688193u, 16437885u, 49128549u, 697834896u, 2891920098u, 4013025360u, 38u, +2700721881u, 3947101334u, 759457045u, 1834582048u, 1957939210u, 3680466417u, 3544656207u, 1547154285u, 2421126823u, 848539077u, 82189428u, 245642745u, 3489174480u, 1574698602u, 2885257619u, 194u, +618707517u, 2555637489u, 3797285229u, 582975648u, 1199761460u, 1222462903u, 543411855u, 3440804133u, 3515699524u, 4242695387u, 410947140u, 1228213725u, 266003216u, 3578525718u, 1541386208u, 973u, +3093537585u, 4188252853u, 1806556963u, 2914878244u, 1703840004u, 1817347220u, 2717059276u, 24151481u, 398628440u, 4033607755u, 2054735704u, 1846101329u, 1330016081u, 712759406u, 3411963748u, 4866u, +2582786037u, 3761395084u, 442850227u, 1689489334u, 4224232727u, 496801509u, 700394494u, 120757408u, 1993142200u, 2988169591u, 1683743932u, 640572055u, 2355113111u, 3563797031u, 4174916852u, 24333u, +29028297u, 1627106239u, 2214251139u, 4152479374u, 3941294452u, 2484007549u, 3501972470u, 603787040u, 1375776408u, 2055946069u, 4123752367u, 3202860276u, 3185630963u, 639115973u, 3694715080u, 121669u, +145141485u, 3840563899u, 2481321104u, 3582527688u, 2526603080u, 3830103157u, 329993168u, 3018935204u, 2583914744u, 1689795754u, 3438892653u, 3129399496u, 3043252930u, 3195579868u, 1293706216u, 608349u, +725707425u, 2022950311u, 3816670932u, 732769258u, 4043080812u, 1970646603u, 1649965844u, 2209774132u, 34671835u, 4154011477u, 14594082u, 2762095596u, 2331362765u, 3092997455u, 2173563787u, 3041746u, +3628537125u, 1524816963u, 1903485478u, 3663846294u, 3035534876u, 1263298427u, 3954861926u, 2458936069u, 173359177u, 3590188201u, 72970414u, 925576092u, 3066879236u, 2580085389u, 2277884346u, 15208732u, +962816441u, 3329117523u, 927492799u, 1139362288u, 2292772496u, 2021524842u, 2594440447u, 3704745757u, 866795887u, 771071821u, 364852074u, 332913164u, 2449494293u, 15525060u, 2799487141u, 76043662u, +519114909u, 3760685728u, 342496702u, 1401844145u, 2873927889u, 1517689620u, 87300349u, 1343859604u, 39012143u, 3855359106u, 1824260370u, 1664565820u, 3657536873u, 77625302u, 1112533817u, 380218313u, +2595574545u, 1623559456u, 1712483514u, 2714253429u, 1484737558u, 3293480807u, 436501746u, 2424330724u, 195060716u, 2096926346u, 531367262u, 4027861806u, 1107815182u, 388126514u, 1267701789u, 1901091566u, +92970837u, 3822829987u, 4267450275u, 686365258u, 3128720497u, 3582502148u, 2182508733u, 3531719028u, 975303582u, 1894697138u, 2656836312u, 2959439846u, 1244108618u, 1940632571u, 2043541649u, 915523239u, 2u, +464854185u, 1934280751u, 4157382195u, 3431826294u, 2758700597u, 732641559u, 2322609077u, 478725958u, 581550618u, 883551099u, 399279674u, 1912297345u, 1925575797u, 1113228264u, 1627773655u, 282648901u, 11u, +2324270925u, 1081469163u, 3607041793u, 4274229586u, 908601100u, 3663207798u, 3023110793u, 2393629792u, 2907753090u, 122788199u, 1996398371u, 971552133u, 1037944395u, 1271174026u, 3843900980u, 1413244506u, 55u, +3031420033u, 1112378521u, 855339782u, 4191278750u, 248038208u, 1136169807u, 2230652081u, 3378214371u, 1653863564u, 613940998u, 1392057263u, 562793371u, 894754680u, 2060902835u, 2039635717u, 2771255238u, 276u, +2272198277u, 1266925312u, 4276698911u, 3776524566u, 1240191044u, 1385881739u, 2563325814u, 4006169969u, 3974350527u, 3069704991u, 2665319019u, 2813966856u, 178806104u, 1714579584u, 1608243995u, 971374304u, 1383u, +2771056793u, 2039659266u, 4203625372u, 1702753650u, 1905987928u, 2634441400u, 4226694479u, 2850980663u, 2691883455u, 2463623071u, 441693210u, 1184932395u, 894030523u, 4277930624u, 3746252680u, 561904225u, 6916u, +970382077u, 1608361741u, 3838257678u, 4218800958u, 940005049u, 287305114u, 3953603214u, 1370001431u, 574515390u, 3728180766u, 2208466052u, 1629694679u, 175185320u, 4209783937u, 1551394220u, 2809521129u, 34580u, +556943089u, 3746841410u, 2011419207u, 3914135610u, 405057953u, 1436525571u, 2588146886u, 2555039863u, 2872576951u, 1461034646u, 2452395672u, 3853506101u, 875926601u, 3869050501u, 3462003808u, 1162703758u, 172903u, +2784715445u, 1554337866u, 1467161447u, 2390808868u, 2025289769u, 2887660559u, 55832543u, 4185264726u, 1477982869u, 3010205937u, 3672043769u, 2087661323u, 84665713u, 2165383322u, 130149860u, 1518551498u, 864516u, +1038675337u, 3476722037u, 3040839940u, 3364109749u, 1536514255u, 1553400909u, 279162718u, 3746454446u, 3094947053u, 2166127798u, 1180349664u, 1848372027u, 423328567u, 2236982018u, 650749302u, 3297790194u, 4322581u, +898409389u, 203741002u, 2319297816u, 3935646860u, 3387603982u, 3472037250u, 1395813591u, 1552403046u, 2589833381u, 2240704401u, 1606781026u, 651925544u, 2116642837u, 2594975498u, 3253746512u, 3604049082u, 21612908u, +197079649u, 1018705011u, 3006554488u, 2498365118u, 4053118026u, 180317069u, 2684100663u, 3467047935u, 64265018u, 2613587416u, 3738937836u, 3259627721u, 1993279593u, 89975604u, 3383830675u, 840376229u, 108064544u, +985398245u, 798557759u, 2147870553u, 3901891001u, 3085720948u, 901585349u, 535601427u, 155370494u, 321325094u, 183035192u, 1514819999u, 3413236721u, 1376463376u, 449878022u, 4034251487u, 4201881148u, 540322720u, +632023929u, 3992788796u, 2149418173u, 2329585823u, 2543702856u, 212959452u, 2678007136u, 776852470u, 1606625470u, 915175960u, 3279132699u, 4181281718u, 2587349587u, 2249390111u, 2991388251u, 3829536560u, 2701613604u, +3160119645u, 2784074796u, 2157156277u, 3057994525u, 4128579690u, 1064797262u, 505133792u, 3884262353u, 3738160054u, 280912505u, 3510761608u, 3726539409u, 51846051u, 2657015966u, 2072039369u, 1967813619u, 623166136u, 3u, +2915696337u, 1035472095u, 2195846796u, 2405070739u, 3463029269u, 1029019018u, 2525668961u, 2241442581u, 1510931090u, 1404562529u, 373938856u, 1452827865u, 259230259u, 400177942u, 1770262256u, 1249133505u, 3115830682u, 15u, +1693579797u, 882393182u, 2389299389u, 3435419105u, 135277163u, 850127798u, 4038410214u, 2617278315u, 3259688156u, 2727845350u, 1869694281u, 2969172029u, 1296151296u, 2000889710u, 261376688u, 1950700231u, 2694251523u, 78u, +4172931689u, 116998615u, 3356562354u, 4292193639u, 676385818u, 4250638990u, 3012181886u, 201489691u, 3413538895u, 754324865u, 758536816u, 1960958259u, 2185789187u, 1414513959u, 1306883442u, 1163566563u, 586355729u, 393u, +3684789261u, 584993079u, 3897909882u, 4281099014u, 3381929094u, 4073325766u, 2176007546u, 1007448458u, 4182792587u, 3771624328u, 3792684080u, 1214856703u, 2339011345u, 2777602501u, 2239449915u, 1522865520u, 2931778646u, 1965u, +1244077121u, 2924965399u, 2309680226u, 4225625890u, 4024743586u, 3186759649u, 2290103142u, 742274996u, 3734093752u, 1678252460u, 1783551220u, 1779316223u, 3105122134u, 1003110619u, 2607314986u, 3319360306u, 1773991343u, 9828u, +1925418309u, 1739925108u, 2958466541u, 3948260268u, 2943848750u, 3048896361u, 2860581121u, 3711374982u, 1490599576u, 4096295008u, 327821509u, 306646525u, 2640708784u, 720585802u, 151673043u, 3711899645u, 280022126u, 49142u, +1037156953u, 109690950u, 1907430819u, 2561432159u, 1834341866u, 2359579920u, 1418003720u, 1377005729u, 3158030588u, 3301605857u, 1639107549u, 1533232625u, 318642032u, 3602929013u, 758365215u, 1379629041u, 1400110634u, 245710u, +890817469u, 548454751u, 947219503u, 4217226205u, 581774740u, 3207965010u, 2795051306u, 2590061350u, 2905251053u, 3623127400u, 3900570452u, 3371195830u, 1593210161u, 834775881u, 3791826079u, 2603177909u, 2705585875u, 1228551u, +159120049u, 2742273756u, 441130219u, 3906261842u, 2908873704u, 3154923162u, 1090354645u, 65404865u, 1641353380u, 935767819u, 2322983080u, 3971077266u, 3671083512u, 4173879406u, 1779261211u, 130987661u, 643027490u, 6142758u, +795600245u, 826466892u, 2205651098u, 2351440026u, 1659466636u, 2889713925u, 1156805932u, 327024326u, 3911799604u, 383871800u, 3024980809u, 2675517148u, 1175548380u, 3689527850u, 306371467u, 654938307u, 3215137450u, 30713790u, +3978001225u, 4132334460u, 2438320898u, 3167265540u, 4002365886u, 1563667738u, 1489062367u, 1635121631u, 2379128836u, 1919359004u, 2240002157u, 492683855u, 1582774607u, 1267770067u, 1531857339u, 3274691535u, 3190785362u, 153568953u, +2710136941u, 3481803120u, 3601669902u, 2951425814u, 2831960249u, 3523371398u, 3150344540u, 3880640860u, 3305709589u, 1006860430u, 2610076195u, 2463419277u, 3618905739u, 2043883040u, 3364319400u, 3488555788u, 3069024925u, 767844768u, +665782817u, 229146419u, 828480330u, 1872227186u, 1274899360u, 436987809u, 2866820816u, 2223335119u, 3643646061u, 739334857u, 165479088u, 3727161796u, 914659513u, 1629480612u, 3936695114u, 262909759u, 2460222741u, 3839223843u, +3328914085u, 1145732095u, 4142401650u, 771201338u, 2079529506u, 2184939046u, 1449202192u, 2526741006u, 1038361123u, 3696674289u, 827395440u, 1455939796u, 278330273u, 3852435765u, 2503606387u, 1314548799u, 3711179113u, 2016250033u, 4u, +3759668537u, 1433693182u, 3532139067u, 3856006694u, 1807712938u, 2334760640u, 2951043666u, 4043770439u, 896838321u, 1303502262u, 4136977204u, 2984731684u, 1391651366u, 2082309641u, 3928097347u, 2277776701u, 1376026382u, 1491315577u, 22u, +1618473501u, 2873498618u, 480826152u, 2100164290u, 448630102u, 3083868610u, 1870316444u, 3038983014u, 189224313u, 2222544015u, 3505016837u, 2038756536u, 2663289537u, 1821613614u, 2460617553u, 2798948917u, 2585164616u, 3161610590u, 111u, +3797400209u, 1482591203u, 2404130763u, 1910886858u, 2243150512u, 2534441162u, 761647631u, 2310013184u, 946121568u, 2522785483u, 345215003u, 1603848092u, 431545799u, 518133481u, 3713153175u, 1109842699u, 40921195u, 2923151065u, 558u, +1807131861u, 3117988723u, 3430719224u, 964499700u, 2625817970u, 4082271220u, 3808238157u, 2960131328u, 435640546u, 4023992824u, 1726075017u, 3724273164u, 2157728996u, 2590667405u, 1385896691u, 1254246203u, 204605976u, 1730853437u, 2793u, +445724713u, 2705041729u, 4268694235u, 527531207u, 244187963u, 3231486919u, 1861321605u, 1915754756u, 2178202733u, 2940094936u, 40440497u, 1441496638u, 2198710392u, 68435139u, 2634516162u, 1976263720u, 1023029881u, 64332593u, 13967u, +2228623565u, 640306757u, 4163601994u, 2637656039u, 1220939815u, 3272532707u, 716673436u, 988839190u, 2301079075u, 1815572794u, 202202488u, 2912515894u, 2403617369u, 342175697u, 287678922u, 1291384011u, 820182111u, 321662966u, 69835u, +2553183233u, 3201533787u, 3638140786u, 303378311u, 1809731782u, 3477761648u, 3583367183u, 649228654u, 2915460784u, 487929380u, 1011012442u, 1677677582u, 3428152256u, 1710878487u, 1438394610u, 2161952759u, 4100910556u, 1608314830u, 349175u, +4175981573u, 3122767049u, 1010834749u, 1516891559u, 458724318u, 208939058u, 736966735u, 3246143274u, 1692402032u, 2439646903u, 760094914u, 4093420615u, 4255859393u, 4259425142u, 2897005755u, 2219829204u, 3324683598u, 3746606858u, 1745876u, +3700038681u, 2728933361u, 759206452u, 3289490500u, 2293621591u, 1044695290u, 3684833675u, 3345814482u, 4167042867u, 3608299924u, 3800474572u, 3287233891u, 4099427785u, 4117256530u, 1600126891u, 2509211431u, 3738516104u, 1553165109u, 8729384u, +1320324221u, 759764921u, 3796032263u, 3562550612u, 2878173366u, 928509156u, 1244299192u, 3844170526u, 3655345154u, 861630440u, 1822503680u, 3551267571u, 3317269744u, 3406413470u, 3705667163u, 3956122564u, 1512711338u, 3470858253u, 43646921u, +2306653809u, 3798824606u, 1800292131u, 632883880u, 1505964946u, 347578487u, 1926528665u, 2040983447u, 1096856590u, 13184908u, 522583809u, 576468673u, 3701446836u, 4147165465u, 1348466634u, 2600743640u, 3268589398u, 174422082u, 218234609u, +2943334453u, 1814253848u, 411526067u, 3164419402u, 3234857434u, 1737892436u, 1042708733u, 1614982645u, 1189315656u, 65924541u, 2612919045u, 2882343365u, 1327364996u, 3555958145u, 2447365878u, 118816313u, 3458045105u, 872110413u, 1091173045u, +1831770377u, 481334651u, 2057630337u, 2937195122u, 3289385285u, 99527591u, 918576371u, 3779945930u, 1651610985u, 329622706u, 179693337u, 1526814940u, 2341857687u, 599921542u, 3646894802u, 594081567u, 110356341u, 65584773u, 1160897930u, 1u, +568917293u, 2406673257u, 1698217093u, 1801073724u, 3562024540u, 497637958u, 297914559u, 1719860467u, 3963087633u, 1648113531u, 898466685u, 3339107404u, 3119353844u, 2999607712u, 1054604826u, 2970407839u, 551781705u, 327923865u, 1509522354u, 6u, +2844586465u, 3443431693u, 4196118171u, 415434029u, 630253518u, 2488189794u, 1489572795u, 9367743u, 2635568983u, 3945600363u, 197366130u, 3810635133u, 2711867335u, 2113136675u, 978056837u, 1967137308u, 2758908528u, 1639619325u, 3252644474u, 31u, +1338030437u, 37289284u, 3800721675u, 2077170149u, 3151267590u, 3851014378u, 3152896681u, 46838716u, 292943027u, 2548132634u, 986830654u, 1873306481u, 674434791u, 1975748786u, 595316891u, 1245751949u, 909640754u, 3903129332u, 3378320483u, 158u, +2395184889u, 186446421u, 1823739191u, 1795916157u, 2871436064u, 2075202709u, 2879581521u, 234193583u, 1464715135u, 4150728578u, 639185976u, 776597814u, 3372173957u, 1288809338u, 2976584457u, 1933792449u, 253236475u, 2335777477u, 4006700531u, 793u, +3385989853u, 932232107u, 528761363u, 389646195u, 1472278434u, 1786078956u, 1513005719u, 1170967918u, 3028608379u, 3573773707u, 3195929884u, 3882989070u, 3975967897u, 2149079397u, 1998020398u, 1079027656u, 1266182377u, 3088952793u, 2853633473u, 3969u, +4045047377u, 366193242u, 2643806816u, 1948230975u, 3066424874u, 340460189u, 3270061301u, 1559872295u, 2258140008u, 688999354u, 3094747536u, 2235076169u, 2699970305u, 2155462397u, 1400167400u, 1100170986u, 2035944590u, 2559862078u, 1383265480u, 19848u, +3045367701u, 1830966214u, 334132192u, 1151220286u, 2447222484u, 1702300948u, 3465404617u, 3504394182u, 2700765449u, 3444996772u, 2588835792u, 2585446256u, 614949639u, 2187377396u, 2705869706u, 1205887635u, 1589788359u, 4209375800u, 2621360106u, 99241u, +2341936617u, 564896481u, 1670660962u, 1461134134u, 3646177829u, 4216537446u, 147153902u, 342101730u, 618925361u, 45114679u, 59277076u, 42329395u, 3074748198u, 2346952388u, 644446644u, 1734470882u, 3653974500u, 3867009817u, 221898646u, 496208u, +3119748493u, 2824482407u, 4058337514u, 3010703375u, 1051019962u, 3902818050u, 735769514u, 1710508650u, 3094626805u, 225573395u, 296385380u, 211646975u, 2488839102u, 3144827351u, 3222233222u, 82419818u, 1090003318u, 2155179905u, 1109493234u, 2481040u, +2713840577u, 1237510150u, 3111818389u, 2168614991u, 960132517u, 2334221067u, 3678847574u, 4257575954u, 2588232138u, 1127866978u, 1481926900u, 1058234875u, 3854260918u, 2839234869u, 3226264225u, 412099093u, 1155049294u, 2185964934u, 1252498876u, 12405201u, +684300997u, 1892583457u, 2674190058u, 2253140366u, 505695291u, 3081170744u, 1214368688u, 4108010590u, 56258806u, 1344367597u, 3114667205u, 996207080u, 2091435407u, 1311272461u, 3246419240u, 2060495468u, 1480279174u, 2339890079u, 1967527086u, 62026006u, +3421504985u, 872982693u, 486048404u, 2675767241u, 2528476457u, 2520951832u, 1776876147u, 3360183767u, 281294034u, 2426870689u, 2688434138u, 686068107u, 1867242444u, 2261395011u, 3347194313u, 1712542751u, 3106428576u, 3109515804u, 1247700840u, 310130032u, +4222623037u, 69946172u, 2430242021u, 493934317u, 4052447696u, 4014824570u, 294446145u, 3916016949u, 1406470173u, 3544418853u, 557268804u, 3430340538u, 746277628u, 2717040465u, 3851069679u, 4267746462u, 2647240993u, 2662677135u, 1943536907u, 1550650161u, +3933246001u, 349730864u, 3561275513u, 2469671587u, 3082369296u, 2894253670u, 1472230729u, 2400215561u, 2737383573u, 542225082u, 2786344024u, 4266800802u, 3731388143u, 700300437u, 2075479214u, 4158863130u, 351303081u, 428483790u, 1127749946u, 3458283511u, 1u, +2486360821u, 1748654324u, 626508381u, 3758423347u, 2526944594u, 1586366465u, 3066186352u, 3411143214u, 802015979u, 2711125413u, 1046818232u, 4154134829u, 1477071535u, 3501502189u, 1787461478u, 3614446468u, 1756515409u, 2142418950u, 1343782434u, 111548372u, 9u, +3841869513u, 153337030u, 3132541907u, 1612247551u, 4044788382u, 3636865031u, 2446029873u, 4170814185u, 4010079898u, 670725177u, 939123867u, 3590804962u, 3090390383u, 327641762u, 347372802u, 892363158u, 192642457u, 2122160160u, 2423944876u, 557741861u, 45u, +2029478381u, 766685154u, 2777807647u, 3766270462u, 3044072727u, 1004455975u, 3640214777u, 3674201743u, 2870530310u, 3353625889u, 400652039u, 774155627u, 2567050031u, 1638208813u, 1736864010u, 166848494u, 963212286u, 2020866208u, 3529789790u, 2788709307u, 225u, +1557457313u, 3833425772u, 1004136347u, 1651483129u, 2335461751u, 727312582u, 1021204702u, 1191139535u, 1467749666u, 3883227560u, 2003260198u, 3870778135u, 4245315563u, 3896076771u, 94385459u, 834242472u, 521094134u, 1514396449u, 469079768u, 1058644651u, 1128u, +3492319269u, 1987259677u, 725714443u, 3962448350u, 3087374164u, 3636562912u, 811056214u, 1660730380u, 3043781035u, 2236268617u, 1426366402u, 2174021493u, 4046708635u, 2300514675u, 471927299u, 4171212360u, 2605470670u, 3277014949u, 2345398841u, 998255959u, 5641u, +281727161u, 1346363797u, 3628572217u, 2632372566u, 2551968936u, 1002945379u, 4055281074u, 4008684604u, 2334003288u, 2591408496u, 2836864716u, 2280172874u, 3053673993u, 2912638787u, 2359636497u, 3676192616u, 142451466u, 3500172860u, 3137059616u, 696312501u, 28206u, +1408635805u, 2436851689u, 962991902u, 276960946u, 4169910091u, 719759601u, 3096536187u, 2863553840u, 3080081852u, 72140594u, 1299421695u, 2810929781u, 2383468079u, 1678292050u, 3208247896u, 1201093898u, 712257334u, 320995116u, 2800396196u, 3481562508u, 141030u, +2748211729u, 3594323854u, 519992216u, 1384804731u, 3669681271u, 3598798009u, 2597779047u, 1432867315u, 2515507375u, 360702973u, 2202141179u, 1169747018u, 3327405806u, 4096492956u, 3156337593u, 1710502197u, 3561286671u, 1604975580u, 1117079092u, 227943359u, 705154u, +856156757u, 791750089u, 2599961084u, 2629056359u, 1168537172u, 814120865u, 103993351u, 2869369282u, 3987602284u, 1803514867u, 2420771303u, 1553767796u, 3752127143u, 3302595599u, 2896786081u, 4257543692u, 626564172u, 3729910608u, 1290428165u, 1139716796u, 3525770u, +4280783785u, 3958750445u, 114903532u, 260379910u, 1547718567u, 4070604326u, 519966755u, 1461944522u, 2758142239u, 427639747u, 3513921925u, 3473871686u, 1580766532u, 3628076111u, 1599028520u, 4107849279u, 3132820864u, 1469683856u, 2157173533u, 1403616685u, 17628851u, +4224049741u, 2613883045u, 574517664u, 1301899550u, 3443625539u, 3173152447u, 2599833779u, 3014755314u, 905809308u, 2138198738u, 389740441u, 189489250u, 3608865368u, 960511372u, 3700175308u, 3359377212u, 2779202436u, 3053451987u, 2195933074u, 2723116131u, 88144256u, +3940379521u, 184513341u, 2872588323u, 2214530454u, 38258512u, 2980860351u, 114267010u, 2188874685u, 234079247u, 2101059099u, 1948702207u, 947446250u, 864457656u, 507589568u, 1321007357u, 3911984176u, 1011110295u, 2382358050u, 2389730781u, 730678769u, 440721283u, +2522028421u, 922566709u, 1478039727u, 2482717681u, 191292562u, 2019399867u, 571335053u, 2354438833u, 1170396237u, 1915360903u, 1153576445u, 442263956u, 27320985u, 2537947841u, 2310069489u, 2380051697u, 760584183u, 3321855659u, 3358719315u, 3653393847u, 2203606415u, +4020207513u, 317866251u, 3095231340u, 3823653814u, 956462812u, 1507064743u, 2856675267u, 3182259573u, 1557013891u, 986869924u, 1472914931u, 2211319781u, 136604925u, 4099804613u, 2960412855u, 3310323895u, 3802920917u, 3724376407u, 3908694690u, 1087100054u, 2428097487u, 2u, +2921168381u, 1589331259u, 2591254812u, 1938399889u, 487346768u, 3240356420u, 1398474448u, 3026395980u, 3490102162u, 639382325u, 3069607360u, 2466664314u, 683024627u, 3319153881u, 1917162391u, 3666717590u, 1834735404u, 1442012855u, 2363604270u, 1140532978u, 3550552844u, 12u, +1720940017u, 3651689002u, 71372173u, 1102064856u, 2436733842u, 3316880212u, 2697404947u, 2247078013u, 270641629u, 3196911629u, 2463134912u, 3743386981u, 3415123137u, 3710867517u, 995877366u, 1153718768u, 583742432u, 2915096981u, 3228086759u, 1407697596u, 572895037u, 64u, +14765493u, 1078575828u, 356860869u, 1215356984u, 3593734619u, 3699499174u, 602122850u, 2645455476u, 1353208147u, 3099656257u, 3725739971u, 1537065723u, 4190713801u, 1374468404u, 684419538u, 1473626545u, 2918712161u, 1690583017u, 3255531910u, 2743520687u, 2864475186u, 320u, +73827465u, 1097911844u, 1784304346u, 1781817624u, 788803912u, 1317626690u, 3010614254u, 342375492u, 2471073442u, 2613379398u, 1448830674u, 3390361323u, 3773699822u, 2577374728u, 3422097691u, 3073165429u, 1708658918u, 4157947792u, 3392757663u, 832701550u, 1437474045u, 1603u, +369137325u, 1194591924u, 331587139u, 319153530u, 3944019562u, 2293166154u, 2168169383u, 1711877463u, 3765432618u, 181995104u, 2949186077u, 4066904728u, 1688629929u, 1971756u, 4225586570u, 2480925260u, 4248327297u, 3609869777u, 4078886431u, 4163507753u, 2892402929u, 8016u, +1845686625u, 1677992324u, 1657935696u, 1595767650u, 2540228626u, 2875896182u, 2250912325u, 4264420021u, 1647293907u, 909975524u, 1861028497u, 3154654459u, 4148182353u, 9858781u, 3948063666u, 3814691712u, 4061767303u, 869479705u, 3214562975u, 3637669585u, 1577112761u, 40083u, +638498533u, 4094994326u, 3994711185u, 3683870955u, 4111208539u, 1494579024u, 2664627036u, 4142230923u, 3941502243u, 254910325u, 715207894u, 2888370409u, 3561042584u, 49293909u, 2560449146u, 1893589380u, 3128967335u, 52431233u, 3187912988u, 1008478744u, 3590596513u, 200416u, +3192492665u, 3295102446u, 2793686745u, 1239485595u, 3376173515u, 3177927828u, 438233293u, 3531285434u, 2527642035u, 1274551629u, 3576039470u, 1556950157u, 625343739u, 246469549u, 4212311138u, 878012310u, 2759934789u, 262156168u, 3054663052u, 747426427u, 773113382u, 1002084u, +3077561437u, 3590610345u, 1083531840u, 1902460682u, 3995965688u, 3004737255u, 2191166468u, 476557986u, 4048275587u, 2077790851u, 700328167u, 3489783493u, 3126718696u, 1232347745u, 3881686506u, 95094258u, 914772058u, 1310780843u, 2388413372u, 3737132138u, 3865566910u, 5010420u, +2502905297u, 773182544u, 1122691908u, 922368819u, 2799959258u, 2138784391u, 2365897751u, 2382789932u, 3061508751u, 1799019667u, 3501640837u, 269048281u, 2748691596u, 1866771432u, 2228563347u, 475471294u, 278892994u, 2258936920u, 3352132269u, 1505791508u, 2147965370u, 25052104u, +3924591893u, 3865912722u, 1318492244u, 316876800u, 1114894403u, 2103987366u, 3239554165u, 3324015070u, 2422641869u, 405163746u, 328335003u, 1345241409u, 858556092u, 743922571u, 2552882145u, 2377356472u, 1394464970u, 2704750008u, 3875759459u, 3233990247u, 2149892259u, 125260522u, +2443090281u, 2149694430u, 2297493928u, 1584384001u, 1279504719u, 1930002239u, 3312868939u, 3735173465u, 3523274756u, 2025818732u, 1641675015u, 2431239749u, 4292780461u, 3719612855u, 4174476133u, 3296847770u, 2677357556u, 638848153u, 2198928114u, 3285049351u, 2159526706u, 626302612u, +3625516813u, 2158537560u, 2897535050u, 3626952711u, 2102556300u, 1060076604u, 3679442809u, 1495998144u, 436504600u, 1539159072u, 3913407781u, 3566264154u, 4284033123u, 1418195095u, 3692511485u, 3599336966u, 501885895u, 3194240768u, 2404705978u, 3540344869u, 2207698941u, 3131513062u, +947714881u, 2202753212u, 1602773364u, 954894374u, 1922846912u, 1005415726u, 1217344862u, 3185023428u, 2182523001u, 3400828064u, 2387169722u, 651451590u, 4240296435u, 2796008183u, 1282688242u, 816815650u, 2509429479u, 3086301952u, 3433595301u, 521855163u, 2448560117u, 2772663424u, 3u, +443607109u, 2423831469u, 3718899526u, 479504575u, 1024299969u, 732111336u, 1791757015u, 3040215253u, 2322680416u, 4119238434u, 3345914021u, 3257257952u, 4021612991u, 1095139031u, 2118473917u, 4084078251u, 3957212803u, 2546607874u, 4283074620u, 2609275818u, 3652865993u, 978415234u, 18u, +2218035545u, 3529222753u, 1414628448u, 2397522879u, 826532549u, 3660556681u, 368850483u, 2316174379u, 3023467491u, 3416322988u, 3844668221u, 3401387875u, 2928195774u, 1180727863u, 2002434994u, 3240522073u, 2606194835u, 4143104782u, 4235503918u, 161477206u, 1084460784u, 597108878u, 91u, +2500243133u, 466244583u, 2778174948u, 3397679804u, 4132662747u, 1122914221u, 1844252419u, 2990937303u, 2232435569u, 4196713055u, 2043471924u, 4122037491u, 1756076985u, 1608672022u, 1422240379u, 3317708479u, 146072290u, 3535654729u, 3997650410u, 807386034u, 1127336624u, 2985544391u, 455u, +3911281073u, 2331222917u, 1005972852u, 4103497135u, 3483444554u, 1319603813u, 631327504u, 2069784629u, 2572243256u, 3803696093u, 1627425032u, 3430318273u, 190450337u, 3748392816u, 2816234600u, 3703640508u, 730361453u, 498404461u, 2808382870u, 4036930174u, 1341715824u, 2042820068u, 2278u, +2376536181u, 3066179997u, 734896966u, 3337616492u, 237353590u, 2303051773u, 3156637521u, 1758988553u, 4271281690u, 1838611283u, 3842157868u, 4266689478u, 952251688u, 1562094896u, 1196271116u, 1338333359u, 3651807269u, 2492022305u, 1157012462u, 3004781689u, 2413611828u, 1624165749u, 11392u, +3292746313u, 2445998099u, 3674484833u, 3803180572u, 1186767953u, 2925324273u, 2898285719u, 205008176u, 4176539268u, 603121827u, 2030920158u, 4153578210u, 466291148u, 3515507185u, 1686388285u, 2396699500u, 1079167162u, 3870176937u, 1490095016u, 2139006558u, 3478124551u, 3825861451u, 56961u, +3578829677u, 3640055906u, 1192554983u, 1836033680u, 1638872473u, 1741719478u, 1606526710u, 1025040883u, 3702827156u, 3015609139u, 1564666198u, 3588021868u, 2331455744u, 397666741u, 4136974133u, 3393562909u, 1100868516u, 2171015502u, 3155507788u, 2105098199u, 210753573u, 1949438075u, 284809u, +714279201u, 1020410350u, 1667807623u, 590233809u, 3899395071u, 118662799u, 3737666256u, 830237120u, 1334266597u, 2193143811u, 3528363697u, 760240157u, 3067344132u, 1988333707u, 3505001481u, 4082912661u, 1209375287u, 2265142919u, 2892637054u, 1935556406u, 1053767867u, 1157255783u, 1424047u, +3571396005u, 807084454u, 4044070820u, 2951169046u, 2317106171u, 593313999u, 1508462096u, 4151185604u, 2376365689u, 2375784464u, 461949303u, 3801200789u, 2451818772u, 1351733946u, 345138223u, 3234694125u, 1751909143u, 2735780004u, 1578283384u, 1087847441u, 973872041u, 1491311620u, 7120236u, +677110841u, 4035422274u, 3040484916u, 1870943346u, 2995596266u, 2966569997u, 3247343184u, 3576058837u, 3291893857u, 3288987730u, 2309746517u, 1826134761u, 3669159272u, 2463702436u, 1725691116u, 3288568737u, 169611126u, 793998134u, 3596449627u, 1144269910u, 574392910u, 3161590805u, 35601181u, +3385554205u, 2997242186u, 2317522696u, 764782141u, 2093079444u, 1947948100u, 3351814035u, 700425004u, 3574567401u, 3560036765u, 2958797996u, 540739215u, 1165927178u, 3728577592u, 38520990u, 3557941799u, 848055633u, 3969990670u, 802378951u, 1426382258u, 2871964551u, 2923052137u, 178005908u, +4042869137u, 2101309045u, 2997678891u, 3823910707u, 1875462628u, 1149805910u, 3874168289u, 3502125023u, 692967821u, 620314645u, 1909088096u, 2703696078u, 1534668594u, 1463018777u, 192604954u, 609839811u, 4240278169u, 2670084166u, 4011894759u, 2836943994u, 1474920868u, 1730358800u, 890029543u, +3034476501u, 1916610637u, 2103492569u, 1939684354u, 787378552u, 1454062256u, 2190972262u, 330755935u, 3464839109u, 3101573225u, 955505888u, 633578504u, 3378375677u, 3020126590u, 963024771u, 3049199055u, 4021521661u, 465518946u, 2879604614u, 1299818086u, 3079637047u, 61859409u, 155180421u, 1u, +2287480617u, 993118596u, 1927528255u, 1108487180u, 3936892762u, 2975343984u, 2364926719u, 1653779677u, 144326361u, 2622964241u, 482562147u, 3167892521u, 4006976497u, 2215731065u, 520156562u, 2361093388u, 2927739124u, 2327594734u, 1513121182u, 2204123137u, 2513283348u, 309297048u, 775902105u, 5u, +2847468493u, 670625686u, 1047706684u, 1247468606u, 2504594627u, 1991818036u, 3234699006u, 3973931091u, 721631806u, 229919317u, 2412810738u, 2954560717u, 2855013304u, 2488720737u, 2600782812u, 3215532348u, 1753793734u, 3048039081u, 3270638616u, 2430681094u, 3976482150u, 1546485242u, 3879510525u, 25u, +1352440577u, 3353128433u, 943566124u, 1942375735u, 3933038544u, 1369155590u, 3288593144u, 2689786274u, 3608159034u, 1149596585u, 3474119098u, 1887901699u, 1390164635u, 3853669096u, 119012174u, 3192759855u, 179034081u, 2355293519u, 3468291195u, 3563470881u, 2702541568u, 3437458918u, 2217683442u, 129u, +2467235589u, 3880740278u, 422863327u, 1121944084u, 2485323538u, 2550810658u, 3558063833u, 564029485u, 860925989u, 1453015633u, 190726307u, 849573907u, 2655855881u, 2088476297u, 595060874u, 3078897387u, 895170408u, 3186533003u, 161586793u, 637485225u, 627805956u, 7425409u, 2498482622u, 647u, +3746243353u, 2223832208u, 2114316639u, 1314753124u, 3836683099u, 4164118700u, 610449983u, 2820147429u, 9662649u, 2970110870u, 953631536u, 4247869535u, 394377517u, 1852446896u, 2975304372u, 2509585047u, 180884747u, 3047763128u, 807933968u, 3187426125u, 3139029780u, 37127045u, 3902478518u, 3237u, +1551347581u, 2529226452u, 1981648605u, 2278798326u, 2003546312u, 3640724320u, 3052249919u, 1215835257u, 48313248u, 1965652462u, 473190387u, 4059478492u, 1971887589u, 672299888u, 1991619974u, 3957990646u, 904423737u, 2353913752u, 4039669843u, 3052228737u, 2810247015u, 185635228u, 2332523406u, 16189u, +3461770609u, 4056197669u, 1318308435u, 2804057040u, 1427796970u, 1023752418u, 2376347711u, 1784208992u, 241566241u, 1238327718u, 2365951937u, 3117523276u, 1269503357u, 3361499442u, 1368165278u, 2610084048u, 227151393u, 3179634169u, 3018480033u, 2376241801u, 1166333190u, 928176143u, 3072682438u, 80947u, +128983861u, 3101119165u, 2296574883u, 1135383313u, 2844017557u, 823794795u, 3291803964u, 331110370u, 1207831207u, 1896671294u, 3239825094u, 2702714494u, 2052549492u, 3922595323u, 2545859097u, 165518353u, 1135756968u, 3013268957u, 2207498280u, 3291274416u, 1536698656u, 345913420u, 2478510303u, 404738u, +644919305u, 2620693937u, 2892939826u, 1381949271u, 1335185898u, 4118973978u, 3574117932u, 1655551853u, 1744188739u, 893421879u, 3314223584u, 628670585u, 1672812871u, 2433107433u, 4139360897u, 827591767u, 1383817544u, 2181442898u, 2447556811u, 3571470194u, 3388525987u, 1729567101u, 3802616923u, 2023692u, +3224596525u, 218567797u, 1579797245u, 2614779062u, 2380962195u, 3415000707u, 690720480u, 3982791973u, 131009104u, 172142101u, 3686216033u, 3143352928u, 4069097059u, 3575602574u, 3516935303u, 4137958839u, 2624120424u, 2317279899u, 3647849465u, 677481788u, 4057728051u, 57900916u, 1833215433u, 10118464u, +3238080737u, 1092838988u, 3604018929u, 188993423u, 3314876386u, 4190101649u, 3453602403u, 2734090681u, 655045524u, 860710505u, 1251210981u, 2831862756u, 3165616114u, 698143690u, 404807335u, 3509925015u, 235700236u, 2996464906u, 1059378143u, 3387408944u, 3108771071u, 289504584u, 576142573u, 50592322u, +3305501797u, 1169227647u, 840225462u, 944967119u, 3689480042u, 3770639064u, 88142835u, 785551521u, 3275227623u, 8585229u, 1961087610u, 1274411893u, 2943178685u, 3490718453u, 2024036675u, 369755891u, 1178501184u, 2097422642u, 1001923422u, 4052142833u, 2658953470u, 1447522923u, 2880712865u, 252961610u, +3642607097u, 1551170942u, 4201127311u, 429868299u, 1267531027u, 1673326140u, 440714179u, 3927757605u, 3491236227u, 42926148u, 1215503458u, 2077092171u, 1830991538u, 273723084u, 1530248787u, 1848779457u, 1597538624u, 1897178619u, 714649816u, 3080844982u, 409865466u, 2942647322u, 1518662438u, 1264808053u, +1033166301u, 3460887418u, 3825767372u, 2149341499u, 2042687839u, 4071663405u, 2203570896u, 2458918841u, 276311955u, 214630744u, 1782549994u, 1795526264u, 565023100u, 1368615422u, 3356276639u, 653962694u, 3692725826u, 895958504u, 3573249082u, 2519323022u, 2049327333u, 1828334722u, 3298344897u, 2029072970u, 1u, +870864209u, 124567907u, 1948967680u, 2156772907u, 1623504605u, 3178447843u, 2427919892u, 3704659615u, 1381559777u, 1073153720u, 322815378u, 387696730u, 2825115502u, 2548109814u, 3896481308u, 3269813473u, 1283759946u, 184825228u, 686376227u, 4006680522u, 1656702075u, 551739020u, 3606822599u, 1555430261u, 7u, +59353749u, 622839536u, 1154903808u, 2193929945u, 3822555731u, 3007337328u, 3549664871u, 1343428893u, 2612831593u, 1070801305u, 1614076891u, 1938483650u, 1240675622u, 4150614481u, 2302537358u, 3464165481u, 2123832437u, 924126141u, 3431881135u, 2853533426u, 3988543083u, 2758695101u, 854243811u, 3482184013u, 36u, +296768745u, 3114197680u, 1479551744u, 2379715134u, 1932909473u, 2151784756u, 568455174u, 2422177173u, 179256078u, 1059039232u, 3775417160u, 1102483659u, 1908410816u, 3573203222u, 2922752202u, 140958223u, 2029227597u, 325663411u, 4274503788u, 1382765245u, 2762846234u, 908573621u, 4271219058u, 231050881u, 184u, +1483843725u, 2686086512u, 3102791427u, 3308641079u, 1074612775u, 2168989190u, 2842275872u, 3520951273u, 896280392u, 1000228864u, 1697216617u, 1217451003u, 952119489u, 686146928u, 1728859126u, 704791118u, 1556203393u, 1628317057u, 4192649756u, 2618858933u, 929329283u, 247900812u, 4176226107u, 1155254409u, 920u, +3124251329u, 545530673u, 2629055250u, 3658303510u, 1078096582u, 2255011359u, 1326477474u, 424887184u, 186434668u, 706177025u, 4191115790u, 1792287720u, 465630150u, 3430734641u, 54361038u, 3523955592u, 3486049669u, 3846617990u, 3783379597u, 209392781u, 351679122u, 1239504061u, 3701261351u, 1481304753u, 4601u, +2736354757u, 2727653368u, 260374362u, 1111648369u, 1095515618u, 2685122204u, 2337420076u, 2124435921u, 932173340u, 3530885125u, 3775709766u, 371504012u, 2328150752u, 4268771317u, 271805193u, 439908776u, 250379165u, 2053220770u, 1737028805u, 1046963909u, 1758395610u, 1902553009u, 1326437572u, 3111556473u, 23006u, +796871897u, 753364955u, 1301871813u, 1263274549u, 1182610795u, 540709133u, 3097165791u, 2032245015u, 365899406u, 474556442u, 1698679650u, 1857520064u, 3050819168u, 4163987403u, 1359025969u, 2199543880u, 1251895825u, 1676169258u, 95209435u, 939852251u, 202043459u, 922830455u, 2337220566u, 2672880478u, 115033u, +3984359485u, 3766824775u, 2214391769u, 2021405450u, 1618086680u, 2703545666u, 2600927067u, 1571290486u, 1829497032u, 2372782210u, 4198430954u, 697665729u, 2369193954u, 3640067834u, 2500162553u, 2407784809u, 1964511831u, 4085878995u, 476047176u, 404293959u, 1010217296u, 319184979u, 3096168239u, 479500504u, 575168u, +2741928241u, 1654254695u, 2482024257u, 1517092660u, 3795466106u, 632826443u, 119733450u, 3561485137u, 557550569u, 3273976460u, 3812285588u, 3488328649u, 3256035178u, 1020469988u, 3910878177u, 3448989455u, 1232624565u, 3249525793u, 2380235884u, 2021469795u, 756119184u, 1595924896u, 2595939307u, 2397502523u, 2875840u, +824739317u, 3976306182u, 3820186694u, 3290496006u, 1797461347u, 3164132219u, 598667250u, 627556501u, 2787752849u, 3484980412u, 1881558759u, 261774065u, 3395274006u, 807382647u, 2374521702u, 65078095u, 1868155533u, 3362727078u, 3311244831u, 1517414385u, 3780595922u, 3684657184u, 94794648u, 3397578026u, 14379202u, +4123696585u, 2701661726u, 1921064290u, 3567578146u, 397372146u, 2935759209u, 2993336253u, 3137782505u, 1053862357u, 245032879u, 817859207u, 1308870327u, 4091468142u, 4036913238u, 3282673918u, 325390477u, 750843073u, 3928733504u, 3671322270u, 3292104632u, 1723110427u, 1243416740u, 473973244u, 4102988242u, 71896013u, +3438613741u, 623406746u, 1015386861u, 658021548u, 1986860734u, 1793894157u, 2081779380u, 2804010640u, 974344492u, 1225164396u, 4089296035u, 2249384339u, 3277471527u, 3004697010u, 3528467706u, 1626952388u, 3754215365u, 2463798336u, 1176742170u, 3575621276u, 25617546u, 1922116406u, 2369866221u, 3335072026u, 359480069u, +13199521u, 3117033734u, 781967009u, 3290107741u, 1344369078u, 379536195u, 1818962310u, 1135151314u, 576755167u, 1830854685u, 3266610992u, 2656987107u, 3502455749u, 2138583165u, 462469349u, 3839794648u, 1591207642u, 3729057092u, 1588743556u, 698237197u, 128087734u, 1020647438u, 3259396515u, 3790458244u, 1797400348u, +65997605u, 2700266782u, 3909835048u, 3565636817u, 2426878097u, 1897680976u, 504876958u, 1380789276u, 2883775836u, 564338833u, 3448153074u, 400033650u, 332409564u, 2102981237u, 2312346747u, 2019104056u, 3661070918u, 1465416277u, 3648750488u, 3491185986u, 640438670u, 808269894u, 3412080688u, 1772422039u, 397067152u, 2u, +}; + +/* These are the indicies of the start of each power of 5 in pow5[] */ +/* The width is calculated by subtracting indices, so there is one extra */ +/* generated using (pow5w 346) from testgen.scm */ +static const uint16_t pow5w[] = { +0u, +1u, +2u, +3u, +4u, +5u, +6u, +7u, +8u, +9u, +10u, +11u, +12u, +13u, +14u, +16u, +18u, +20u, +22u, +24u, +26u, +28u, +30u, +32u, +34u, +36u, +38u, +40u, +42u, +45u, +48u, +51u, +54u, +57u, +60u, +63u, +66u, +69u, +72u, +75u, +78u, +81u, +84u, +88u, +92u, +96u, +100u, +104u, +108u, +112u, +116u, +120u, +124u, +128u, +132u, +136u, +140u, +145u, +150u, +155u, +160u, +165u, +170u, +175u, +180u, +185u, +190u, +195u, +200u, +205u, +211u, +217u, +223u, +229u, +235u, +241u, +247u, +253u, +259u, +265u, +271u, +277u, +283u, +289u, +296u, +303u, +310u, +317u, +324u, +331u, +338u, +345u, +352u, +359u, +366u, +373u, +380u, +387u, +395u, +403u, +411u, +419u, +427u, +435u, +443u, +451u, +459u, +467u, +475u, +483u, +491u, +499u, +508u, +517u, +526u, +535u, +544u, +553u, +562u, +571u, +580u, +589u, +598u, +607u, +616u, +625u, +635u, +645u, +655u, +665u, +675u, +685u, +695u, +705u, +715u, +725u, +735u, +745u, +755u, +766u, +777u, +788u, +799u, +810u, +821u, +832u, +843u, +854u, +865u, +876u, +887u, +898u, +909u, +921u, +933u, +945u, +957u, +969u, +981u, +993u, +1005u, +1017u, +1029u, +1041u, +1053u, +1065u, +1077u, +1090u, +1103u, +1116u, +1129u, +1142u, +1155u, +1168u, +1181u, +1194u, +1207u, +1220u, +1233u, +1246u, +1259u, +1273u, +1287u, +1301u, +1315u, +1329u, +1343u, +1357u, +1371u, +1385u, +1399u, +1413u, +1427u, +1441u, +1456u, +1471u, +1486u, +1501u, +1516u, +1531u, +1546u, +1561u, +1576u, +1591u, +1606u, +1621u, +1636u, +1651u, +1667u, +1683u, +1699u, +1715u, +1731u, +1747u, +1763u, +1779u, +1795u, +1811u, +1827u, +1843u, +1859u, +1875u, +1892u, +1909u, +1926u, +1943u, +1960u, +1977u, +1994u, +2011u, +2028u, +2045u, +2062u, +2079u, +2096u, +2113u, +2131u, +2149u, +2167u, +2185u, +2203u, +2221u, +2239u, +2257u, +2275u, +2293u, +2311u, +2329u, +2347u, +2365u, +2384u, +2403u, +2422u, +2441u, +2460u, +2479u, +2498u, +2517u, +2536u, +2555u, +2574u, +2593u, +2612u, +2632u, +2652u, +2672u, +2692u, +2712u, +2732u, +2752u, +2772u, +2792u, +2812u, +2832u, +2852u, +2872u, +2892u, +2913u, +2934u, +2955u, +2976u, +2997u, +3018u, +3039u, +3060u, +3081u, +3102u, +3123u, +3144u, +3165u, +3186u, +3208u, +3230u, +3252u, +3274u, +3296u, +3318u, +3340u, +3362u, +3384u, +3406u, +3428u, +3450u, +3472u, +3494u, +3517u, +3540u, +3563u, +3586u, +3609u, +3632u, +3655u, +3678u, +3701u, +3724u, +3747u, +3770u, +3793u, +3817u, +3841u, +3865u, +3889u, +3913u, +3937u, +3961u, +3985u, +4009u, +4033u, +4057u, +4081u, +4105u, +4129u, +4154u, +4179u, +4204u, +4229u, +4254u, +4279u, +4304u, +4329u, +4354u, +4379u, +4404u, +4429u, +4454u, +4479u, +4505u, +}; + +/* returns result: 0 = OK; non-zero = error */ +int get_pow5 (uint32_t exp, const uint32_t **p5, int *sz_in_32bit_words) +{ + if (exp <= MAX_POW5_IN_TABLE) + { + uint16_t idx = pow5w[exp]; + *p5 = &pow5[idx]; + *sz_in_32bit_words = pow5w[exp + 1] - idx; + return 0; + } + else + { + *p5 = &pow5[0]; + *sz_in_32bit_words = 0; + return 1; + } +} + +#endif diff --git a/contrib/10.roundtrip/nitro.mk b/contrib/10.roundtrip/nitro.mk new file mode 100644 index 00000000..57919a80 --- /dev/null +++ b/contrib/10.roundtrip/nitro.mk @@ -0,0 +1,4 @@ +CONTRIB_DEFS += -DPIC_CSTRING_TO_DOUBLE=emyg_strtod -DPIC_DOUBLE_TO_CSTRING=emyg_dtoa + +CONTRIB_SRCS += contrib/10.roundtrip/emyg_dtoa.c \ + contrib/10.roundtrip/emyg_atod.c From 3f7c5034d76c82b4d8151e19a5963e16f3daa017 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Fri, 8 Jan 2016 23:47:16 -0500 Subject: [PATCH 6/8] Fix some c99isms --- contrib/10.roundtrip/emyg_dtoa.c | 14 ++++++++------ extlib/benz/include/picrin/compat.h | 8 ++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/contrib/10.roundtrip/emyg_dtoa.c b/contrib/10.roundtrip/emyg_dtoa.c index 9315c5f5..1a8abd50 100644 --- a/contrib/10.roundtrip/emyg_dtoa.c +++ b/contrib/10.roundtrip/emyg_dtoa.c @@ -51,7 +51,7 @@ typedef struct DiyFp_s { static const int kDiySignificandSize = 64; static const int kDpSignificandSize = 52; -static const int kDpExponentBias = 0x3FF + kDpSignificandSize; +static const int kDpExponentBias = 0x3FF + 52 /*kDpSignificandSize*/; static const int kDpMinExponent = -kDpExponentBias; static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000); static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF); @@ -96,14 +96,14 @@ static inline DiyFp DiyFp_multiply (const DiyFp lhs, const DiyFp rhs) { uint64_t l = _umul128(lhs.f, rhs.f, &h); if (l & (uint64_t(1) << 63)) // rounding h++; - return DiyFp_fro_parts(h, e + rhs.e + 64); + return DiyFp_fro_parts(h, lhs.e + rhs.e + 64); #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) unsigned __int128 p = (unsigned __int128 )(lhs.f) * (unsigned __int128 )(rhs.f); uint64_t h = p >> 64; uint64_t l = (uint64_t )(p); - if (l & (uint64_t(1) << 63)) // rounding + if (l & (((uint64_t )1) << 63)) // rounding h++; - return DiyFp_from_parts(h, e + rhs.e + 64); + return DiyFp_from_parts(h, lhs.e + rhs.e + 64); #else const uint64_t M32 = 0xFFFFFFFF; const uint64_t a = lhs.f >> 32; @@ -382,7 +382,8 @@ static inline void Prettify(char* buffer, int length, int k) { if (length <= kk && kk <= 21) { // 1234e7 -> 12340000000 - for (int i = length; i < kk; i++) + int i; + for (i = length; i < kk; i++) buffer[i] = '0'; buffer[kk] = '.'; buffer[kk + 1] = '0'; @@ -396,11 +397,12 @@ static inline void Prettify(char* buffer, int length, int k) { } else if (-6 < kk && kk <= 0) { // 1234e-6 -> 0.001234 + int i; const int offset = 2 - kk; memmove(&buffer[offset], &buffer[0], length); buffer[0] = '0'; buffer[1] = '.'; - for (int i = 2; i < offset; i++) + for (i = 2; i < offset; i++) buffer[i] = '0'; buffer[length + offset] = '\0'; } diff --git a/extlib/benz/include/picrin/compat.h b/extlib/benz/include/picrin/compat.h index 4d53379c..8f2bb886 100644 --- a/extlib/benz/include/picrin/compat.h +++ b/extlib/benz/include/picrin/compat.h @@ -282,16 +282,16 @@ atof(const char *nptr) #if PIC_ENABLE_STDIO # include -void -PIC_INLINE pic_dtoa(double dval, char *buf) +PIC_INLINE void +pic_dtoa(double dval, char *buf) { sprintf(buf, "%g", dval); } #else -void -PIC_INLINE pic_dtoa(double dval, char *buf) +PIC_INLINE void +pic_dtoa(double dval, char *buf) { # define fabs(x) ((x) >= 0 ? (x) : -(x)) long lval, tlval; From 5116220d621ff5dcce8698482d2041650cb258ef Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Fri, 8 Jan 2016 23:51:51 -0500 Subject: [PATCH 7/8] Fix more c99isms --- contrib/10.roundtrip/emyg_dtoa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/10.roundtrip/emyg_dtoa.c b/contrib/10.roundtrip/emyg_dtoa.c index 1a8abd50..9fbc5e19 100644 --- a/contrib/10.roundtrip/emyg_dtoa.c +++ b/contrib/10.roundtrip/emyg_dtoa.c @@ -51,8 +51,8 @@ typedef struct DiyFp_s { static const int kDiySignificandSize = 64; static const int kDpSignificandSize = 52; -static const int kDpExponentBias = 0x3FF + 52 /*kDpSignificandSize*/; -static const int kDpMinExponent = -kDpExponentBias; +static const int kDpExponentBias = 0x3FF + 52 /* 0x3FF + kDpSignificandSize */; +static const int kDpMinExponent = -(0x3FF + 52) /* -kDpExponentBias */; static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000); static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF); static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000); From fa2b72b020984dfb89e7cc4bce4b48c9db955f2d Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sat, 9 Jan 2016 00:15:49 -0500 Subject: [PATCH 8/8] Use emyg_atod instead of emyg_strtod --- contrib/10.roundtrip/emyg_atod.c | 5 +++++ contrib/10.roundtrip/emyg_atod.h | 2 ++ contrib/10.roundtrip/nitro.mk | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/contrib/10.roundtrip/emyg_atod.c b/contrib/10.roundtrip/emyg_atod.c index 321d80e9..f742e15c 100644 --- a/contrib/10.roundtrip/emyg_atod.c +++ b/contrib/10.roundtrip/emyg_atod.c @@ -736,6 +736,11 @@ no_conv: return minus ? -res : res; } +double emyg_atod (const char *nptr) +{ + return emyg_strtod(nptr, NULL); +} + #ifdef TESTING_QUOREM int main (int argc, char **argv) diff --git a/contrib/10.roundtrip/emyg_atod.h b/contrib/10.roundtrip/emyg_atod.h index 7857a36e..3c875fbc 100644 --- a/contrib/10.roundtrip/emyg_atod.h +++ b/contrib/10.roundtrip/emyg_atod.h @@ -7,6 +7,8 @@ extern "C" { double emyg_strtod (const char *nptr, char **endptr); +double emyg_atod (const char *nptr); + #ifdef __cplusplus } #endif diff --git a/contrib/10.roundtrip/nitro.mk b/contrib/10.roundtrip/nitro.mk index 57919a80..e28f3ffb 100644 --- a/contrib/10.roundtrip/nitro.mk +++ b/contrib/10.roundtrip/nitro.mk @@ -1,4 +1,4 @@ -CONTRIB_DEFS += -DPIC_CSTRING_TO_DOUBLE=emyg_strtod -DPIC_DOUBLE_TO_CSTRING=emyg_dtoa +CONTRIB_DEFS += -DPIC_CSTRING_TO_DOUBLE=emyg_atod -DPIC_DOUBLE_TO_CSTRING=emyg_dtoa CONTRIB_SRCS += contrib/10.roundtrip/emyg_dtoa.c \ contrib/10.roundtrip/emyg_atod.c