Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

549 lines
14 KiB

/* @(#)CM_VerSion xcf_fp.c atm09 1.3 16499.eco sum= 31680 atm09.002 */
/* @(#)CM_VerSion xcf_fp.c atm08 1.3 16343.eco sum= 19313 atm08.005 */
/***********************************************************************/
/* */
/* Copyright 1990-1996 Adobe Systems Incorporated. */
/* All rights reserved. */
/* */
/* Patents Pending */
/* */
/* NOTICE: All information contained herein is the property of Adobe */
/* Systems Incorporated. Many of the intellectual and technical */
/* concepts contained herein are proprietary to Adobe, are protected */
/* as trade secrets, and are made available only to Adobe licensees */
/* for their internal use. Any reproduction or dissemination of this */
/* software is strictly forbidden unless prior written permission is */
/* obtained from Adobe. */
/* */
/* PostScript and Display PostScript are trademarks of Adobe Systems */
/* Incorporated or its subsidiaries and may be registered in certain */
/* jurisdictions. */
/* */
/***********************************************************************
* SCCS Id: %W%
* Changed: %G% %U%
***********************************************************************/
/*
* Fixed point multiply, divide, and conversions.
* The double-to-int conversion is assumed to truncate rather than round;
* this is specified by the C language manual. The direction of truncation
* is machine-dependent, but is toward zero rather than toward minus
* infinity on the Vax and Sun. This explains the peculiar way in which
* fixmul and fixdiv do rounding.
*/
#include "xcf_priv.h"
#if (USE_FIXMUL == USE_HWFP)
Fixed XCF_FixMul(Fixed x, Fixed y) /* returns x*y */
{
double d = (double) x * (double) y / fixedScale;
d += (d < 0)? -0.5 : 0.5;
if (d >= FixedPosInf) return FixedPosInf;
if (d <= FixedNegInf) return FixedNegInf;
return (Fixed) d;
}
#endif
#if (USE_FIXMUL == USE_SWFP)
Fixed XCF_SWFixMul(Fixed x, Fixed y);
Fixed XCF_SWFixMul(Fixed x, Fixed y) /* returns x*y */
{
Int32 xu, yu, up, sign;
if (x && y) {
sign = x ^ y;
if (x < 0) x = -x;
if (y < 0) y = -y;
xu = x >> 16; x = x & 0xffff;
yu = y >> 16; y = y & 0xffff;
up = (xu * yu);
if (!(up >> 15)) { /* overflow */
x = (x * yu) + (xu * y) + (up << 16) +
((((unsigned int)(x * y) >> 15) + 1) >> 1);
if (x >= 0) return (sign < 0) ? -x : x;
}
return (sign < 0) ? FixedNegInf : FixedPosInf;
}
return 0;
}
#endif
#if (USE_FIXDIV == USE_HWFP)
Fixed XCF_FixDiv(Fixed x, Fixed y) /* returns x/y */
{
double d;
if (y == 0) return (x < 0)? FixedNegInf : FixedPosInf;
d = (double) x / (double) y * fixedScale;
d += (d < 0)? -0.5 : 0.5;
if (d >= FixedPosInf) return FixedPosInf;
if (d <= FixedNegInf) return FixedNegInf;
return (Fixed) d;
}
#endif
#if (USE_FIXDIV == USE_SWFP)
Fixed XCF_SWFixDiv(Fixed i, Fixed j);
Fixed XCF_SWFixDiv(Fixed i, Fixed j)
{
Int32 q,m;
unsigned int sign = (unsigned int)((i ^ j) >> 31) & 1; /* should not need & */
if (i) { /* zero divided by anything is zero */
if (j) { /* divide by zero is infinity */
if (i < 0) i = -i; /* get absolute value for unsigned divide */
if (j < 0) j = -j; /* get absolute value for unsigned divide */
q = i / j; /* do the divide */
m = i % j; /* and remainder -- same operation? */
if (!(q >> 15)) { /* otherwise it's overflow */
q = q << 16;
if (m) { /* otherwise no remainder -- we're done */
if (m >> 15) { /* sigh. Do this the hard way */
m = m << 1; if (m > j) { q += 0x8000; m -= j;};
m = m << 1; if (m > j) { q += 0x4000; m -= j;};
m = m << 1; if (m > j) { q += 0x2000; m -= j;};
m = m << 1; if (m > j) { q += 0x1000; m -= j;};
m = m << 1; if (m > j) { q += 0x800; m -= j;};
m = m << 1; if (m > j) { q += 0x400; m -= j;};
m = m << 1; if (m > j) { q += 0x200; m -= j;};
m = m << 1; if (m > j) { q += 0x100; m -= j;};
m = m << 1; if (m > j) { q += 0x80; m -= j;};
m = m << 1; if (m > j) { q += 0x40; m -= j;};
m = m << 1; if (m > j) { q += 0x20; m -= j;};
m = m << 1; if (m > j) { q += 0x10; m -= j;};
m = m << 1; if (m > j) { q += 0x8; m -= j;};
m = m << 1; if (m > j) { q += 0x4; m -= j;};
m = m << 1; if (m > j) { q += 0x2; m -= j;};
m = m << 1; if (m > j) { q += 0x1; m -= j;};
if ((m << 1) > j) q += 1; /* round the result */
return ((sign)? -q : q);
} else { /* oh, good -- we can use another divide */
m = m << 16;
q += m / j;
m = m % j;
if ((m << 1) > j) q += 1; /* round the result */
return ((sign)? -q : q);
}
}
return ((sign)? -q : q);
}
} return (sign + FixedPosInf);
} return ((j) ? 0 : FixedPosInf);
}
#endif
#if (USE_FRACMUL == USE_HWFP)
Frac XCF_FracMul(Frac x, Frac y)
{
Int32 sign = x ^ y;
double d = (double) x * (double) y / fracScale;
if (sign >= 0) { /* positive result */
d += 0.5;
if (d < (double)FixedPosInf) return (Fixed) d;
return FixedPosInf;
}
/* result is negative */
d -= 0.5;
if(d > (double)FixedNegInf) return (Fixed) d;
return FixedNegInf;
}
#endif
#if (USE_FRACMUL == USE_SWFP)
Frac XCF_SWFracMul(Frac x, Frac y);
Frac XCF_SWFracMul(Frac x, Frac y)
{
Int32 xu, yu, up, sign;
if (x && y) {
sign = x ^ y;
if (x < 0) x = -x;
if (y < 0) y = -y;
xu = x >> 16; x = x & 0xffff;
yu = y >> 16; y = y & 0xffff;
up = (xu * yu);
if (!(up >> 29)) { /* overflow */
x = (x * yu) + (xu * y) + ((unsigned int)(x * y) >> 16) + 0x2000;
x = (x >> 14) & 0x3ffff;
x += (up << 2);
if (x >= 0) return (sign < 0) ? -x : x;
}
return (sign < 0) ? FixedNegInf : FixedPosInf;
}
return 0;
}
#endif
static long convFract[] =
{
65536L,
6553L,
655L,
66L,
6L
};
/* Converts a number in Fixed format to a string and stores it in s. */
void XCF_Fixed2CString(Fixed f, char PTR_PREFIX *s, short precision,
boolean fracType)
{
char u[12];
char PTR_PREFIX *t;
short v;
char sign;
Card32 frac;
long fracPrec = (precision <= 4) ? convFract[precision] : 0L;
if ((sign = f < 0) != 0)
f = -f;
/* If f started out as fixedMax or -fixedMax, the precision adjustment
puts it out of bounds. Reset it correctly. */
if (f >= 0x7FFF7FFF)
f =(Fixed)0x7fffffff;
else
f += fracType ? 0x03 : (fracPrec + 1) >> 1;
v = fracType ? (short)(f >> 30) : (short)(f >> 16);
f &= fracType ? 0x3fffffff : 0x0000ffff;
if (sign && (v || f >= fracPrec))
*s++ = '-';
t = u;
do
{
*t++ = v % 10 + '0';
v /= 10;
} while (v);
for (; t > u;)
*s++ = *--t;
if (f >= fracPrec)
{
/* If this is a fracType then shift the value right by 2 so we don't
have to worry about overflow. If the current callers request
more than 9 significant digits then we'll have to re-evaluate
this to make sure we don't lose any precision. */
frac = fracType ? f >> 2 : f;
*s++ = '.';
for (v = precision; v-- && frac;)
{
frac = (frac << 3) + (frac << 1); /* multiply by 10 */
*s++ = fracType ? (char)((frac >> 28) + '0') : (char)((frac >> 16) + '0');
frac &= fracType ? 0x0fffffff : 0x0000ffff;
}
for (; *--s == '0';)
;
if (*s != '.')
s++;
}
*s = '\0';
}
#if USE_FXL
static Fxl powersof10[MAXEXP - MINEXP + 1] = {
{ 1441151880, -27 },
{ 1801439850, -24 },
{ 1125899906, -20 },
{ 1407374883, -17 },
{ 1759218604, -14 },
{ 1099511627, -10 },
{ 1374389534, -7 },
{ 1717986918, -4 },
{ 1073741824, 0 },
{ 1342177280, 3 },
{ 1677721600, 6 },
{ 2097152000, 9 },
{ 1310720000, 13 }
};
#define Odd(x) ((x) & 1)
#define isdigit(c) ((c) >= '0' && (c) <= '9')
/* mkfxl -- create a normalized Fxl from mantissa and exponent */
static Fxl mkfxl(Frac mantissa, Int32 exp)
{
Fxl fxl;
if (mantissa == 0)
exp = 0;
else {
boolean neg;
if (mantissa >= 0)
neg = 0;
else {
mantissa = -mantissa;
neg = 1;
}
for (; (mantissa & mostSigBit) == 0; exp--)
mantissa <<= 1;
if (neg)
mantissa = -mantissa;
}
fxl.mantissa = mantissa;
fxl.exp = exp;
return fxl;
}
static Fxl fxladd (Fxl a, Fxl b)
{
Frac mantissa, fa, fb;
Int32 shift, exp;
if (FxlIsZero(a))
return b;
if (FxlIsZero(b))
return a;
shift = a.exp - b.exp;
if (shift < 0) {
Fxl t;
t = a;
a = b;
b = t;
shift = -shift;
}
exp = a.exp;
fa = a.mantissa;
fb = b.mantissa;
if (shift > 0)
if (fb >= 0) {
fb >>= (shift - 1);
fb = (fb >> 1) + Odd(fb);
}
else {
fb = (-fb) >> (shift - 1);
fb = -((fb >> 1) + Odd(fb));
}
if ((fa < 0) == (fb < 0)) { /* signs alike */
boolean neg = (fa < 0) ? 1 : 0;
unsigned long f;
if (neg) {
fa = -fa;
fb = -fb;
}
f = fa + fb;
if (f >= (Card32) 0x80000000l) { /* overflow */
mantissa = (f >> 1) + Odd(f);
exp++;
} else
mantissa = f;
if (neg)
mantissa = -mantissa;
} else
mantissa = fa + fb;
return mkfxl(mantissa, exp);
}
static Fxl fxlmul(Fxl a, Fxl b)
{
Frac f;
/* Force a to be in [.5 .. 1) (as Frac!) to keep in range */
if (a.mantissa >= 0)
f = (a.mantissa >> 1) + Odd(a.mantissa);
else
f = -(((-a.mantissa) >> 1) + Odd(a.mantissa));
return mkfxl(XCF_FracMul(f, b.mantissa), a.exp + b.exp + 1);
}
static Fxl fxlpow10 (Fxl f, IntX n)
{
if (n < 0) {
for (; n < MINEXP; n -= MINEXP)
f = fxlmul(f, powersof10[0]);
f = fxlmul(f, powersof10[n - MINEXP]);
}
else if (n > 0) {
for (; n > MAXEXP; n -= MAXEXP)
f = fxlmul(f, powersof10[MAXEXP - MINEXP]);
f = fxlmul(f, powersof10[n - MINEXP]);
}
return f;
}
#if 0
static Fxl FixedToFxl (Fixed f)
{
return mkfxl(f, expFixed);
}
#endif
static Fxl Int32ToFxl (Int32 i)
{
return mkfxl(i, expInteger);
}
/*
* strtofxl
* convert a PostScript numeric token to a Fxl. we have to accept
* three formats: (see pslrm 2, pp 27-28)
* integers: [+-]?[0-9]+
* reals: [+-]?[0-9]*('.'[0-9]*)?([eE][+-]?[0-9]+)?
* radix numbers: [0-9]+'#'[0-9a-zA-Z]+
* note that this routine is a bit more forgiving than PostScript itself.
*/
static Fxl strtofxl(XCF_Handle h, Card8 PTR_PREFIX *token)
{
long c;
Card8 PTR_PREFIX *s;
boolean neg;
Fxl f;
c = *token;
if (c == '-') {
neg = 1;
token++;
}
else {
neg = 0;
if (c == '+')
token++;
}
for (c = *(s = token); isdigit(c); c = *++s);
if (c == '#')
if (s == token)
goto INVALID;
else {
unsigned long radix = h->callbacks.atoi((char *) token);
if (radix > 36)
goto INVALID;
else {
char *t;
long number = h->callbacks.strtol((char *) s + 1, &t, (int) radix);
if (*t != '\0')
goto INVALID;
return Int32ToFxl(neg ? -number : number);
}
}
f = Int32ToFxl(h->callbacks.strtol((char *) token, NULL, 10));
if (c == '.') {
for (c = *(token = ++s); isdigit(c); c = *++s);
if (s != token)
f = fxladd(f, fxlpow10(Int32ToFxl(h->callbacks.strtol((char *) token, NULL, 10)), (IntX)(token - s)));
}
if (c == 'e' || c == 'E') {
token = ++s;
c = *s;
if (c == '+' || c == '-')
c = *++s;
for (; isdigit(c); c = *++s);
f = fxlpow10(f, h->callbacks.atoi((char *) token));
}
if (neg)
f.mantissa = -f.mantissa;
if (c == '\0')
return f;
INVALID:
f.mantissa = 1;
f.exp = 30000; /* big enough to overflow, always */
return f;
}
static Fixed FxlToFixed (Fxl fxl)
{
Fixed f = fxl.mantissa;
Int32 shift = fxl.exp - expFixed;
boolean neg = false;
if (f == 0 || shift == 0)
return f;
else if (shift < 0)
{
Fixed tempF = f >> (-shift - 1);
if (tempF < 0) {
neg = true;
tempF = -tempF;
}
f = (tempF >> 1) + (tempF & 1);
return neg ? -f : f;
} else
return (fxl.mantissa < 0) ? FixedNegInf : FixedPosInf;
}
static Frac FxlToFrac (Fxl fxl)
{
Fixed f = fxl.mantissa;
Int32 shift = fxl.exp;
boolean neg = false;
if (f == 0 || shift == 0)
return f;
else if (shift < 0) {
Fixed tempF = f >> (-shift - 1);
if (tempF < 0) {
neg = 1;
tempF = -tempF;
}
f = (tempF >> 1) + (tempF & 1);
return neg ? -f : f;
} else
return (fxl.mantissa < 0) ? FixedNegInf : FixedPosInf;
}
/* ConvertFixed -- takes an ascii token and converts to a 16.16 fixed */
Fixed XCF_ConvertFixed (XCF_Handle h, char *s)
{
Fxl f;
f = strtofxl(h, (unsigned char *) s);
return FxlToFixed(f);
}
/* ConvertFrac -- takes an ascii token and converts to a 2.30 frac */
Frac XCF_ConvertFrac (XCF_Handle h, char *s)
{
Fxl f;
f = strtofxl(h, (unsigned char *) s);
return FxlToFrac(f);
}
#endif