/contrib/sdk/sources/newlib/libc/stdlib/btowc.c |
---|
0,0 → 1,33 |
#include <wchar.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <reent.h> |
#include <string.h> |
#include "local.h" |
wint_t |
btowc (int c) |
{ |
mbstate_t mbs; |
int retval = 0; |
wchar_t pwc; |
unsigned char b; |
if (c == EOF) |
return WEOF; |
b = (unsigned char)c; |
/* Put mbs in initial state. */ |
memset (&mbs, '\0', sizeof (mbs)); |
_REENT_CHECK_MISC(_REENT); |
retval = __mbtowc (_REENT, &pwc, (const char *) &b, 1, |
__locale_charset (), &mbs); |
if (retval != 0 && retval != 1) |
return WEOF; |
return (wint_t)pwc; |
} |
/contrib/sdk/sources/newlib/libc/stdlib/ldtoa.c |
---|
0,0 → 1,3868 |
/* Extended precision arithmetic functions for long double I/O. |
* This program has been placed in the public domain. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <string.h> |
#include <stdlib.h> |
#include "mprec.h" |
/* These are the externally visible entries. */ |
/* linux name: long double _IO_strtold (char *, char **); */ |
long double _strtold (char *, char **); |
char *_ldtoa_r (struct _reent *, long double, int, int, int *, int *, |
char **); |
int _ldcheck (long double *); |
#if 0 |
void _IO_ldtostr (long double *, char *, int, int, char); |
#endif |
/* Number of 16 bit words in external x type format */ |
#define NE 10 |
/* Number of 16 bit words in internal format */ |
#define NI (NE+3) |
/* Array offset to exponent */ |
#define E 1 |
/* Array offset to high guard word */ |
#define M 2 |
/* Number of bits of precision */ |
#define NBITS ((NI-4)*16) |
/* Maximum number of decimal digits in ASCII conversion |
* = NBITS*log10(2) |
*/ |
#define NDEC (NBITS*8/27) |
/* The exponent of 1.0 */ |
#define EXONE (0x3fff) |
/* Maximum exponent digits - base 10 */ |
#define MAX_EXP_DIGITS 5 |
/* Control structure for long double conversion including rounding precision values. |
* rndprc can be set to 80 (if NE=6), 64, 56, 53, or 24 bits. |
*/ |
typedef struct |
{ |
int rlast; |
int rndprc; |
int rw; |
int re; |
int outexpon; |
unsigned short rmsk; |
unsigned short rmbit; |
unsigned short rebit; |
unsigned short rbit[NI]; |
unsigned short equot[NI]; |
} LDPARMS; |
static void esub (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, LDPARMS * ldp); |
static void emul (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, LDPARMS * ldp); |
static void ediv (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, LDPARMS * ldp); |
static int ecmp (_CONST short unsigned int *a, _CONST short unsigned int *b); |
static int enormlz (short unsigned int *x); |
static int eshift (short unsigned int *x, int sc); |
static void eshup1 (register short unsigned int *x); |
static void eshup8 (register short unsigned int *x); |
static void eshup6 (register short unsigned int *x); |
static void eshdn1 (register short unsigned int *x); |
static void eshdn8 (register short unsigned int *x); |
static void eshdn6 (register short unsigned int *x); |
static void eneg (short unsigned int *x); |
static void emov (register _CONST short unsigned int *a, |
register short unsigned int *b); |
static void eclear (register short unsigned int *x); |
static void einfin (register short unsigned int *x, register LDPARMS * ldp); |
static void efloor (short unsigned int *x, short unsigned int *y, |
LDPARMS * ldp); |
static void etoasc (short unsigned int *x, char *string, int ndigs, |
int outformat, LDPARMS * ldp); |
union uconv |
{ |
unsigned short pe; |
long double d; |
}; |
#if LDBL_MANT_DIG == 24 |
static void e24toe (short unsigned int *pe, short unsigned int *y, |
LDPARMS * ldp); |
#elif LDBL_MANT_DIG == 53 |
static void e53toe (short unsigned int *pe, short unsigned int *y, |
LDPARMS * ldp); |
#elif LDBL_MANT_DIG == 64 |
static void e64toe (short unsigned int *pe, short unsigned int *y, |
LDPARMS * ldp); |
#else |
static void e113toe (short unsigned int *pe, short unsigned int *y, |
LDPARMS * ldp); |
#endif |
/* econst.c */ |
/* e type constants used by high precision check routines */ |
#if NE == 10 |
/* 0.0 */ |
static _CONST unsigned short ezero[NE] = { 0x0000, 0x0000, 0x0000, 0x0000, |
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
}; |
/* 1.0E0 */ |
static _CONST unsigned short eone[NE] = { 0x0000, 0x0000, 0x0000, 0x0000, |
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff, |
}; |
#else |
/* 0.0 */ |
static _CONST unsigned short ezero[NE] = { |
0, 0000000, 0000000, 0000000, 0000000, 0000000, |
}; |
/* 1.0E0 */ |
static _CONST unsigned short eone[NE] = { |
0, 0000000, 0000000, 0000000, 0100000, 0x3fff, |
}; |
#endif |
/* Debugging routine for displaying errors */ |
#ifdef DEBUG |
/* Notice: the order of appearance of the following |
* messages is bound to the error codes defined |
* in mconf.h. |
*/ |
static _CONST char *_CONST ermsg[7] = { |
"unknown", /* error code 0 */ |
"domain", /* error code 1 */ |
"singularity", /* et seq. */ |
"overflow", |
"underflow", |
"total loss of precision", |
"partial loss of precision" |
}; |
#define mtherr(name, code) printf( "\n%s %s error\n", name, ermsg[code] ); |
#else |
#define mtherr(name, code) |
#endif |
/* ieee.c |
* |
* Extended precision IEEE binary floating point arithmetic routines |
* |
* Numbers are stored in C language as arrays of 16-bit unsigned |
* short integers. The arguments of the routines are pointers to |
* the arrays. |
* |
* |
* External e type data structure, simulates Intel 8087 chip |
* temporary real format but possibly with a larger significand: |
* |
* NE-1 significand words (least significant word first, |
* most significant bit is normally set) |
* exponent (value = EXONE for 1.0, |
* top bit is the sign) |
* |
* |
* Internal data structure of a number (a "word" is 16 bits): |
* |
* ei[0] sign word (0 for positive, 0xffff for negative) |
* ei[1] biased exponent (value = EXONE for the number 1.0) |
* ei[2] high guard word (always zero after normalization) |
* ei[3] |
* to ei[NI-2] significand (NI-4 significand words, |
* most significant word first, |
* most significant bit is set) |
* ei[NI-1] low guard word (0x8000 bit is rounding place) |
* |
* |
* |
* Routines for external format numbers |
* |
* asctoe( string, e ) ASCII string to extended double e type |
* asctoe64( string, &d ) ASCII string to long double |
* asctoe53( string, &d ) ASCII string to double |
* asctoe24( string, &f ) ASCII string to single |
* asctoeg( string, e, prec, ldp ) ASCII string to specified precision |
* e24toe( &f, e, ldp ) IEEE single precision to e type |
* e53toe( &d, e, ldp ) IEEE double precision to e type |
* e64toe( &d, e, ldp ) IEEE long double precision to e type |
* e113toe( &d, e, ldp ) IEEE long double precision to e type |
* eabs(e) absolute value |
* eadd( a, b, c ) c = b + a |
* eclear(e) e = 0 |
* ecmp (a, b) Returns 1 if a > b, 0 if a == b, |
* -1 if a < b, -2 if either a or b is a NaN. |
* ediv( a, b, c, ldp ) c = b / a |
* efloor( a, b, ldp ) truncate to integer, toward -infinity |
* efrexp( a, exp, s ) extract exponent and significand |
* eifrac( e, &l, frac ) e to long integer and e type fraction |
* euifrac( e, &l, frac ) e to unsigned long integer and e type fraction |
* einfin( e, ldp ) set e to infinity, leaving its sign alone |
* eldexp( a, n, b ) multiply by 2**n |
* emov( a, b ) b = a |
* emul( a, b, c, ldp ) c = b * a |
* eneg(e) e = -e |
* eround( a, b ) b = nearest integer value to a |
* esub( a, b, c, ldp ) c = b - a |
* e24toasc( &f, str, n ) single to ASCII string, n digits after decimal |
* e53toasc( &d, str, n ) double to ASCII string, n digits after decimal |
* e64toasc( &d, str, n ) long double to ASCII string |
* etoasc(e,str,n,fmt,ldp)e to ASCII string, n digits after decimal |
* etoe24( e, &f ) convert e type to IEEE single precision |
* etoe53( e, &d ) convert e type to IEEE double precision |
* etoe64( e, &d ) convert e type to IEEE long double precision |
* ltoe( &l, e ) long (32 bit) integer to e type |
* ultoe( &l, e ) unsigned long (32 bit) integer to e type |
* eisneg( e ) 1 if sign bit of e != 0, else 0 |
* eisinf( e ) 1 if e has maximum exponent (non-IEEE) |
* or is infinite (IEEE) |
* eisnan( e ) 1 if e is a NaN |
* esqrt( a, b ) b = square root of a |
* |
* |
* Routines for internal format numbers |
* |
* eaddm( ai, bi ) add significands, bi = bi + ai |
* ecleaz(ei) ei = 0 |
* ecleazs(ei) set ei = 0 but leave its sign alone |
* ecmpm( ai, bi ) compare significands, return 1, 0, or -1 |
* edivm( ai, bi, ldp ) divide significands, bi = bi / ai |
* emdnorm(ai,l,s,exp,ldp) normalize and round off |
* emovi( a, ai ) convert external a to internal ai |
* emovo( ai, a, ldp ) convert internal ai to external a |
* emovz( ai, bi ) bi = ai, low guard word of bi = 0 |
* emulm( ai, bi, ldp ) multiply significands, bi = bi * ai |
* enormlz(ei) left-justify the significand |
* eshdn1( ai ) shift significand and guards down 1 bit |
* eshdn8( ai ) shift down 8 bits |
* eshdn6( ai ) shift down 16 bits |
* eshift( ai, n ) shift ai n bits up (or down if n < 0) |
* eshup1( ai ) shift significand and guards up 1 bit |
* eshup8( ai ) shift up 8 bits |
* eshup6( ai ) shift up 16 bits |
* esubm( ai, bi ) subtract significands, bi = bi - ai |
* |
* |
* The result is always normalized and rounded to NI-4 word precision |
* after each arithmetic operation. |
* |
* Exception flags are NOT fully supported. |
* |
* Define USE_INFINITY in mconf.h for support of infinity; otherwise a |
* saturation arithmetic is implemented. |
* |
* Define NANS for support of Not-a-Number items; otherwise the |
* arithmetic will never produce a NaN output, and might be confused |
* by a NaN input. |
* If NaN's are supported, the output of ecmp(a,b) is -2 if |
* either a or b is a NaN. This means asking if(ecmp(a,b) < 0) |
* may not be legitimate. Use if(ecmp(a,b) == -1) for less-than |
* if in doubt. |
* Signaling NaN's are NOT supported; they are treated the same |
* as quiet NaN's. |
* |
* Denormals are always supported here where appropriate (e.g., not |
* for conversion to DEC numbers). |
*/ |
/* |
* Revision history: |
* |
* 5 Jan 84 PDP-11 assembly language version |
* 6 Dec 86 C language version |
* 30 Aug 88 100 digit version, improved rounding |
* 15 May 92 80-bit long double support |
* 22 Nov 00 Revised to fit into newlib by Jeff Johnston <jjohnstn@redhat.com> |
* |
* Author: S. L. Moshier. |
* |
* Copyright (c) 1984,2000 S.L. Moshier |
* |
* Permission to use, copy, modify, and distribute this software for any |
* purpose without fee is hereby granted, provided that this entire notice |
* is included in all copies of any software which is or includes a copy |
* or modification of this software and in all copies of the supporting |
* documentation for such software. |
* |
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED |
* WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION |
* OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS |
* SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. |
* |
*/ |
#include <stdio.h> |
/* #include "\usr\include\stdio.h" */ |
/*#include "ehead.h"*/ |
/*#include "mconf.h"*/ |
/* mconf.h |
* |
* Common include file for math routines |
* |
* |
* |
* SYNOPSIS: |
* |
* #include "mconf.h" |
* |
* |
* |
* DESCRIPTION: |
* |
* This file contains definitions for error codes that are |
* passed to the common error handling routine mtherr() |
* (which see). |
* |
* The file also includes a conditional assembly definition |
* for the type of computer arithmetic (IEEE, DEC, Motorola |
* IEEE, or UNKnown). |
* |
* For Digital Equipment PDP-11 and VAX computers, certain |
* IBM systems, and others that use numbers with a 56-bit |
* significand, the symbol DEC should be defined. In this |
* mode, most floating point constants are given as arrays |
* of octal integers to eliminate decimal to binary conversion |
* errors that might be introduced by the compiler. |
* |
* For computers, such as IBM PC, that follow the IEEE |
* Standard for Binary Floating Point Arithmetic (ANSI/IEEE |
* Std 754-1985), the symbol IBMPC should be defined. These |
* numbers have 53-bit significands. In this mode, constants |
* are provided as arrays of hexadecimal 16 bit integers. |
* |
* To accommodate other types of computer arithmetic, all |
* constants are also provided in a normal decimal radix |
* which one can hope are correctly converted to a suitable |
* format by the available C language compiler. To invoke |
* this mode, the symbol UNK is defined. |
* |
* An important difference among these modes is a predefined |
* set of machine arithmetic constants for each. The numbers |
* MACHEP (the machine roundoff error), MAXNUM (largest number |
* represented), and several other parameters are preset by |
* the configuration symbol. Check the file const.c to |
* ensure that these values are correct for your computer. |
* |
* For ANSI C compatibility, define ANSIC equal to 1. Currently |
* this affects only the atan2() function and others that use it. |
*/ |
/* Constant definitions for math error conditions |
*/ |
#define DOMAIN 1 /* argument domain error */ |
#define SING 2 /* argument singularity */ |
#define OVERFLOW 3 /* overflow range error */ |
#define UNDERFLOW 4 /* underflow range error */ |
#define TLOSS 5 /* total loss of precision */ |
#define PLOSS 6 /* partial loss of precision */ |
#define EDOM 33 |
#define ERANGE 34 |
typedef struct |
{ |
double r; |
double i; |
} cmplx; |
/* Type of computer arithmetic */ |
#ifndef DEC |
#ifdef __IEEE_LITTLE_ENDIAN |
#define IBMPC 1 |
#else /* !__IEEE_LITTLE_ENDIAN */ |
#define MIEEE 1 |
#endif /* !__IEEE_LITTLE_ENDIAN */ |
#endif /* !DEC */ |
/* Define 1 for ANSI C atan2() function |
* See atan.c and clog.c. |
*/ |
#define ANSIC 1 |
/*define VOLATILE volatile*/ |
#define VOLATILE |
#define NANS |
#define USE_INFINITY |
/* NaN's require infinity support. */ |
#ifdef NANS |
#ifndef INFINITY |
#define USE_INFINITY |
#endif |
#endif |
/* This handles 64-bit long ints. */ |
#define LONGBITS (8 * sizeof(long)) |
static void eaddm (short unsigned int *x, short unsigned int *y); |
static void esubm (short unsigned int *x, short unsigned int *y); |
static void emdnorm (short unsigned int *s, int lost, int subflg, |
long int exp, int rcntrl, LDPARMS * ldp); |
static int asctoeg (char *ss, short unsigned int *y, int oprec, |
LDPARMS * ldp); |
static void enan (short unsigned int *nan, int size); |
#if LDBL_MANT_DIG == 24 |
static void toe24 (short unsigned int *x, short unsigned int *y); |
#elif LDBL_MANT_DIG == 53 |
static void toe53 (short unsigned int *x, short unsigned int *y); |
#elif LDBL_MANT_DIG == 64 |
static void toe64 (short unsigned int *a, short unsigned int *b); |
#else |
static void toe113 (short unsigned int *a, short unsigned int *b); |
#endif |
static void eiremain (short unsigned int *den, short unsigned int *num, |
LDPARMS * ldp); |
static int ecmpm (register short unsigned int *a, |
register short unsigned int *b); |
static int edivm (short unsigned int *den, short unsigned int *num, |
LDPARMS * ldp); |
static int emulm (short unsigned int *a, short unsigned int *b, |
LDPARMS * ldp); |
static int eisneg (_CONST short unsigned int *x); |
static int eisinf (_CONST short unsigned int *x); |
static void emovi (_CONST short unsigned int *a, short unsigned int *b); |
static void emovo (short unsigned int *a, short unsigned int *b, |
LDPARMS * ldp); |
static void emovz (register short unsigned int *a, |
register short unsigned int *b); |
static void ecleaz (register short unsigned int *xi); |
static void eadd1 (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, int subflg, LDPARMS * ldp); |
static int eisnan (_CONST short unsigned int *x); |
static int eiisnan (short unsigned int *x); |
#ifdef DEC |
static void etodec (), todec (), dectoe (); |
#endif |
/* |
; Clear out entire external format number. |
; |
; unsigned short x[]; |
; eclear( x ); |
*/ |
static void |
eclear (register short unsigned int *x) |
{ |
register int i; |
for (i = 0; i < NE; i++) |
*x++ = 0; |
} |
/* Move external format number from a to b. |
* |
* emov( a, b ); |
*/ |
static void |
emov (register _CONST short unsigned int *a, register short unsigned int *b) |
{ |
register int i; |
for (i = 0; i < NE; i++) |
*b++ = *a++; |
} |
/* |
; Negate external format number |
; |
; unsigned short x[NE]; |
; eneg( x ); |
*/ |
static void |
eneg (short unsigned int *x) |
{ |
#ifdef NANS |
if (eisnan (x)) |
return; |
#endif |
x[NE - 1] ^= 0x8000; /* Toggle the sign bit */ |
} |
/* Return 1 if external format number is negative, |
* else return zero. |
*/ |
static int |
eisneg (_CONST short unsigned int *x) |
{ |
#ifdef NANS |
if (eisnan (x)) |
return (0); |
#endif |
if (x[NE - 1] & 0x8000) |
return (1); |
else |
return (0); |
} |
/* Return 1 if external format number has maximum possible exponent, |
* else return zero. |
*/ |
static int |
eisinf (_CONST short unsigned int *x) |
{ |
if ((x[NE - 1] & 0x7fff) == 0x7fff) |
{ |
#ifdef NANS |
if (eisnan (x)) |
return (0); |
#endif |
return (1); |
} |
else |
return (0); |
} |
/* Check if e-type number is not a number. |
*/ |
static int |
eisnan (_CONST short unsigned int *x) |
{ |
#ifdef NANS |
int i; |
/* NaN has maximum exponent */ |
if ((x[NE - 1] & 0x7fff) != 0x7fff) |
return (0); |
/* ... and non-zero significand field. */ |
for (i = 0; i < NE - 1; i++) |
{ |
if (*x++ != 0) |
return (1); |
} |
#endif |
return (0); |
} |
/* |
; Fill entire number, including exponent and significand, with |
; largest possible number. These programs implement a saturation |
; value that is an ordinary, legal number. A special value |
; "infinity" may also be implemented; this would require tests |
; for that value and implementation of special rules for arithmetic |
; operations involving inifinity. |
*/ |
static void |
einfin (register short unsigned int *x, register LDPARMS * ldp) |
{ |
register int i; |
#ifdef USE_INFINITY |
for (i = 0; i < NE - 1; i++) |
*x++ = 0; |
*x |= 32767; |
ldp = ldp; |
#else |
for (i = 0; i < NE - 1; i++) |
*x++ = 0xffff; |
*x |= 32766; |
if (ldp->rndprc < NBITS) |
{ |
if (ldp->rndprc == 113) |
{ |
*(x - 9) = 0; |
*(x - 8) = 0; |
} |
if (ldp->rndprc == 64) |
{ |
*(x - 5) = 0; |
} |
if (ldp->rndprc == 53) |
{ |
*(x - 4) = 0xf800; |
} |
else |
{ |
*(x - 4) = 0; |
*(x - 3) = 0; |
*(x - 2) = 0xff00; |
} |
} |
#endif |
} |
/* Move in external format number, |
* converting it to internal format. |
*/ |
static void |
emovi (_CONST short unsigned int *a, short unsigned int *b) |
{ |
register _CONST unsigned short *p; |
register unsigned short *q; |
int i; |
q = b; |
p = a + (NE - 1); /* point to last word of external number */ |
/* get the sign bit */ |
if (*p & 0x8000) |
*q++ = 0xffff; |
else |
*q++ = 0; |
/* get the exponent */ |
*q = *p--; |
*q++ &= 0x7fff; /* delete the sign bit */ |
#ifdef USE_INFINITY |
if ((*(q - 1) & 0x7fff) == 0x7fff) |
{ |
#ifdef NANS |
if (eisnan (a)) |
{ |
*q++ = 0; |
for (i = 3; i < NI; i++) |
*q++ = *p--; |
return; |
} |
#endif |
for (i = 2; i < NI; i++) |
*q++ = 0; |
return; |
} |
#endif |
/* clear high guard word */ |
*q++ = 0; |
/* move in the significand */ |
for (i = 0; i < NE - 1; i++) |
*q++ = *p--; |
/* clear low guard word */ |
*q = 0; |
} |
/* Move internal format number out, |
* converting it to external format. |
*/ |
static void |
emovo (short unsigned int *a, short unsigned int *b, LDPARMS * ldp) |
{ |
register unsigned short *p, *q; |
unsigned short i; |
p = a; |
q = b + (NE - 1); /* point to output exponent */ |
/* combine sign and exponent */ |
i = *p++; |
if (i) |
*q-- = *p++ | 0x8000; |
else |
*q-- = *p++; |
#ifdef USE_INFINITY |
if (*(p - 1) == 0x7fff) |
{ |
#ifdef NANS |
if (eiisnan (a)) |
{ |
enan (b, NBITS); |
return; |
} |
#endif |
einfin (b, ldp); |
return; |
} |
#endif |
/* skip over guard word */ |
++p; |
/* move the significand */ |
for (i = 0; i < NE - 1; i++) |
*q-- = *p++; |
} |
/* Clear out internal format number. |
*/ |
static void |
ecleaz (register short unsigned int *xi) |
{ |
register int i; |
for (i = 0; i < NI; i++) |
*xi++ = 0; |
} |
/* same, but don't touch the sign. */ |
static void |
ecleazs (register short unsigned int *xi) |
{ |
register int i; |
++xi; |
for (i = 0; i < NI - 1; i++) |
*xi++ = 0; |
} |
/* Move internal format number from a to b. |
*/ |
static void |
emovz (register short unsigned int *a, register short unsigned int *b) |
{ |
register int i; |
for (i = 0; i < NI - 1; i++) |
*b++ = *a++; |
/* clear low guard word */ |
*b = 0; |
} |
/* Return nonzero if internal format number is a NaN. |
*/ |
static int |
eiisnan (short unsigned int *x) |
{ |
int i; |
if ((x[E] & 0x7fff) == 0x7fff) |
{ |
for (i = M + 1; i < NI; i++) |
{ |
if (x[i] != 0) |
return (1); |
} |
} |
return (0); |
} |
#if LDBL_MANT_DIG == 64 |
/* Return nonzero if internal format number is infinite. */ |
static int |
eiisinf (unsigned short x[]) |
{ |
#ifdef NANS |
if (eiisnan (x)) |
return (0); |
#endif |
if ((x[E] & 0x7fff) == 0x7fff) |
return (1); |
return (0); |
} |
#endif /* LDBL_MANT_DIG == 64 */ |
/* |
; Compare significands of numbers in internal format. |
; Guard words are included in the comparison. |
; |
; unsigned short a[NI], b[NI]; |
; cmpm( a, b ); |
; |
; for the significands: |
; returns +1 if a > b |
; 0 if a == b |
; -1 if a < b |
*/ |
static int |
ecmpm (register short unsigned int *a, register short unsigned int *b) |
{ |
int i; |
a += M; /* skip up to significand area */ |
b += M; |
for (i = M; i < NI; i++) |
{ |
if (*a++ != *b++) |
goto difrnt; |
} |
return (0); |
difrnt: |
if (*(--a) > *(--b)) |
return (1); |
else |
return (-1); |
} |
/* |
; Shift significand down by 1 bit |
*/ |
static void |
eshdn1 (register short unsigned int *x) |
{ |
register unsigned short bits; |
int i; |
x += M; /* point to significand area */ |
bits = 0; |
for (i = M; i < NI; i++) |
{ |
if (*x & 1) |
bits |= 1; |
*x >>= 1; |
if (bits & 2) |
*x |= 0x8000; |
bits <<= 1; |
++x; |
} |
} |
/* |
; Shift significand up by 1 bit |
*/ |
static void |
eshup1 (register short unsigned int *x) |
{ |
register unsigned short bits; |
int i; |
x += NI - 1; |
bits = 0; |
for (i = M; i < NI; i++) |
{ |
if (*x & 0x8000) |
bits |= 1; |
*x <<= 1; |
if (bits & 2) |
*x |= 1; |
bits <<= 1; |
--x; |
} |
} |
/* |
; Shift significand down by 8 bits |
*/ |
static void |
eshdn8 (register short unsigned int *x) |
{ |
register unsigned short newbyt, oldbyt; |
int i; |
x += M; |
oldbyt = 0; |
for (i = M; i < NI; i++) |
{ |
newbyt = *x << 8; |
*x >>= 8; |
*x |= oldbyt; |
oldbyt = newbyt; |
++x; |
} |
} |
/* |
; Shift significand up by 8 bits |
*/ |
static void |
eshup8 (register short unsigned int *x) |
{ |
int i; |
register unsigned short newbyt, oldbyt; |
x += NI - 1; |
oldbyt = 0; |
for (i = M; i < NI; i++) |
{ |
newbyt = *x >> 8; |
*x <<= 8; |
*x |= oldbyt; |
oldbyt = newbyt; |
--x; |
} |
} |
/* |
; Shift significand up by 16 bits |
*/ |
static void |
eshup6 (register short unsigned int *x) |
{ |
int i; |
register unsigned short *p; |
p = x + M; |
x += M + 1; |
for (i = M; i < NI - 1; i++) |
*p++ = *x++; |
*p = 0; |
} |
/* |
; Shift significand down by 16 bits |
*/ |
static void |
eshdn6 (register short unsigned int *x) |
{ |
int i; |
register unsigned short *p; |
x += NI - 1; |
p = x + 1; |
for (i = M; i < NI - 1; i++) |
*(--p) = *(--x); |
*(--p) = 0; |
} |
/* |
; Add significands |
; x + y replaces y |
*/ |
static void |
eaddm (short unsigned int *x, short unsigned int *y) |
{ |
register unsigned long a; |
int i; |
unsigned int carry; |
x += NI - 1; |
y += NI - 1; |
carry = 0; |
for (i = M; i < NI; i++) |
{ |
a = (unsigned long) (*x) + (unsigned long) (*y) + carry; |
if (a & 0x10000) |
carry = 1; |
else |
carry = 0; |
*y = (unsigned short) a; |
--x; |
--y; |
} |
} |
/* |
; Subtract significands |
; y - x replaces y |
*/ |
static void |
esubm (short unsigned int *x, short unsigned int *y) |
{ |
unsigned long a; |
int i; |
unsigned int carry; |
x += NI - 1; |
y += NI - 1; |
carry = 0; |
for (i = M; i < NI; i++) |
{ |
a = (unsigned long) (*y) - (unsigned long) (*x) - carry; |
if (a & 0x10000) |
carry = 1; |
else |
carry = 0; |
*y = (unsigned short) a; |
--x; |
--y; |
} |
} |
/* Divide significands */ |
/* Multiply significand of e-type number b |
by 16-bit quantity a, e-type result to c. */ |
static void |
m16m (short unsigned int a, short unsigned int *b, short unsigned int *c) |
{ |
register unsigned short *pp; |
register unsigned long carry; |
unsigned short *ps; |
unsigned short p[NI]; |
unsigned long aa, m; |
int i; |
aa = a; |
pp = &p[NI - 2]; |
*pp++ = 0; |
*pp = 0; |
ps = &b[NI - 1]; |
for (i = M + 1; i < NI; i++) |
{ |
if (*ps == 0) |
{ |
--ps; |
--pp; |
*(pp - 1) = 0; |
} |
else |
{ |
m = (unsigned long) aa **ps--; |
carry = (m & 0xffff) + *pp; |
*pp-- = (unsigned short) carry; |
carry = (carry >> 16) + (m >> 16) + *pp; |
*pp = (unsigned short) carry; |
*(pp - 1) = carry >> 16; |
} |
} |
for (i = M; i < NI; i++) |
c[i] = p[i]; |
} |
/* Divide significands. Neither the numerator nor the denominator |
is permitted to have its high guard word nonzero. */ |
static int |
edivm (short unsigned int *den, short unsigned int *num, LDPARMS * ldp) |
{ |
int i; |
register unsigned short *p; |
unsigned long tnum; |
unsigned short j, tdenm, tquot; |
unsigned short tprod[NI + 1]; |
unsigned short *equot = ldp->equot; |
p = &equot[0]; |
*p++ = num[0]; |
*p++ = num[1]; |
for (i = M; i < NI; i++) |
{ |
*p++ = 0; |
} |
eshdn1 (num); |
tdenm = den[M + 1]; |
for (i = M; i < NI; i++) |
{ |
/* Find trial quotient digit (the radix is 65536). */ |
tnum = (((unsigned long) num[M]) << 16) + num[M + 1]; |
/* Do not execute the divide instruction if it will overflow. */ |
if ((tdenm * 0xffffUL) < tnum) |
tquot = 0xffff; |
else |
tquot = tnum / tdenm; |
/* Prove that the divide worked. */ |
/* |
tcheck = (unsigned long )tquot * tdenm; |
if( tnum - tcheck > tdenm ) |
tquot = 0xffff; |
*/ |
/* Multiply denominator by trial quotient digit. */ |
m16m (tquot, den, tprod); |
/* The quotient digit may have been overestimated. */ |
if (ecmpm (tprod, num) > 0) |
{ |
tquot -= 1; |
esubm (den, tprod); |
if (ecmpm (tprod, num) > 0) |
{ |
tquot -= 1; |
esubm (den, tprod); |
} |
} |
/* |
if( ecmpm( tprod, num ) > 0 ) |
{ |
eshow( "tprod", tprod ); |
eshow( "num ", num ); |
printf( "tnum = %08lx, tden = %04x, tquot = %04x\n", |
tnum, den[M+1], tquot ); |
} |
*/ |
esubm (tprod, num); |
/* |
if( ecmpm( num, den ) >= 0 ) |
{ |
eshow( "num ", num ); |
eshow( "den ", den ); |
printf( "tnum = %08lx, tden = %04x, tquot = %04x\n", |
tnum, den[M+1], tquot ); |
} |
*/ |
equot[i] = tquot; |
eshup6 (num); |
} |
/* test for nonzero remainder after roundoff bit */ |
p = &num[M]; |
j = 0; |
for (i = M; i < NI; i++) |
{ |
j |= *p++; |
} |
if (j) |
j = 1; |
for (i = 0; i < NI; i++) |
num[i] = equot[i]; |
return ((int) j); |
} |
/* Multiply significands */ |
static int |
emulm (short unsigned int *a, short unsigned int *b, LDPARMS * ldp) |
{ |
unsigned short *p, *q; |
unsigned short pprod[NI]; |
unsigned short j; |
int i; |
unsigned short *equot = ldp->equot; |
equot[0] = b[0]; |
equot[1] = b[1]; |
for (i = M; i < NI; i++) |
equot[i] = 0; |
j = 0; |
p = &a[NI - 1]; |
q = &equot[NI - 1]; |
for (i = M + 1; i < NI; i++) |
{ |
if (*p == 0) |
{ |
--p; |
} |
else |
{ |
m16m (*p--, b, pprod); |
eaddm (pprod, equot); |
} |
j |= *q; |
eshdn6 (equot); |
} |
for (i = 0; i < NI; i++) |
b[i] = equot[i]; |
/* return flag for lost nonzero bits */ |
return ((int) j); |
} |
/* |
static void eshow(str, x) |
char *str; |
unsigned short *x; |
{ |
int i; |
printf( "%s ", str ); |
for( i=0; i<NI; i++ ) |
printf( "%04x ", *x++ ); |
printf( "\n" ); |
} |
*/ |
/* |
* Normalize and round off. |
* |
* The internal format number to be rounded is "s". |
* Input "lost" indicates whether the number is exact. |
* This is the so-called sticky bit. |
* |
* Input "subflg" indicates whether the number was obtained |
* by a subtraction operation. In that case if lost is nonzero |
* then the number is slightly smaller than indicated. |
* |
* Input "exp" is the biased exponent, which may be negative. |
* the exponent field of "s" is ignored but is replaced by |
* "exp" as adjusted by normalization and rounding. |
* |
* Input "rcntrl" is the rounding control. |
*/ |
static void |
emdnorm (short unsigned int *s, int lost, int subflg, long int exp, |
int rcntrl, LDPARMS * ldp) |
{ |
int i, j; |
unsigned short r; |
/* Normalize */ |
j = enormlz (s); |
/* a blank significand could mean either zero or infinity. */ |
#ifndef USE_INFINITY |
if (j > NBITS) |
{ |
ecleazs (s); |
return; |
} |
#endif |
exp -= j; |
#ifndef USE_INFINITY |
if (exp >= 32767L) |
goto overf; |
#else |
if ((j > NBITS) && (exp < 32767L)) |
{ |
ecleazs (s); |
return; |
} |
#endif |
if (exp < 0L) |
{ |
if (exp > (long) (-NBITS - 1)) |
{ |
j = (int) exp; |
i = eshift (s, j); |
if (i) |
lost = 1; |
} |
else |
{ |
ecleazs (s); |
return; |
} |
} |
/* Round off, unless told not to by rcntrl. */ |
if (rcntrl == 0) |
goto mdfin; |
/* Set up rounding parameters if the control register changed. */ |
if (ldp->rndprc != ldp->rlast) |
{ |
ecleaz (ldp->rbit); |
switch (ldp->rndprc) |
{ |
default: |
case NBITS: |
ldp->rw = NI - 1; /* low guard word */ |
ldp->rmsk = 0xffff; |
ldp->rmbit = 0x8000; |
ldp->rebit = 1; |
ldp->re = ldp->rw - 1; |
break; |
case 113: |
ldp->rw = 10; |
ldp->rmsk = 0x7fff; |
ldp->rmbit = 0x4000; |
ldp->rebit = 0x8000; |
ldp->re = ldp->rw; |
break; |
case 64: |
ldp->rw = 7; |
ldp->rmsk = 0xffff; |
ldp->rmbit = 0x8000; |
ldp->rebit = 1; |
ldp->re = ldp->rw - 1; |
break; |
/* For DEC arithmetic */ |
case 56: |
ldp->rw = 6; |
ldp->rmsk = 0xff; |
ldp->rmbit = 0x80; |
ldp->rebit = 0x100; |
ldp->re = ldp->rw; |
break; |
case 53: |
ldp->rw = 6; |
ldp->rmsk = 0x7ff; |
ldp->rmbit = 0x0400; |
ldp->rebit = 0x800; |
ldp->re = ldp->rw; |
break; |
case 24: |
ldp->rw = 4; |
ldp->rmsk = 0xff; |
ldp->rmbit = 0x80; |
ldp->rebit = 0x100; |
ldp->re = ldp->rw; |
break; |
} |
ldp->rbit[ldp->re] = ldp->rebit; |
ldp->rlast = ldp->rndprc; |
} |
/* Shift down 1 temporarily if the data structure has an implied |
* most significant bit and the number is denormal. |
* For rndprc = 64 or NBITS, there is no implied bit. |
* But Intel long double denormals lose one bit of significance even so. |
*/ |
#if IBMPC |
if ((exp <= 0) && (ldp->rndprc != NBITS)) |
#else |
if ((exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS)) |
#endif |
{ |
lost |= s[NI - 1] & 1; |
eshdn1 (s); |
} |
/* Clear out all bits below the rounding bit, |
* remembering in r if any were nonzero. |
*/ |
r = s[ldp->rw] & ldp->rmsk; |
if (ldp->rndprc < NBITS) |
{ |
i = ldp->rw + 1; |
while (i < NI) |
{ |
if (s[i]) |
r |= 1; |
s[i] = 0; |
++i; |
} |
} |
s[ldp->rw] &= ~ldp->rmsk; |
if ((r & ldp->rmbit) != 0) |
{ |
if (r == ldp->rmbit) |
{ |
if (lost == 0) |
{ /* round to even */ |
if ((s[ldp->re] & ldp->rebit) == 0) |
goto mddone; |
} |
else |
{ |
if (subflg != 0) |
goto mddone; |
} |
} |
eaddm (ldp->rbit, s); |
} |
mddone: |
#if IBMPC |
if ((exp <= 0) && (ldp->rndprc != NBITS)) |
#else |
if ((exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS)) |
#endif |
{ |
eshup1 (s); |
} |
if (s[2] != 0) |
{ /* overflow on roundoff */ |
eshdn1 (s); |
exp += 1; |
} |
mdfin: |
s[NI - 1] = 0; |
if (exp >= 32767L) |
{ |
#ifndef USE_INFINITY |
overf: |
#endif |
#ifdef USE_INFINITY |
s[1] = 32767; |
for (i = 2; i < NI - 1; i++) |
s[i] = 0; |
#else |
s[1] = 32766; |
s[2] = 0; |
for (i = M + 1; i < NI - 1; i++) |
s[i] = 0xffff; |
s[NI - 1] = 0; |
if ((ldp->rndprc < 64) || (ldp->rndprc == 113)) |
{ |
s[ldp->rw] &= ~ldp->rmsk; |
if (ldp->rndprc == 24) |
{ |
s[5] = 0; |
s[6] = 0; |
} |
} |
#endif |
return; |
} |
if (exp < 0) |
s[1] = 0; |
else |
s[1] = (unsigned short) exp; |
} |
/* |
; Subtract external format numbers. |
; |
; unsigned short a[NE], b[NE], c[NE]; |
; LDPARMS *ldp; |
; esub( a, b, c, ldp ); c = b - a |
*/ |
static void |
esub (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, LDPARMS * ldp) |
{ |
#ifdef NANS |
if (eisnan (a)) |
{ |
emov (a, c); |
return; |
} |
if (eisnan (b)) |
{ |
emov (b, c); |
return; |
} |
/* Infinity minus infinity is a NaN. |
* Test for subtracting infinities of the same sign. |
*/ |
if (eisinf (a) && eisinf (b) && ((eisneg (a) ^ eisneg (b)) == 0)) |
{ |
mtherr ("esub", DOMAIN); |
enan (c, NBITS); |
return; |
} |
#endif |
eadd1 (a, b, c, 1, ldp); |
} |
static void |
eadd1 (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, int subflg, LDPARMS * ldp) |
{ |
unsigned short ai[NI], bi[NI], ci[NI]; |
int i, lost, j, k; |
long lt, lta, ltb; |
#ifdef USE_INFINITY |
if (eisinf (a)) |
{ |
emov (a, c); |
if (subflg) |
eneg (c); |
return; |
} |
if (eisinf (b)) |
{ |
emov (b, c); |
return; |
} |
#endif |
emovi (a, ai); |
emovi (b, bi); |
if (subflg) |
ai[0] = ~ai[0]; |
/* compare exponents */ |
lta = ai[E]; |
ltb = bi[E]; |
lt = lta - ltb; |
if (lt > 0L) |
{ /* put the larger number in bi */ |
emovz (bi, ci); |
emovz (ai, bi); |
emovz (ci, ai); |
ltb = bi[E]; |
lt = -lt; |
} |
lost = 0; |
if (lt != 0L) |
{ |
if (lt < (long) (-NBITS - 1)) |
goto done; /* answer same as larger addend */ |
k = (int) lt; |
lost = eshift (ai, k); /* shift the smaller number down */ |
} |
else |
{ |
/* exponents were the same, so must compare significands */ |
i = ecmpm (ai, bi); |
if (i == 0) |
{ /* the numbers are identical in magnitude */ |
/* if different signs, result is zero */ |
if (ai[0] != bi[0]) |
{ |
eclear (c); |
return; |
} |
/* if same sign, result is double */ |
/* double denomalized tiny number */ |
if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0)) |
{ |
eshup1 (bi); |
goto done; |
} |
/* add 1 to exponent unless both are zero! */ |
for (j = 1; j < NI - 1; j++) |
{ |
if (bi[j] != 0) |
{ |
/* This could overflow, but let emovo take care of that. */ |
ltb += 1; |
break; |
} |
} |
bi[E] = (unsigned short) ltb; |
goto done; |
} |
if (i > 0) |
{ /* put the larger number in bi */ |
emovz (bi, ci); |
emovz (ai, bi); |
emovz (ci, ai); |
} |
} |
if (ai[0] == bi[0]) |
{ |
eaddm (ai, bi); |
subflg = 0; |
} |
else |
{ |
esubm (ai, bi); |
subflg = 1; |
} |
emdnorm (bi, lost, subflg, ltb, 64, ldp); |
done: |
emovo (bi, c, ldp); |
} |
/* |
; Divide. |
; |
; unsigned short a[NE], b[NE], c[NE]; |
; LDPARMS *ldp; |
; ediv( a, b, c, ldp ); c = b / a |
*/ |
static void |
ediv (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, LDPARMS * ldp) |
{ |
unsigned short ai[NI], bi[NI]; |
int i; |
long lt, lta, ltb; |
#ifdef NANS |
/* Return any NaN input. */ |
if (eisnan (a)) |
{ |
emov (a, c); |
return; |
} |
if (eisnan (b)) |
{ |
emov (b, c); |
return; |
} |
/* Zero over zero, or infinity over infinity, is a NaN. */ |
if (((ecmp (a, ezero) == 0) && (ecmp (b, ezero) == 0)) |
|| (eisinf (a) && eisinf (b))) |
{ |
mtherr ("ediv", DOMAIN); |
enan (c, NBITS); |
return; |
} |
#endif |
/* Infinity over anything else is infinity. */ |
#ifdef USE_INFINITY |
if (eisinf (b)) |
{ |
if (eisneg (a) ^ eisneg (b)) |
*(c + (NE - 1)) = 0x8000; |
else |
*(c + (NE - 1)) = 0; |
einfin (c, ldp); |
return; |
} |
if (eisinf (a)) |
{ |
eclear (c); |
return; |
} |
#endif |
emovi (a, ai); |
emovi (b, bi); |
lta = ai[E]; |
ltb = bi[E]; |
if (bi[E] == 0) |
{ /* See if numerator is zero. */ |
for (i = 1; i < NI - 1; i++) |
{ |
if (bi[i] != 0) |
{ |
ltb -= enormlz (bi); |
goto dnzro1; |
} |
} |
eclear (c); |
return; |
} |
dnzro1: |
if (ai[E] == 0) |
{ /* possible divide by zero */ |
for (i = 1; i < NI - 1; i++) |
{ |
if (ai[i] != 0) |
{ |
lta -= enormlz (ai); |
goto dnzro2; |
} |
} |
if (ai[0] == bi[0]) |
*(c + (NE - 1)) = 0; |
else |
*(c + (NE - 1)) = 0x8000; |
einfin (c, ldp); |
mtherr ("ediv", SING); |
return; |
} |
dnzro2: |
i = edivm (ai, bi, ldp); |
/* calculate exponent */ |
lt = ltb - lta + EXONE; |
emdnorm (bi, i, 0, lt, 64, ldp); |
/* set the sign */ |
if (ai[0] == bi[0]) |
bi[0] = 0; |
else |
bi[0] = 0Xffff; |
emovo (bi, c, ldp); |
} |
/* |
; Multiply. |
; |
; unsigned short a[NE], b[NE], c[NE]; |
; LDPARMS *ldp |
; emul( a, b, c, ldp ); c = b * a |
*/ |
static void |
emul (_CONST short unsigned int *a, _CONST short unsigned int *b, |
short unsigned int *c, LDPARMS * ldp) |
{ |
unsigned short ai[NI], bi[NI]; |
int i, j; |
long lt, lta, ltb; |
#ifdef NANS |
/* NaN times anything is the same NaN. */ |
if (eisnan (a)) |
{ |
emov (a, c); |
return; |
} |
if (eisnan (b)) |
{ |
emov (b, c); |
return; |
} |
/* Zero times infinity is a NaN. */ |
if ((eisinf (a) && (ecmp (b, ezero) == 0)) |
|| (eisinf (b) && (ecmp (a, ezero) == 0))) |
{ |
mtherr ("emul", DOMAIN); |
enan (c, NBITS); |
return; |
} |
#endif |
/* Infinity times anything else is infinity. */ |
#ifdef USE_INFINITY |
if (eisinf (a) || eisinf (b)) |
{ |
if (eisneg (a) ^ eisneg (b)) |
*(c + (NE - 1)) = 0x8000; |
else |
*(c + (NE - 1)) = 0; |
einfin (c, ldp); |
return; |
} |
#endif |
emovi (a, ai); |
emovi (b, bi); |
lta = ai[E]; |
ltb = bi[E]; |
if (ai[E] == 0) |
{ |
for (i = 1; i < NI - 1; i++) |
{ |
if (ai[i] != 0) |
{ |
lta -= enormlz (ai); |
goto mnzer1; |
} |
} |
eclear (c); |
return; |
} |
mnzer1: |
if (bi[E] == 0) |
{ |
for (i = 1; i < NI - 1; i++) |
{ |
if (bi[i] != 0) |
{ |
ltb -= enormlz (bi); |
goto mnzer2; |
} |
} |
eclear (c); |
return; |
} |
mnzer2: |
/* Multiply significands */ |
j = emulm (ai, bi, ldp); |
/* calculate exponent */ |
lt = lta + ltb - (EXONE - 1); |
emdnorm (bi, j, 0, lt, 64, ldp); |
/* calculate sign of product */ |
if (ai[0] == bi[0]) |
bi[0] = 0; |
else |
bi[0] = 0xffff; |
emovo (bi, c, ldp); |
} |
#if LDBL_MANT_DIG > 64 |
static void |
e113toe (short unsigned int *pe, short unsigned int *y, LDPARMS * ldp) |
{ |
register unsigned short r; |
unsigned short *e, *p; |
unsigned short yy[NI]; |
int denorm, i; |
e = pe; |
denorm = 0; |
ecleaz (yy); |
#ifdef IBMPC |
e += 7; |
#endif |
r = *e; |
yy[0] = 0; |
if (r & 0x8000) |
yy[0] = 0xffff; |
r &= 0x7fff; |
#ifdef USE_INFINITY |
if (r == 0x7fff) |
{ |
#ifdef NANS |
#ifdef IBMPC |
for (i = 0; i < 7; i++) |
{ |
if (pe[i] != 0) |
{ |
enan (y, NBITS); |
return; |
} |
} |
#else /* !IBMPC */ |
for (i = 1; i < 8; i++) |
{ |
if (pe[i] != 0) |
{ |
enan (y, NBITS); |
return; |
} |
} |
#endif /* !IBMPC */ |
#endif /* NANS */ |
eclear (y); |
einfin (y, ldp); |
if (*e & 0x8000) |
eneg (y); |
return; |
} |
#endif /* INFINITY */ |
yy[E] = r; |
p = &yy[M + 1]; |
#ifdef IBMPC |
for (i = 0; i < 7; i++) |
*p++ = *(--e); |
#else /* IBMPC */ |
++e; |
for (i = 0; i < 7; i++) |
*p++ = *e++; |
#endif /* IBMPC */ |
/* If denormal, remove the implied bit; else shift down 1. */ |
if (r == 0) |
{ |
yy[M] = 0; |
} |
else |
{ |
yy[M] = 1; |
eshift (yy, -1); |
} |
emovo (yy, y, ldp); |
} |
/* move out internal format to ieee long double */ |
static void |
toe113 (short unsigned int *a, short unsigned int *b) |
{ |
register unsigned short *p, *q; |
unsigned short i; |
#ifdef NANS |
if (eiisnan (a)) |
{ |
enan (b, 113); |
return; |
} |
#endif |
p = a; |
#ifdef MIEEE |
q = b; |
#else |
q = b + 7; /* point to output exponent */ |
#endif |
/* If not denormal, delete the implied bit. */ |
if (a[E] != 0) |
{ |
eshup1 (a); |
} |
/* combine sign and exponent */ |
i = *p++; |
#ifdef MIEEE |
if (i) |
*q++ = *p++ | 0x8000; |
else |
*q++ = *p++; |
#else |
if (i) |
*q-- = *p++ | 0x8000; |
else |
*q-- = *p++; |
#endif |
/* skip over guard word */ |
++p; |
/* move the significand */ |
#ifdef MIEEE |
for (i = 0; i < 7; i++) |
*q++ = *p++; |
#else |
for (i = 0; i < 7; i++) |
*q-- = *p++; |
#endif |
} |
#endif /* LDBL_MANT_DIG > 64 */ |
#if LDBL_MANT_DIG == 64 |
static void |
e64toe (short unsigned int *pe, short unsigned int *y, LDPARMS * ldp) |
{ |
unsigned short yy[NI]; |
unsigned short *p, *q, *e; |
int i; |
e = pe; |
p = yy; |
for (i = 0; i < NE - 5; i++) |
*p++ = 0; |
#ifdef IBMPC |
for (i = 0; i < 5; i++) |
*p++ = *e++; |
#endif |
#ifdef DEC |
for (i = 0; i < 5; i++) |
*p++ = *e++; |
#endif |
#ifdef MIEEE |
p = &yy[0] + (NE - 1); |
*p-- = *e++; |
++e; /* MIEEE skips over 2nd short */ |
for (i = 0; i < 4; i++) |
*p-- = *e++; |
#endif |
#ifdef IBMPC |
/* For Intel long double, shift denormal significand up 1 |
-- but only if the top significand bit is zero. */ |
if ((yy[NE - 1] & 0x7fff) == 0 && (yy[NE - 2] & 0x8000) == 0) |
{ |
unsigned short temp[NI + 1]; |
emovi (yy, temp); |
eshup1 (temp); |
emovo (temp, y, ldp); |
return; |
} |
#endif |
#ifdef USE_INFINITY |
/* Point to the exponent field. */ |
p = &yy[NE - 1]; |
if ((*p & 0x7fff) == 0x7fff) |
{ |
#ifdef NANS |
#ifdef IBMPC |
for (i = 0; i < 4; i++) |
{ |
if ((i != 3 && pe[i] != 0) |
/* Check for Intel long double infinity pattern. */ |
|| (i == 3 && pe[i] != 0x8000)) |
{ |
enan (y, NBITS); |
return; |
} |
} |
#endif |
#ifdef MIEEE |
for (i = 2; i <= 5; i++) |
{ |
if (pe[i] != 0) |
{ |
enan (y, NBITS); |
return; |
} |
} |
#endif |
#endif /* NANS */ |
eclear (y); |
einfin (y, ldp); |
if (*p & 0x8000) |
eneg (y); |
return; |
} |
#endif /* USE_INFINITY */ |
p = yy; |
q = y; |
for (i = 0; i < NE; i++) |
*q++ = *p++; |
} |
/* move out internal format to ieee long double */ |
static void |
toe64 (short unsigned int *a, short unsigned int *b) |
{ |
register unsigned short *p, *q; |
unsigned short i; |
#ifdef NANS |
if (eiisnan (a)) |
{ |
enan (b, 64); |
return; |
} |
#endif |
#ifdef IBMPC |
/* Shift Intel denormal significand down 1. */ |
if (a[E] == 0) |
eshdn1 (a); |
#endif |
p = a; |
#ifdef MIEEE |
q = b; |
#else |
q = b + 4; /* point to output exponent */ |
/* NOTE: Intel data type is 96 bits wide, clear the last word here. */ |
*(q + 1) = 0; |
#endif |
/* combine sign and exponent */ |
i = *p++; |
#ifdef MIEEE |
if (i) |
*q++ = *p++ | 0x8000; |
else |
*q++ = *p++; |
*q++ = 0; /* leave 2nd short blank */ |
#else |
if (i) |
*q-- = *p++ | 0x8000; |
else |
*q-- = *p++; |
#endif |
/* skip over guard word */ |
++p; |
/* move the significand */ |
#ifdef MIEEE |
for (i = 0; i < 4; i++) |
*q++ = *p++; |
#else |
#ifdef USE_INFINITY |
#ifdef IBMPC |
if (eiisinf (a)) |
{ |
/* Intel long double infinity. */ |
*q-- = 0x8000; |
*q-- = 0; |
*q-- = 0; |
*q = 0; |
return; |
} |
#endif /* IBMPC */ |
#endif /* USE_INFINITY */ |
for (i = 0; i < 4; i++) |
*q-- = *p++; |
#endif |
} |
#endif /* LDBL_MANT_DIG == 64 */ |
#if LDBL_MANT_DIG == 53 |
/* |
; Convert IEEE double precision to e type |
; double d; |
; unsigned short x[N+2]; |
; e53toe( &d, x ); |
*/ |
static void |
e53toe (short unsigned int *pe, short unsigned int *y, LDPARMS * ldp) |
{ |
#ifdef DEC |
dectoe (pe, y); /* see etodec.c */ |
#else |
register unsigned short r; |
register unsigned short *p, *e; |
unsigned short yy[NI]; |
int denorm, k; |
e = pe; |
denorm = 0; /* flag if denormalized number */ |
ecleaz (yy); |
#ifdef IBMPC |
e += 3; |
#endif |
#ifdef DEC |
e += 3; |
#endif |
r = *e; |
yy[0] = 0; |
if (r & 0x8000) |
yy[0] = 0xffff; |
yy[M] = (r & 0x0f) | 0x10; |
r &= ~0x800f; /* strip sign and 4 significand bits */ |
#ifdef USE_INFINITY |
if (r == 0x7ff0) |
{ |
#ifdef NANS |
#ifdef IBMPC |
if (((pe[3] & 0xf) != 0) || (pe[2] != 0) |
|| (pe[1] != 0) || (pe[0] != 0)) |
{ |
enan (y, NBITS); |
return; |
} |
#else /* !IBMPC */ |
if (((pe[0] & 0xf) != 0) || (pe[1] != 0) |
|| (pe[2] != 0) || (pe[3] != 0)) |
{ |
enan (y, NBITS); |
return; |
} |
#endif /* !IBMPC */ |
#endif /* NANS */ |
eclear (y); |
einfin (y, ldp); |
if (yy[0]) |
eneg (y); |
return; |
} |
#endif |
r >>= 4; |
/* If zero exponent, then the significand is denormalized. |
* So, take back the understood high significand bit. */ |
if (r == 0) |
{ |
denorm = 1; |
yy[M] &= ~0x10; |
} |
r += EXONE - 01777; |
yy[E] = r; |
p = &yy[M + 1]; |
#ifdef IBMPC |
*p++ = *(--e); |
*p++ = *(--e); |
*p++ = *(--e); |
#else /* !IBMPC */ |
++e; |
*p++ = *e++; |
*p++ = *e++; |
*p++ = *e++; |
#endif /* !IBMPC */ |
(void) eshift (yy, -5); |
if (denorm) |
{ /* if zero exponent, then normalize the significand */ |
if ((k = enormlz (yy)) > NBITS) |
ecleazs (yy); |
else |
yy[E] -= (unsigned short) (k - 1); |
} |
emovo (yy, y, ldp); |
#endif /* !DEC */ |
} |
/* |
; e type to IEEE double precision |
; double d; |
; unsigned short x[NE]; |
; etoe53( x, &d ); |
*/ |
#ifdef DEC |
static void |
etoe53 (x, e) |
unsigned short *x, *e; |
{ |
etodec (x, e); /* see etodec.c */ |
} |
static void |
toe53 (x, y) |
unsigned short *x, *y; |
{ |
todec (x, y); |
} |
#else |
static void |
toe53 (short unsigned int *x, short unsigned int *y) |
{ |
unsigned short i; |
unsigned short *p; |
#ifdef NANS |
if (eiisnan (x)) |
{ |
enan (y, 53); |
return; |
} |
#endif |
p = &x[0]; |
#ifdef IBMPC |
y += 3; |
#endif |
#ifdef DEC |
y += 3; |
#endif |
*y = 0; /* output high order */ |
if (*p++) |
*y = 0x8000; /* output sign bit */ |
i = *p++; |
if (i >= (unsigned int) 2047) |
{ /* Saturate at largest number less than infinity. */ |
#ifdef USE_INFINITY |
*y |= 0x7ff0; |
#ifdef IBMPC |
*(--y) = 0; |
*(--y) = 0; |
*(--y) = 0; |
#else /* !IBMPC */ |
++y; |
*y++ = 0; |
*y++ = 0; |
*y++ = 0; |
#endif /* IBMPC */ |
#else /* !USE_INFINITY */ |
*y |= (unsigned short) 0x7fef; |
#ifdef IBMPC |
*(--y) = 0xffff; |
*(--y) = 0xffff; |
*(--y) = 0xffff; |
#else /* !IBMPC */ |
++y; |
*y++ = 0xffff; |
*y++ = 0xffff; |
*y++ = 0xffff; |
#endif |
#endif /* !USE_INFINITY */ |
return; |
} |
if (i == 0) |
{ |
(void) eshift (x, 4); |
} |
else |
{ |
i <<= 4; |
(void) eshift (x, 5); |
} |
i |= *p++ & (unsigned short) 0x0f; /* *p = xi[M] */ |
*y |= (unsigned short) i; /* high order output already has sign bit set */ |
#ifdef IBMPC |
*(--y) = *p++; |
*(--y) = *p++; |
*(--y) = *p; |
#else /* !IBMPC */ |
++y; |
*y++ = *p++; |
*y++ = *p++; |
*y++ = *p++; |
#endif /* !IBMPC */ |
} |
#endif /* not DEC */ |
#endif /* LDBL_MANT_DIG == 53 */ |
#if LDBL_MANT_DIG == 24 |
/* |
; Convert IEEE single precision to e type |
; float d; |
; unsigned short x[N+2]; |
; dtox( &d, x ); |
*/ |
void |
e24toe (short unsigned int *pe, short unsigned int *y, LDPARMS * ldp) |
{ |
register unsigned short r; |
register unsigned short *p, *e; |
unsigned short yy[NI]; |
int denorm, k; |
e = pe; |
denorm = 0; /* flag if denormalized number */ |
ecleaz (yy); |
#ifdef IBMPC |
e += 1; |
#endif |
#ifdef DEC |
e += 1; |
#endif |
r = *e; |
yy[0] = 0; |
if (r & 0x8000) |
yy[0] = 0xffff; |
yy[M] = (r & 0x7f) | 0200; |
r &= ~0x807f; /* strip sign and 7 significand bits */ |
#ifdef USE_INFINITY |
if (r == 0x7f80) |
{ |
#ifdef NANS |
#ifdef MIEEE |
if (((pe[0] & 0x7f) != 0) || (pe[1] != 0)) |
{ |
enan (y, NBITS); |
return; |
} |
#else /* !MIEEE */ |
if (((pe[1] & 0x7f) != 0) || (pe[0] != 0)) |
{ |
enan (y, NBITS); |
return; |
} |
#endif /* !MIEEE */ |
#endif /* NANS */ |
eclear (y); |
einfin (y, ldp); |
if (yy[0]) |
eneg (y); |
return; |
} |
#endif |
r >>= 7; |
/* If zero exponent, then the significand is denormalized. |
* So, take back the understood high significand bit. */ |
if (r == 0) |
{ |
denorm = 1; |
yy[M] &= ~0200; |
} |
r += EXONE - 0177; |
yy[E] = r; |
p = &yy[M + 1]; |
#ifdef IBMPC |
*p++ = *(--e); |
#endif |
#ifdef DEC |
*p++ = *(--e); |
#endif |
#ifdef MIEEE |
++e; |
*p++ = *e++; |
#endif |
(void) eshift (yy, -8); |
if (denorm) |
{ /* if zero exponent, then normalize the significand */ |
if ((k = enormlz (yy)) > NBITS) |
ecleazs (yy); |
else |
yy[E] -= (unsigned short) (k - 1); |
} |
emovo (yy, y, ldp); |
} |
static void |
toe24 (short unsigned int *x, short unsigned int *y) |
{ |
unsigned short i; |
unsigned short *p; |
#ifdef NANS |
if (eiisnan (x)) |
{ |
enan (y, 24); |
return; |
} |
#endif |
p = &x[0]; |
#ifdef IBMPC |
y += 1; |
#endif |
#ifdef DEC |
y += 1; |
#endif |
*y = 0; /* output high order */ |
if (*p++) |
*y = 0x8000; /* output sign bit */ |
i = *p++; |
if (i >= 255) |
{ /* Saturate at largest number less than infinity. */ |
#ifdef USE_INFINITY |
*y |= (unsigned short) 0x7f80; |
#ifdef IBMPC |
*(--y) = 0; |
#endif |
#ifdef DEC |
*(--y) = 0; |
#endif |
#ifdef MIEEE |
++y; |
*y = 0; |
#endif |
#else /* !USE_INFINITY */ |
*y |= (unsigned short) 0x7f7f; |
#ifdef IBMPC |
*(--y) = 0xffff; |
#endif |
#ifdef DEC |
*(--y) = 0xffff; |
#endif |
#ifdef MIEEE |
++y; |
*y = 0xffff; |
#endif |
#endif /* !USE_INFINITY */ |
return; |
} |
if (i == 0) |
{ |
(void) eshift (x, 7); |
} |
else |
{ |
i <<= 7; |
(void) eshift (x, 8); |
} |
i |= *p++ & (unsigned short) 0x7f; /* *p = xi[M] */ |
*y |= i; /* high order output already has sign bit set */ |
#ifdef IBMPC |
*(--y) = *p; |
#endif |
#ifdef DEC |
*(--y) = *p; |
#endif |
#ifdef MIEEE |
++y; |
*y = *p; |
#endif |
} |
#endif /* LDBL_MANT_DIG == 24 */ |
/* Compare two e type numbers. |
* |
* unsigned short a[NE], b[NE]; |
* ecmp( a, b ); |
* |
* returns +1 if a > b |
* 0 if a == b |
* -1 if a < b |
* -2 if either a or b is a NaN. |
*/ |
static int |
ecmp (_CONST short unsigned int *a, _CONST short unsigned int *b) |
{ |
unsigned short ai[NI], bi[NI]; |
register unsigned short *p, *q; |
register int i; |
int msign; |
#ifdef NANS |
if (eisnan (a) || eisnan (b)) |
return (-2); |
#endif |
emovi (a, ai); |
p = ai; |
emovi (b, bi); |
q = bi; |
if (*p != *q) |
{ /* the signs are different */ |
/* -0 equals + 0 */ |
for (i = 1; i < NI - 1; i++) |
{ |
if (ai[i] != 0) |
goto nzro; |
if (bi[i] != 0) |
goto nzro; |
} |
return (0); |
nzro: |
if (*p == 0) |
return (1); |
else |
return (-1); |
} |
/* both are the same sign */ |
if (*p == 0) |
msign = 1; |
else |
msign = -1; |
i = NI - 1; |
do |
{ |
if (*p++ != *q++) |
{ |
goto diff; |
} |
} |
while (--i > 0); |
return (0); /* equality */ |
diff: |
if (*(--p) > *(--q)) |
return (msign); /* p is bigger */ |
else |
return (-msign); /* p is littler */ |
} |
/* |
; Shift significand |
; |
; Shifts significand area up or down by the number of bits |
; given by the variable sc. |
*/ |
static int |
eshift (short unsigned int *x, int sc) |
{ |
unsigned short lost; |
unsigned short *p; |
if (sc == 0) |
return (0); |
lost = 0; |
p = x + NI - 1; |
if (sc < 0) |
{ |
sc = -sc; |
while (sc >= 16) |
{ |
lost |= *p; /* remember lost bits */ |
eshdn6 (x); |
sc -= 16; |
} |
while (sc >= 8) |
{ |
lost |= *p & 0xff; |
eshdn8 (x); |
sc -= 8; |
} |
while (sc > 0) |
{ |
lost |= *p & 1; |
eshdn1 (x); |
sc -= 1; |
} |
} |
else |
{ |
while (sc >= 16) |
{ |
eshup6 (x); |
sc -= 16; |
} |
while (sc >= 8) |
{ |
eshup8 (x); |
sc -= 8; |
} |
while (sc > 0) |
{ |
eshup1 (x); |
sc -= 1; |
} |
} |
if (lost) |
lost = 1; |
return ((int) lost); |
} |
/* |
; normalize |
; |
; Shift normalizes the significand area pointed to by argument |
; shift count (up = positive) is returned. |
*/ |
static int |
enormlz (short unsigned int *x) |
{ |
register unsigned short *p; |
int sc; |
sc = 0; |
p = &x[M]; |
if (*p != 0) |
goto normdn; |
++p; |
if (*p & 0x8000) |
return (0); /* already normalized */ |
while (*p == 0) |
{ |
eshup6 (x); |
sc += 16; |
/* With guard word, there are NBITS+16 bits available. |
* return true if all are zero. |
*/ |
if (sc > NBITS) |
return (sc); |
} |
/* see if high byte is zero */ |
while ((*p & 0xff00) == 0) |
{ |
eshup8 (x); |
sc += 8; |
} |
/* now shift 1 bit at a time */ |
while ((*p & 0x8000) == 0) |
{ |
eshup1 (x); |
sc += 1; |
if (sc > (NBITS + 16)) |
{ |
mtherr ("enormlz", UNDERFLOW); |
return (sc); |
} |
} |
return (sc); |
/* Normalize by shifting down out of the high guard word |
of the significand */ |
normdn: |
if (*p & 0xff00) |
{ |
eshdn8 (x); |
sc -= 8; |
} |
while (*p != 0) |
{ |
eshdn1 (x); |
sc -= 1; |
if (sc < -NBITS) |
{ |
mtherr ("enormlz", OVERFLOW); |
return (sc); |
} |
} |
return (sc); |
} |
/* Convert e type number to decimal format ASCII string. |
* The constants are for 64 bit precision. |
*/ |
#define NTEN 12 |
#define MAXP 4096 |
#if NE == 10 |
static _CONST unsigned short etens[NTEN + 1][NE] = { |
{0x6576, 0x4a92, 0x804a, 0x153f, |
0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */ |
{0x6a32, 0xce52, 0x329a, 0x28ce, |
0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */ |
{0x526c, 0x50ce, 0xf18b, 0x3d28, |
0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,}, |
{0x9c66, 0x58f8, 0xbc50, 0x5c54, |
0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,}, |
{0x851e, 0xeab7, 0x98fe, 0x901b, |
0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,}, |
{0x0235, 0x0137, 0x36b1, 0x336c, |
0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,}, |
{0x50f8, 0x25fb, 0xc76b, 0x6b71, |
0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,}, |
{0x0000, 0x0000, 0x0000, 0x0000, |
0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,}, |
{0x0000, 0x0000, 0x0000, 0x0000, |
0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,}, |
{0x0000, 0x0000, 0x0000, 0x0000, |
0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,}, |
{0x0000, 0x0000, 0x0000, 0x0000, |
0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,}, |
{0x0000, 0x0000, 0x0000, 0x0000, |
0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,}, |
{0x0000, 0x0000, 0x0000, 0x0000, |
0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */ |
}; |
static _CONST unsigned short emtens[NTEN + 1][NE] = { |
{0x2030, 0xcffc, 0xa1c3, 0x8123, |
0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */ |
{0x8264, 0xd2cb, 0xf2ea, 0x12d4, |
0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */ |
{0xf53f, 0xf698, 0x6bd3, 0x0158, |
0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,}, |
{0xe731, 0x04d4, 0xe3f2, 0xd332, |
0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,}, |
{0xa23e, 0x5308, 0xfefb, 0x1155, |
0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,}, |
{0xe26d, 0xdbde, 0xd05d, 0xb3f6, |
0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,}, |
{0x2a20, 0x6224, 0x47b3, 0x98d7, |
0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,}, |
{0x0b5b, 0x4af2, 0xa581, 0x18ed, |
0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,}, |
{0xbf71, 0xa9b3, 0x7989, 0xbe68, |
0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,}, |
{0x3d4d, 0x7c3d, 0x36ba, 0x0d2b, |
0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,}, |
{0xc155, 0xa4a8, 0x404e, 0x6113, |
0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,}, |
{0xd70a, 0x70a3, 0x0a3d, 0xa3d7, |
0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,}, |
{0xcccd, 0xcccc, 0xcccc, 0xcccc, |
0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */ |
}; |
#else |
static _CONST unsigned short etens[NTEN + 1][NE] = { |
{0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */ |
{0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */ |
{0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,}, |
{0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,}, |
{0xddbc, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,}, |
{0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,}, |
{0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,}, |
{0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,}, |
{0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,}, |
{0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,}, |
{0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,}, |
{0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,}, |
{0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */ |
}; |
static _CONST unsigned short emtens[NTEN + 1][NE] = { |
{0x2de4, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */ |
{0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */ |
{0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,}, |
{0x7133, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,}, |
{0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,}, |
{0xac7d, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,}, |
{0x3f24, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,}, |
{0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,}, |
{0x4c2f, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,}, |
{0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,}, |
{0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,}, |
{0x3d71, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,}, |
{0xcccd, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */ |
}; |
#endif |
/* ASCII string outputs for unix */ |
#if 0 |
void |
_IO_ldtostr (x, string, ndigs, flags, fmt) |
long double *x; |
char *string; |
int ndigs; |
int flags; |
char fmt; |
{ |
unsigned short w[NI]; |
char *t, *u; |
LDPARMS rnd; |
LDPARMS *ldp = &rnd; |
rnd.rlast = -1; |
rnd.rndprc = NBITS; |
if (sizeof (long double) == 16) |
e113toe ((unsigned short *) x, w, ldp); |
else |
e64toe ((unsigned short *) x, w, ldp); |
etoasc (w, string, ndigs, -1, ldp); |
if (ndigs == 0 && flags == 0) |
{ |
/* Delete the decimal point unless alternate format. */ |
t = string; |
while (*t != '.') |
++t; |
u = t + 1; |
while (*t != '\0') |
*t++ = *u++; |
} |
if (*string == ' ') |
{ |
t = string; |
u = t + 1; |
while (*t != '\0') |
*t++ = *u++; |
} |
if (fmt == 'E') |
{ |
t = string; |
while (*t != 'e') |
++t; |
*t = 'E'; |
} |
} |
#endif |
/* This routine will not return more than NDEC+1 digits. */ |
char * |
_ldtoa_r (struct _reent *ptr, long double d, int mode, int ndigits, |
int *decpt, int *sign, char **rve) |
{ |
unsigned short e[NI]; |
char *s, *p; |
int i, j, k; |
int orig_ndigits; |
LDPARMS rnd; |
LDPARMS *ldp = &rnd; |
char *outstr; |
char outbuf[NDEC + MAX_EXP_DIGITS + 10]; |
union uconv du; |
du.d = d; |
orig_ndigits = ndigits; |
rnd.rlast = -1; |
rnd.rndprc = NBITS; |
_REENT_CHECK_MP (ptr); |
/* reentrancy addition to use mprec storage pool */ |
if (_REENT_MP_RESULT (ptr)) |
{ |
_REENT_MP_RESULT (ptr)->_k = _REENT_MP_RESULT_K (ptr); |
_REENT_MP_RESULT (ptr)->_maxwds = 1 << _REENT_MP_RESULT_K (ptr); |
Bfree (ptr, _REENT_MP_RESULT (ptr)); |
_REENT_MP_RESULT (ptr) = 0; |
} |
#if LDBL_MANT_DIG == 24 |
e24toe (&du.pe, e, ldp); |
#elif LDBL_MANT_DIG == 53 |
e53toe (&du.pe, e, ldp); |
#elif LDBL_MANT_DIG == 64 |
e64toe (&du.pe, e, ldp); |
#else |
e113toe (&du.pe, e, ldp); |
#endif |
if (eisneg (e)) |
*sign = 1; |
else |
*sign = 0; |
/* Mode 3 is "f" format. */ |
if (mode != 3) |
ndigits -= 1; |
/* Mode 0 is for %.999 format, which is supposed to give a |
minimum length string that will convert back to the same binary value. |
For now, just ask for 20 digits which is enough but sometimes too many. */ |
if (mode == 0) |
ndigits = 20; |
/* This sanity limit must agree with the corresponding one in etoasc, to |
keep straight the returned value of outexpon. */ |
if (ndigits > NDEC) |
ndigits = NDEC; |
etoasc (e, outbuf, ndigits, mode, ldp); |
s = outbuf; |
if (eisinf (e) || eisnan (e)) |
{ |
*decpt = 9999; |
goto stripspaces; |
} |
*decpt = ldp->outexpon + 1; |
/* Transform the string returned by etoasc into what the caller wants. */ |
/* Look for decimal point and delete it from the string. */ |
s = outbuf; |
while (*s != '\0') |
{ |
if (*s == '.') |
goto yesdecpt; |
++s; |
} |
goto nodecpt; |
yesdecpt: |
/* Delete the decimal point. */ |
while (*s != '\0') |
{ |
*s = *(s + 1); |
++s; |
} |
nodecpt: |
/* Back up over the exponent field. */ |
while (*s != 'E' && s > outbuf) |
--s; |
*s = '\0'; |
stripspaces: |
/* Strip leading spaces and sign. */ |
p = outbuf; |
while (*p == ' ' || *p == '-') |
++p; |
/* Find new end of string. */ |
s = outbuf; |
while ((*s++ = *p++) != '\0') |
; |
--s; |
/* Strip trailing zeros. */ |
if (mode == 2) |
k = 1; |
else if (ndigits > ldp->outexpon) |
k = ndigits; |
else |
k = ldp->outexpon; |
while (*(s - 1) == '0' && ((s - outbuf) > k)) |
*(--s) = '\0'; |
/* In f format, flush small off-scale values to zero. |
Rounding has been taken care of by etoasc. */ |
if (mode == 3 && ((ndigits + ldp->outexpon) < 0)) |
{ |
s = outbuf; |
*s = '\0'; |
*decpt = 0; |
} |
/* reentrancy addition to use mprec storage pool */ |
/* we want to have enough space to hold the formatted result */ |
if (mode == 3) /* f format, account for sign + dec digits + decpt + frac */ |
i = *decpt + orig_ndigits + 3; |
else /* account for sign + max precision digs + E + exp sign + exponent */ |
i = orig_ndigits + MAX_EXP_DIGITS + 4; |
j = sizeof (__ULong); |
for (_REENT_MP_RESULT_K (ptr) = 0; |
sizeof (_Bigint) - sizeof (__ULong) + j <= i; j <<= 1) |
_REENT_MP_RESULT_K (ptr)++; |
_REENT_MP_RESULT (ptr) = Balloc (ptr, _REENT_MP_RESULT_K (ptr)); |
/* Copy from internal temporary buffer to permanent buffer. */ |
outstr = (char *) _REENT_MP_RESULT (ptr); |
strcpy (outstr, outbuf); |
if (rve) |
*rve = outstr + (s - outbuf); |
return outstr; |
} |
/* Routine used to tell if long double is NaN or Infinity or regular number. |
Returns: 0 = regular number |
1 = Nan |
2 = Infinity |
*/ |
int |
_ldcheck (long double *d) |
{ |
unsigned short e[NI]; |
LDPARMS rnd; |
LDPARMS *ldp = &rnd; |
union uconv du; |
rnd.rlast = -1; |
rnd.rndprc = NBITS; |
du.d = *d; |
#if LDBL_MANT_DIG == 24 |
e24toe (&du.pe, e, ldp); |
#elif LDBL_MANT_DIG == 53 |
e53toe (&du.pe, e, ldp); |
#elif LDBL_MANT_DIG == 64 |
e64toe (&du.pe, e, ldp); |
#else |
e113toe (&du.pe, e, ldp); |
#endif |
if ((e[NE - 1] & 0x7fff) == 0x7fff) |
{ |
#ifdef NANS |
if (eisnan (e)) |
return (1); |
#endif |
return (2); |
} |
else |
return (0); |
} /* _ldcheck */ |
static void |
etoasc (short unsigned int *x, char *string, int ndigits, int outformat, |
LDPARMS * ldp) |
{ |
long digit; |
unsigned short y[NI], t[NI], u[NI], w[NI]; |
_CONST unsigned short *p, *r, *ten; |
unsigned short sign; |
int i, j, k, expon, rndsav, ndigs; |
char *s, *ss; |
unsigned short m; |
unsigned short *equot = ldp->equot; |
ndigs = ndigits; |
rndsav = ldp->rndprc; |
#ifdef NANS |
if (eisnan (x)) |
{ |
sprintf (string, " NaN "); |
expon = 9999; |
goto bxit; |
} |
#endif |
ldp->rndprc = NBITS; /* set to full precision */ |
emov (x, y); /* retain external format */ |
if (y[NE - 1] & 0x8000) |
{ |
sign = 0xffff; |
y[NE - 1] &= 0x7fff; |
} |
else |
{ |
sign = 0; |
} |
expon = 0; |
ten = &etens[NTEN][0]; |
emov (eone, t); |
/* Test for zero exponent */ |
if (y[NE - 1] == 0) |
{ |
for (k = 0; k < NE - 1; k++) |
{ |
if (y[k] != 0) |
goto tnzro; /* denormalized number */ |
} |
goto isone; /* legal all zeros */ |
} |
tnzro: |
/* Test for infinity. |
*/ |
if (y[NE - 1] == 0x7fff) |
{ |
if (sign) |
sprintf (string, " -Infinity "); |
else |
sprintf (string, " Infinity "); |
expon = 9999; |
goto bxit; |
} |
/* Test for exponent nonzero but significand denormalized. |
* This is an error condition. |
*/ |
if ((y[NE - 1] != 0) && ((y[NE - 2] & 0x8000) == 0)) |
{ |
mtherr ("etoasc", DOMAIN); |
sprintf (string, "NaN"); |
expon = 9999; |
goto bxit; |
} |
/* Compare to 1.0 */ |
i = ecmp (eone, y); |
if (i == 0) |
goto isone; |
if (i < 0) |
{ /* Number is greater than 1 */ |
/* Convert significand to an integer and strip trailing decimal zeros. */ |
emov (y, u); |
u[NE - 1] = EXONE + NBITS - 1; |
p = &etens[NTEN - 4][0]; |
m = 16; |
do |
{ |
ediv (p, u, t, ldp); |
efloor (t, w, ldp); |
for (j = 0; j < NE - 1; j++) |
{ |
if (t[j] != w[j]) |
goto noint; |
} |
emov (t, u); |
expon += (int) m; |
noint: |
p += NE; |
m >>= 1; |
} |
while (m != 0); |
/* Rescale from integer significand */ |
u[NE - 1] += y[NE - 1] - (unsigned int) (EXONE + NBITS - 1); |
emov (u, y); |
/* Find power of 10 */ |
emov (eone, t); |
m = MAXP; |
p = &etens[0][0]; |
while (ecmp (ten, u) <= 0) |
{ |
if (ecmp (p, u) <= 0) |
{ |
ediv (p, u, u, ldp); |
emul (p, t, t, ldp); |
expon += (int) m; |
} |
m >>= 1; |
if (m == 0) |
break; |
p += NE; |
} |
} |
else |
{ /* Number is less than 1.0 */ |
/* Pad significand with trailing decimal zeros. */ |
if (y[NE - 1] == 0) |
{ |
while ((y[NE - 2] & 0x8000) == 0) |
{ |
emul (ten, y, y, ldp); |
expon -= 1; |
} |
} |
else |
{ |
emovi (y, w); |
for (i = 0; i < NDEC + 1; i++) |
{ |
if ((w[NI - 1] & 0x7) != 0) |
break; |
/* multiply by 10 */ |
emovz (w, u); |
eshdn1 (u); |
eshdn1 (u); |
eaddm (w, u); |
u[1] += 3; |
while (u[2] != 0) |
{ |
eshdn1 (u); |
u[1] += 1; |
} |
if (u[NI - 1] != 0) |
break; |
if (eone[NE - 1] <= u[1]) |
break; |
emovz (u, w); |
expon -= 1; |
} |
emovo (w, y, ldp); |
} |
k = -MAXP; |
p = &emtens[0][0]; |
r = &etens[0][0]; |
emov (y, w); |
emov (eone, t); |
while (ecmp (eone, w) > 0) |
{ |
if (ecmp (p, w) >= 0) |
{ |
emul (r, w, w, ldp); |
emul (r, t, t, ldp); |
expon += k; |
} |
k /= 2; |
if (k == 0) |
break; |
p += NE; |
r += NE; |
} |
ediv (t, eone, t, ldp); |
} |
isone: |
/* Find the first (leading) digit. */ |
emovi (t, w); |
emovz (w, t); |
emovi (y, w); |
emovz (w, y); |
eiremain (t, y, ldp); |
digit = equot[NI - 1]; |
while ((digit == 0) && (ecmp (y, ezero) != 0)) |
{ |
eshup1 (y); |
emovz (y, u); |
eshup1 (u); |
eshup1 (u); |
eaddm (u, y); |
eiremain (t, y, ldp); |
digit = equot[NI - 1]; |
expon -= 1; |
} |
s = string; |
if (sign) |
*s++ = '-'; |
else |
*s++ = ' '; |
/* Examine number of digits requested by caller. */ |
if (outformat == 3) |
ndigs += expon; |
/* |
else if( ndigs < 0 ) |
ndigs = 0; |
*/ |
if (ndigs > NDEC) |
ndigs = NDEC; |
if (digit == 10) |
{ |
*s++ = '1'; |
*s++ = '.'; |
if (ndigs > 0) |
{ |
*s++ = '0'; |
ndigs -= 1; |
} |
expon += 1; |
if (ndigs < 0) |
{ |
ss = s; |
goto doexp; |
} |
} |
else |
{ |
*s++ = (char) digit + '0'; |
*s++ = '.'; |
} |
/* Generate digits after the decimal point. */ |
for (k = 0; k <= ndigs; k++) |
{ |
/* multiply current number by 10, without normalizing */ |
eshup1 (y); |
emovz (y, u); |
eshup1 (u); |
eshup1 (u); |
eaddm (u, y); |
eiremain (t, y, ldp); |
*s++ = (char) equot[NI - 1] + '0'; |
} |
digit = equot[NI - 1]; |
--s; |
ss = s; |
/* round off the ASCII string */ |
if (digit > 4) |
{ |
/* Test for critical rounding case in ASCII output. */ |
if (digit == 5) |
{ |
emovo (y, t, ldp); |
if (ecmp (t, ezero) != 0) |
goto roun; /* round to nearest */ |
if (ndigs < 0 || (*(s - 1 - (*(s - 1) == '.')) & 1) == 0) |
goto doexp; /* round to even */ |
} |
/* Round up and propagate carry-outs */ |
roun: |
--s; |
k = *s & 0x7f; |
/* Carry out to most significant digit? */ |
if (ndigs < 0) |
{ |
/* This will print like "1E-6". */ |
*s = '1'; |
expon += 1; |
goto doexp; |
} |
else if (k == '.') |
{ |
--s; |
k = *s; |
k += 1; |
*s = (char) k; |
/* Most significant digit carries to 10? */ |
if (k > '9') |
{ |
expon += 1; |
*s = '1'; |
} |
goto doexp; |
} |
/* Round up and carry out from less significant digits */ |
k += 1; |
*s = (char) k; |
if (k > '9') |
{ |
*s = '0'; |
goto roun; |
} |
} |
doexp: |
#ifdef __GO32__ |
if (expon >= 0) |
sprintf (ss, "e+%02d", expon); |
else |
sprintf (ss, "e-%02d", -expon); |
#else |
sprintf (ss, "E%d", expon); |
#endif |
bxit: |
ldp->rndprc = rndsav; |
ldp->outexpon = expon; |
} |
#if 0 /* Broken, unusable implementation of strtold */ |
/* |
; ASCTOQ |
; ASCTOQ.MAC LATEST REV: 11 JAN 84 |
; SLM, 3 JAN 78 |
; |
; Convert ASCII string to quadruple precision floating point |
; |
; Numeric input is free field decimal number |
; with max of 15 digits with or without |
; decimal point entered as ASCII from teletype. |
; Entering E after the number followed by a second |
; number causes the second number to be interpreted |
; as a power of 10 to be multiplied by the first number |
; (i.e., "scientific" notation). |
; |
; Usage: |
; asctoq( string, q ); |
*/ |
long double |
_strtold (char *s, char **se) |
{ |
union uconv x; |
LDPARMS rnd; |
LDPARMS *ldp = &rnd; |
int lenldstr; |
rnd.rlast = -1; |
rnd.rndprc = NBITS; |
lenldstr = asctoeg (s, &x.pe, LDBL_MANT_DIG, ldp); |
if (se) |
*se = s + lenldstr; |
return x.d; |
} |
#define REASONABLE_LEN 200 |
static int |
asctoeg (char *ss, short unsigned int *y, int oprec, LDPARMS * ldp) |
{ |
unsigned short yy[NI], xt[NI], tt[NI]; |
int esign, decflg, sgnflg, nexp, exp, prec, lost; |
int k, trail, c, rndsav; |
long lexp; |
unsigned short nsign; |
_CONST unsigned short *p; |
char *sp, *s, *lstr; |
int lenldstr; |
int mflag = 0; |
char tmpstr[REASONABLE_LEN]; |
/* Copy the input string. */ |
c = strlen (ss) + 2; |
if (c <= REASONABLE_LEN) |
lstr = tmpstr; |
else |
{ |
lstr = (char *) calloc (c, 1); |
mflag = 1; |
} |
s = ss; |
lenldstr = 0; |
while (*s == ' ') /* skip leading spaces */ |
{ |
++s; |
++lenldstr; |
} |
sp = lstr; |
for (k = 0; k < c; k++) |
{ |
if ((*sp++ = *s++) == '\0') |
break; |
} |
*sp = '\0'; |
s = lstr; |
rndsav = ldp->rndprc; |
ldp->rndprc = NBITS; /* Set to full precision */ |
lost = 0; |
nsign = 0; |
decflg = 0; |
sgnflg = 0; |
nexp = 0; |
exp = 0; |
prec = 0; |
ecleaz (yy); |
trail = 0; |
nxtcom: |
k = *s - '0'; |
if ((k >= 0) && (k <= 9)) |
{ |
/* Ignore leading zeros */ |
if ((prec == 0) && (decflg == 0) && (k == 0)) |
goto donchr; |
/* Identify and strip trailing zeros after the decimal point. */ |
if ((trail == 0) && (decflg != 0)) |
{ |
sp = s; |
while ((*sp >= '0') && (*sp <= '9')) |
++sp; |
/* Check for syntax error */ |
c = *sp & 0x7f; |
if ((c != 'e') && (c != 'E') && (c != '\0') |
&& (c != '\n') && (c != '\r') && (c != ' ') && (c != ',')) |
goto error; |
--sp; |
while (*sp == '0') |
*sp-- = 'z'; |
trail = 1; |
if (*s == 'z') |
goto donchr; |
} |
/* If enough digits were given to more than fill up the yy register, |
* continuing until overflow into the high guard word yy[2] |
* guarantees that there will be a roundoff bit at the top |
* of the low guard word after normalization. |
*/ |
if (yy[2] == 0) |
{ |
if (decflg) |
nexp += 1; /* count digits after decimal point */ |
eshup1 (yy); /* multiply current number by 10 */ |
emovz (yy, xt); |
eshup1 (xt); |
eshup1 (xt); |
eaddm (xt, yy); |
ecleaz (xt); |
xt[NI - 2] = (unsigned short) k; |
eaddm (xt, yy); |
} |
else |
{ |
/* Mark any lost non-zero digit. */ |
lost |= k; |
/* Count lost digits before the decimal point. */ |
if (decflg == 0) |
nexp -= 1; |
} |
prec += 1; |
goto donchr; |
} |
switch (*s) |
{ |
case 'z': |
break; |
case 'E': |
case 'e': |
goto expnt; |
case '.': /* decimal point */ |
if (decflg) |
goto error; |
++decflg; |
break; |
case '-': |
nsign = 0xffff; |
if (sgnflg) |
goto error; |
++sgnflg; |
break; |
case '+': |
if (sgnflg) |
goto error; |
++sgnflg; |
break; |
case ',': |
case ' ': |
case '\0': |
case '\n': |
case '\r': |
goto daldone; |
case 'i': |
case 'I': |
goto infinite; |
default: |
error: |
#ifdef NANS |
enan (yy, NI * 16); |
#else |
mtherr ("asctoe", DOMAIN); |
ecleaz (yy); |
#endif |
goto aexit; |
} |
donchr: |
++s; |
goto nxtcom; |
/* Exponent interpretation */ |
expnt: |
esign = 1; |
exp = 0; |
++s; |
/* check for + or - */ |
if (*s == '-') |
{ |
esign = -1; |
++s; |
} |
if (*s == '+') |
++s; |
while ((*s >= '0') && (*s <= '9')) |
{ |
exp *= 10; |
exp += *s++ - '0'; |
if (exp > 4977) |
{ |
if (esign < 0) |
goto zero; |
else |
goto infinite; |
} |
} |
if (esign < 0) |
exp = -exp; |
if (exp > 4932) |
{ |
infinite: |
ecleaz (yy); |
yy[E] = 0x7fff; /* infinity */ |
goto aexit; |
} |
if (exp < -4977) |
{ |
zero: |
ecleaz (yy); |
goto aexit; |
} |
daldone: |
nexp = exp - nexp; |
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */ |
while ((nexp > 0) && (yy[2] == 0)) |
{ |
emovz (yy, xt); |
eshup1 (xt); |
eshup1 (xt); |
eaddm (yy, xt); |
eshup1 (xt); |
if (xt[2] != 0) |
break; |
nexp -= 1; |
emovz (xt, yy); |
} |
if ((k = enormlz (yy)) > NBITS) |
{ |
ecleaz (yy); |
goto aexit; |
} |
lexp = (EXONE - 1 + NBITS) - k; |
emdnorm (yy, lost, 0, lexp, 64, ldp); |
/* convert to external format */ |
/* Multiply by 10**nexp. If precision is 64 bits, |
* the maximum relative error incurred in forming 10**n |
* for 0 <= n <= 324 is 8.2e-20, at 10**180. |
* For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947. |
* For 0 >= n >= -999, it is -1.55e-19 at 10**-435. |
*/ |
lexp = yy[E]; |
if (nexp == 0) |
{ |
k = 0; |
goto expdon; |
} |
esign = 1; |
if (nexp < 0) |
{ |
nexp = -nexp; |
esign = -1; |
if (nexp > 4096) |
{ /* Punt. Can't handle this without 2 divides. */ |
emovi (etens[0], tt); |
lexp -= tt[E]; |
k = edivm (tt, yy, ldp); |
lexp += EXONE; |
nexp -= 4096; |
} |
} |
p = &etens[NTEN][0]; |
emov (eone, xt); |
exp = 1; |
do |
{ |
if (exp & nexp) |
emul (p, xt, xt, ldp); |
p -= NE; |
exp = exp + exp; |
} |
while (exp <= MAXP); |
emovi (xt, tt); |
if (esign < 0) |
{ |
lexp -= tt[E]; |
k = edivm (tt, yy, ldp); |
lexp += EXONE; |
} |
else |
{ |
lexp += tt[E]; |
k = emulm (tt, yy, ldp); |
lexp -= EXONE - 1; |
} |
expdon: |
/* Round and convert directly to the destination type */ |
if (oprec == 53) |
lexp -= EXONE - 0x3ff; |
else if (oprec == 24) |
lexp -= EXONE - 0177; |
#ifdef DEC |
else if (oprec == 56) |
lexp -= EXONE - 0201; |
#endif |
ldp->rndprc = oprec; |
emdnorm (yy, k, 0, lexp, 64, ldp); |
aexit: |
ldp->rndprc = rndsav; |
yy[0] = nsign; |
switch (oprec) |
{ |
#ifdef DEC |
case 56: |
todec (yy, y); /* see etodec.c */ |
break; |
#endif |
#if LDBL_MANT_DIG == 53 |
case 53: |
toe53 (yy, y); |
break; |
#elif LDBL_MANT_DIG == 24 |
case 24: |
toe24 (yy, y); |
break; |
#elif LDBL_MANT_DIG == 64 |
case 64: |
toe64 (yy, y); |
break; |
#elif LDBL_MANT_DIG == 113 |
case 113: |
toe113 (yy, y); |
break; |
#else |
case NBITS: |
emovo (yy, y, ldp); |
break; |
#endif |
} |
lenldstr += s - lstr; |
if (mflag) |
free (lstr); |
return lenldstr; |
} |
#endif |
/* y = largest integer not greater than x |
* (truncated toward minus infinity) |
* |
* unsigned short x[NE], y[NE] |
* LDPARMS *ldp |
* |
* efloor( x, y, ldp ); |
*/ |
static _CONST unsigned short bmask[] = { |
0xffff, |
0xfffe, |
0xfffc, |
0xfff8, |
0xfff0, |
0xffe0, |
0xffc0, |
0xff80, |
0xff00, |
0xfe00, |
0xfc00, |
0xf800, |
0xf000, |
0xe000, |
0xc000, |
0x8000, |
0x0000, |
}; |
static void |
efloor (short unsigned int *x, short unsigned int *y, LDPARMS * ldp) |
{ |
register unsigned short *p; |
int e, expon, i; |
unsigned short f[NE]; |
emov (x, f); /* leave in external format */ |
expon = (int) f[NE - 1]; |
e = (expon & 0x7fff) - (EXONE - 1); |
if (e <= 0) |
{ |
eclear (y); |
goto isitneg; |
} |
/* number of bits to clear out */ |
e = NBITS - e; |
emov (f, y); |
if (e <= 0) |
return; |
p = &y[0]; |
while (e >= 16) |
{ |
*p++ = 0; |
e -= 16; |
} |
/* clear the remaining bits */ |
*p &= bmask[e]; |
/* truncate negatives toward minus infinity */ |
isitneg: |
if ((unsigned short) expon & (unsigned short) 0x8000) |
{ |
for (i = 0; i < NE - 1; i++) |
{ |
if (f[i] != y[i]) |
{ |
esub (eone, y, y, ldp); |
break; |
} |
} |
} |
} |
static void |
eiremain (short unsigned int *den, short unsigned int *num, LDPARMS * ldp) |
{ |
long ld, ln; |
unsigned short j; |
unsigned short *equot = ldp->equot; |
ld = den[E]; |
ld -= enormlz (den); |
ln = num[E]; |
ln -= enormlz (num); |
ecleaz (equot); |
while (ln >= ld) |
{ |
if (ecmpm (den, num) <= 0) |
{ |
esubm (den, num); |
j = 1; |
} |
else |
{ |
j = 0; |
} |
eshup1 (equot); |
equot[NI - 1] |= j; |
eshup1 (num); |
ln -= 1; |
} |
emdnorm (num, 0, 0, ln, 0, ldp); |
} |
/* NaN bit patterns |
*/ |
#ifdef MIEEE |
#if !defined(__mips) |
static _CONST unsigned short nan113[8] = { |
0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff |
}; |
static _CONST unsigned short nan64[6] = { |
0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff |
}; |
static _CONST unsigned short nan53[4] = { 0x7fff, 0xffff, 0xffff, 0xffff }; |
static _CONST unsigned short nan24[2] = { 0x7fff, 0xffff }; |
#elif defined(__mips_nan2008) /* __mips */ |
static _CONST unsigned short nan113[8] = { 0x7fff, 0x8000, 0, 0, 0, 0, 0, 0 }; |
static _CONST unsigned short nan64[6] = { 0x7fff, 0xc000, 0, 0, 0, 0 }; |
static _CONST unsigned short nan53[4] = { 0x7ff8, 0, 0, 0 }; |
static _CONST unsigned short nan24[2] = { 0x7fc0, 0 }; |
#else /* __mips && !__mips_nan2008 */ |
static _CONST unsigned short nan113[8] = { |
0x7fff, 0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff |
}; |
static _CONST unsigned short nan64[6] = { |
0x7fff, 0xbfff, 0xffff, 0xffff, 0xffff, 0xffff |
}; |
static _CONST unsigned short nan53[4] = { 0x7ff7, 0xffff, 0xffff, 0xffff }; |
static _CONST unsigned short nan24[2] = { 0x7fbf, 0xffff }; |
#endif /* __mips && !__mips_nan2008 */ |
#else /* !MIEEE */ |
#if !defined(__mips) || defined(__mips_nan2008) |
static _CONST unsigned short nan113[8] = { 0, 0, 0, 0, 0, 0, 0x8000, 0x7fff }; |
static _CONST unsigned short nan64[6] = { 0, 0, 0, 0, 0xc000, 0x7fff }; |
static _CONST unsigned short nan53[4] = { 0, 0, 0, 0x7ff8 }; |
static _CONST unsigned short nan24[2] = { 0, 0x7fc0 }; |
#else /* __mips && !__mips_nan2008 */ |
static _CONST unsigned short nan113[8] = { |
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff, 0x7fff |
}; |
static _CONST unsigned short nan64[6] = { |
0xffff, 0xffff, 0xffff, 0xffff, 0xbfff, 0x7fff |
}; |
static _CONST unsigned short nan53[4] = { 0xffff, 0xffff, 0xffff, 0x7ff7 }; |
static _CONST unsigned short nan24[2] = { 0xffff, 0x7fbf }; |
#endif /* __mips && !__mips_nan2008 */ |
#endif /* !MIEEE */ |
static void |
enan (short unsigned int *nan, int size) |
{ |
int i, n; |
_CONST unsigned short *p; |
switch (size) |
{ |
#ifndef DEC |
case 113: |
n = 8; |
p = nan113; |
break; |
case 64: |
n = 6; |
p = nan64; |
break; |
case 53: |
n = 4; |
p = nan53; |
break; |
case 24: |
n = 2; |
p = nan24; |
break; |
case NBITS: |
#if !defined(__mips) || defined(__mips_nan2008) |
for (i = 0; i < NE - 2; i++) |
*nan++ = 0; |
*nan++ = 0xc000; |
#else /* __mips && !__mips_nan2008 */ |
for (i = 0; i < NE - 2; i++) |
*nan++ = 0xffff; |
*nan++ = 0xbfff; |
#endif /* __mips && !__mips_nan2008 */ |
*nan++ = 0x7fff; |
return; |
case NI * 16: |
*nan++ = 0; |
*nan++ = 0x7fff; |
*nan++ = 0; |
#if !defined(__mips) || defined(__mips_nan2008) |
*nan++ = 0xc000; |
for (i = 4; i < NI - 1; i++) |
*nan++ = 0; |
#else /* __mips && !__mips_nan2008 */ |
*nan++ = 0xbfff; |
for (i = 4; i < NI - 1; i++) |
*nan++ = 0xffff; |
#endif /* __mips && !__mips_nan2008 */ |
*nan++ = 0; |
return; |
#endif |
default: |
mtherr ("enan", DOMAIN); |
return; |
} |
for (i = 0; i < n; i++) |
*nan++ = *p++; |
} |
/contrib/sdk/sources/newlib/libc/stdlib/mblen.c |
---|
0,0 → 1,81 |
/* |
FUNCTION |
<<mblen>>---minimal multibyte length function |
INDEX |
mblen |
ANSI_SYNOPSIS |
#include <stdlib.h> |
int mblen(const char *<[s]>, size_t <[n]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
int mblen(<[s]>, <[n]>) |
const char *<[s]>; |
size_t <[n]>; |
DESCRIPTION |
When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming |
implementation of <<mblen>>. In this case, the |
only ``multi-byte character sequences'' recognized are single bytes, |
and thus <<1>> is returned unless <[s]> is the null pointer or |
has a length of 0 or is the empty string. |
When _MB_CAPABLE is defined, this routine calls <<_mbtowc_r>> to perform |
the conversion, passing a state variable to allow state dependent |
decoding. The result is based on the locale setting which may |
be restricted to a defined set of locales. |
RETURNS |
This implementation of <<mblen>> returns <<0>> if |
<[s]> is <<NULL>> or the empty string; it returns <<1>> if not _MB_CAPABLE or |
the character is a single-byte character; it returns <<-1>> |
if the multi-byte character is invalid; otherwise it returns |
the number of bytes in the multibyte character. |
PORTABILITY |
<<mblen>> is required in the ANSI C standard. However, the precise |
effects vary with the locale. |
<<mblen>> requires no supporting OS subroutines. |
*/ |
#ifndef _REENT_ONLY |
#include <newlib.h> |
#include <stdlib.h> |
#include <wchar.h> |
#include "local.h" |
int |
_DEFUN (mblen, (s, n), |
const char *s _AND |
size_t n) |
{ |
#ifdef _MB_CAPABLE |
int retval = 0; |
struct _reent *reent = _REENT; |
mbstate_t *state; |
_REENT_CHECK_MISC(reent); |
state = &(_REENT_MBLEN_STATE(reent)); |
retval = __mbtowc (reent, NULL, s, n, __locale_charset (), state); |
if (retval < 0) |
{ |
state->__count = 0; |
return -1; |
} |
else |
return retval; |
#else /* not _MB_CAPABLE */ |
if (s == NULL || *s == '\0') |
return 0; |
if (n == 0) |
return -1; |
return 1; |
#endif /* not _MB_CAPABLE */ |
} |
#endif /* !_REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/mblen_r.c |
---|
0,0 → 1,77 |
/* |
FUNCTION |
<<_mblen_r>>---reentrant minimal multibyte length function |
INDEX |
_mblen_r |
ANSI_SYNOPSIS |
#include <stdlib.h> |
int _mblen_r(struct _reent *<[r]>, const char *<[s]>, size_t <[n]>, int *<[state]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
int _mblen_r(<[r]>, <[s]>, <[n]>, <[state]>) |
struct _reent *<[r]>; |
const char *<[s]>; |
size_t <[n]>; |
int *<[state]>; |
DESCRIPTION |
When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming |
implementation of <<_mblen_r>>. In this case, the |
only ``multi-byte character sequences'' recognized are single bytes, |
and thus <<1>> is returned unless <[s]> is the null pointer or |
has a length of 0 or is the empty string. |
When _MB_CAPABLE is defined, this routine calls <<_mbtowc_r>> to perform |
the conversion, passing a state variable to allow state dependent |
decoding. The result is based on the locale setting which may |
be restricted to a defined set of locales. |
RETURNS |
This implementation of <<_mblen_r>> returns <<0>> if |
<[s]> is <<NULL>> or the empty string; it returns <<1>> if not _MB_CAPABLE or |
the character is a single-byte character; it returns <<-1>> |
if the multi-byte character is invalid; otherwise it returns |
the number of bytes in the multibyte character. |
PORTABILITY |
<<_mblen>> is required in the ANSI C standard. However, the precise |
effects vary with the locale. |
<<_mblen_r>> requires no supporting OS subroutines. |
*/ |
#include <newlib.h> |
#include <stdlib.h> |
#include <wchar.h> |
#include "local.h" |
int |
_DEFUN (_mblen_r, (r, s, n, state), |
struct _reent *r _AND |
const char *s _AND |
size_t n _AND |
mbstate_t *state) |
{ |
#ifdef _MB_CAPABLE |
int retval; |
retval = __mbtowc (r, NULL, s, n, __locale_charset (), state); |
if (retval < 0) |
{ |
state->__count = 0; |
return -1; |
} |
return retval; |
#else /* not _MB_CAPABLE */ |
if (s == NULL || *s == '\0') |
return 0; |
if (n == 0) |
return -1; |
return 1; |
#endif /* not _MB_CAPABLE */ |
} |
/contrib/sdk/sources/newlib/libc/stdlib/mbrlen.c |
---|
0,0 → 1,22 |
#include <reent.h> |
#include <newlib.h> |
#include <wchar.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <errno.h> |
size_t |
mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps) |
{ |
#ifdef _MB_CAPABLE |
if (ps == NULL) |
{ |
struct _reent *reent = _REENT; |
_REENT_CHECK_MISC(reent); |
ps = &(_REENT_MBRLEN_STATE(reent)); |
} |
#endif |
return mbrtowc(NULL, s, n, ps); |
} |
/contrib/sdk/sources/newlib/libc/stdlib/mbsinit.c |
---|
0,0 → 1,14 |
#include <reent.h> |
#include <wchar.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <errno.h> |
int |
mbsinit(const mbstate_t *ps) |
{ |
if (ps == NULL || ps->__count == 0) |
return 1; |
else |
return 0; |
} |
/contrib/sdk/sources/newlib/libc/stdlib/mbsnrtowcs.c |
---|
0,0 → 1,182 |
/* |
FUNCTION |
<<mbsrtowcs>>, <<mbsnrtowcs>>---convert a character string to a wide-character string |
INDEX |
mbsrtowcs |
INDEX |
_mbsrtowcs_r |
INDEX |
mbsnrtowcs |
INDEX |
_mbsnrtowcs_r |
ANSI_SYNOPSIS |
#include <wchar.h> |
size_t mbsrtowcs(wchar_t *__restrict <[dst]>, |
const char **__restrict <[src]>, |
size_t <[len]>, |
mbstate_t *__restrict <[ps]>); |
#include <wchar.h> |
size_t _mbsrtowcs_r(struct _reent *<[ptr]>, wchar_t *<[dst]>, |
const char **<[src]>, size_t <[len]>, |
mbstate_t *<[ps]>); |
#include <wchar.h> |
size_t mbsnrtowcs(wchar_t *__ restrict <[dst]>, |
const char **__restrict <[src]>, size_t <[nms]>, |
size_t <[len]>, mbstate_t *__restrict <[ps]>); |
#include <wchar.h> |
size_t _mbsnrtowcs_r(struct _reent *<[ptr]>, wchar_t *<[dst]>, |
const char **<[src]>, size_t <[nms]>, |
size_t <[len]>, mbstate_t *<[ps]>); |
TRAD_SYNOPSIS |
#include <wchar.h> |
size_t mbsrtowcs(<[dst]>, <[src]>, <[len]>, <[ps]>) |
wchar_t *__restrict <[dst]>; |
const char **__restrict <[src]>; |
size_t <[len]>; |
mbstate_t *__restrict <[ps]>; |
#include <wchar.h> |
size_t _mbsrtowcs_r(<[ptr]>, <[dst]>, <[src]>, <[len]>, <[ps]>) |
struct _reent *<[ptr]>; |
wchar_t *<[dst]>; |
const char **<[src]>; |
size_t <[len]>; |
mbstate_t *<[ps]>; |
#include <wchar.h> |
size_t mbsnrtowcs(<[dst]>, <[src]>, <[nms]>, <[len]>, <[ps]>) |
wchar_t *__restrict <[dst]>; |
const char **__restrict <[src]>; |
size_t <[nms]>; |
size_t <[len]>; |
mbstate_t *__restrict <[ps]>; |
#include <wchar.h> |
size_t _mbsnrtowcs_r(<[ptr]>, <[dst]>, <[src]>, <[nms]>, <[len]>, <[ps]>) |
struct _reent *<[ptr]>; |
wchar_t *<[dst]>; |
const char **<[src]>; |
size_t <[nms]>; |
size_t <[len]>; |
mbstate_t *<[ps]>; |
DESCRIPTION |
The <<mbsrtowcs>> function converts a sequence of multibyte characters |
pointed to indirectly by <[src]> into a sequence of corresponding wide |
characters and stores at most <[len]> of them in the wchar_t array pointed |
to by <[dst]>, until it encounters a terminating null character ('\0'). |
If <[dst]> is NULL, no characters are stored. |
If <[dst]> is not NULL, the pointer pointed to by <[src]> is updated to point |
to the character after the one that conversion stopped at. If conversion |
stops because a null character is encountered, *<[src]> is set to NULL. |
The mbstate_t argument, <[ps]>, is used to keep track of the shift state. If |
it is NULL, <<mbsrtowcs>> uses an internal, static mbstate_t object, which |
is initialized to the initial conversion state at program startup. |
The <<mbsnrtowcs>> function behaves identically to <<mbsrtowcs>>, except that |
conversion stops after reading at most <[nms]> bytes from the buffer pointed |
to by <[src]>. |
RETURNS |
The <<mbsrtowcs>> and <<mbsnrtowcs>> functions return the number of wide |
characters stored in the array pointed to by <[dst]> if successful, otherwise |
it returns (size_t)-1. |
PORTABILITY |
<<mbsrtowcs>> is defined by the C99 standard. |
<<mbsnrtowcs>> is defined by the POSIX.1-2008 standard. |
*/ |
#include <reent.h> |
#include <newlib.h> |
#include <wchar.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <errno.h> |
size_t |
_DEFUN (_mbsnrtowcs_r, (r, dst, src, nms, len, ps), |
struct _reent *r _AND |
wchar_t *dst _AND |
const char **src _AND |
size_t nms _AND |
size_t len _AND |
mbstate_t *ps) |
{ |
wchar_t *ptr = dst; |
const char *tmp_src; |
size_t max; |
size_t count = 0; |
int bytes; |
#ifdef _MB_CAPABLE |
if (ps == NULL) |
{ |
_REENT_CHECK_MISC(r); |
ps = &(_REENT_MBSRTOWCS_STATE(r)); |
} |
#endif |
if (dst == NULL) |
{ |
/* Ignore original len value and do not alter src pointer if the |
dst pointer is NULL. */ |
len = (size_t)-1; |
tmp_src = *src; |
src = &tmp_src; |
} |
max = len; |
while (len > 0) |
{ |
bytes = _mbrtowc_r (r, ptr, *src, nms, ps); |
if (bytes > 0) |
{ |
*src += bytes; |
nms -= bytes; |
++count; |
ptr = (dst == NULL) ? NULL : ptr + 1; |
--len; |
} |
else if (bytes == -2) |
{ |
*src += nms; |
return count; |
} |
else if (bytes == 0) |
{ |
*src = NULL; |
return count; |
} |
else |
{ |
ps->__count = 0; |
r->_errno = EILSEQ; |
return (size_t)-1; |
} |
} |
return (size_t)max; |
} |
#ifndef _REENT_ONLY |
size_t |
_DEFUN (mbsnrtowcs, (dst, src, nms, len, ps), |
wchar_t *__restrict dst _AND |
const char **__restrict src _AND |
size_t nms _AND |
size_t len _AND |
mbstate_t *__restrict ps) |
{ |
return _mbsnrtowcs_r (_REENT, dst, src, nms, len, ps); |
} |
#endif /* !_REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/mbsrtowcs.c |
---|
0,0 → 1,31 |
/* doc in mbsnrtowcs.c */ |
#include <reent.h> |
#include <newlib.h> |
#include <wchar.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <errno.h> |
size_t |
_DEFUN (_mbsrtowcs_r, (r, dst, src, len, ps), |
struct _reent *r _AND |
wchar_t *dst _AND |
const char **src _AND |
size_t len _AND |
mbstate_t *ps) |
{ |
return _mbsnrtowcs_r (r, dst, src, (size_t) -1, len, ps); |
} |
#ifndef _REENT_ONLY |
size_t |
_DEFUN (mbsrtowcs, (dst, src, len, ps), |
wchar_t *__restrict dst _AND |
const char **__restrict src _AND |
size_t len _AND |
mbstate_t *__restrict ps) |
{ |
return _mbsnrtowcs_r (_REENT, dst, src, (size_t) -1, len, ps); |
} |
#endif /* !_REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs.c |
---|
0,0 → 1,83 |
/* |
FUNCTION |
<<mbstowcs>>---minimal multibyte string to wide char converter |
INDEX |
mbstowcs |
ANSI_SYNOPSIS |
#include <stdlib.h> |
int mbstowcs(wchar_t *restrict <[pwc]>, const char *restrict <[s]>, size_t <[n]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
int mbstowcs(<[pwc]>, <[s]>, <[n]>) |
wchar_t *<[pwc]>; |
const char *<[s]>; |
size_t <[n]>; |
DESCRIPTION |
When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming |
implementation of <<mbstowcs>>. In this case, the |
only ``multi-byte character sequences'' recognized are single bytes, |
and they are ``converted'' to wide-char versions simply by byte |
extension. |
When _MB_CAPABLE is defined, this routine calls <<_mbstowcs_r>> to perform |
the conversion, passing a state variable to allow state dependent |
decoding. The result is based on the locale setting which may |
be restricted to a defined set of locales. |
RETURNS |
This implementation of <<mbstowcs>> returns <<0>> if |
<[s]> is <<NULL>> or is the empty string; |
it returns <<-1>> if _MB_CAPABLE and one of the |
multi-byte characters is invalid or incomplete; |
otherwise it returns the minimum of: <<n>> or the |
number of multi-byte characters in <<s>> plus 1 (to |
compensate for the nul character). |
If the return value is -1, the state of the <<pwc>> string is |
indeterminate. If the input has a length of 0, the output |
string will be modified to contain a wchar_t nul terminator. |
PORTABILITY |
<<mbstowcs>> is required in the ANSI C standard. However, the precise |
effects vary with the locale. |
<<mbstowcs>> requires no supporting OS subroutines. |
*/ |
#ifndef _REENT_ONLY |
#include <newlib.h> |
#include <stdlib.h> |
#include <wchar.h> |
size_t |
_DEFUN (mbstowcs, (pwcs, s, n), |
wchar_t *__restrict pwcs _AND |
const char *__restrict s _AND |
size_t n) |
{ |
#ifdef _MB_CAPABLE |
mbstate_t state; |
state.__count = 0; |
return _mbstowcs_r (_REENT, pwcs, s, n, &state); |
#else /* not _MB_CAPABLE */ |
int count = 0; |
if (n != 0) { |
do { |
if ((*pwcs++ = (wchar_t) *s++) == 0) |
break; |
count++; |
} while (--n != 0); |
} |
return count; |
#endif /* not _MB_CAPABLE */ |
} |
#endif /* !_REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/mbstowcs_r.c |
---|
0,0 → 1,38 |
#include <stdlib.h> |
#include <wchar.h> |
#include "local.h" |
size_t |
_DEFUN (_mbstowcs_r, (reent, pwcs, s, n, state), |
struct _reent *r _AND |
wchar_t *__restrict pwcs _AND |
const char *__restrict s _AND |
size_t n _AND |
mbstate_t *state) |
{ |
size_t ret = 0; |
char *t = (char *)s; |
int bytes; |
if (!pwcs) |
n = (size_t) 1; /* Value doesn't matter as long as it's not 0. */ |
while (n > 0) |
{ |
bytes = __mbtowc (r, pwcs, t, MB_CUR_MAX, __locale_charset (), state); |
if (bytes < 0) |
{ |
state->__count = 0; |
return -1; |
} |
else if (bytes == 0) |
break; |
t += bytes; |
++ret; |
if (pwcs) |
{ |
++pwcs; |
--n; |
} |
} |
return ret; |
} |
/contrib/sdk/sources/newlib/libc/stdlib/random.c |
---|
0,0 → 1,82 |
/* |
FUNCTION |
<<random>>, <<srandom>>---pseudo-random numbers |
INDEX |
random |
INDEX |
srandom |
ANSI_SYNOPSIS |
#define _XOPEN_SOURCE 500 |
#include <stdlib.h> |
long int random(void); |
void srandom(unsigned int <[seed]>); |
DESCRIPTION |
<<random>> returns a different integer each time it is called; each |
integer is chosen by an algorithm designed to be unpredictable, so |
that you can use <<random>> when you require a random number. |
The algorithm depends on a static variable called the ``random seed''; |
starting with a given value of the random seed always produces the |
same sequence of numbers in successive calls to <<random>>. |
You can set the random seed using <<srandom>>; it does nothing beyond |
storing its argument in the static variable used by <<rand>>. You can |
exploit this to make the pseudo-random sequence less predictable, if |
you wish, by using some other unpredictable value (often the least |
significant parts of a time-varying value) as the random seed before |
beginning a sequence of calls to <<rand>>; or, if you wish to ensure |
(for example, while debugging) that successive runs of your program |
use the same ``random'' numbers, you can use <<srandom>> to set the same |
random seed at the outset. |
RETURNS |
<<random>> returns the next pseudo-random integer in sequence; it is a |
number between <<0>> and <<RAND_MAX>> (inclusive). |
<<srandom>> does not return a result. |
NOTES |
<<random>> and <<srandom>> are unsafe for multi-threaded applications. |
_XOPEN_SOURCE may be any value >= 500. |
PORTABILITY |
<<random>> is required by XSI. This implementation uses the same |
algorithm as <<rand>>. |
<<random>> requires no supporting OS subroutines. |
*/ |
#ifndef _REENT_ONLY |
#include <stdlib.h> |
#include <reent.h> |
void |
_DEFUN (srandom, (seed), unsigned int seed) |
{ |
struct _reent *reent = _REENT; |
_REENT_CHECK_RAND48(reent); |
_REENT_RAND_NEXT(reent) = seed; |
} |
long int |
_DEFUN_VOID (random) |
{ |
struct _reent *reent = _REENT; |
/* This multiplier was obtained from Knuth, D.E., "The Art of |
Computer Programming," Vol 2, Seminumerical Algorithms, Third |
Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */ |
_REENT_CHECK_RAND48(reent); |
_REENT_RAND_NEXT(reent) = |
_REENT_RAND_NEXT(reent) * __extension__ 6364136223846793005LL + 1; |
return (long int)((_REENT_RAND_NEXT(reent) >> 32) & RAND_MAX); |
} |
#endif /* _REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/wcsnrtombs.c |
---|
0,0 → 1,188 |
/* |
FUNCTION |
<<wcsrtombs>>, <<wcsnrtombs>>---convert a wide-character string to a character string |
INDEX |
wcsrtombs |
INDEX |
_wcsrtombs_r |
INDEX |
wcsnrtombs |
INDEX |
_wcsnrtombs_r |
ANSI_SYNOPSIS |
#include <wchar.h> |
size_t wcsrtombs(char *__restrict <[dst]>, |
const wchar_t **__restrict <[src]>, size_t <[len]>, |
mbstate_t *__restrict <[ps]>); |
#include <wchar.h> |
size_t _wcsrtombs_r(struct _reent *<[ptr]>, char *<[dst]>, |
const wchar_t **<[src]>, size_t <[len]>, |
mbstate_t *<[ps]>); |
#include <wchar.h> |
size_t wcsnrtombs(char *__restrict <[dst]>, |
const wchar_t **__restrict <[src]>, |
size_t <[nwc]>, size_t <[len]>, |
mbstate_t *__restrict <[ps]>); |
#include <wchar.h> |
size_t _wcsnrtombs_r(struct _reent *<[ptr]>, char *<[dst]>, |
const wchar_t **<[src]>, size_t <[nwc]>, |
size_t <[len]>, mbstate_t *<[ps]>); |
TRAD_SYNOPSIS |
#include <wchar.h> |
size_t wcsrtombs(<[dst]>, <[src]>, <[len]>, <[ps]>) |
char *__restrict <[dst]>; |
const wchar_t **__restrict <[src]>; |
size_t <[len]>; |
mbstate_t *__restrict <[ps]>; |
#include <wchar.h> |
size_t _wcsrtombs_r(<[ptr]>, <[dst]>, <[src]>, <[len]>, <[ps]>) |
struct _rent *<[ptr]>; |
char *<[dst]>; |
const wchar_t **<[src]>; |
size_t <[len]>; |
mbstate_t *<[ps]>; |
#include <wchar.h> |
size_t wcsnrtombs(<[dst]>, <[src]>, <[nwc]>, <[len]>, <[ps]>) |
char *__restrict <[dst]>; |
const wchar_t **__restrict <[src]>; |
size_t <[nwc]>; |
size_t <[len]>; |
mbstate_t *__restrict <[ps]>; |
#include <wchar.h> |
size_t _wcsnrtombs_r(<[ptr]>, <[dst]>, <[src]>, <[nwc]>, <[len]>, <[ps]>) |
struct _rent *<[ptr]>; |
char *<[dst]>; |
const wchar_t **<[src]>; |
size_t <[nwc]>; |
size_t <[len]>; |
mbstate_t *<[ps]>; |
DESCRIPTION |
The <<wcsrtombs>> function converts a string of wide characters indirectly |
pointed to by <[src]> to a corresponding multibyte character string stored in |
the array pointed to by <[dst]>. No more than <[len]> bytes are written to |
<[dst]>. |
If <[dst]> is NULL, no characters are stored. |
If <[dst]> is not NULL, the pointer pointed to by <[src]> is updated to point |
to the character after the one that conversion stopped at. If conversion |
stops because a null character is encountered, *<[src]> is set to NULL. |
The mbstate_t argument, <[ps]>, is used to keep track of the shift state. If |
it is NULL, <<wcsrtombs>> uses an internal, static mbstate_t object, which |
is initialized to the initial conversion state at program startup. |
The <<wcsnrtombs>> function behaves identically to <<wcsrtombs>>, except that |
conversion stops after reading at most <[nwc]> characters from the buffer |
pointed to by <[src]>. |
RETURNS |
The <<wcsrtombs>> and <<wcsnrtombs>> functions return the number of bytes |
stored in the array pointed to by <[dst]> (not including any terminating |
null), if successful, otherwise it returns (size_t)-1. |
PORTABILITY |
<<wcsrtombs>> is defined by C99 standard. |
<<wcsnrtombs>> is defined by the POSIX.1-2008 standard. |
*/ |
#include <reent.h> |
#include <newlib.h> |
#include <wchar.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <errno.h> |
#include "local.h" |
size_t |
_DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps), |
struct _reent *r _AND |
char *dst _AND |
const wchar_t **src _AND |
size_t nwc _AND |
size_t len _AND |
mbstate_t *ps) |
{ |
char *ptr = dst; |
char buff[10]; |
wchar_t *pwcs; |
size_t n; |
int i; |
#ifdef _MB_CAPABLE |
if (ps == NULL) |
{ |
_REENT_CHECK_MISC(r); |
ps = &(_REENT_WCSRTOMBS_STATE(r)); |
} |
#endif |
/* If no dst pointer, treat len as maximum possible value. */ |
if (dst == NULL) |
len = (size_t)-1; |
n = 0; |
pwcs = (wchar_t *)(*src); |
while (n < len && nwc-- > 0) |
{ |
int count = ps->__count; |
wint_t wch = ps->__value.__wch; |
int bytes = __wctomb (r, buff, *pwcs, __locale_charset (), ps); |
if (bytes == -1) |
{ |
r->_errno = EILSEQ; |
ps->__count = 0; |
return (size_t)-1; |
} |
if (n + bytes <= len) |
{ |
n += bytes; |
if (dst) |
{ |
for (i = 0; i < bytes; ++i) |
*ptr++ = buff[i]; |
++(*src); |
} |
if (*pwcs++ == 0x00) |
{ |
if (dst) |
*src = NULL; |
ps->__count = 0; |
return n - 1; |
} |
} |
else |
{ |
/* not enough room, we must back up state to before __wctomb call */ |
ps->__count = count; |
ps->__value.__wch = wch; |
len = 0; |
} |
} |
return n; |
} |
#ifndef _REENT_ONLY |
size_t |
_DEFUN (wcsnrtombs, (dst, src, nwc, len, ps), |
char *__restrict dst _AND |
const wchar_t **__restrict src _AND |
size_t nwc _AND |
size_t len _AND |
mbstate_t *__restrict ps) |
{ |
return _wcsnrtombs_r (_REENT, dst, src, nwc, len, ps); |
} |
#endif /* !_REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/wcsrtombs.c |
---|
0,0 → 1,28 |
/* Doc in wcsnrtombs.c */ |
#include <reent.h> |
#include <newlib.h> |
#include <wchar.h> |
size_t |
_DEFUN (_wcsrtombs_r, (r, dst, src, len, ps), |
struct _reent *r _AND |
char *dst _AND |
const wchar_t **src _AND |
size_t len _AND |
mbstate_t *ps) |
{ |
return _wcsnrtombs_r (r, dst, src, (size_t) -1, len, ps); |
} |
#ifndef _REENT_ONLY |
size_t |
_DEFUN (wcsrtombs, (dst, src, len, ps), |
char *__restrict dst _AND |
const wchar_t **__restrict src _AND |
size_t len _AND |
mbstate_t *__restrict ps) |
{ |
return _wcsnrtombs_r (_REENT, dst, src, (size_t) -1, len, ps); |
} |
#endif /* !_REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/wcstod.c |
---|
0,0 → 1,232 |
/* |
FUNCTION |
<<wcstod>>, <<wcstof>>---wide char string to double or float |
INDEX |
wcstod |
INDEX |
_wcstod_r |
INDEX |
wcstof |
INDEX |
_wcstof_r |
ANSI_SYNOPSIS |
#include <stdlib.h> |
double wcstod(const wchar_t *__restrict <[str]>, |
wchar_t **__restrict <[tail]>); |
float wcstof(const wchar_t *__restrict <[str]>, |
wchar_t **__restrict <[tail]>); |
double _wcstod_r(void *<[reent]>, |
const wchar_t *<[str]>, wchar_t **<[tail]>); |
float _wcstof_r(void *<[reent]>, |
const wchar_t *<[str]>, wchar_t **<[tail]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
double wcstod(<[str]>,<[tail]>) |
wchar_t *__restrict <[str]>; |
wchar_t **__restrict <[tail]>; |
float wcstof(<[str]>,<[tail]>) |
wchar_t *__restrict <[str]>; |
wchar_t **__restrict <[tail]>; |
double _wcstod_r(<[reent]>,<[str]>,<[tail]>) |
wchar_t *<[reent]>; |
wchar_t *<[str]>; |
wchar_t **<[tail]>; |
float _wcstof_r(<[reent]>,<[str]>,<[tail]>) |
wchar_t *<[reent]>; |
wchar_t *<[str]>; |
wchar_t **<[tail]>; |
DESCRIPTION |
The function <<wcstod>> parses the wide character string <[str]>, |
producing a substring which can be converted to a double |
value. The substring converted is the longest initial |
subsequence of <[str]>, beginning with the first |
non-whitespace character, that has one of these formats: |
.[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>] |
.[+|-].<[digits]>[(e|E)[+|-]<[digits]>] |
.[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)] |
.[+|-](n|N)(a|A)(n|N)[<(>[<[hexdigits]>]<)>] |
.[+|-]0(x|X)<[hexdigits]>[.[<[hexdigits]>]][(p|P)[+|-]<[digits]>] |
.[+|-]0(x|X).<[hexdigits]>[(p|P)[+|-]<[digits]>] |
The substring contains no characters if <[str]> is empty, consists |
entirely of whitespace, or if the first non-whitespace |
character is something other than <<+>>, <<->>, <<.>>, or a |
digit, and cannot be parsed as infinity or NaN. If the platform |
does not support NaN, then NaN is treated as an empty substring. |
If the substring is empty, no conversion is done, and |
the value of <[str]> is stored in <<*<[tail]>>>. Otherwise, |
the substring is converted, and a pointer to the final string |
(which will contain at least the terminating null character of |
<[str]>) is stored in <<*<[tail]>>>. If you want no |
assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>. |
<<wcstof>> is identical to <<wcstod>> except for its return type. |
This implementation returns the nearest machine number to the |
input decimal string. Ties are broken by using the IEEE |
round-even rule. However, <<wcstof>> is currently subject to |
double rounding errors. |
The alternate functions <<_wcstod_r>> and <<_wcstof_r>> are |
reentrant versions of <<wcstod>> and <<wcstof>>, respectively. |
The extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
Return the converted substring value, if any. If |
no conversion could be performed, 0 is returned. If the |
correct value is out of the range of representable values, |
plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is |
stored in errno. If the correct value would cause underflow, 0 |
is returned and <<ERANGE>> is stored in errno. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
/*- |
* Copyright (c) 2002 Tim J. Robbins |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <string.h> |
#include <wchar.h> |
#include <wctype.h> |
#include <locale.h> |
#include <math.h> |
double |
_DEFUN (_wcstod_r, (ptr, nptr, endptr), |
struct _reent *ptr _AND |
_CONST wchar_t *nptr _AND |
wchar_t **endptr) |
{ |
static const mbstate_t initial; |
mbstate_t mbs; |
double val; |
char *buf, *end; |
const wchar_t *wcp; |
size_t len; |
while (iswspace(*nptr)) |
nptr++; |
/* |
* Convert the supplied numeric wide char. string to multibyte. |
* |
* We could attempt to find the end of the numeric portion of the |
* wide char. string to avoid converting unneeded characters but |
* choose not to bother; optimising the uncommon case where |
* the input string contains a lot of text after the number |
* duplicates a lot of strtod()'s functionality and slows down the |
* most common cases. |
*/ |
wcp = nptr; |
mbs = initial; |
if ((len = _wcsrtombs_r(ptr, NULL, &wcp, 0, &mbs)) == (size_t)-1) { |
if (endptr != NULL) |
*endptr = (wchar_t *)nptr; |
return (0.0); |
} |
if ((buf = _malloc_r(ptr, len + 1)) == NULL) |
return (0.0); |
mbs = initial; |
_wcsrtombs_r(ptr, buf, &wcp, len + 1, &mbs); |
/* Let strtod() do most of the work for us. */ |
val = _strtod_r(ptr, buf, &end); |
/* |
* We only know where the number ended in the _multibyte_ |
* representation of the string. If the caller wants to know |
* where it ended, count multibyte characters to find the |
* corresponding position in the wide char string. |
*/ |
if (endptr != NULL) { |
/* The only valid multibyte char in a float converted by |
strtod/wcstod is the radix char. What we do here is, |
figure out if the radix char was in the valid leading |
float sequence in the incoming string. If so, the |
multibyte float string is strlen(radix char) - 1 bytes |
longer than the incoming wide char string has characters. |
To fix endptr, reposition end as if the radix char was |
just one byte long. The resulting difference (end - buf) |
is then equivalent to the number of valid wide characters |
in the input string. */ |
len = strlen (_localeconv_r (ptr)->decimal_point); |
if (len > 1) { |
char *d = strstr (buf, |
_localeconv_r (ptr)->decimal_point); |
if (d && d < end) |
end -= len - 1; |
} |
*endptr = (wchar_t *)nptr + (end - buf); |
} |
_free_r(ptr, buf); |
return (val); |
} |
float |
_DEFUN (_wcstof_r, (ptr, nptr, endptr), |
struct _reent *ptr _AND |
_CONST wchar_t *nptr _AND |
wchar_t **endptr) |
{ |
double retval = _wcstod_r (ptr, nptr, endptr); |
if (isnan (retval)) |
return nanf (NULL); |
return (float)retval; |
} |
#ifndef _REENT_ONLY |
double |
_DEFUN (wcstod, (nptr, endptr), |
_CONST wchar_t *__restrict nptr _AND wchar_t **__restrict endptr) |
{ |
return _wcstod_r (_REENT, nptr, endptr); |
} |
float |
_DEFUN (wcstof, (nptr, endptr), |
_CONST wchar_t *__restrict nptr _AND |
wchar_t **__restrict endptr) |
{ |
double retval = _wcstod_r (_REENT, nptr, endptr); |
if (isnan (retval)) |
return nanf (NULL); |
return (float)retval; |
} |
#endif |
/contrib/sdk/sources/newlib/libc/stdlib/wcstol.c |
---|
0,0 → 1,227 |
/* |
FUNCTION |
<<wcstol>>---wide string to long |
INDEX |
wcstol |
INDEX |
_wcstol_r |
ANSI_SYNOPSIS |
#include <wchar.h> |
long wcstol(const wchar_t *__restrict <[s]>, |
wchar_t **__restrict <[ptr]>,int <[base]>); |
long _wcstol_r(void *<[reent]>, |
const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
long wcstol (<[s]>, <[ptr]>, <[base]>) |
wchar_t *__restrict <[s]>; |
wchar_t **__restrict <[ptr]>; |
int <[base]>; |
long _wcstol_r (<[reent]>, <[s]>, <[ptr]>, <[base]>) |
struct _reent *<[reent]>; |
wchar_t *<[s]>; |
wchar_t **<[ptr]>; |
int <[base]>; |
DESCRIPTION |
The function <<wcstol>> converts the wide string <<*<[s]>>> to |
a <<long>>. First, it breaks down the string into three parts: |
leading whitespace, which is ignored; a subject string consisting |
of characters resembling an integer in the radix specified by <[base]>; |
and a trailing portion consisting of zero or more unparseable characters, |
and always including the terminating null character. Then, it attempts |
to convert the subject string into a <<long>> and returns the |
result. |
If the value of <[base]> is 0, the subject string is expected to look |
like a normal C integer constant: an optional sign, a possible `<<0x>>' |
indicating a hexadecimal base, and a number. If <[base]> is between |
2 and 36, the expected form of the subject is a sequence of letters |
and digits representing an integer in the radix specified by <[base]>, |
with an optional plus or minus sign. The letters <<a>>--<<z>> (or, |
equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35; |
only letters whose ascribed values are less than <[base]> are |
permitted. If <[base]> is 16, a leading <<0x>> is permitted. |
The subject sequence is the longest initial sequence of the input |
string that has the expected form, starting with the first |
non-whitespace character. If the string is empty or consists entirely |
of whitespace, or if the first non-whitespace character is not a |
permissible letter or digit, the subject string is empty. |
If the subject string is acceptable, and the value of <[base]> is zero, |
<<wcstol>> attempts to determine the radix from the input string. A |
string with a leading <<0x>> is treated as a hexadecimal value; a string with |
a leading 0 and no <<x>> is treated as octal; all other strings are |
treated as decimal. If <[base]> is between 2 and 36, it is used as the |
conversion radix, as described above. If the subject string begins with |
a minus sign, the value is negated. Finally, a pointer to the first |
character past the converted subject string is stored in <[ptr]>, if |
<[ptr]> is not <<NULL>>. |
If the subject string is empty (or not in acceptable form), no conversion |
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is |
not <<NULL>>). |
The alternate function <<_wcstol_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<wcstol>> returns the converted value, if any. If no conversion was |
made, 0 is returned. |
<<wcstol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of |
the converted value is too large, and sets <<errno>> to <<ERANGE>>. |
PORTABILITY |
<<wcstol>> is ANSI. |
No supporting OS subroutines are required. |
*/ |
/*- |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <limits.h> |
#include <wctype.h> |
#include <errno.h> |
#include <wchar.h> |
#include <reent.h> |
/* |
* Convert a wide string to a long integer. |
* |
* Ignores `locale' stuff. Assumes that the upper and lower case |
* alphabets and digits are each contiguous. |
*/ |
long |
_DEFUN (_wcstol_r, (rptr, nptr, endptr, base), |
struct _reent *rptr _AND |
_CONST wchar_t *nptr _AND |
wchar_t **endptr _AND |
int base) |
{ |
register const wchar_t *s = nptr; |
register unsigned long acc; |
register int c; |
register unsigned long cutoff; |
register int neg = 0, any, cutlim; |
/* |
* Skip white space and pick up leading +/- sign if any. |
* If base is 0, allow 0x for hex and 0 for octal, else |
* assume decimal; if base is already 16, allow 0x. |
*/ |
do { |
c = *s++; |
} while (iswspace(c)); |
if (c == L'-') { |
neg = 1; |
c = *s++; |
} else if (c == L'+') |
c = *s++; |
if ((base == 0 || base == 16) && |
c == L'0' && (*s == L'x' || *s == L'X')) { |
c = s[1]; |
s += 2; |
base = 16; |
} |
if (base == 0) |
base = c == L'0' ? 8 : 10; |
/* |
* Compute the cutoff value between legal numbers and illegal |
* numbers. That is the largest legal value, divided by the |
* base. An input number that is greater than this value, if |
* followed by a legal input character, is too big. One that |
* is equal to this value may be valid or not; the limit |
* between valid and invalid numbers is then based on the last |
* digit. For instance, if the range for longs is |
* [-2147483648..2147483647] and the input base is 10, |
* cutoff will be set to 214748364 and cutlim to either |
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated |
* a value > 214748364, or equal but the next digit is > 7 (or 8), |
* the number is too big, and we will return a range error. |
* |
* Set any if any `digits' consumed; make it negative to indicate |
* overflow. |
*/ |
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; |
cutlim = cutoff % (unsigned long)base; |
cutoff /= (unsigned long)base; |
for (acc = 0, any = 0;; c = *s++) { |
if (iswdigit(c)) |
c -= L'0'; |
else if (iswalpha(c)) |
c -= iswupper(c) ? L'A' - 10 : L'a' - 10; |
else |
break; |
if (c >= base) |
break; |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) |
any = -1; |
else { |
any = 1; |
acc *= base; |
acc += c; |
} |
} |
if (any < 0) { |
acc = neg ? LONG_MIN : LONG_MAX; |
rptr->_errno = ERANGE; |
} else if (neg) |
acc = -acc; |
if (endptr != 0) |
*endptr = (wchar_t *) (any ? s - 1 : nptr); |
return (acc); |
} |
#ifndef _REENT_ONLY |
long |
_DEFUN (wcstol, (s, ptr, base), |
_CONST wchar_t *__restrict s _AND |
wchar_t **__restrict ptr _AND |
int base) |
{ |
return _wcstol_r (_REENT, s, ptr, base); |
} |
#endif |
/contrib/sdk/sources/newlib/libc/stdlib/wcstold.c |
---|
0,0 → 1,108 |
/* |
(C) Copyright IBM Corp. 2009 |
All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions are met: |
* Redistributions of source code must retain the above copyright notice, |
this list of conditions and the following disclaimer. |
* Redistributions in binary form must reproduce the above copyright |
notice, this list of conditions and the following disclaimer in the |
documentation and/or other materials provided with the distribution. |
* Neither the name of IBM nor the names of its contributors may be |
used to endorse or promote products derived from this software without |
specific prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdlib.h> |
#include <string.h> |
#include <wchar.h> |
#include <wctype.h> |
#include <locale.h> |
#include "local.h" |
long double |
wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr) |
{ |
#ifdef _LDBL_EQ_DBL |
/* On platforms where long double is as wide as double. */ |
return wcstod(nptr, endptr); |
#else /* This is a duplicate of the code in wcstod.c, but converted to long double. */ |
static const mbstate_t initial; |
mbstate_t mbs; |
long double val; |
char *buf, *end; |
const wchar_t *wcp; |
size_t len; |
while (iswspace (*nptr)) |
nptr++; |
/* Convert the supplied numeric wide char string to multibyte. */ |
wcp = nptr; |
mbs = initial; |
if ((len = wcsrtombs (NULL, &wcp, 0, &mbs)) == (size_t)-1) |
{ |
if (endptr != NULL) |
*endptr = (wchar_t *) nptr; |
return 0.0L; |
} |
if ((buf = malloc (len + 1)) == NULL) |
return 0.0L; |
mbs = initial; |
wcsrtombs (buf, &wcp, len + 1, &mbs); |
val = strtold (buf, &end); |
/* We only know where the number ended in the _multibyte_ |
representation of the string. If the caller wants to know |
where it ended, count multibyte characters to find the |
corresponding position in the wide char string. */ |
if (endptr != NULL) |
{ |
/* The only valid multibyte char in a float converted by |
strtold/wcstold is the radix char. What we do here is, |
figure out if the radix char was in the valid leading |
float sequence in the incoming string. If so, the |
multibyte float string is strlen (radix char) - 1 bytes |
longer than the incoming wide char string has characters. |
To fix endptr, reposition end as if the radix char was |
just one byte long. The resulting difference (end - buf) |
is then equivalent to the number of valid wide characters |
in the input string. */ |
len = strlen (localeconv ()->decimal_point); |
if (len > 1) |
{ |
char *d = strstr (buf, localeconv ()->decimal_point); |
if (d && d < end) |
end -= len - 1; |
} |
*endptr = (wchar_t *) nptr + (end - buf); |
} |
free (buf); |
return val; |
#endif /* _LDBL_EQ_DBL */ |
} |
/contrib/sdk/sources/newlib/libc/stdlib/wcstoll.c |
---|
0,0 → 1,139 |
/* |
FUNCTION |
<<wcstoll>>---wide string to long long |
INDEX |
wcstoll |
INDEX |
_wcstoll_r |
ANSI_SYNOPSIS |
#include <wchar.h> |
long long wcstoll(const wchar_t *__restrict <[s]>, |
wchar_t **__restrict <[ptr]>,int <[base]>); |
long long _wcstoll_r(void *<[reent]>, |
const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
long long wcstoll (<[s]>, <[ptr]>, <[base]>) |
const wchar_t *__restrict <[s]>; |
wchar_t **__restrict <[ptr]>; |
int <[base]>; |
long long _wcstoll_r (<[reent]>, <[s]>, <[ptr]>, <[base]>) |
wchar_t *<[reent]>; |
const wchar_t *<[s]>; |
wchar_t **<[ptr]>; |
int <[base]>; |
DESCRIPTION |
The function <<wcstoll>> converts the wide string <<*<[s]>>> to |
a <<long long>>. First, it breaks down the string into three parts: |
leading whitespace, which is ignored; a subject string consisting |
of characters resembling an integer in the radix specified by <[base]>; |
and a trailing portion consisting of zero or more unparseable characters, |
and always including the terminating null character. Then, it attempts |
to convert the subject string into a <<long long>> and returns the |
result. |
If the value of <[base]> is 0, the subject string is expected to look |
like a normal C integer constant: an optional sign, a possible `<<0x>>' |
indicating a hexadecimal base, and a number. If <[base]> is between |
2 and 36, the expected form of the subject is a sequence of letters |
and digits representing an integer in the radix specified by <[base]>, |
with an optional plus or minus sign. The letters <<a>>--<<z>> (or, |
equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35; |
only letters whose ascribed values are less than <[base]> are |
permitted. If <[base]> is 16, a leading <<0x>> is permitted. |
The subject sequence is the longest initial sequence of the input |
string that has the expected form, starting with the first |
non-whitespace character. If the string is empty or consists entirely |
of whitespace, or if the first non-whitespace character is not a |
permissible letter or digit, the subject string is empty. |
If the subject string is acceptable, and the value of <[base]> is zero, |
<<wcstoll>> attempts to determine the radix from the input string. A |
string with a leading <<0x>> is treated as a hexadecimal value; a string with |
a leading 0 and no <<x>> is treated as octal; all other strings are |
treated as decimal. If <[base]> is between 2 and 36, it is used as the |
conversion radix, as described above. If the subject string begins with |
a minus sign, the value is negated. Finally, a pointer to the first |
character past the converted subject string is stored in <[ptr]>, if |
<[ptr]> is not <<NULL>>. |
If the subject string is empty (or not in acceptable form), no conversion |
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is |
not <<NULL>>). |
The alternate function <<_wcstoll_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<wcstoll>> returns the converted value, if any. If no conversion was |
made, 0 is returned. |
<<wcstoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of |
the converted value is too large, and sets <<errno>> to <<ERANGE>>. |
PORTABILITY |
<<wcstoll>> is ANSI. |
No supporting OS subroutines are required. |
*/ |
/*- |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <limits.h> |
#include <wctype.h> |
#include <errno.h> |
#include <wchar.h> |
#include <reent.h> |
#ifndef _REENT_ONLY |
long long |
_DEFUN (wcstoll, (s, ptr, base), |
_CONST wchar_t *__restrict s _AND |
wchar_t **__restrict ptr _AND |
int base) |
{ |
return _wcstoll_r (_REENT, s, ptr, base); |
} |
#endif |
/contrib/sdk/sources/newlib/libc/stdlib/wcstoll_r.c |
---|
0,0 → 1,140 |
/* |
This code is based on strtoul.c which has the following copyright. |
It is used to convert a wide string into a signed long long. |
long long _wcstoll_r (struct _reent *rptr, const wchar_t *s, |
wchar_t **ptr, int base); |
*/ |
/*- |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#ifdef __GNUC__ |
#define _GNU_SOURCE |
#include <_ansi.h> |
#include <limits.h> |
#include <wctype.h> |
#include <errno.h> |
#include <wchar.h> |
#include <reent.h> |
/* |
* Convert a wide string to a long long integer. |
* |
* Ignores `locale' stuff. Assumes that the upper and lower case |
* alphabets and digits are each contiguous. |
*/ |
long long |
_DEFUN (_wcstoll_r, (rptr, nptr, endptr, base), |
struct _reent *rptr _AND |
_CONST wchar_t *nptr _AND |
wchar_t **endptr _AND |
int base) |
{ |
register const wchar_t *s = nptr; |
register unsigned long long acc; |
register int c; |
register unsigned long long cutoff; |
register int neg = 0, any, cutlim; |
/* |
* Skip white space and pick up leading +/- sign if any. |
* If base is 0, allow 0x for hex and 0 for octal, else |
* assume decimal; if base is already 16, allow 0x. |
*/ |
do { |
c = *s++; |
} while (iswspace(c)); |
if (c == L'-') { |
neg = 1; |
c = *s++; |
} else if (c == L'+') |
c = *s++; |
if ((base == 0 || base == 16) && |
c == L'0' && (*s == L'x' || *s == L'X')) { |
c = s[1]; |
s += 2; |
base = 16; |
} |
if (base == 0) |
base = c == L'0' ? 8 : 10; |
/* |
* Compute the cutoff value between legal numbers and illegal |
* numbers. That is the largest legal value, divided by the |
* base. An input number that is greater than this value, if |
* followed by a legal input character, is too big. One that |
* is equal to this value may be valid or not; the limit |
* between valid and invalid numbers is then based on the last |
* digit. For instance, if the range for longs is |
* [-2147483648..2147483647] and the input base is 10, |
* cutoff will be set to 214748364 and cutlim to either |
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated |
* a value > 214748364, or equal but the next digit is > 7 (or 8), |
* the number is too big, and we will return a range error. |
* |
* Set any if any `digits' consumed; make it negative to indicate |
* overflow. |
*/ |
cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX; |
cutlim = cutoff % (unsigned long long)base; |
cutoff /= (unsigned long long)base; |
for (acc = 0, any = 0;; c = *s++) { |
if (iswdigit(c)) |
c -= L'0'; |
else if (iswalpha(c)) |
c -= iswupper(c) ? L'A' - 10 : L'a' - 10; |
else |
break; |
if (c >= base) |
break; |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) |
any = -1; |
else { |
any = 1; |
acc *= base; |
acc += c; |
} |
} |
if (any < 0) { |
acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX; |
rptr->_errno = ERANGE; |
} else if (neg) |
acc = -acc; |
if (endptr != 0) |
*endptr = (wchar_t *) (any ? s - 1 : nptr); |
return (acc); |
} |
#endif /* __GNUC__ */ |
/contrib/sdk/sources/newlib/libc/stdlib/wcstombs.c |
---|
0,0 → 1,83 |
/* |
FUNCTION |
<<wcstombs>>---minimal wide char string to multibyte string converter |
INDEX |
wcstombs |
ANSI_SYNOPSIS |
#include <stdlib.h> |
size_t wcstombs(char *restrict <[s]>, const wchar_t *restrict <[pwc]>, size_t <[n]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
size_t wcstombs(<[s]>, <[pwc]>, <[n]>) |
char *<[s]>; |
const wchar_t *<[pwc]>; |
size_t <[n]>; |
DESCRIPTION |
When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming |
implementation of <<wcstombs>>. In this case, |
all wide-characters are expected to represent single bytes and so |
are converted simply by casting to char. |
When _MB_CAPABLE is defined, this routine calls <<_wcstombs_r>> to perform |
the conversion, passing a state variable to allow state dependent |
decoding. The result is based on the locale setting which may |
be restricted to a defined set of locales. |
RETURNS |
This implementation of <<wcstombs>> returns <<0>> if |
<[s]> is <<NULL>> or is the empty string; |
it returns <<-1>> if _MB_CAPABLE and one of the |
wide-char characters does not represent a valid multi-byte character; |
otherwise it returns the minimum of: <<n>> or the |
number of bytes that are transferred to <<s>>, not including the |
nul terminator. |
If the return value is -1, the state of the <<pwc>> string is |
indeterminate. If the input has a length of 0, the output |
string will be modified to contain a wchar_t nul terminator if |
<<n>> > 0. |
PORTABILITY |
<<wcstombs>> is required in the ANSI C standard. However, the precise |
effects vary with the locale. |
<<wcstombs>> requires no supporting OS subroutines. |
*/ |
#ifndef _REENT_ONLY |
#include <newlib.h> |
#include <stdlib.h> |
#include <wchar.h> |
size_t |
_DEFUN (wcstombs, (s, pwcs, n), |
char *__restrict s _AND |
const wchar_t *__restrict pwcs _AND |
size_t n) |
{ |
#ifdef _MB_CAPABLE |
mbstate_t state; |
state.__count = 0; |
return _wcstombs_r (_REENT, s, pwcs, n, &state); |
#else /* not _MB_CAPABLE */ |
int count = 0; |
if (n != 0) { |
do { |
if ((*s++ = (char) *pwcs++) == 0) |
break; |
count++; |
} while (--n != 0); |
} |
return count; |
#endif /* not _MB_CAPABLE */ |
} |
#endif /* !_REENT_ONLY */ |
/contrib/sdk/sources/newlib/libc/stdlib/wcstombs_r.c |
---|
0,0 → 1,48 |
#include <stdlib.h> |
#include <wchar.h> |
#include "local.h" |
size_t |
_DEFUN (_wcstombs_r, (reent, s, pwcs, n, state), |
struct _reent *r _AND |
char *__restrict s _AND |
const wchar_t *__restrict pwcs _AND |
size_t n _AND |
mbstate_t *state) |
{ |
char *ptr = s; |
size_t max = n; |
char buff[8]; |
int i, bytes, num_to_copy; |
if (s == NULL) |
{ |
size_t num_bytes = 0; |
while (*pwcs != 0) |
{ |
bytes = __wctomb (r, buff, *pwcs++, __locale_charset (), state); |
if (bytes == -1) |
return -1; |
num_bytes += bytes; |
} |
return num_bytes; |
} |
else |
{ |
while (n > 0) |
{ |
bytes = __wctomb (r, buff, *pwcs, __locale_charset (), state); |
if (bytes == -1) |
return -1; |
num_to_copy = (n > bytes ? bytes : (int)n); |
for (i = 0; i < num_to_copy; ++i) |
*ptr++ = buff[i]; |
if (*pwcs == 0x00) |
return ptr - s - (n >= bytes); |
++pwcs; |
n -= num_to_copy; |
} |
return max; |
} |
} |
/contrib/sdk/sources/newlib/libc/stdlib/wcstoul.c |
---|
0,0 → 1,207 |
/* |
FUNCTION |
<<wcstoul>>---wide string to unsigned long |
INDEX |
wcstoul |
INDEX |
_wcstoul_r |
ANSI_SYNOPSIS |
#include <wchar.h> |
unsigned long wcstoul(const wchar_t *__restrict <[s]>, |
wchar_t **__restrict <[ptr]>, int <[base]>); |
unsigned long _wcstoul_r(void *<[reent]>, const wchar_t *<[s]>, |
wchar_t **<[ptr]>, int <[base]>); |
TRAD_SYNOPSIS |
#include <wchar.h> |
unsigned long wcstoul(<[s]>, <[ptr]>, <[base]>) |
wchar_t *__restrict <[s]>; |
wchar_t **__restrict <[ptr]>; |
int <[base]>; |
unsigned long _wcstoul_r(<[reent]>, <[s]>, <[ptr]>, <[base]>) |
wchar_t *<[reent]>; |
wchar_t *<[s]>; |
wchar_t **<[ptr]>; |
int <[base]>; |
DESCRIPTION |
The function <<wcstoul>> converts the wide string <<*<[s]>>> to |
an <<unsigned long>>. First, it breaks down the string into three parts: |
leading whitespace, which is ignored; a subject string consisting |
of the digits meaningful in the radix specified by <[base]> |
(for example, <<0>> through <<7>> if the value of <[base]> is 8); |
and a trailing portion consisting of one or more unparseable characters, |
which always includes the terminating null character. Then, it attempts |
to convert the subject string into an unsigned long integer, and returns the |
result. |
If the value of <[base]> is zero, the subject string is expected to look |
like a normal C integer constant (save that no optional sign is permitted): |
a possible <<0x>> indicating hexadecimal radix, and a number. |
If <[base]> is between 2 and 36, the expected form of the subject is a |
sequence of digits (which may include letters, depending on the |
base) representing an integer in the radix specified by <[base]>. |
The letters <<a>>--<<z>> (or <<A>>--<<Z>>) are used as digits valued from |
10 to 35. If <[base]> is 16, a leading <<0x>> is permitted. |
The subject sequence is the longest initial sequence of the input |
string that has the expected form, starting with the first |
non-whitespace character. If the string is empty or consists entirely |
of whitespace, or if the first non-whitespace character is not a |
permissible digit, the subject string is empty. |
If the subject string is acceptable, and the value of <[base]> is zero, |
<<wcstoul>> attempts to determine the radix from the input string. A |
string with a leading <<0x>> is treated as a hexadecimal value; a string with |
a leading <<0>> and no <<x>> is treated as octal; all other strings are |
treated as decimal. If <[base]> is between 2 and 36, it is used as the |
conversion radix, as described above. Finally, a pointer to the first |
character past the converted subject string is stored in <[ptr]>, if |
<[ptr]> is not <<NULL>>. |
If the subject string is empty (that is, if <<*>><[s]> does not start |
with a substring in acceptable form), no conversion |
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is |
not <<NULL>>). |
The alternate function <<_wcstoul_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<wcstoul>> returns the converted value, if any. If no conversion was |
made, <<0>> is returned. |
<<wcstoul>> returns <<ULONG_MAX>> if the magnitude of the converted |
value is too large, and sets <<errno>> to <<ERANGE>>. |
PORTABILITY |
<<wcstoul>> is ANSI. |
<<wcstoul>> requires no supporting OS subroutines. |
*/ |
/* |
* Copyright (c) 1990 Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <limits.h> |
#include <wctype.h> |
#include <wchar.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <reent.h> |
/* |
* Convert a wide string to an unsigned long integer. |
* |
* Ignores `locale' stuff. Assumes that the upper and lower case |
* alphabets and digits are each contiguous. |
*/ |
unsigned long |
_DEFUN (_wcstoul_r, (rptr, nptr, endptr, base), |
struct _reent *rptr _AND |
_CONST wchar_t *nptr _AND |
wchar_t **endptr _AND |
int base) |
{ |
register const wchar_t *s = nptr; |
register unsigned long acc; |
register int c; |
register unsigned long cutoff; |
register int neg = 0, any, cutlim; |
/* |
* See strtol for comments as to the logic used. |
*/ |
do { |
c = *s++; |
} while (iswspace(c)); |
if (c == L'-') { |
neg = 1; |
c = *s++; |
} else if (c == L'+') |
c = *s++; |
if ((base == 0 || base == 16) && |
c == L'0' && (*s == L'x' || *s == L'X')) { |
c = s[1]; |
s += 2; |
base = 16; |
} |
if (base == 0) |
base = c == L'0' ? 8 : 10; |
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; |
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; |
for (acc = 0, any = 0;; c = *s++) { |
if (iswdigit(c)) |
c -= L'0'; |
else if (iswalpha(c)) |
c -= iswupper(c) ? L'A' - 10 : L'a' - 10; |
else |
break; |
if (c >= base) |
break; |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) |
any = -1; |
else { |
any = 1; |
acc *= base; |
acc += c; |
} |
} |
if (any < 0) { |
acc = ULONG_MAX; |
rptr->_errno = ERANGE; |
} else if (neg) |
acc = -acc; |
if (endptr != 0) |
*endptr = (wchar_t *) (any ? s - 1 : nptr); |
return (acc); |
} |
#ifndef _REENT_ONLY |
unsigned long |
_DEFUN (wcstoul, (s, ptr, base), |
_CONST wchar_t *__restrict s _AND |
wchar_t **__restrict ptr _AND |
int base) |
{ |
return _wcstoul_r (_REENT, s, ptr, base); |
} |
#endif |
/contrib/sdk/sources/newlib/libc/stdlib/wcstoull.c |
---|
0,0 → 1,140 |
/* |
FUNCTION |
<<wcstoull>>---wide string to unsigned long long |
INDEX |
wcstoull |
INDEX |
_wcstoull_r |
ANSI_SYNOPSIS |
#include <wchar.h> |
unsigned long long wcstoull(const wchar_t *__restrict <[s]>, |
wchar_t **__restrict <[ptr]>, int <[base]>); |
unsigned long long _wcstoull_r(void *<[reent]>, const wchar_t *<[s]>, |
wchar_t **<[ptr]>, int <[base]>); |
TRAD_SYNOPSIS |
#include <wchar.h> |
unsigned long long wcstoull(<[s]>, <[ptr]>, <[base]>) |
wchar_t *__restrict <[s]>; |
wchar_t **__restrict <[ptr]>; |
int <[base]>; |
unsigned long long _wcstoull_r(<[reent]>, <[s]>, <[ptr]>, <[base]>) |
wchar_t *<[reent]>; |
wchar_t *<[s]>; |
wchar_t **<[ptr]>; |
int <[base]>; |
DESCRIPTION |
The function <<wcstoull>> converts the wide string <<*<[s]>>> to |
an <<unsigned long long>>. First, it breaks down the string into three parts: |
leading whitespace, which is ignored; a subject string consisting |
of the digits meaningful in the radix specified by <[base]> |
(for example, <<0>> through <<7>> if the value of <[base]> is 8); |
and a trailing portion consisting of one or more unparseable characters, |
which always includes the terminating null character. Then, it attempts |
to convert the subject string into an unsigned long long integer, and returns the |
result. |
If the value of <[base]> is zero, the subject string is expected to look |
like a normal C integer constant: an optional sign (<<+>> or <<->>), |
a possible <<0x>> indicating hexadecimal radix or a possible <0> indicating |
octal radix, and a number. |
If <[base]> is between 2 and 36, the expected form of the subject is a |
sequence of digits (which may include letters, depending on the |
base) representing an integer in the radix specified by <[base]>. |
The letters <<a>>--<<z>> (or <<A>>--<<Z>>) are used as digits valued from |
10 to 35. If <[base]> is 16, a leading <<0x>> is permitted. |
The subject sequence is the longest initial sequence of the input |
string that has the expected form, starting with the first |
non-whitespace character. If the string is empty or consists entirely |
of whitespace, or if the first non-whitespace character is not a |
permissible digit, the subject string is empty. |
If the subject string is acceptable, and the value of <[base]> is zero, |
<<wcstoull>> attempts to determine the radix from the input string. A |
string with a leading <<0x>> is treated as a hexadecimal value; a string with |
a leading <<0>> and no <<x>> is treated as octal; all other strings are |
treated as decimal. If <[base]> is between 2 and 36, it is used as the |
conversion radix, as described above. Finally, a pointer to the first |
character past the converted subject string is stored in <[ptr]>, if |
<[ptr]> is not <<NULL>>. |
If the subject string is empty (that is, if <<*>><[s]> does not start |
with a substring in acceptable form), no conversion |
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is |
not <<NULL>>). |
The alternate function <<_wcstoull_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<wcstoull>> returns <<0>> and sets <<errno>> to <<EINVAL>> if the value of |
<[base]> is not supported. |
<<wcstoull>> returns the converted value, if any. If no conversion was |
made, <<0>> is returned. |
<<wcstoull>> returns <<ULLONG_MAX>> if the magnitude of the converted |
value is too large, and sets <<errno>> to <<ERANGE>>. |
PORTABILITY |
<<wcstoull>> is ANSI. |
<<wcstoull>> requires no supporting OS subroutines. |
*/ |
/* |
* Copyright (c) 1990 Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <wchar.h> |
#include <reent.h> |
#ifndef _REENT_ONLY |
unsigned long long |
_DEFUN (wcstoull, (s, ptr, base), |
_CONST wchar_t *__restrict s _AND |
wchar_t **__restrict ptr _AND |
int base) |
{ |
return _wcstoull_r (_REENT, s, ptr, base); |
} |
#endif |
/contrib/sdk/sources/newlib/libc/stdlib/wcstoull_r.c |
---|
0,0 → 1,130 |
/* |
This code is based on wcstoul.c which has the following copyright. |
It is used to convert a wide string into an unsigned long long. |
unsigned long long _wcstoull_r (struct _reent *rptr, const wchar_t *s, |
wchar_t **ptr, int base); |
*/ |
/* |
* Copyright (c) 1990 Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#ifdef __GNUC__ |
#define _GNU_SOURCE |
#include <_ansi.h> |
#include <limits.h> |
#include <wchar.h> |
#include <wctype.h> |
#include <errno.h> |
#include <reent.h> |
/* Make up for older non-compliant limits.h. (This is a C99/POSIX function, |
* and both require ULLONG_MAX in limits.h.) */ |
#if !defined(ULLONG_MAX) |
# define ULLONG_MAX ULONG_LONG_MAX |
#endif |
/* |
* Convert a wide string to an unsigned long long integer. |
* |
* Ignores `locale' stuff. Assumes that the upper and lower case |
* alphabets and digits are each contiguous. |
*/ |
unsigned long long |
_DEFUN (_wcstoull_r, (rptr, nptr, endptr, base), |
struct _reent *rptr _AND |
_CONST wchar_t *nptr _AND |
wchar_t **endptr _AND |
int base) |
{ |
register const wchar_t *s = nptr; |
register unsigned long long acc; |
register int c; |
register unsigned long long cutoff; |
register int neg = 0, any, cutlim; |
if(base < 0 || base == 1 || base > 36) { |
rptr->_errno = EINVAL; |
return(0ULL); |
} |
/* |
* See strtol for comments as to the logic used. |
*/ |
do { |
c = *s++; |
} while (iswspace(c)); |
if (c == L'-') { |
neg = 1; |
c = *s++; |
} else if (c == L'+') |
c = *s++; |
if ((base == 0 || base == 16) && |
c == L'0' && (*s == L'x' || *s == L'X')) { |
c = s[1]; |
s += 2; |
base = 16; |
} |
if (base == 0) |
base = c == L'0' ? 8 : 10; |
cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base; |
cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base; |
for (acc = 0, any = 0;; c = *s++) { |
if (iswdigit(c)) |
c -= L'0'; |
else if (iswalpha(c)) |
c -= iswupper(c) ? L'A' - 10 : L'a' - 10; |
else |
break; |
if (c >= base) |
break; |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) |
any = -1; |
else { |
any = 1; |
acc *= base; |
acc += c; |
} |
} |
if (any < 0) { |
acc = ULLONG_MAX; |
rptr->_errno = ERANGE; |
} else if (neg) |
acc = -acc; |
if (endptr != 0) |
*endptr = (wchar_t *) (any ? s - 1 : nptr); |
return (acc); |
} |
#endif /* __GNUC__ */ |
/contrib/sdk/sources/newlib/libc/stdlib/wctob.c |
---|
0,0 → 1,26 |
#include <reent.h> |
#include <wchar.h> |
#include <stdio.h> |
#include <string.h> |
#include <limits.h> |
#include "local.h" |
int |
wctob (wint_t wc) |
{ |
struct _reent *reent; |
mbstate_t mbs; |
unsigned char pmb[MB_LEN_MAX]; |
if (wc == WEOF) |
return EOF; |
/* Put mbs in initial state. */ |
memset (&mbs, '\0', sizeof (mbs)); |
reent = _REENT; |
_REENT_CHECK_MISC(reent); |
return __wctomb (reent, (char *) pmb, wc, __locale_charset (), &mbs) == 1 |
? (int) pmb[0] : EOF; |
} |
/contrib/sdk/sources/newlib/libc/stdlib/wctomb.c |
---|
0,0 → 1,81 |
/* |
FUNCTION |
<<wctomb>>---minimal wide char to multibyte converter |
INDEX |
wctomb |
ANSI_SYNOPSIS |
#include <stdlib.h> |
int wctomb(char *<[s]>, wchar_t <[wchar]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
int wctomb(<[s]>, <[wchar]>) |
char *<[s]>; |
wchar_t <[wchar]>; |
DESCRIPTION |
When _MB_CAPABLE is not defined, this is a minimal ANSI-conforming |
implementation of <<wctomb>>. The |
only ``wide characters'' recognized are single bytes, |
and they are ``converted'' to themselves. |
When _MB_CAPABLE is defined, this routine calls <<_wctomb_r>> to perform |
the conversion, passing a state variable to allow state dependent |
decoding. The result is based on the locale setting which may |
be restricted to a defined set of locales. |
Each call to <<wctomb>> modifies <<*<[s]>>> unless <[s]> is a null |
pointer or _MB_CAPABLE is defined and <[wchar]> is invalid. |
RETURNS |
This implementation of <<wctomb>> returns <<0>> if |
<[s]> is <<NULL>>; it returns <<-1>> if _MB_CAPABLE is enabled |
and the wchar is not a valid multi-byte character, it returns <<1>> |
if _MB_CAPABLE is not defined or the wchar is in reality a single |
byte character, otherwise it returns the number of bytes in the |
multi-byte character. |
PORTABILITY |
<<wctomb>> is required in the ANSI C standard. However, the precise |
effects vary with the locale. |
<<wctomb>> requires no supporting OS subroutines. |
*/ |
#ifndef _REENT_ONLY |
#include <newlib.h> |
#include <stdlib.h> |
#include <errno.h> |
#include "local.h" |
int |
_DEFUN (wctomb, (s, wchar), |
char *s _AND |
wchar_t wchar) |
{ |
#ifdef _MB_CAPABLE |
struct _reent *reent = _REENT; |
_REENT_CHECK_MISC(reent); |
return __wctomb (reent, s, wchar, __locale_charset (), |
&(_REENT_WCTOMB_STATE(reent))); |
#else /* not _MB_CAPABLE */ |
if (s == NULL) |
return 0; |
/* Verify that wchar is a valid single-byte character. */ |
if ((size_t)wchar >= 0x100) { |
errno = EILSEQ; |
return -1; |
} |
*s = (char) wchar; |
return 1; |
#endif /* not _MB_CAPABLE */ |
} |
#endif /* !_REENT_ONLY */ |