diff options
author | Henry Stiles <henry.stiles@artifex.com> | 1998-07-28 06:22:20 +0000 |
---|---|---|
committer | Henry Stiles <henry.stiles@artifex.com> | 1998-07-28 06:22:20 +0000 |
commit | 5fbdbaab7335a147a3a7890b5c6fc123926815db (patch) | |
tree | 154edc89b06c38333fd6d4b9abaf0ee8740ddf6a /gs/src/zdouble.c | |
parent | 14cf10e3738f95f7864978c5a4778b50fb39524b (diff) |
This commit was generated by cvs2svn to compensate for changes in r257,
which included commits to RCS files with non-trunk default branches.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@258 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs/src/zdouble.c')
-rw-r--r-- | gs/src/zdouble.c | 532 |
1 files changed, 290 insertions, 242 deletions
diff --git a/gs/src/zdouble.c b/gs/src/zdouble.c index 7ed995ecf..5e070e41b 100644 --- a/gs/src/zdouble.c +++ b/gs/src/zdouble.c @@ -1,20 +1,20 @@ /* Copyright (C) 1995, 1996 Aladdin Enterprises. All rights reserved. - - This file is part of Aladdin Ghostscript. - - Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author - or distributor accepts any responsibility for the consequences of using it, - or for whether it serves any particular purpose or works at all, unless he - or she says so in writing. Refer to the Aladdin Ghostscript Free Public - License (the "License") for full details. - - Every copy of Aladdin Ghostscript must include a copy of the License, - normally in a plain ASCII text file named PUBLIC. The License grants you - the right to copy, modify and redistribute Aladdin Ghostscript, but only - under certain conditions described in the License. Among other things, the - License requires that the copyright notice and this notice be preserved on - all copies. -*/ + + This file is part of Aladdin Ghostscript. + + Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author + or distributor accepts any responsibility for the consequences of using it, + or for whether it serves any particular purpose or works at all, unless he + or she says so in writing. Refer to the Aladdin Ghostscript Free Public + License (the "License") for full details. + + Every copy of Aladdin Ghostscript must include a copy of the License, + normally in a plain ASCII text file named PUBLIC. The License grants you + the right to copy, modify and redistribute Aladdin Ghostscript, but only + under certain conditions described in the License. Among other things, the + License requires that the copyright notice and this notice be preserved on + all copies. + */ /* zdouble.c */ /* Double-precision floating point arithmetic operators */ @@ -65,31 +65,35 @@ private int near double_unary(P2(os_ptr, double (*)(P1(double)))); /* <dnum1> <dnum2> <dresult> .dadd <dresult> */ private int zdadd(os_ptr op) -{ dbegin_binary(); - return double_result(op, 2, num[0] + num[1]); +{ + dbegin_binary(); + return double_result(op, 2, num[0] + num[1]); } /* <dnum1> <dnum2> <dresult> .ddiv <dresult> */ private int zddiv(os_ptr op) -{ dbegin_binary(); - if ( num[1] == 0.0 ) - return_error(e_undefinedresult); - return double_result(op, 2, num[0] / num[1]); +{ + dbegin_binary(); + if (num[1] == 0.0) + return_error(e_undefinedresult); + return double_result(op, 2, num[0] / num[1]); } /* <dnum1> <dnum2> <dresult> .dmul <dresult> */ private int zdmul(os_ptr op) -{ dbegin_binary(); - return double_result(op, 2, num[0] * num[1]); +{ + dbegin_binary(); + return double_result(op, 2, num[0] * num[1]); } /* <dnum1> <dnum2> <dresult> .dsub <dresult> */ private int zdsub(os_ptr op) -{ dbegin_binary(); - return double_result(op, 2, num[0] - num[1]); +{ + dbegin_binary(); + return double_result(op, 2, num[0] - num[1]); } /* ------ Simple functions ------ */ @@ -97,172 +101,198 @@ zdsub(os_ptr op) /* <dnum> <dresult> .dabs <dresult> */ private int zdabs(os_ptr op) -{ return double_unary(op, fabs); +{ + return double_unary(op, fabs); } /* <dnum> <dresult> .dceiling <dresult> */ private int zdceiling(os_ptr op) -{ return double_unary(op, ceil); +{ + return double_unary(op, ceil); } /* <dnum> <dresult> .dfloor <dresult> */ private int zdfloor(os_ptr op) -{ return double_unary(op, floor); +{ + return double_unary(op, floor); } /* <dnum> <dresult> .dneg <dresult> */ private int zdneg(os_ptr op) -{ dbegin_unary(); - return double_result(op, 1, -num); +{ + dbegin_unary(); + return double_result(op, 1, -num); } /* <dnum> <dresult> .dround <dresult> */ private int zdround(os_ptr op) -{ dbegin_unary(); - return double_result(op, 1, floor(num + 0.5)); +{ + dbegin_unary(); + return double_result(op, 1, floor(num + 0.5)); } /* <dnum> <dresult> .dsqrt <dresult> */ private int zdsqrt(os_ptr op) -{ dbegin_unary(); - if ( num < 0.0 ) - return_error(e_rangecheck); - return double_result(op, 1, sqrt(num)); +{ + dbegin_unary(); + if (num < 0.0) + return_error(e_rangecheck); + return double_result(op, 1, sqrt(num)); } /* <dnum> <dresult> .dtruncate <dresult> */ private int zdtruncate(os_ptr op) -{ dbegin_unary(); - return double_result(op, 1, (num < 0 ? ceil(num) : floor(num))); +{ + dbegin_unary(); + return double_result(op, 1, (num < 0 ? ceil(num) : floor(num))); } /* ------ Transcendental functions ------ */ private int near -darc(os_ptr op, double (*afunc)(P1(double))) -{ dbegin_unary(); - return double_result(op, 1, (*afunc)(num) * radians_to_degrees); +darc(os_ptr op, double (*afunc) (P1(double))) +{ + dbegin_unary(); + return double_result(op, 1, (*afunc) (num) * radians_to_degrees); } /* <dnum> <dresult> .darccos <dresult> */ private int zdarccos(os_ptr op) -{ return darc(op, acos); +{ + return darc(op, acos); } /* <dnum> <dresult> .darcsin <dresult> */ private int zdarcsin(os_ptr op) -{ return darc(op, asin); +{ + return darc(op, asin); } /* <dnum> <ddenom> <dresult> .datan <dresult> */ private int zdatan(register os_ptr op) -{ double result; - dbegin_binary(); - if ( num[0] == 0 ) /* on X-axis, special case */ - { if ( num[1] == 0 ) - return_error(e_undefinedresult); - result = (num[1] < 0 ? 180 : 0); - } - else - { result = atan2(num[0], num[1]) * radians_to_degrees; - if ( result < 0 ) - result += 360; - } - return double_result(op, 2, result); +{ + double result; + + dbegin_binary(); + if (num[0] == 0) { /* on X-axis, special case */ + if (num[1] == 0) + return_error(e_undefinedresult); + result = (num[1] < 0 ? 180 : 0); + } else { + result = atan2(num[0], num[1]) * radians_to_degrees; + if (result < 0) + result += 360; + } + return double_result(op, 2, result); } /* <dnum> <dresult> .dcos <dresult> */ private int zdcos(os_ptr op) -{ return double_unary(op, gs_cos_degrees); +{ + return double_unary(op, gs_cos_degrees); } /* <dbase> <dexponent> <dresult> .dexp <dresult> */ private int zdexp(os_ptr op) -{ double ipart; - dbegin_binary(); - if ( num[0] == 0.0 && num[1] == 0.0 ) - return_error(e_undefinedresult); - if ( num[0] < 0.0 && modf(num[1], &ipart) != 0.0 ) - return_error(e_undefinedresult); - return double_result(op, 2, pow(num[0], num[1])); +{ + double ipart; + + dbegin_binary(); + if (num[0] == 0.0 && num[1] == 0.0) + return_error(e_undefinedresult); + if (num[0] < 0.0 && modf(num[1], &ipart) != 0.0) + return_error(e_undefinedresult); + return double_result(op, 2, pow(num[0], num[1])); } private int near -dlog(os_ptr op, double (*lfunc)(P1(double))) -{ dbegin_unary(); - if ( num <= 0.0 ) - return_error(e_rangecheck); - return double_result(op, 1, (*lfunc)(num)); +dlog(os_ptr op, double (*lfunc) (P1(double))) +{ + dbegin_unary(); + if (num <= 0.0) + return_error(e_rangecheck); + return double_result(op, 1, (*lfunc) (num)); } /* <dposnum> <dresult> .dln <dresult> */ private int zdln(os_ptr op) -{ return dlog(op, log); +{ + return dlog(op, log); } /* <dposnum> <dresult> .dlog <dresult> */ private int zdlog(os_ptr op) -{ return dlog(op, log10); +{ + return dlog(op, log10); } /* <dnum> <dresult> .dsin <dresult> */ private int zdsin(os_ptr op) -{ return double_unary(op, gs_sin_degrees); +{ + return double_unary(op, gs_sin_degrees); } /* ------ Comparison ------ */ private int near dcompare(os_ptr op, int mask) -{ double num[2]; - int code = double_params(op, 2, num); - if ( code < 0 ) - return code; - make_bool(op - 1, - (mask & (num[0] < num[1] ? 1 : num[0] > num[1] ? 4 : 2)) - != 0); - pop(1); - return 0; +{ + double num[2]; + int code = double_params(op, 2, num); + + if (code < 0) + return code; + make_bool(op - 1, + (mask & (num[0] < num[1] ? 1 : num[0] > num[1] ? 4 : 2)) + != 0); + pop(1); + return 0; } /* <dnum1> <dnum2> .deq <bool> */ private int zdeq(os_ptr op) -{ return dcompare(op, 2); +{ + return dcompare(op, 2); } /* <dnum1> <dnum2> .dge <bool> */ private int zdge(os_ptr op) -{ return dcompare(op, 6); +{ + return dcompare(op, 6); } /* <dnum1> <dnum2> .dgt <bool> */ private int zdgt(os_ptr op) -{ return dcompare(op, 4); +{ + return dcompare(op, 4); } /* <dnum1> <dnum2> .dle <bool> */ private int zdle(os_ptr op) -{ return dcompare(op, 3); +{ + return dcompare(op, 3); } /* <dnum1> <dnum2> .dlt <bool> */ private int zdlt(os_ptr op) -{ return dcompare(op, 1); +{ + return dcompare(op, 1); } /* <dnum1> <dnum2> .dne <bool> */ private int zdne(os_ptr op) -{ return dcompare(op, 5); +{ + return dcompare(op, 5); } /* ------ Conversion ------ */ @@ -273,44 +303,46 @@ zdne(os_ptr op) /* <dnum> <dresult> .cvd <dresult> */ private int zcvd(os_ptr op) -{ dbegin_unary(); - return double_result(op, 1, num); +{ + dbegin_unary(); + return double_result(op, 1, num); } /* <string> <dresult> .cvsd <dresult> */ private int zcvsd(os_ptr op) -{ int code = double_params_result(op, 0, NULL); - double num; - char buf[max_chars + 2]; - char *str = buf; - uint len; - char end; - - if ( code < 0 ) - return code; - check_read_type(op[-1], t_string); - len = r_size(op - 1); - if ( len > max_chars ) - return_error(e_limitcheck); - memcpy(str, op[-1].value.bytes, len); - /* - * We check syntax in the following way: we remove whitespace, - * verify that the string contains only [0123456789+-.dDeE], - * then append a $ and then check that the next character after - * the scanned number is a $. - */ - while ( len > 0 && isspace(*str) ) - ++str, --len; - while ( len > 0 && isspace(str[len - 1]) ) - --len; - str[len] = 0; - if ( strspn(str, "0123456789+-.dDeE") != len ) - return_error(e_syntaxerror); - strcat(str, "$"); - if ( sscanf(str, "%lf%c", &num, &end) != 2 || end != '$' ) - return_error(e_syntaxerror); - return double_result(op, 1, num); +{ + int code = double_params_result(op, 0, NULL); + double num; + char buf[max_chars + 2]; + char *str = buf; + uint len; + char end; + + if (code < 0) + return code; + check_read_type(op[-1], t_string); + len = r_size(op - 1); + if (len > max_chars) + return_error(e_limitcheck); + memcpy(str, op[-1].value.bytes, len); + /* + * We check syntax in the following way: we remove whitespace, + * verify that the string contains only [0123456789+-.dDeE], + * then append a $ and then check that the next character after + * the scanned number is a $. + */ + while (len > 0 && isspace(*str)) + ++str, --len; + while (len > 0 && isspace(str[len - 1])) + --len; + str[len] = 0; + if (strspn(str, "0123456789+-.dDeE") != len) + return_error(e_syntaxerror); + strcat(str, "$"); + if (sscanf(str, "%lf%c", &num, &end) != 2 || end != '$') + return_error(e_syntaxerror); + return double_result(op, 1, num); } /* <dnum> .dcvi <int> */ @@ -319,17 +351,18 @@ zdcvi(os_ptr op) { #define alt_min_long (-1L << (arch_sizeof_long * 8 - 1)) #define alt_max_long (~(alt_min_long)) - static const double min_int_real = (alt_min_long * 1.0 - 1); - static const double max_int_real = (alt_max_long * 1.0 + 1); - double num; - int code = double_params(op, 1, &num); - if ( code < 0 ) - return code; + static const double min_int_real = (alt_min_long * 1.0 - 1); + static const double max_int_real = (alt_max_long * 1.0 + 1); + double num; + int code = double_params(op, 1, &num); - if ( num < min_int_real || num > max_int_real ) - return_error(e_rangecheck); - make_int(op, (long)num); /* truncates toward 0 */ - return 0; + if (code < 0) + return code; + + if (num < min_int_real || num > max_int_real) + return_error(e_rangecheck); + make_int(op, (long)num); /* truncates toward 0 */ + return 0; } /* <dnum> .dcvr <real> */ @@ -338,151 +371,166 @@ zdcvr(os_ptr op) { #define b30 (0x40000000L * 1.0) #define max_mag (0xffffff * b30 * b30 * b30 * 0x4000) - static const float min_real = -max_mag; - static const float max_real = max_mag; + static const float min_real = -max_mag; + static const float max_real = max_mag; + #undef b30 #undef max_mag - double num; - int code = double_params(op, 1, &num); - if ( code < 0 ) - return code; - if ( num < min_real || num > max_real ) - return_error(e_rangecheck); - make_real(op, (float)num); - return 0; + double num; + int code = double_params(op, 1, &num); + + if (code < 0) + return code; + if (num < min_real || num > max_real) + return_error(e_rangecheck); + make_real(op, (float)num); + return 0; } /* <dnum> <string> .dcvs <substring> */ private int zdcvs(os_ptr op) -{ double num; - int code = double_params(op - 1, 1, &num); - char str[max_chars + 1]; - int len; - - if ( code < 0 ) - return code; - check_write_type(*op, t_string); - /* - * To get fully accurate output results for IEEE double- - * precision floats (53 bits of mantissa), the ANSI - * %g default of 6 digits is not enough; 16 are needed. - * Unfortunately, using %.16g produces unfortunate artifacts such as - * 1.2 printing as 1.200000000000005. Therefore, we print using %g, - * and if the result isn't accurate enough, print again - * using %.16g. - */ - { double scanned; - sprintf(str, "%g", num); - sscanf(str, "%lf", &scanned); - if ( scanned != num ) - sprintf(str, "%.16g", num); - } - len = strlen(str); - if ( len > r_size(op) ) - return_error(e_rangecheck); - memcpy(op->value.bytes, str, len); - op[-1] = *op; - r_set_size(op - 1, len); - pop(1); - return 0; +{ + double num; + int code = double_params(op - 1, 1, &num); + char str[max_chars + 1]; + int len; + + if (code < 0) + return code; + check_write_type(*op, t_string); + /* + * To get fully accurate output results for IEEE double- + * precision floats (53 bits of mantissa), the ANSI + * %g default of 6 digits is not enough; 16 are needed. + * Unfortunately, using %.16g produces unfortunate artifacts such as + * 1.2 printing as 1.200000000000005. Therefore, we print using %g, + * and if the result isn't accurate enough, print again + * using %.16g. + */ + { + double scanned; + + sprintf(str, "%g", num); + sscanf(str, "%lf", &scanned); + if (scanned != num) + sprintf(str, "%.16g", num); + } + len = strlen(str); + if (len > r_size(op)) + return_error(e_rangecheck); + memcpy(op->value.bytes, str, len); + op[-1] = *op; + r_set_size(op - 1, len); + pop(1); + return 0; } /* ------ Initialization table ------ */ -BEGIN_OP_DEFS(zdouble_op_defs) { +const op_def zdouble_op_defs[] = +{ /* Arithmetic */ - {"3.dadd", zdadd}, - {"3.ddiv", zddiv}, - {"3.dmul", zdmul}, - {"3.dsub", zdsub}, + {"3.dadd", zdadd}, + {"3.ddiv", zddiv}, + {"3.dmul", zdmul}, + {"3.dsub", zdsub}, /* Simple functions */ - {"2.dabs", zdabs}, - {"2.dceiling", zdceiling}, - {"2.dfloor", zdfloor}, - {"2.dneg", zdneg}, - {"2.dround", zdround}, - {"2.dsqrt", zdsqrt}, - {"2.dtruncate", zdtruncate}, + {"2.dabs", zdabs}, + {"2.dceiling", zdceiling}, + {"2.dfloor", zdfloor}, + {"2.dneg", zdneg}, + {"2.dround", zdround}, + {"2.dsqrt", zdsqrt}, + {"2.dtruncate", zdtruncate}, /* Transcendental functions */ - {"2.darccos", zdarccos}, - {"2.darcsin", zdarcsin}, - {"3.datan", zdatan}, - {"2.dcos", zdcos}, - {"3.dexp", zdexp}, - {"2.dln", zdln}, - {"2.dlog", zdlog}, - {"2.dsin", zdsin}, + {"2.darccos", zdarccos}, + {"2.darcsin", zdarcsin}, + {"3.datan", zdatan}, + {"2.dcos", zdcos}, + {"3.dexp", zdexp}, + {"2.dln", zdln}, + {"2.dlog", zdlog}, + {"2.dsin", zdsin}, /* Comparison */ - {"2.deq", zdeq}, - {"2.dge", zdge}, - {"2.dgt", zdgt}, - {"2.dle", zdle}, - {"2.dlt", zdlt}, - {"2.dne", zdne}, + {"2.deq", zdeq}, + {"2.dge", zdge}, + {"2.dgt", zdgt}, + {"2.dle", zdle}, + {"2.dlt", zdlt}, + {"2.dne", zdne}, /* Conversion */ - {"2.cvd", zcvd}, - {"2.cvsd", zcvsd}, - {"1.dcvi", zdcvi}, - {"1.dcvr", zdcvr}, - {"2.dcvs", zdcvs}, -END_OP_DEFS(0) } + {"2.cvd", zcvd}, + {"2.cvsd", zcvsd}, + {"1.dcvi", zdcvi}, + {"1.dcvr", zdcvr}, + {"2.dcvs", zdcvs}, + op_def_end(0) +}; /* ------ Internal procedures ------ */ /* Get some double arguments. */ private int near double_params(os_ptr op, int count, double *pval) -{ pval += count; - while ( --count >= 0 ) - { switch ( r_type(op) ) - { - case t_real: - *--pval = op->value.realval; - break; - case t_integer: - *--pval = op->value.intval; - break; - case t_string: - if ( !r_has_attr(op, a_read) || - r_size(op) != sizeof(double) - ) - return_error(e_typecheck); - --pval; - memcpy(pval, op->value.bytes, sizeof(double)); - break; - case t__invalid: - return_error(e_stackunderflow); - default: - return_error(e_typecheck); - } - op--; - } - return 0; +{ + pval += count; + while (--count >= 0) { + switch (r_type(op)) { + case t_real: + *--pval = op->value.realval; + break; + case t_integer: + *--pval = op->value.intval; + break; + case t_string: + if (!r_has_attr(op, a_read) || + r_size(op) != sizeof(double) + ) + return_error(e_typecheck); + + --pval; + memcpy(pval, op->value.bytes, sizeof(double)); + + break; + case t__invalid: + return_error(e_stackunderflow); + default: + return_error(e_typecheck); + } + op--; + } + return 0; } /* Get some double arguments, and check for a double result. */ private int near double_params_result(os_ptr op, int count, double *pval) -{ check_write_type(*op, t_string); - if ( r_size(op) != sizeof(double) ) - return_error(e_typecheck); - return double_params(op - 1, count, pval); +{ + check_write_type(*op, t_string); + if (r_size(op) != sizeof(double)) + return_error(e_typecheck); + + return double_params(op - 1, count, pval); } /* Return a double result. */ private int near double_result(os_ptr op, int count, double result) -{ os_ptr op1 = op - count; - ref_assign_inline(op1, op); - memcpy(op1->value.bytes, &result, sizeof(double)); - pop(count); - return 0; +{ + os_ptr op1 = op - count; + + ref_assign_inline(op1, op); + memcpy(op1->value.bytes, &result, sizeof(double)); + + pop(count); + return 0; } /* Apply a unary function to a double operand. */ private int near -double_unary(os_ptr op, double (*func)(P1(double))) -{ dbegin_unary(); - return double_result(op, 1, (*func)(num)); +double_unary(os_ptr op, double (*func) (P1(double))) +{ + dbegin_unary(); + return double_result(op, 1, (*func) (num)); } |