/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include /* * Common constants, types, and declarations for floating point * base conversion */ /* PRIVATE CONSTANTS */ /* exponent bias */ #define SINGLE_BIAS 127 #define DOUBLE_BIAS 1023 #define EXTENDED_BIAS 16383 #define QUAD_BIAS 16383 /* PRIVATE TYPES */ /* * Unpacked binary floating point format. The binary point lies * to the right of the most significant bit in significand[0]. * The exponent is unbiased. The significand array is long enough * that the last word never contains any bits we need to keep, * just rounding information. */ #define UNPACKED_SIZE 5 typedef struct { int sign; enum fp_class_type fpclass; int exponent; unsigned significand[UNPACKED_SIZE]; } unpacked; /* * Packed binary floating point formats. The *_msw structure * corresponds to the most significant word. */ #ifdef _LITTLE_ENDIAN typedef struct { unsigned significand:23; unsigned exponent:8; unsigned sign:1; } single_msw; typedef struct { unsigned significand:20; unsigned exponent:11; unsigned sign:1; } double_msw; typedef struct { unsigned exponent:15; unsigned sign:1; unsigned unused:16; } extended_msw; typedef struct { unsigned significand:16; unsigned exponent:15; unsigned sign:1; } quadruple_msw; typedef struct { single_msw msw; } single_formatted; typedef struct { unsigned significand2; double_msw msw; } double_formatted; typedef struct { unsigned significand2; unsigned significand; extended_msw msw; } extended_formatted; typedef struct { unsigned significand4; unsigned significand3; unsigned significand2; quadruple_msw msw; } quadruple_formatted; #else typedef struct { unsigned sign:1; unsigned exponent:8; unsigned significand:23; } single_msw; typedef struct { unsigned sign:1; unsigned exponent:11; unsigned significand:20; } double_msw; typedef struct { unsigned sign:1; unsigned exponent:15; unsigned unused:16; } extended_msw; typedef struct { unsigned sign:1; unsigned exponent:15; unsigned significand:16; } quadruple_msw; typedef struct { single_msw msw; } single_formatted; typedef struct { double_msw msw; unsigned significand2; } double_formatted; typedef struct { extended_msw msw; unsigned significand; unsigned significand2; } extended_formatted; typedef struct { quadruple_msw msw; unsigned significand2; unsigned significand3; unsigned significand4; } quadruple_formatted; #endif typedef union { single_formatted f; single x; } single_equivalence; typedef union { double_formatted f; double x; } double_equivalence; typedef union { extended_formatted f; extended x; } extended_equivalence; typedef union { quadruple_formatted f; quadruple x; } quadruple_equivalence; /* * Multiple precision floating point type. This type is suitable * for representing positive floating point numbers of variable * precision in either binary or decimal. The bsignificand array * holds the digits of a multi-word integer, stored least significant * digit first, in either radix 2^16 or 10^4. blength is the * length of the significand array. bexponent is a power of two * or ten, so that the value represented is * * 2^(bexponent) * sum (bsignificand[i] * 2^(i*16)) * * if binary, or * * 10^(bexponent) * sum (bsignificand[i] * 10^(i*4)) * * if decimal, where the sum runs from i = 0 to blength - 1. * (Whether the representation is binary or decimal is implied * from context.) bsize indicates the size of the significand * array and may be larger than _BIG_FLOAT_SIZE if storage has * been allocated at runtime. */ #define _BIG_FLOAT_SIZE (DECIMAL_STRING_LENGTH/2) typedef struct { unsigned short bsize; unsigned short blength; short int bexponent; unsigned short bsignificand[_BIG_FLOAT_SIZE]; } _big_float; /* structure for storing IEEE modes and status flags */ typedef struct { int status, mode; } __ieee_flags_type; /* PRIVATE GLOBAL VARIABLES */ /* * Flags to indicate whether any NaNs or infinities have been read * or written. These are exported solely for the use of the old * Sun Fortran runtime library. Once that becomes obsolete, these * can be removed. */ extern int *_thr_get_inf_read(void); extern int *_thr_get_inf_written(void); extern int *_thr_get_nan_read(void); extern int *_thr_get_nan_written(void); #define __inf_read (*(int *)_thr_get_inf_read()) #define __inf_written (*(int *)_thr_get_inf_written()) #define __nan_read (*(int *)_thr_get_nan_read()) #define __nan_written (*(int *)_thr_get_nan_written()) /* * Powers of 5 in base 2**16 and powers of 2 in base 10**4. * * __tbl_10_small_digits contains * 5**0, * 5**1, ... * 5**__TBL_10_SMALL_SIZE-1 * __tbl_10_big_digits contains * 5**0, * 5**__TBL_10_SMALL_SIZE, ... * 5**__TBL_10_SMALL_SIZE*(__TBL_10_BIG_SIZE-1) * __tbl_10_huge_digits contains * 5**0, * 5**__TBL_10_SMALL_SIZE*__TBL_10_BIG_SIZE, ... * 5**__TBL_10_SMALL_SIZE*__TBL_10_BIG_SIZE*(__TBL_10_HUGE_SIZE-1) * * so that any power of 5 from 5**0 to * 5**__TBL_10_SMALL_SIZE*__TBL_10_BIG_SIZE*__TBL_10_HUGE_SIZE * can be represented as a product of at most three table entries. * * Similarly any power of 2 from 2**0 to * 2**__TBL_2_SMALL_SIZE*__TBL_2_BIG_SIZE*__TBL_2_HUGE_SIZE * can be represented as a product of at most three table entries. * * Since the powers vary greatly in size, the tables are condensed: * entry i in table x is stored in * x_digits[x_start[i]] (least significant) * through * x_digits[x_start[i+1]-1] (most significant) */ #define __TBL_10_SMALL_SIZE 64 #define __TBL_10_BIG_SIZE 16 #define __TBL_10_HUGE_SIZE 6 extern const unsigned short __tbl_10_small_digits[], __tbl_10_small_start[], __tbl_10_big_digits[], __tbl_10_big_start[], __tbl_10_huge_digits[], __tbl_10_huge_start[]; #define __TBL_2_SMALL_SIZE 176 #define __TBL_2_BIG_SIZE 16 #define __TBL_2_HUGE_SIZE 6 extern const unsigned short __tbl_2_small_digits[], __tbl_2_small_start[], __tbl_2_big_digits[], __tbl_2_big_start[], __tbl_2_huge_digits[], __tbl_2_huge_start[]; /* * Powers of ten. For i = 0, 1, ..., __TBL_TENS_MAX, __tbl_tens[i] * = 10^i rounded to double precision. (10^i is representable exactly * in double precision for i <= __TBL_TENS_EXACT.) */ #define __TBL_TENS_EXACT 22 #define __TBL_TENS_MAX 49 extern const double __tbl_tens[]; /* PRIVATE FUNCTIONS */ extern void __base_conversion_set_exception(fp_exception_field_type); extern void __four_digits_quick(unsigned short, char *); extern int __fast_double_to_decimal(double *dd, decimal_mode *pm, decimal_record *pd, fp_exception_field_type *ps); extern void __pack_single(unpacked *, single *, enum fp_direction_type, fp_exception_field_type *); extern void __pack_double(unpacked *, double *, enum fp_direction_type, fp_exception_field_type *); extern void __pack_extended(unpacked *, extended *, enum fp_direction_type, fp_exception_field_type *); extern void __pack_quadruple(unpacked *, quadruple *, enum fp_direction_type, fp_exception_field_type *); extern void __infnanstring(enum fp_class_type cl, int ndigits, char *buf); extern void __big_float_times_power(_big_float *pbf, int mult, int n, int precision, _big_float **pnewbf); extern void __get_ieee_flags(__ieee_flags_type *); extern void __set_ieee_flags(__ieee_flags_type *); extern double __mul_set(double, double, int *); extern double __div_set(double, double, int *); extern double __dabs(double *); #if defined(sparc) || defined(__sparc) extern enum fp_direction_type _QgetRD(void); #endif