root/usr/src/lib/libc/inc/base_conversion.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (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 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef BASE_CONVERSION_H
#define BASE_CONVERSION_H

#include <errno.h>
#include <floatingpoint.h>
#include <sys/isa_defs.h>

/*
 * 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 */

/*
 * Thread-specific flags to indicate whether any NaNs or infinities
 * have been read or written.
 */
extern int *_thrp_get_inf_read(void);
extern int *_thrp_get_inf_written(void);
extern int *_thrp_get_nan_read(void);
extern int *_thrp_get_nan_written(void);

#define __inf_read              (*(int *)_thrp_get_inf_read())
#define __inf_written           (*(int *)_thrp_get_inf_written())
#define __nan_read              (*(int *)_thrp_get_nan_read())
#define __nan_written           (*(int *)_thrp_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

#include "base_inlines.h"

#endif  /* BASE_CONVERSION_H */