OpenSolaris_b135/lib/libbc/libc/gen/common/base_conversion.h

Compare this file to the similar file:
Show the results in this format:

/*
 * 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 1995 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_base_conversion_h
#define	_base_conversion_h

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <errno.h>

#include <floatingpoint.h>

#ifdef DEBUG
#include <stdio.h>
#include <assert.h>
#endif

/* Sun floating-point PRIVATE include file.  */

/* PRIVATE MACROS	 */

#ifdef DEBUG
#define PRIVATE
#else
#define PRIVATE static
#endif

/* PRIVATE CONSTANTS	 */

#define	SINGLE_BIAS	  127
#define DOUBLE_BIAS	 1023
#define EXTENDED_BIAS	16383
#define QUAD_BIAS	16383

#define SINGLE_MAXE	  97	/* Maximum decimal exponent we need to
				 * consider. */
#define DOUBLE_MAXE	 771	/* Maximum decimal exponent we need to
				 * consider. */
#define EXTENDED_MAXE  12330	/* Maximum decimal exponent we need to
				 * consider. */
#define QUAD_MAXE  12330	/* Maximum decimal exponent we need to
				 * consider. */

#define UNPACKED_SIZE	5	/* Size of unpacked significand.  */

/* PRIVATE TYPES 	 */

/*
 * Unpack floating-point internal format.
 * Value is 0.s0s1..sn * 2**(1+exponent)
 */
typedef struct {		
	int             sign;
	enum fp_class_type fpclass;
	int             exponent;	/* Unbiased exponent. */
	unsigned        significand[UNPACKED_SIZE];	/* Last word is round */
							/* and sticky. */
} unpacked;

#ifdef i386
typedef struct {		/* Most significant word formats. */
	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 {		/* Floating-point formats in detail. */
	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 {		/* Most significant word formats. */
	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 {		/* Floating-point formats in detail. */
	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 {			/* Floating-point formats equivalenced. */
	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;

/* PRIVATE GLOBAL VARIABLES */

/* Current floating-point exceptions. */
fp_exception_field_type _fp_current_exceptions;

/* Current rounding direction. */
enum fp_direction_type	_fp_current_direction;

/* Current rounding precision. */
enum fp_precision_type	_fp_current_precision;

/* PRIVATE FUNCTIONS */

extern void _fp_set_exception(enum fp_exception_type);
/* enum fp_exception_type ex ; */	/* exception to be set in curexcep */

/*
 * Default size for _big_float - suitable for single and double precision.
 */

#define _BIG_FLOAT_SIZE	(DECIMAL_STRING_LENGTH/2)
#define _BIG_FLOAT_DIGIT short unsigned	/* big_float significand type */

/* Maximum number of integer digits in a representable extended or quad. */
#define _INTEGER_SIZE	4932	

typedef struct {		/* Variable-precision floating-point type */
				/* used for intermediate results.	 */
	unsigned short  bsize;	/* Maximum allowable logical length of */
				/* significand. */
	unsigned short  blength;	/* Logical length of significand. */
	short int       bexponent;	/*
					 * Exponent to be attached to least
					 * significant word of significand.
					 * exponent >= 0 implies all integer,
					 * with decimal point to right of
					 * least significant word of
					 * significand, and is equivalent to
					 * number of omitted trailing zeros
					 * of significand. -length < exponent
					 * < 0  implies decimal point within
					 * significand. exponent = -length
					 * implies decimal point to left of
					 * most significand word. exponent <
					 * -length implies decimal point to
					 * left of most significant word with
					 * -length-exponent leading zeros.
					 */
	/*
	 * NOTE: bexponent represents a power of 2 or 10, even though big
	 * digits are powers of 2**16 or 10**4.
	 */
	_BIG_FLOAT_DIGIT bsignificand[_BIG_FLOAT_SIZE];
	/*
	 * Significand of digits in base 10**4 or 2**16. significand[0] is
	 * least significant, significand[length-1] is most significant.
	 */
} _big_float;

#define BIG_FLOAT_TIMES_NOMEM	(_big_float *)0
#define BIG_FLOAT_TIMES_TOOBIG	(_big_float *)1

/* Internal functions defined in base conversion support routines. */

extern void     _multiply_base_ten(_big_float *, _BIG_FLOAT_DIGIT);
extern void     _multiply_base_ten_by_two(_big_float *, short unsigned);
extern void     _multiply_base_two(_big_float *, _BIG_FLOAT_DIGIT,
    long unsigned);
extern void     _carry_propagate_two(unsigned long, _BIG_FLOAT_DIGIT *);
extern void     _carry_propagate_ten(unsigned long, _BIG_FLOAT_DIGIT *);
extern void     _multiply_base_two_vector(short unsigned, _BIG_FLOAT_DIGIT *,
    short unsigned *, _BIG_FLOAT_DIGIT []);
extern void     _multiply_base_ten_vector(short unsigned, _BIG_FLOAT_DIGIT *,
    short unsigned *, _BIG_FLOAT_DIGIT []);
extern void     _fourdigitsquick(short unsigned, char*);
extern void     _unpacked_to_big_float(unpacked *, _big_float *, int *);
extern void     _big_binary_to_big_decimal(_big_float *, _big_float *);
extern void     _left_shift_base_ten(_big_float *, short unsigned);
extern void     _left_shift_base_two(_big_float *, short unsigned);
extern void     _right_shift_base_two(_big_float *, short unsigned,
    _BIG_FLOAT_DIGIT *);
extern void     _free_big_float(_big_float *);
extern void	_base_conversion_abort(int, char *);
extern void	_display_big_float(_big_float *, unsigned);
extern void	_integerstring_to_big_decimal(char [], unsigned, unsigned,
    unsigned *, _big_float *);
extern void	_fractionstring_to_big_decimal(char [], unsigned, unsigned,
    _big_float *);
extern void	_big_decimal_to_big_binary(_big_float *, _big_float *);
extern void	_fp_rightshift(unpacked *, int);
extern void	_fp_leftshift(unpacked *, unsigned);
extern void	_fp_normalize(unpacked *);
extern void	_pack_single(unpacked *, single *);
extern void	_pack_double(unpacked *, double *);
extern void	_pack_extended(unpacked *, extended *);
extern void	_pack_quadruple(unpacked *, quadruple *);
extern void	_unpack_single(unpacked *, single *);
extern void	_unpack_double(unpacked *, double *);
extern void	_unpack_extended(unpacked *, extended *);
extern void	_unpack_quadruple(unpacked *, quadruple *);
extern void	_unpacked_to_decimal(unpacked *, decimal_mode *,
    decimal_record *, fp_exception_field_type *);
extern enum fp_class_type	_class_single(single *);
extern enum fp_class_type	_class_double(double *);
extern enum fp_class_type	_class_extended(extended *);
extern enum fp_class_type	_class_quadruple(quadruple *);

/*
 * Fundamental utilities that multiply or add two shorts into a unsigned long, 
 * sometimes add an unsigned long carry, 
 * compute quotient and remainder in underlying base, and return
 * quo<<16 | rem as  a unsigned long.
 */

extern unsigned long _umac(_BIG_FLOAT_DIGIT, _BIG_FLOAT_DIGIT, unsigned long);
	/* p = x * y + c ; return p */

#define _prodc_b65536(x,y,c) (_umac((x),(y),(c)))

extern unsigned long _prodc_b10000(_BIG_FLOAT_DIGIT, _BIG_FLOAT_DIGIT,
    unsigned long);
/* p = x * y + c ; return (p/10000 << */

extern unsigned long _prod_b10000(_BIG_FLOAT_DIGIT, _BIG_FLOAT_DIGIT);
/* p = x * y ; return (p/10000 << 16 | p%10000) */

extern unsigned long _prod_10000_b65536(_BIG_FLOAT_DIGIT, long unsigned);
/* p = x * 10000 + c ; return p */

extern unsigned long _prod_65536_b10000(_BIG_FLOAT_DIGIT, long unsigned);
/* p = x * 65536 + c ; return (p/10000 << 16 | p%10000) */

#define _rshift_b65536(x,n,c) ((((unsigned long) (x)) << (16-(n))) + ((c)<<16))

#define _lshift_b65536(x,n,c) ((((unsigned long) (x)) << (n)) + (c))

extern unsigned long _lshift_b10000(_BIG_FLOAT_DIGIT, _BIG_FLOAT_DIGIT,
    long unsigned);
/* p = x << n + c ; return (p/10000 << 16 | p%10000) */

#define _carry_in_b65536(x,c) ((x) + (c))

extern unsigned long _carry_in_b10000(_BIG_FLOAT_DIGIT, long unsigned);
/* p = x + c ; return (p/10000 << 16 | p%10000) */

#define _carry_out_b65536(c) (c)

extern unsigned long _carry_out_b10000(unsigned long);
/* p = c ; return (p/10000 << 16 | p%10000) */

/*
 * Header file for revised "fast" base conversion based upon table look-up
 * methods.
 */

extern void
_big_float_times_power(_big_float *, int, int, int, _big_float **);

/* Variables defined in _small_powers.c and _big_powers.c	 */
/* Used in base conversion. */

/*
 * The run-time structure consists of two large tables of powers - either
 * powers of 10**4 in base 2**16 or vice versa.
 * 
 * Suppose it's powers of T in base B.  Then
 * 
 * _tiny_powers_T       contains TTINY entries, T**0, T**1, ... T**TTINY-1 where
 * T is 2 or 10, TTINY is 16 or 4 _small_powers_T      contains TSMALL
 * entries, T**0, T**1, ... T**TSMALL-1 where T is 2**TTINY or 10**TTINY
 * _big_powers_T        contains TBIG entries, T**0, T**1, ... T**TBIG-1
 * where T is (2**TTINY)**TSMALL or (10**TTINY)**TSMALL
 * 
 * so that any power of T from 0 to T**(TTINY*TSMALL*TBIG-1) can be represented
 * as a product of just two table entries.  Since the powers vary greatly in
 * size, the tables are condensed to exclude leading and trailing zeros.  The
 * following tables
 * 
 * _max_tiny_powers_T			contains one entry, TTINY
 * _start_tiny_powers_T                 contains TTINY entries
 * _leading_zeros_tiny_powers_T         contains TTINY entries
 * _max_small_powers_T			contains one entry, TSMALL
 * _start_small_powers_T                contains TSMALL entries
 * _leading_zeros_small_powers_T        contains TSMALL entries
 * _max_big_powers_T			contains one entry, TBIG
 * _start_big_powers_T                  contains TBIG entries
 * _leading_zeros_big_powers_T          contains TBIG entries
 * 
 * The powers are maintained with x[start] less significant than x[start+1], so
 * 
 * The powers are maintained with x[start] less significant than x[start+1], so
 * that the interpretation of a _small_powers_T entry is that
 * 
 * T**i = (B**leading_zeros[i]) * (x[start[i]] + x[start[i]+1] * B + ...
 * x[start[i+1]-1] * B**(start[i+1]-start[i]) )
 * 
 * where B = (2 or 10)**TTINY
 * 
 * The powers are listed consecutively in the tables, with start index and
 * leading zero information retained and printed out at the end.
 * 
 */

extern unsigned short _max_tiny_powers_ten;
extern unsigned short _tiny_powers_ten[];
extern unsigned short _start_tiny_powers_ten[];
extern unsigned short _leading_zeros_tiny_powers_ten[];
extern unsigned short _max_tiny_powers_two;
extern unsigned short _tiny_powers_two[];
extern unsigned short _start_tiny_powers_two[];

extern unsigned short _max_small_powers_ten;
extern unsigned short _small_powers_ten[];
extern unsigned short _start_small_powers_ten[];
extern unsigned short _leading_zeros_small_powers_ten[];
extern unsigned short _max_small_powers_two;
extern unsigned short _small_powers_two[];
extern unsigned short _start_small_powers_two[];

extern unsigned short _max_big_powers_ten;
extern unsigned short _big_powers_ten[];
extern unsigned short _start_big_powers_ten[];
extern unsigned short _leading_zeros_big_powers_ten[];
extern unsigned short _max_big_powers_two;
extern unsigned short _big_powers_two[];
extern unsigned short _start_big_powers_two[];

#endif /* _base_conversion_h */