From owner-svn-src-head@FreeBSD.ORG Sun Dec 30 15:20:28 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6BA09570; Sun, 30 Dec 2012 15:20:28 +0000 (UTC) (envelope-from kevlo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 4FB538FC14; Sun, 30 Dec 2012 15:20:28 +0000 (UTC) Received: from svn.freebsd.org (svn.FreeBSD.org [8.8.178.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBUFKSYA026449; Sun, 30 Dec 2012 15:20:28 GMT (envelope-from kevlo@svn.freebsd.org) Received: (from kevlo@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBUFKR0o026446; Sun, 30 Dec 2012 15:20:27 GMT (envelope-from kevlo@svn.freebsd.org) Message-Id: <201212301520.qBUFKR0o026446@svn.freebsd.org> From: Kevin Lo Date: Sun, 30 Dec 2012 15:20:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r244861 - head/usr.bin/dc X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 30 Dec 2012 15:20:28 -0000 Author: kevlo Date: Sun Dec 30 15:20:27 2012 New Revision: 244861 URL: http://svnweb.freebsd.org/changeset/base/244861 Log: - Use BN_set_negative() and BN_is_negative() instead of subtracting or comparing to zero. - Fix fractional number exponentiation, especially for negative exponents. Obtained from: OpenBSD Modified: head/usr.bin/dc/bcode.c head/usr.bin/dc/bcode.h head/usr.bin/dc/inout.c Modified: head/usr.bin/dc/bcode.c ============================================================================== --- head/usr.bin/dc/bcode.c Sun Dec 30 14:44:14 2012 (r244860) +++ head/usr.bin/dc/bcode.c Sun Dec 30 15:20:27 2012 (r244861) @@ -29,8 +29,6 @@ __FBSDID("$FreeBSD$"); #include "extern.h" -BIGNUM zero; - #define __inline #define MAX_ARRAY_INDEX 2048 @@ -250,8 +248,12 @@ init_bmachine(bool extended_registers) if (bmachine.readstack == NULL) err(1, NULL); bmachine.obase = bmachine.ibase = 10; - BN_init(&zero); - bn_check(BN_zero(&zero)); +} + +u_int +bmachine_scale(void) +{ + return (bmachine.scale); } /* Reset the things needed before processing a (new) file */ @@ -407,7 +409,7 @@ split_number(const struct number *n, BIG } } -__inline void +void normalize(struct number *n, u_int s) { @@ -427,7 +429,7 @@ void negate(struct number *n) { - bn_check(BN_sub(n->number, &zero, n->number)); + BN_set_negative(n->number, !BN_is_negative(n->number)); } static __inline void @@ -581,7 +583,7 @@ set_scale(void) n = pop_number(); if (n != NULL) { - if (BN_cmp(n->number, &zero) < 0) + if (BN_is_negative(n->number)) warnx("scale must be a nonnegative number"); else { scale = get_ulong(n); @@ -878,7 +880,7 @@ load_array(void) if (inumber == NULL) return; idx = get_ulong(inumber); - if (BN_cmp(inumber->number, &zero) < 0) + if (BN_is_negative(inumber->number)) warnx("negative idx"); else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) warnx("idx too big"); @@ -917,7 +919,7 @@ store_array(void) return; } idx = get_ulong(inumber); - if (BN_cmp(inumber->number, &zero) < 0) { + if (BN_is_negative(inumber->number)) { warnx("negative idx"); stack_free_value(value); } else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) { @@ -1009,7 +1011,7 @@ bsub(void) } void -bmul_number(struct number *r, struct number *a, struct number *b) +bmul_number(struct number *r, struct number *a, struct number *b, u_int scale) { BN_CTX *ctx; @@ -1023,11 +1025,9 @@ bmul_number(struct number *r, struct num bn_check(BN_mul(r->number, a->number, b->number, ctx)); BN_CTX_free(ctx); - if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) { - r->scale = rscale; - normalize(r, max(bmachine.scale, max(ascale, bscale))); - } else - r->scale = rscale; + r->scale = rscale; + if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) + normalize(r, max(scale, max(ascale, bscale))); } static void @@ -1046,7 +1046,7 @@ bmul(void) } r = new_number(); - bmul_number(r, a, b); + bmul_number(r, a, b, bmachine.scale); push_number(r); free_number(a); @@ -1172,7 +1172,7 @@ static void bexp(void) { struct number *a, *p, *r; - u_int scale; + u_int rscale; bool neg; p = pop_number(); @@ -1185,15 +1185,27 @@ bexp(void) return; } - if (p->scale != 0) - warnx("Runtime warning: non-zero scale in exponent"); + if (p->scale != 0) { + BIGNUM *i, *f; + i = BN_new(); + bn_checkp(i); + f = BN_new(); + bn_checkp(f); + split_number(p, i, f); + if (!BN_is_zero(f)) + warnx("Runtime warning: non-zero fractional part " + "in exponent"); + BN_free(i); + BN_free(f); + } + normalize(p, 0); neg = false; - if (BN_cmp(p->number, &zero) < 0) { + if (BN_is_negative(p->number)) { neg = true; negate(p); - scale = bmachine.scale; + rscale = bmachine.scale; } else { /* Posix bc says min(a.scale * b, max(a.scale, scale) */ u_long b; @@ -1201,30 +1213,37 @@ bexp(void) b = BN_get_word(p->number); m = max(a->scale, bmachine.scale); - scale = a->scale * (u_int)b; - if (scale > m || (a->scale > 0 && (b == BN_MASK2 || + rscale = a->scale * (u_int)b; + if (rscale > m || (a->scale > 0 && (b == BN_MASK2 || b > UINT_MAX))) - scale = m; + rscale = m; } if (BN_is_zero(p->number)) { r = new_number(); bn_check(BN_one(r->number)); - normalize(r, scale); + normalize(r, rscale); } else { + u_int ascale, mscale; + + ascale = a->scale; while (!BN_is_bit_set(p->number, 0)) { - bmul_number(a, a, a); + ascale *= 2; + bmul_number(a, a, a, ascale); bn_check(BN_rshift1(p->number, p->number)); } r = dup_number(a); - normalize(r, scale); bn_check(BN_rshift1(p->number, p->number)); + mscale = ascale; while (!BN_is_zero(p->number)) { - bmul_number(a, a, a); - if (BN_is_bit_set(p->number, 0)) - bmul_number(r, r, a); + ascale *= 2; + bmul_number(a, a, a, ascale); + if (BN_is_bit_set(p->number, 0)) { + mscale += ascale; + bmul_number(r, r, a, mscale); + } bn_check(BN_rshift1(p->number, p->number)); } @@ -1237,13 +1256,18 @@ bexp(void) bn_check(BN_one(one)); ctx = BN_CTX_new(); bn_checkp(ctx); - scale_number(one, r->scale + scale); - normalize(r, scale); - bn_check(BN_div(r->number, NULL, one, r->number, ctx)); + scale_number(one, r->scale + rscale); + + if (BN_is_zero(r->number)) + warnx("divide by zero"); + else + bn_check(BN_div(r->number, NULL, one, + r->number, ctx)); BN_free(one); BN_CTX_free(ctx); + r->scale = rscale; } else - normalize(r, scale); + normalize(r, rscale); } push_number(r); free_number(a); @@ -1282,7 +1306,7 @@ bsqrt(void) if (BN_is_zero(n->number)) { r = new_number(); push_number(r); - } else if (BN_cmp(n->number, &zero) < 0) + } else if (BN_is_negative(n->number)) warnx("square root of negative number"); else { scale = max(bmachine.scale, n->scale); Modified: head/usr.bin/dc/bcode.h ============================================================================== --- head/usr.bin/dc/bcode.h Sun Dec 30 14:44:14 2012 (r244860) +++ head/usr.bin/dc/bcode.h Sun Dec 30 15:20:27 2012 (r244861) @@ -85,6 +85,7 @@ struct source { void init_bmachine(bool); void reset_bmachine(struct source *); +u_int bmachine_scale(void); void scale_number(BIGNUM *, int); void normalize(struct number *, u_int); void eval(void); @@ -93,6 +94,4 @@ void pbn(const char *, const BIGNUM * void negate(struct number *); void split_number(const struct number *, BIGNUM *, BIGNUM *); void bmul_number(struct number *, struct number *, - struct number *); - -extern BIGNUM zero; + struct number *, u_int); Modified: head/usr.bin/dc/inout.c ============================================================================== --- head/usr.bin/dc/inout.c Sun Dec 30 14:44:14 2012 (r244860) +++ head/usr.bin/dc/inout.c Sun Dec 30 15:20:27 2012 (r244861) @@ -322,7 +322,7 @@ printnumber(FILE *f, const struct number i++; } sz = i; - if (BN_cmp(b->number, &zero) < 0) + if (BN_is_negative(b->number)) putcharwrap(f, '-'); for (i = 0; i < sz; i++) { p = stack_popstring(&stack); @@ -353,7 +353,8 @@ printnumber(FILE *f, const struct number putcharwrap(f, ' '); i = 1; - bmul_number(fract_part, fract_part, num_base); + bmul_number(fract_part, fract_part, num_base, + bmachine_scale()); split_number(fract_part, int_part->number, NULL); rem = BN_get_word(int_part->number); p = get_digit(rem, digits, base); @@ -402,8 +403,8 @@ print_ascii(FILE *f, const struct number v = BN_dup(n->number); bn_checkp(v); - if (BN_cmp(v, &zero) < 0) - bn_check(BN_sub(v, &zero, v)); + if (BN_is_negative(v)) + BN_set_negative(v, 0); numbits = BN_num_bytes(v) * 8; while (numbits > 0) {