phobos 0.61

This commit is contained in:
Brad Roberts 2007-09-10 02:09:57 +00:00
parent c528883866
commit dba8d9bcaa
32 changed files with 1088 additions and 261 deletions

View file

@ -24,6 +24,42 @@ byte[] _d_arraycat(byte[] x, byte[] y, uint size)
return a; return a;
} }
byte[] _d_arraycatn(uint size, uint n, ...)
{ byte[] a;
uint length;
byte[]* p;
uint i;
byte[] b;
p = cast(byte[]*)(&n + 1);
for (i = 0; i < n; i++)
{
b = *p++;
length += b.length;
}
if (!length)
return null;
a = new byte[length * size];
p = cast(byte[]*)(&n + 1);
uint j = 0;
for (i = 0; i < n; i++)
{
b = *p++;
if (b.length)
{
memcpy(&a[j], b, b.length * size);
j += b.length * size;
}
}
*(int *)&a = length; // jam length
//a.length = length;
return a;
}
byte[] _d_arraycopy(uint size, byte[] from, byte[] to) byte[] _d_arraycopy(uint size, byte[] from, byte[] to)
{ {
//printf("f = %p,%d, t = %p,%d\n", (void*)from, from.length, (void*)to, to.length); //printf("f = %p,%d, t = %p,%d\n", (void*)from, from.length, (void*)to, to.length);

View file

@ -20,3 +20,10 @@ extern (C):
void qsort(void *base, uint nelems, uint elemsize, void qsort(void *base, uint nelems, uint elemsize,
int (*compare)(void *elem1, void *elem2)); int (*compare)(void *elem1, void *elem2));
char* getenv(char*);
int rand();
void srand(uint);
int random(int num);
void randomize();

View file

@ -14,7 +14,7 @@
// CRC-32 calculation // CRC-32 calculation
module crc; module crc;
static uint[256] crc32_table = private uint[256] crc32_table =
[ [
0x00000000,0x77073096,0xee0e612c,0x990951ba,0x076dc419,0x706af48f,0xe963a535, 0x00000000,0x77073096,0xee0e612c,0x990951ba,0x076dc419,0x706af48f,0xe963a535,
0x9e6495a3,0x0edb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,0x09b64c2b,0x7eb17cbd, 0x9e6495a3,0x0edb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,0x09b64c2b,0x7eb17cbd,

View file

@ -92,19 +92,26 @@ void _d_delclass(Object *p)
{ {
if (*p) if (*p)
{ {
version(none) version(0)
{ {
ClassInfo **pc = (ClassInfo **)*p; ClassInfo **pc = (ClassInfo **)*p;
if (*pc) if (*pc)
{ {
ClassInfo c = **pc; ClassInfo c = **pc;
if (c.deallocator)
{
if (c.destructor) if (c.destructor)
{ {
fp_t fp = (fp_t)c.destructor; fp_t fp = (fp_t)c.destructor;
(*fp)(*p); // call destructor (*fp)(*p); // call destructor
} }
fp_t fp = (fp_t)c.deallocator;
(*fp)(*p); // call deallocator
*pc = null; // zero vptr *pc = null; // zero vptr
*p = null;
return;
}
} }
} }
_gc.free(*p); _gc.free(*p);

View file

@ -139,7 +139,7 @@ debug (LOGGING)
/* ============================ GC =============================== */ /* ============================ GC =============================== */
alias int size_t; //alias int size_t;
alias void (*GC_FINALIZER)(void *p, void *dummy); alias void (*GC_FINALIZER)(void *p, void *dummy);
class GCLock { } // just a dummy so we can get a global lock class GCLock { } // just a dummy so we can get a global lock

View file

@ -2,7 +2,9 @@
DMD=..\..\dmd DMD=..\..\dmd
#DMD=\dmd\bin\dmd #DMD=\dmd\bin\dmd
CFLAGS=-g -mn -6 -r -Igc CFLAGS=-g -mn -6 -r -Igc
DFLAGS=-unittest -g -release #DFLAGS=-unittest -g -release
DFLAGS=-release -O -inline
#DFLAGS=-release -inline -O
CC=sc CC=sc
.c.obj: .c.obj:

View file

@ -19,7 +19,7 @@ void printStats(GC *gc)
{ {
GCStats stats; GCStats stats;
gc.getStats(stats); //gc.getStats(stats);
printf("poolsize = x%x, usedsize = x%x, freelistsize = x%x, freeblocks = %d, pageblocks = %d\n", printf("poolsize = x%x, usedsize = x%x, freelistsize = x%x, freeblocks = %d, pageblocks = %d\n",
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks); stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
} }

View file

@ -23,9 +23,10 @@ ubyte outp(uint, ubyte);
ushort outpw(uint, ushort); ushort outpw(uint, ushort);
uint outpl(uint, uint); uint outpl(uint, uint);
extended cos(extended); real cos(real);
extended fabs(extended); real fabs(real);
extended rint(extended); real rint(real);
long rndtol(extended); long rndtol(real);
extended sin(extended); real sin(real);
extended sqrt(extended); real sqrt(real);
real ldexp(real, int);

View file

@ -13,10 +13,12 @@
# This relies on LIB.EXE 8.00 or later, and MAKE.EXE 5.01 or later. # This relies on LIB.EXE 8.00 or later, and MAKE.EXE 5.01 or later.
CFLAGS=-g -mn -6 -r CFLAGS=-g -mn -6 -r
DFLAGS=-unittest -g DFLAGS=-O -release
#DFLAGS=-unittest -g
CC=sc CC=sc
DMD=\dmd\bin\dmd #DMD=\dmd\bin\dmd
#DMD=..\dmd DMD=..\dmd
.c.obj: .c.obj:
$(CC) -c $(CFLAGS) $* $(CC) -c $(CFLAGS) $*
@ -56,10 +58,13 @@ OBJS= assert.obj deh.obj switch.obj complex.obj gcstats.obj \
stream.obj switcherr.obj com.obj array.obj gc.obj adi.obj \ stream.obj switcherr.obj com.obj array.obj gc.obj adi.obj \
qsort.obj math2.obj date.obj dateparse.obj thread.obj obj.obj \ qsort.obj math2.obj date.obj dateparse.obj thread.obj obj.obj \
iunknown.obj crc32.obj conv.obj arraycast.obj \ iunknown.obj crc32.obj conv.obj arraycast.obj \
ti_Aa.obj ti_C.obj ti_int.obj ti_char.obj \ ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \
ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \ ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \
ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \ ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \
ti_float.obj ti_double.obj ti_extended.obj ti_delegate.obj ti_float.obj ti_double.obj ti_real.obj ti_delegate.obj \
ti_creal.obj ti_ireal.obj \
ti_cfloat.obj ti_ifloat.obj \
ti_cdouble.obj ti_idouble.obj
HDR=mars.h HDR=mars.h
@ -76,14 +81,16 @@ SRC4=dchar.d ctype.d achar.d aaA.d adi.d file.d compiler.d system.d \
moduleinit.d cast.d math.d qsort.d moduleinit.d cast.d math.d qsort.d
SRC5=outbuffer.d unittest.d stream.d ctype.d regexp.d random.d adi.d \ SRC5=outbuffer.d unittest.d stream.d ctype.d regexp.d random.d adi.d \
ti_Aa.d ti_C.d ti_int.d ti_char.d ti_Aa.d ti_Ag.d ti_C.d ti_int.d ti_char.d
SRC6=math2.d thread.d obj.d iunknown.d intrinsic.d time.d memset.c \ SRC6=math2.d thread.d obj.d iunknown.d intrinsic.d time.d memset.d \
array.d switcherr.d arraycast.d array.d switcherr.d arraycast.d
SRC7=ti_wchar.d ti_uint.d ti_short.d ti_ushort.d \ SRC7=ti_wchar.d ti_uint.d ti_short.d ti_ushort.d \
ti_byte.d ti_ubyte.d ti_long.d ti_ulong.d ti_ptr.d \ ti_byte.d ti_ubyte.d ti_long.d ti_ulong.d ti_ptr.d \
ti_float.d ti_double.d ti_extended.d ti_delegate.d ti_float.d ti_double.d ti_real.d ti_delegate.d \
ti_creal.d ti_ireal.d ti_cfloat.d ti_ifloat.d \
ti_cdouble.d ti_idouble.d
SRC8=crc32.d stdint.d conv.d gcstats.d SRC8=crc32.d stdint.d conv.d gcstats.d
@ -109,6 +116,7 @@ gc.obj : gc.d
invariant.obj : invariant.d invariant.obj : invariant.d
math.obj : math.d math.obj : math.d
math2.obj : math2.d math2.obj : math2.d
memset.obj : memset.d
minit.obj : minit.asm minit.obj : minit.asm
moduleinit.obj : moduleinit.d moduleinit.obj : moduleinit.d
monitor.obj : mars.h monitor.c monitor.obj : mars.h monitor.c
@ -118,6 +126,7 @@ switch.obj : switch.d
system.obj : system.d system.obj : system.d
thread.obj : thread.d thread.obj : thread.d
ti_Aa.obj : ti_Aa.d ti_Aa.obj : ti_Aa.d
ti_Ag.obj : ti_Ag.d
ti_C.obj : ti_C.d ti_C.obj : ti_C.d
ti_char.obj : ti_char.d ti_char.obj : ti_char.d
ti_int.obj : ti_int.d ti_int.obj : ti_int.d

486
math.d
View file

@ -1,55 +1,51 @@
// math.d // math.d
// Written by Walter Bright // Written by Walter Bright
// Copyright (c) 2001 Digital Mars // Copyright (c) 2001-2003 Digital Mars
// All Rights Reserved // All Rights Reserved
// www.digitalmars.com // www.digitalmars.com
module math;
import c.stdio; import c.stdio;
import intrinsic;
extern (C) extern (C)
{ {
// BUG: these have double arguments, but we need extended // BUG: these have double arguments, but we need real
extended acos(double); real acos(double);
extended asin(double); real asin(double);
extended atan(double); real atan(double);
extended atan2(double, double); real atan2(double, double);
extended cos(double); real cosh(double);
extended sin(double); real sinh(double);
extended tan(double); real tanh(double);
extended cosh(double); real exp(double);
extended sinh(double); real log(double);
extended tanh(double); real log10(double);
extended exp(double); real modf(double, double *);
extended frexp(double,int *); real pow(double, double);
extended ldexp(double,int); real ceil(double);
extended log(double); real floor(double);
extended log10(double); real log1p(double);
extended modf(double, double *); real expm1(double);
extended pow(double, double); real atof(char *);
extended sqrt(double);
extended ceil(double);
extended floor(double);
extended log1p(double);
extended expm1(double);
extended atof(char *);
extended hypot(double, double);
} }
const extended PI = 3.14159265358979323846; const real PI = 3.14159265358979323846;
const extended LOG2 = 0.30102999566398119521; const real LOG2 = 0.30102999566398119521;
const extended LN2 = 0.6931471805599453094172321; const real LN2 = 0.6931471805599453094172321;
const extended LOG2T = 3.32192809488736234787; const real LOG2T = 3.32192809488736234787;
const extended LOG2E = 1.4426950408889634074; const real LOG2E = 1.4426950408889634074;
const extended E = 2.7182818284590452354; const real E = 2.7182818284590452354;
const extended LOG10E = 0.43429448190325182765; const real LOG10E = 0.43429448190325182765;
const extended LN10 = 2.30258509299404568402; const real LN10 = 2.30258509299404568402;
const extended PI_2 = 1.57079632679489661923; const real PI_2 = 1.57079632679489661923;
const extended PI_4 = 0.78539816339744830962; const real PI_4 = 0.78539816339744830962;
const extended M_1_PI = 0.31830988618379067154; const real M_1_PI = 0.31830988618379067154;
const extended M_2_PI = 0.63661977236758134308; const real M_2_PI = 0.63661977236758134308;
const extended M_2_SQRTPI = 1.12837916709551257390; const real M_2_SQRTPI = 1.12837916709551257390;
const extended SQRT2 = 1.41421356237309504880; const real SQRT2 = 1.41421356237309504880;
const extended SQRT1_2 = 0.70710678118654752440; const real SQRT1_2 = 0.70710678118654752440;
/* /*
Octal versions: Octal versions:
@ -70,7 +66,7 @@ const extended SQRT1_2 = 0.70710678118654752440;
* Is number a nan? * Is number a nan?
*/ */
int isnan(extended e) int isnan(real e)
{ {
ushort* pe = (ushort *)&e; ushort* pe = (ushort *)&e;
ulong* ps = (ulong *)&e; ulong* ps = (ulong *)&e;
@ -83,7 +79,7 @@ unittest
{ {
assert(isnan(float.nan)); assert(isnan(float.nan));
assert(isnan(-double.nan)); assert(isnan(-double.nan));
assert(isnan(extended.nan)); assert(isnan(real.nan));
assert(!isnan(53.6)); assert(!isnan(53.6));
assert(!isnan(float.infinity)); assert(!isnan(float.infinity));
@ -93,7 +89,7 @@ unittest
* Is number finite? * Is number finite?
*/ */
int isfinite(extended e) int isfinite(real e)
{ {
ushort* pe = (ushort *)&e; ushort* pe = (ushort *)&e;
@ -111,7 +107,7 @@ unittest
/********************************* /*********************************
* Is number normalized? * Is number normalized?
* Need one for each format because subnormal floats might * Need one for each format because subnormal floats might
* be converted to normal extendeds. * be converted to normal reals.
*/ */
int isnormal(float f) int isnormal(float f)
@ -133,7 +129,7 @@ int isnormal(double d)
return e && e != 0x7FF00000; return e && e != 0x7FF00000;
} }
int isnormal(extended e) int isnormal(real e)
{ {
ushort* pe = (ushort *)&e; ushort* pe = (ushort *)&e;
long* ps = (long *)&e; long* ps = (long *)&e;
@ -145,7 +141,7 @@ unittest
{ {
float f = 3; float f = 3;
double d = 500; double d = 500;
extended e = 10e+48; real e = 10e+48;
assert(isnormal(f)); assert(isnormal(f));
assert(isnormal(d)); assert(isnormal(d));
@ -156,7 +152,7 @@ unittest
* Is number subnormal? (Also called "denormal".) * Is number subnormal? (Also called "denormal".)
* Subnormals have a 0 exponent and a 0 most significant mantissa bit. * Subnormals have a 0 exponent and a 0 most significant mantissa bit.
* Need one for each format because subnormal floats might * Need one for each format because subnormal floats might
* be converted to normal extendeds. * be converted to normal reals.
*/ */
int issubnormal(float f) int issubnormal(float f)
@ -190,7 +186,7 @@ unittest
assert(f != 0); assert(f != 0);
} }
int issubnormal(extended e) int issubnormal(real e)
{ {
ushort* pe = (ushort *)&e; ushort* pe = (ushort *)&e;
long* ps = (long *)&e; long* ps = (long *)&e;
@ -200,7 +196,7 @@ int issubnormal(extended e)
unittest unittest
{ {
extended f; real f;
for (f = 1; !issubnormal(f); f /= 2) for (f = 1; !issubnormal(f); f /= 2)
assert(f != 0); assert(f != 0);
@ -210,7 +206,7 @@ unittest
* Is number infinity? * Is number infinity?
*/ */
int isinf(extended e) int isinf(real e)
{ {
ushort* pe = (ushort *)&e; ushort* pe = (ushort *)&e;
ulong* ps = (ulong *)&e; ulong* ps = (ulong *)&e;
@ -224,7 +220,7 @@ unittest
assert(isinf(float.infinity)); assert(isinf(float.infinity));
assert(!isinf(float.nan)); assert(!isinf(float.nan));
assert(isinf(double.infinity)); assert(isinf(double.infinity));
assert(isinf(-extended.infinity)); assert(isinf(-real.infinity));
assert(isinf(-1.0 / 0.0)); assert(isinf(-1.0 / 0.0));
} }
@ -233,7 +229,7 @@ unittest
* Get sign bit. * Get sign bit.
*/ */
int signbit(extended e) int signbit(real e)
{ {
ubyte* pe = (ubyte *)&e; ubyte* pe = (ubyte *)&e;
@ -254,7 +250,7 @@ unittest
* Copy sign. * Copy sign.
*/ */
extended copysign(extended to, extended from) real copysign(real to, real from)
{ {
ubyte* pto = (ubyte *)&to; ubyte* pto = (ubyte *)&to;
ubyte* pfrom = (ubyte *)&from; ubyte* pfrom = (ubyte *)&from;
@ -267,7 +263,7 @@ extended copysign(extended to, extended from)
unittest unittest
{ {
extended e; real e;
e = copysign(21, 23.8); e = copysign(21, 23.8);
assert(e == 21); assert(e == 21);
@ -281,6 +277,384 @@ unittest
e = copysign(-21, -23.8); e = copysign(-21, -23.8);
assert(e == -21); assert(e == -21);
e = copysign(extended.nan, -23.8); e = copysign(real.nan, -23.8);
assert(isnan(e) && signbit(e)); assert(isnan(e) && signbit(e));
} }
/****************************************************************************
* Tangent.
*/
real tan(real x)
{
asm
{
fld x[EBP] ; // load theta
fxam ; // test for oddball values
fstsw AX ;
sahf ;
jc trigerr ; // x is NAN, infinity, or empty
// 387's can handle denormals
SC18: fptan ;
fstp ST(0) ; // dump X, which is always 1
fstsw AX ;
sahf ;
jnp Lret ; // C2 = 1 (x is out of range)
// Do argument reduction to bring x into range
fldpi ;
fxch ;
SC17: fprem1 ;
fstsw AX ;
sahf ;
jp SC17 ;
fstp ST(1) ; // remove pi from stack
jmp SC18 ;
}
trigerr:
return real.nan;
Lret:
;
}
unittest
{
static real vals[][2] = // angle,tan
[
[ 0, 0],
[ .5, .5463024898],
[ 1, 1.557407725],
[ 1.5, 14.10141995],
[ 2, -2.185039863],
[ 2.5,-.7470222972],
[ 3, -.1425465431],
[ 3.5, .3745856402],
[ 4, 1.157821282],
[ 4.5, 4.637332055],
[ 5, -3.380515006],
[ 5.5,-.9955840522],
[ 6, -.2910061914],
[ 6.5, .2202772003],
[ 10, .6483608275],
// special angles
[ PI_4, 1],
//[ PI_2, real.infinity],
[ 3*PI_4, -1],
[ PI, 0],
[ 5*PI_4, 1],
//[ 3*PI_2, -real.infinity],
[ 7*PI_4, -1],
[ 2*PI, 0],
// overflow
[ real.infinity, real.nan],
[ real.nan, real.nan],
[ 1e+100, real.nan],
];
int i;
for (i = 0; i < vals.length; i++)
{
real x = vals[i][0];
real r = vals[i][1];
real t = tan(x);
//printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r);
assert(mfeq(r, t, .0000001));
x = -x;
r = -r;
t = tan(x);
//printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r);
assert(mfeq(r, t, .0000001));
}
}
/****************************************************************************
* hypotenuese.
* This is based on code from:
* Cephes Math Library Release 2.1: January, 1989
* Copyright 1984, 1987, 1989 by Stephen L. Moshier
* Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
real hypot(real zre, real zim)
{
const int PRECL = 32;
const int MAXEXPL = real.max_exp; //16384;
const int MINEXPL = real.min_exp; //-16384;
real x, y, b, re, im;
int ex, ey, e;
// Note, hypot(INFINITY,NAN) = INFINITY.
if (isinf(zre) || isinf(zim))
return real.infinity;
if (isnan(zre))
return zre;
if (isnan(zim))
return zim;
re = fabs(zre);
im = fabs(zim);
if (re == 0.0)
return im;
if (im == 0.0)
return re;
// Get the exponents of the numbers
x = frexp(re, ex);
y = frexp(im, ey);
// Check if one number is tiny compared to the other
e = ex - ey;
if (e > PRECL)
return re;
if (e < -PRECL)
return im;
// Find approximate exponent e of the geometric mean.
e = (ex + ey) >> 1;
// Rescale so mean is about 1
x = ldexp(re, -e);
y = ldexp(im, -e);
// Hypotenuse of the right triangle
b = sqrt(x * x + y * y);
// Compute the exponent of the answer.
y = frexp(b, ey);
ey = e + ey;
// Check it for overflow and underflow.
if (ey > MAXEXPL + 2)
{
//return __matherr(_OVERFLOW, INFINITY, x, y, "hypotl");
return real.infinity;
}
if (ey < MINEXPL - 2)
return 0.0;
// Undo the scaling
b = ldexp(b, e);
return b;
}
unittest
{
static real vals[][3] = // x,y,hypot
[
[ 0, 0, 0],
[ 0, -0, 0],
[ 3, 4, 5],
[ -300, -400, 500],
[ real.min, real.min, 4.75473e-4932L],
[ real.max/2, real.max/2, 0x1.6a09e667f3bcc908p+16383L /*8.41267e+4931L*/],
[ real.infinity, real.nan, real.infinity],
[ real.nan, real.nan, real.nan],
];
int i;
for (i = 0; i < vals.length; i++)
{
real x = vals[i][0];
real y = vals[i][1];
real z = vals[i][2];
real h = hypot(x, y);
//printf("hypot(%Lg, %Lg) = %Lg, should be %Lg\n", x, y, h, z);
//if (!mfeq(z, h, .0000001))
//printf("%La\n", h);
assert(mfeq(z, h, .0000001));
}
}
/*********************************************************************
* Returns:
* x such that value=x*2**n, .5 <= |x| < 1.0
* x has same sign as value.
* *eptr = n
*
* Special cases:
* value x *eptr
* +-0.0 +-0.0 0
* +-inf +-inf int.max/int.min
* +-NaN +-NaN int.min
* +-NaNs +-NaN int.min
*/
real frexp(real value, out int eptr)
{
ushort* vu = (ushort*)&value;
long* vl = (long*)&value;
uint exp;
// If exponent is non-zero
exp = vu[4] & 0x7FFF;
if (exp)
{
if (exp == 0x7FFF)
{ // infinity or NaN
if (*vl & 0x7FFFFFFFFFFFFFFF) // if NaN
{ *vl |= 0xC000000000000000; // convert NANS to NANQ
eptr = int.min;
}
else if (vu[4] & 0x8000)
{ // negative infinity
eptr = int.min;
}
else
{ // positive infinity
eptr = int.max;
}
}
else
{
eptr = exp - 0x3FFE;
vu[4] = (0x8000 & vu[4]) | 0x3FFE;
}
}
else if (!*vl)
{
// value is +-0.0
eptr = 0;
}
else
{ // denormal
int i = -0x3FFD;
do
{
i--;
*vl <<= 1;
} while (*vl > 0);
eptr = i;
vu[4] = (0x8000 & vu[4]) | 0x3FFE;
}
return value;
}
unittest
{
static real vals[][3] = // x,frexp,eptr
[
[0.0, 0.0, 0],
[-0.0, -0.0, 0],
[1.0, .5, 1],
[-1.0, -.5, 1],
[2.0, .5, 2],
[155.67e20, 0x1.A5F1C2EB3FE4Fp-1, 74], // normal
[1.0e-320, 0x1.FAp-1, -1063],
[real.min, .5, -16381],
[real.min/2.0L, .5, -16382], // denormal
[real.infinity,real.infinity,int.max],
[-real.infinity,-real.infinity,int.min],
[real.nan,real.nan,int.min],
[-real.nan,-real.nan,int.min],
// Don't really support signalling nan's in D
//[real.nans,real.nan,int.min],
//[-real.nans,-real.nan,int.min],
];
int i;
for (i = 0; i < vals.length; i++)
{
real x = vals[i][0];
real e = vals[i][1];
int exp = (int)vals[i][2];
int eptr;
real v = frexp(x, eptr);
//printf("frexp(%Lg) = %Lg, should be %Lg, eptr = %d, should be %d\n", x, v, e, eptr, exp);
assert(mfeq(e, v, .0000001));
assert(exp == eptr);
}
}
/*******************************************************************
* Fast integral powers.
*/
real pow(real x, uint n)
{
real p;
switch (n)
{
case 0:
p = 1.0;
break;
case 1:
p = x;
break;
case 2:
p = x * x;
break;
default:
p = 1.0;
while (1)
{
if (n & 1)
p *= x;
n >>= 1;
if (!n)
break;
x *= x;
}
break;
}
return p;
}
real pow(real x, int n)
{
if (n < 0)
return pow((double)x, cast(double)n);
else
return pow(x, cast(uint)n);
}
unittest
{
real x = 46;
assert(pow(x,0) == 1.0);
assert(pow(x,1) == x);
assert(pow(x,2) == x * x);
assert(pow(x,3) == x * x * x);
assert(pow(x,8) == (x * x) * (x * x) * (x * x) * (x * x));
}
/****************************************
* Simple function to compare two floating point values
* to a specified precision.
* Returns:
* 1 match
* 0 nomatch
*/
private int mfeq(real x, real y, real precision)
{
if (x == y)
return 1;
if (isnan(x))
return isnan(y);
if (isnan(y))
return 0;
return fabs(x - y) <= precision;
}

201
math2.d
View file

@ -21,12 +21,12 @@ private import math, string, c.stdlib, c.stdio;
* compare floats with given precision * compare floats with given precision
*/ */
bit feq(extended a, extended b) bit feq(real a, real b)
{ {
return feq(a, b, 0.000001); return feq(a, b, 0.000001);
} }
bit feq(extended a, extended b, extended eps) bit feq(real a, real b, real eps)
{ {
return abs(a - b) <= eps; return abs(a - b) <= eps;
} }
@ -45,7 +45,7 @@ long abs(long n)
return n > 0 ? n : -n; return n > 0 ? n : -n;
} }
extended abs(extended n) real abs(real n)
{ {
// just let the compiler handle it // just let the compiler handle it
return intrinsic.fabs(n); return intrinsic.fabs(n);
@ -65,7 +65,7 @@ long sqr(long n)
return n * n; return n * n;
} }
extended sqr(extended n) real sqr(real n)
{ {
return n * n; return n * n;
} }
@ -81,7 +81,7 @@ private ushort fp_cw_chop = 7999;
* Integer part * Integer part
*/ */
extended trunc(extended n) real trunc(real n)
{ {
ushort cw; ushort cw;
asm asm
@ -104,7 +104,7 @@ unittest
* Fractional part * Fractional part
*/ */
extended frac(extended n) real frac(real n)
{ {
return n - trunc(n); return n - trunc(n);
} }
@ -119,12 +119,12 @@ unittest
* Polynomial of X * Polynomial of X
*/ */
extended poly(extended x, extended[] coefficients) real poly(real x, real[] coefficients)
{ {
debug (math2) printf("poly(), coefficients.length = %d\n", coefficients.length); debug (math2) printf("poly(), coefficients.length = %d\n", coefficients.length);
if (!coefficients.length) if (!coefficients.length)
return 0; return 0;
extended result = coefficients[coefficients.length - 1]; real result = coefficients[coefficients.length - 1];
for (int i = coefficients.length - 2; i >= 0; i--) for (int i = coefficients.length - 2; i >= 0; i--)
result = result * x + coefficients[i]; result = result * x + coefficients[i];
return result; return result;
@ -133,8 +133,8 @@ extended poly(extended x, extended[] coefficients)
unittest unittest
{ {
debug (math2) printf("unittest.poly()\n"); debug (math2) printf("unittest.poly()\n");
static extended[4] k = [ 4, 3, 2, 1 ]; static real[4] k = [ 4, 3, 2, 1 ];
assert(feq(poly(2, k), cast(extended) 8 * 1 + 4 * 2 + 2 * 3 + 4)); assert(feq(poly(2, k), cast(real) 8 * 1 + 4 * 2 + 2 * 3 + 4));
} }
/********************************* /*********************************
@ -165,7 +165,7 @@ unittest
assert(sign(-666L) == -1); assert(sign(-666L) == -1);
} }
int sign(extended n) int sign(real n)
{ {
return (n > 0 ? +1 : (n < 0 ? -1 : 0)); return (n > 0 ? +1 : (n < 0 ? -1 : 0));
} }
@ -181,62 +181,62 @@ unittest
* Cycles <-> radians <-> grads <-> degrees conversions * Cycles <-> radians <-> grads <-> degrees conversions
*/ */
extended cycle2deg(extended c) real cycle2deg(real c)
{ {
return c * 360; return c * 360;
} }
extended cycle2rad(extended c) real cycle2rad(real c)
{ {
return c * PI * 2; return c * PI * 2;
} }
extended cycle2grad(extended c) real cycle2grad(real c)
{ {
return c * 400; return c * 400;
} }
extended deg2cycle(extended d) real deg2cycle(real d)
{ {
return d / 360; return d / 360;
} }
extended deg2rad(extended d) real deg2rad(real d)
{ {
return d / 180 * PI; return d / 180 * PI;
} }
extended deg2grad(extended d) real deg2grad(real d)
{ {
return d / 90 * 100; return d / 90 * 100;
} }
extended rad2deg(extended r) real rad2deg(real r)
{ {
return r / PI * 180; return r / PI * 180;
} }
extended rad2cycle(extended r) real rad2cycle(real r)
{ {
return r / (PI * 2); return r / (PI * 2);
} }
extended rad2grad(extended r) real rad2grad(real r)
{ {
return r / PI * 200; return r / PI * 200;
} }
extended grad2deg(extended g) real grad2deg(real g)
{ {
return g / 100 * 90; return g / 100 * 90;
} }
extended grad2cycle(extended g) real grad2cycle(real g)
{ {
return g / 400; return g / 400;
} }
extended grad2rad(extended g) real grad2rad(real g)
{ {
return g / 200 * PI; return g / 200 * PI;
} }
@ -261,9 +261,9 @@ unittest
* Arithmetic average of values * Arithmetic average of values
*/ */
extended avg(extended[] n) real avg(real[] n)
{ {
extended result = 0; real result = 0;
for (uint i = 0; i < n.length; i++) for (uint i = 0; i < n.length; i++)
result += n[i]; result += n[i];
return result / n.length; return result / n.length;
@ -271,7 +271,7 @@ extended avg(extended[] n)
unittest unittest
{ {
static extended[4] n = [ 1, 2, 4, 5 ]; static real[4] n = [ 1, 2, 4, 5 ];
assert(feq(avg(n), 3)); assert(feq(avg(n), 3));
} }
@ -307,9 +307,9 @@ unittest
assert(sum(n) == 6); assert(sum(n) == 6);
} }
extended sum(extended[] n) real sum(real[] n)
{ {
extended result = 0; real result = 0;
for (uint i = 0; i < n.length; i++) for (uint i = 0; i < n.length; i++)
result += n[i]; result += n[i];
return result; return result;
@ -317,7 +317,7 @@ extended sum(extended[] n)
unittest unittest
{ {
static extended[3] n = [ 1, 2, 3 ]; static real[3] n = [ 1, 2, 3 ];
assert(feq(sum(n), 6)); assert(feq(sum(n), 6));
} }
@ -355,9 +355,9 @@ unittest
assert(min(n) == -1); assert(min(n) == -1);
} }
extended min(extended[] n) real min(real[] n)
{ {
extended result = extended.max; real result = real.max;
for (uint i = 0; i < n.length; i++) for (uint i = 0; i < n.length; i++)
{ {
if (n[i] < result) if (n[i] < result)
@ -368,7 +368,7 @@ extended min(extended[] n)
unittest unittest
{ {
static extended[3] n = [ 2.0, -1.0, 0.0 ]; static real[3] n = [ 2.0, -1.0, 0.0 ];
assert(feq(min(n), -1)); assert(feq(min(n), -1));
} }
@ -392,7 +392,7 @@ unittest
assert(min(1L, 2L) == 1); assert(min(1L, 2L) == 1);
} }
extended min(extended a, extended b) real min(real a, real b)
{ {
return a < b ? a : b; return a < b ? a : b;
} }
@ -436,9 +436,9 @@ unittest
assert(max(n) == 2); assert(max(n) == 2);
} }
extended max(extended[] n) real max(real[] n)
{ {
extended result = extended.min; real result = real.min;
for (uint i = 0; i < n.length; i++) for (uint i = 0; i < n.length; i++)
if (n[i] > result) if (n[i] > result)
result = n[i]; result = n[i];
@ -447,7 +447,7 @@ extended max(extended[] n)
unittest unittest
{ {
static extended[3] n = [ 0.0, 2.0, -1.0 ]; static real[3] n = [ 0.0, 2.0, -1.0 ];
assert(feq(max(n), 2)); assert(feq(max(n), 2));
} }
@ -471,7 +471,7 @@ unittest
assert(max(1L, 2L) == 2); assert(max(1L, 2L) == 2);
} }
extended max(extended a, extended b) real max(real a, real b)
{ {
return a > b ? a : b; return a > b ? a : b;
} }
@ -485,7 +485,7 @@ unittest
* Arccosine * Arccosine
*/ */
extended acos(extended x) real acos(real x)
{ {
return atan2(intrinsic.sqrt(1 - x * x), x); return atan2(intrinsic.sqrt(1 - x * x), x);
} }
@ -500,7 +500,7 @@ unittest
*/ */
extended asin(extended x) real asin(real x)
{ {
return atan2(x, intrinsic.sqrt(1 - x * x)); return atan2(x, intrinsic.sqrt(1 - x * x));
} }
@ -515,7 +515,7 @@ unittest
* Arctangent * Arctangent
*/ */
extended atan(extended x) real atan(real x)
{ {
asm asm
{ {
@ -536,7 +536,7 @@ unittest
* Arctangent y/x * Arctangent y/x
*/ */
extended atan2(extended y, extended x) real atan2(real y, real x)
{ {
asm asm
{ {
@ -557,7 +557,7 @@ unittest
* Arccotangent * Arccotangent
*/ */
extended acot(extended x) real acot(real x)
{ {
return tan(1.0 / x); return tan(1.0 / x);
} }
@ -571,7 +571,7 @@ unittest
* Arcsecant * Arcsecant
*/ */
extended asec(extended x) real asec(real x)
{ {
return intrinsic.cos(1.0 / x); return intrinsic.cos(1.0 / x);
} }
@ -581,7 +581,7 @@ extended asec(extended x)
* Arccosecant * Arccosecant
*/ */
extended acosec(extended x) real acosec(real x)
{ {
return intrinsic.sin(1.0 / x); return intrinsic.sin(1.0 / x);
} }
@ -590,7 +590,8 @@ extended acosec(extended x)
* Tangent * Tangent
*/ */
extended tan(extended x) /+
real tan(real x)
{ {
asm asm
{ {
@ -605,12 +606,13 @@ unittest
{ {
assert(feq(tan(PI / 3), intrinsic.sqrt(3))); assert(feq(tan(PI / 3), intrinsic.sqrt(3)));
} }
+/
/************************************* /*************************************
* Cotangent * Cotangent
*/ */
extended cot(extended x) real cot(real x)
{ {
asm asm
{ {
@ -630,7 +632,7 @@ unittest
* Secant * Secant
*/ */
extended sec(extended x) real sec(real x)
{ {
asm asm
{ {
@ -647,7 +649,7 @@ extended sec(extended x)
* Cosecant * Cosecant
*/ */
extended cosec(extended x) real cosec(real x)
{ {
asm asm
{ {
@ -662,8 +664,8 @@ extended cosec(extended x)
/************************************* /*************************************
* Hypotenuse of right triangle * Hypotenuse of right triangle
*/ */
/+
extended hypot(extended x, extended y) real hypot(real x, real y)
{ {
asm asm
{ {
@ -697,12 +699,13 @@ unittest
{ {
assert(feq(hypot(3, 4), 5)); assert(feq(hypot(3, 4), 5));
} }
+/
/********************************************* /*********************************************
* Extract mantissa and exponent from float * Extract mantissa and exponent from float
*/ */
extended frexp(extended x, out int exponent) real frexp(real x, out int exponent)
{ {
asm asm
{ {
@ -731,7 +734,7 @@ done:
unittest unittest
{ {
int exponent; int exponent;
extended mantissa = frexp(123.456, exponent); real mantissa = frexp(123.456, exponent);
assert(feq(mantissa * pow(2, exponent), 123.456)); assert(feq(mantissa * pow(2, exponent), 123.456));
} }
@ -739,7 +742,7 @@ unittest
* Make a float out of mantissa and exponent * Make a float out of mantissa and exponent
*/ */
extended ldexp(extended x, int exponent) real ldexp(real x, int exponent)
{ {
asm asm
{ {
@ -760,7 +763,7 @@ unittest
* Round to nearest int > x * Round to nearest int > x
*/ */
long ceil(extended x) long ceil(real x)
{ {
return frac(x) > 0 ? trunc(x) + 1 : trunc(x); return frac(x) > 0 ? trunc(x) + 1 : trunc(x);
} }
@ -775,7 +778,7 @@ unittest
* Round to nearest int < x * Round to nearest int < x
*/ */
long floor(extended x) long floor(real x)
{ {
return frac(x) < 0 ? trunc(x) - 1 : trunc(x); return frac(x) < 0 ? trunc(x) - 1 : trunc(x);
} }
@ -790,7 +793,7 @@ unittest
* Base 10 logarithm * Base 10 logarithm
*/ */
extended log10(extended x) real log10(real x)
{ {
asm asm
{ {
@ -810,7 +813,7 @@ unittest
* Base 2 logarithm * Base 2 logarithm
*/ */
extended log2(extended x) real log2(real x)
{ {
asm asm
{ {
@ -830,7 +833,7 @@ unittest
* Natural logarithm * Natural logarithm
*/ */
extended log(extended x) real log(real x)
{ {
asm asm
{ {
@ -850,7 +853,7 @@ unittest
* Natural logarithm of (x + 1) * Natural logarithm of (x + 1)
*/ */
extended log1p(extended x) real log1p(real x)
{ {
asm asm
{ {
@ -870,7 +873,7 @@ unittest
* Logarithm * Logarithm
*/ */
extended log(extended x, extended base) real log(real x, real base)
{ {
asm asm
{ {
@ -894,7 +897,7 @@ unittest
* (base + 1) logarithm of x * (base + 1) logarithm of x
*/ */
extended log1p(extended x, extended base) real log1p(real x, real base)
{ {
asm asm
{ {
@ -918,7 +921,7 @@ unittest
* Exponent * Exponent
*/ */
extended exp(extended x) real exp(real x)
{ {
asm asm
{ {
@ -947,7 +950,7 @@ unittest
* Base to exponent * Base to exponent
*/ */
extended pow(extended base, extended exponent) real pow(real base, real exponent)
{ {
return exp(exponent * log(base)); return exp(exponent * log(base));
} }
@ -961,9 +964,9 @@ unittest
* Hyperbolic cosine * Hyperbolic cosine
*/ */
extended cosh(extended x) real cosh(real x)
{ {
extended z = exp(x) / 2; real z = exp(x) / 2;
return z + 0.25 / z; return z + 0.25 / z;
} }
@ -976,9 +979,9 @@ unittest
* Hyperbolic sine * Hyperbolic sine
*/ */
extended sinh(extended x) real sinh(real x)
{ {
extended z = exp(x) / 2; real z = exp(x) / 2;
return z - 0.25 / z; return z - 0.25 / z;
} }
@ -991,9 +994,9 @@ unittest
* Hyperbolic tangent * Hyperbolic tangent
*/ */
private extended tanh_domain; private real tanh_domain;
extended tanh(extended x) real tanh(real x)
{ {
if (x > tanh_domain) if (x > tanh_domain)
return 1; return 1;
@ -1001,7 +1004,7 @@ extended tanh(extended x)
return -1; return -1;
else else
{ {
extended z = sqr(exp(x)); real z = sqr(exp(x));
return (z - 1) / (z + 1); return (z - 1) / (z + 1);
} }
} }
@ -1015,7 +1018,7 @@ unittest
* Hyperbolic cotangent * Hyperbolic cotangent
*/ */
extended coth(extended x) real coth(real x)
{ {
return 1 / tanh(x); return 1 / tanh(x);
} }
@ -1029,7 +1032,7 @@ unittest
* Hyperbolic secant * Hyperbolic secant
*/ */
extended sech(extended x) real sech(real x)
{ {
return 1 / cosh(x); return 1 / cosh(x);
} }
@ -1038,7 +1041,7 @@ extended sech(extended x)
* Hyperbolic cosecant * Hyperbolic cosecant
*/ */
extended cosech(extended x) real cosech(real x)
{ {
return 1 / sinh(x); return 1 / sinh(x);
} }
@ -1047,7 +1050,7 @@ extended cosech(extended x)
* Hyperbolic arccosine * Hyperbolic arccosine
*/ */
extended acosh(extended x) real acosh(real x)
{ {
if (x <= 1) if (x <= 1)
return 0; return 0;
@ -1067,7 +1070,7 @@ unittest
* Hyperbolic arcsine * Hyperbolic arcsine
*/ */
extended asinh(extended x) real asinh(real x)
{ {
if (!x) if (!x)
return 0; return 0;
@ -1077,7 +1080,7 @@ extended asinh(extended x)
return -log(2) - log(1.0e10); return -log(2) - log(1.0e10);
else else
{ {
extended z = x * x; real z = x * x;
return x > 0 ? return x > 0 ?
log1p(x + z / (1.0 + intrinsic.sqrt(1.0 + z))) : log1p(x + z / (1.0 + intrinsic.sqrt(1.0 + z))) :
-log1p(-x + z / (1.0 + intrinsic.sqrt(1.0 + z))); -log1p(-x + z / (1.0 + intrinsic.sqrt(1.0 + z)));
@ -1094,16 +1097,16 @@ unittest
* Hyperbolic arctangent * Hyperbolic arctangent
*/ */
extended atanh(extended x) real atanh(real x)
{ {
if (!x) if (!x)
return 0; return 0;
else else
{ {
if (x >= 1) if (x >= 1)
return extended.max; return real.max;
else if (x <= -1) else if (x <= -1)
return -extended.max; return -real.max;
else else
return x > 0 ? return x > 0 ?
0.5 * log1p((2.0 * x) / (1.0 - x)) : 0.5 * log1p((2.0 * x) / (1.0 - x)) :
@ -1121,7 +1124,7 @@ unittest
* Hyperbolic arccotangent * Hyperbolic arccotangent
*/ */
extended acoth(extended x) real acoth(real x)
{ {
return 1 / acot(x); return 1 / acot(x);
} }
@ -1135,7 +1138,7 @@ unittest
* Hyperbolic arcsecant * Hyperbolic arcsecant
*/ */
extended asech(extended x) real asech(real x)
{ {
return 1 / asec(x); return 1 / asec(x);
} }
@ -1144,7 +1147,7 @@ extended asech(extended x)
* Hyperbolic arccosecant * Hyperbolic arccosecant
*/ */
extended acosech(extended x) real acosech(real x)
{ {
return 1 / acosec(x); return 1 / acosec(x);
} }
@ -1153,15 +1156,15 @@ extended acosech(extended x)
* Convert string to float * Convert string to float
*/ */
extended atof(char[] s) real atof(char[] s)
{ {
if (!s.length) if (!s.length)
return extended.nan; return real.nan;
extended result = 0; real result = 0;
uint i = 0; uint i = 0;
while (s[i] == "\t" || s[i] == " ") while (s[i] == "\t" || s[i] == " ")
if (++i >= s.length) if (++i >= s.length)
return extended.nan; return real.nan;
bit neg = false; bit neg = false;
if (s[i] == "-") if (s[i] == "-")
{ {
@ -1171,7 +1174,7 @@ extended atof(char[] s)
else if (s[i] == "+") else if (s[i] == "+")
i++; i++;
if (i >= s.length) if (i >= s.length)
return extended.nan; return real.nan;
bit hex; bit hex;
if (s[s.length - 1] == "h") if (s[s.length - 1] == "h")
{ {
@ -1183,7 +1186,7 @@ extended atof(char[] s)
hex = true; hex = true;
i += 2; i += 2;
if (i >= s.length) if (i >= s.length)
return extended.nan; return real.nan;
} }
else else
hex = false; hex = false;
@ -1210,10 +1213,10 @@ extended atof(char[] s)
else if (s[i] >= "A" && s[i] <= "F") else if (s[i] >= "A" && s[i] <= "F")
result += s[i] - "A" + 10; result += s[i] - "A" + 10;
else else
return extended.nan; return real.nan;
} }
else else
return extended.nan; return real.nan;
if (++i >= s.length) if (++i >= s.length)
goto done; goto done;
} }
@ -1246,10 +1249,10 @@ extended atof(char[] s)
else if (s[i] >= "A" && s[i] <= "F") else if (s[i] >= "A" && s[i] <= "F")
result += s[i] - "A" + 10; result += s[i] - "A" + 10;
else else
return extended.nan; return real.nan;
} }
else else
return extended.nan; return real.nan;
if (++i >= s.length) if (++i >= s.length)
{ {
result /= k; result /= k;
@ -1259,7 +1262,7 @@ extended atof(char[] s)
result /= k; result /= k;
} }
if (++i >= s.length) if (++i >= s.length)
return extended.nan; return real.nan;
bit eneg = false; bit eneg = false;
if (s[i] == "-") if (s[i] == "-")
{ {
@ -1269,7 +1272,7 @@ extended atof(char[] s)
else if (s[i] == "+") else if (s[i] == "+")
i++; i++;
if (i >= s.length) if (i >= s.length)
return extended.nan; return real.nan;
int e = 0; int e = 0;
while (i < s.length) while (i < s.length)
{ {
@ -1277,7 +1280,7 @@ extended atof(char[] s)
if (s[i] >= "0" && s[i] <= "9") if (s[i] >= "0" && s[i] <= "9")
e += s[i] - "0"; e += s[i] - "0";
else else
return extended.nan; return real.nan;
i++; i++;
} }
if (eneg) if (eneg)
@ -1300,8 +1303,8 @@ unittest
assert(feq(atof(".456"), .456)); assert(feq(atof(".456"), .456));
assert(feq(atof("123.456"), 123.456)); assert(feq(atof("123.456"), 123.456));
assert(feq(atof("1.23456E+2"), 123.456)); assert(feq(atof("1.23456E+2"), 123.456));
assert(feq(atof("1A2h"), 1A2h)); //assert(feq(atof("1A2h"), 1A2h));
assert(feq(atof("1a2h"), 1a2h)); //assert(feq(atof("1a2h"), 1a2h));
assert(feq(atof("0x1A2"), 0x1A2)); assert(feq(atof("0x1A2"), 0x1A2));
assert(feq(atof("0x1a2p2"), 0x1a2p2)); assert(feq(atof("0x1a2p2"), 0x1a2p2));
assert(feq(atof("0x1a2p+2"), 0x1a2p+2)); assert(feq(atof("0x1a2p+2"), 0x1a2p+2));
@ -1314,7 +1317,7 @@ unittest
* Convert float to string * Convert float to string
*/ */
char[] toString(extended x) char[] toString(real x)
{ {
char[1024] buffer; char[1024] buffer;
char* p = buffer; char* p = buffer;
@ -1355,5 +1358,5 @@ unittest
static this() static this()
{ {
tanh_domain = log(extended.max) / 2; tanh_domain = log(real.max) / 2;
} }

View file

@ -1,5 +1,11 @@
#include <string.h> extern (C)
{
// Functions from the C library.
void *memcpy(void *, void *, uint);
}
extern (C):
short *_memset16(short *p, short value, int count) short *_memset16(short *p, short value, int count)
{ {
@ -12,6 +18,21 @@ short *_memset16(short *p, short value, int count)
} }
int *_memset32(int *p, int value, int count) int *_memset32(int *p, int value, int count)
{
version (X86)
{
asm
{
mov EDI,p ;
mov EAX,value ;
mov ECX,count ;
mov EDX,EDI ;
rep ;
stosd ;
mov EAX,EDX ;
}
}
else
{ {
int *pstart = p; int *pstart = p;
int *ptop; int *ptop;
@ -20,21 +41,22 @@ int *_memset32(int *p, int value, int count)
*p = value; *p = value;
return pstart; return pstart;
} }
}
long long *_memset64(long long *p, long long value, int count) long *_memset64(long *p, long value, int count)
{ {
long long *pstart = p; long *pstart = p;
long long *ptop; long *ptop;
for (ptop = &p[count]; p < ptop; p++) for (ptop = &p[count]; p < ptop; p++)
*p = value; *p = value;
return pstart; return pstart;
} }
long double *_memset80(long double *p, long double value, int count) real *_memset80(real *p, real value, int count)
{ {
long double *pstart = p; real *pstart = p;
long double *ptop; real *ptop;
for (ptop = &p[count]; p < ptop; p++) for (ptop = &p[count]; p < ptop; p++)
*p = value; *p = value;

View file

@ -121,11 +121,11 @@ class OutBuffer
offset += double.size; offset += double.size;
} }
void write(extended f) void write(real f)
{ {
reserve(extended.size); reserve(real.size);
*(extended *)&data[offset] = f; *(real *)&data[offset] = f;
offset += extended.size; offset += real.size;
} }
void write(char[] s) void write(char[] s)

View file

@ -145,9 +145,9 @@ enum : ubyte
}; };
// BUG: should this include '$'? // BUG: should this include '$'?
static int isword(tchar c) { return isalnum(c) || c == '_'; } private int isword(tchar c) { return isalnum(c) || c == '_'; }
static uint inf = ~0u; private uint inf = ~0u;
/********************************* /*********************************
* Throws RegExpError on error * Throws RegExpError on error
@ -467,7 +467,7 @@ public tchar[][] exec()
tchar[][] result; tchar[][] result;
result = new tchar[pmatch.length][]; result = new tchar[][pmatch.length];
for (int i = 0; i < pmatch.length; i++) for (int i = 0; i < pmatch.length; i++)
{ {
if (pmatch[i].rm_so == pmatch[i].rm_eo) if (pmatch[i].rm_so == pmatch[i].rm_eo)
@ -2313,7 +2313,7 @@ public tchar[] replace(tchar[] format)
// Static version that doesn't require a RegExp object to be created // Static version that doesn't require a RegExp object to be created
static tchar[] replace3(tchar[] format, tchar[] input, regmatch_t[] pmatch) private tchar[] replace3(tchar[] format, tchar[] input, regmatch_t[] pmatch)
{ {
OutBuffer buf; OutBuffer buf;
tchar[] result; tchar[] result;

View file

@ -67,6 +67,12 @@ class Stream
this() { } this() { }
// close the stream somehow; the default
// does nothing
void close()
{
}
// reads block of data of specified size, // reads block of data of specified size,
// returns actual number of bytes read // returns actual number of bytes read
abstract uint readBlock(void* buffer, uint size); abstract uint readBlock(void* buffer, uint size);
@ -98,9 +104,9 @@ class Stream
void read(out ulong x) { readExact(&x, x.size); } void read(out ulong x) { readExact(&x, x.size); }
void read(out float x) { readExact(&x, x.size); } void read(out float x) { readExact(&x, x.size); }
void read(out double x) { readExact(&x, x.size); } void read(out double x) { readExact(&x, x.size); }
void read(out extended x) { readExact(&x, x.size); } void read(out real x) { readExact(&x, x.size); }
void read(out imaginary x) { readExact(&x, x.size); } void read(out ireal x) { readExact(&x, x.size); }
void read(out complex x) { readExact(&x, x.size); } void read(out creal x) { readExact(&x, x.size); }
void read(out char x) { readExact(&x, x.size); } void read(out char x) { readExact(&x, x.size); }
void read(out wchar x) { readExact(&x, x.size); } void read(out wchar x) { readExact(&x, x.size); }
@ -442,7 +448,7 @@ class Stream
c = getc(); c = getc();
count++; count++;
} }
extended n = 0; real n = 0;
while (isdigit(c) && width) while (isdigit(c) && width)
{ {
n = n * 10 + (c - "0"); n = n * 10 + (c - "0");
@ -487,7 +493,7 @@ class Stream
c = getc(); c = getc();
count++; count++;
} }
extended exp = 0; real exp = 0;
while (isdigit(c) && width) while (isdigit(c) && width)
{ {
exp = exp * 10 + (c - "0"); exp = exp * 10 + (c - "0");
@ -518,9 +524,9 @@ class Stream
*cast(double*)*arg = n; *cast(double*)*arg = n;
} break; } break;
case "L": // extended case "L": // real
{ {
*cast(extended*)*arg = n; *cast(real*)*arg = n;
} break; } break;
default: // float default: // float
@ -642,9 +648,9 @@ nws:
void write(ulong x) { writeExact(&x, x.size); } void write(ulong x) { writeExact(&x, x.size); }
void write(float x) { writeExact(&x, x.size); } void write(float x) { writeExact(&x, x.size); }
void write(double x) { writeExact(&x, x.size); } void write(double x) { writeExact(&x, x.size); }
void write(extended x) { writeExact(&x, x.size); } void write(real x) { writeExact(&x, x.size); }
void write(imaginary x) { writeExact(&x, x.size); } void write(ireal x) { writeExact(&x, x.size); }
void write(complex x) { writeExact(&x, x.size); } void write(creal x) { writeExact(&x, x.size); }
void write(char x) { writeExact(&x, x.size); } void write(char x) { writeExact(&x, x.size); }
void write(wchar x) { writeExact(&x, x.size); } void write(wchar x) { writeExact(&x, x.size); }
@ -944,7 +950,7 @@ class File: Stream
} }
// closes file, if it is open; otherwise, does nothing // closes file, if it is open; otherwise, does nothing
void close() override void close()
{ {
if (hFile) if (hFile)
{ {
@ -1165,6 +1171,7 @@ class SliceStream : Stream
ulong low; // low stream offset. ulong low; // low stream offset.
ulong high; // high stream offset. ulong high; // high stream offset.
bit bounded; // upper-bounded by high. bit bounded; // upper-bounded by high.
bit nestClose; // if set, close base when closing this stream.
// set the base stream and the low offset but leave the high unbounded. // set the base stream and the low offset but leave the high unbounded.
this (Stream base, ulong low) this (Stream base, ulong low)
@ -1205,6 +1212,17 @@ class SliceStream : Stream
seekable = base.seekable; seekable = base.seekable;
} }
override void close ()
{
try
{
if (base !== null && nestClose)
base.close ();
}
finally
base = null;
}
override uint readBlock (void *buffer, uint size) override uint readBlock (void *buffer, uint size)
in in
{ {
@ -1257,7 +1275,7 @@ class SliceStream : Stream
switch (rel) switch (rel)
{ {
case SeekPos.Set: case SeekPos.Set:
output = low; output = low + offset;
break; break;
case SeekPos.Current: case SeekPos.Current:
@ -1310,28 +1328,28 @@ class SliceStream : Stream
} }
// helper functions // helper functions
static bit iswhite(char c) private bit iswhite(char c)
{ {
return c == " " || c == "\t" || c == "\r" || c == "\n"; return c == " " || c == "\t" || c == "\r" || c == "\n";
} }
static bit isdigit(char c) private bit isdigit(char c)
{ {
return c >= "0" && c <= "9"; return c >= "0" && c <= "9";
} }
static bit isoctdigit(char c) private bit isoctdigit(char c)
{ {
return c >= "0" && c <= "7"; return c >= "0" && c <= "7";
} }
static bit ishexdigit(char c) private bit ishexdigit(char c)
{ {
return isdigit(c) || (c >= "A" && c <= "F") || (c >= "a" && c <= "f"); return isdigit(c) || (c >= "A" && c <= "F") || (c >= "a" && c <= "f");
} }
// API imports // API imports
private static extern(Windows) private extern(Windows)
{ {
private import windows; private import windows;
HANDLE GetStdHandle(DWORD); HANDLE GetStdHandle(DWORD);

View file

@ -71,13 +71,13 @@ const char[6] whitespace = " \t\v\r\n\f";
* Returns !=0 if c is whitespace * Returns !=0 if c is whitespace
*/ */
private int iswhite(char c) int iswhite(char c)
{ {
return find(whitespace, c) != -1; return find(whitespace, c) != -1;
} }
/********************************* /*********************************
* Convert string to integer / extended. * Convert string to integer / real.
*/ */
long atoi(char[] s) long atoi(char[] s)
@ -85,7 +85,7 @@ long atoi(char[] s)
return atoi(toStringz(s)); return atoi(toStringz(s));
} }
extended atof(char[] s) real atof(char[] s)
{ {
// BUG: should implement atold() // BUG: should implement atold()
return atof(toStringz(s)); return atof(toStringz(s));
@ -616,7 +616,7 @@ unittest
char[] word1 = "peter"; char[] word1 = "peter";
char[] word2 = "paul"; char[] word2 = "paul";
char[] word3 = "jerry"; char[] word3 = "jerry";
char[3][] words; char[][3] words;
char[] r; char[] r;
int i; int i;
@ -796,7 +796,7 @@ char[][] splitlines(char[] s)
if (istart != i) if (istart != i)
nlines++; nlines++;
lines = new char[nlines][]; lines = new char[][nlines];
nlines = 0; nlines = 0;
istart = 0; istart = 0;
for (i = 0; i < s.length; i++) for (i = 0; i < s.length; i++)

View file

@ -22,27 +22,27 @@ int _d_switch_string(char[][] table, char[] ca)
assert(ca.length >= 0); assert(ca.length >= 0);
// Make sure table[] is sorted correctly // Make sure table[] is sorted correctly
int i; int j;
for (i = 1; i < table.length; i++) for (j = 1; j < table.length; j++)
{ {
int len1 = table[i - 1].length; int len1 = table[j - 1].length;
int len2 = table[i].length; int len2 = table[j].length;
assert(len1 <= len2); assert(len1 <= len2);
if (len1 == len2) if (len1 == len2)
{ {
int c; int ci;
c = memcmp(table[i - 1], table[i], len1); ci = memcmp(table[j - 1], table[j], len1);
assert(c < 0); // c==0 means a duplicate assert(ci < 0); // ci==0 means a duplicate
} }
} }
} }
out (result) out (result)
{ {
int i; int i;
int c; int cj;
//printf("out _d_switch_string()\n"); //printf("out _d_switch_string()\n");
if (result == -1) if (result == -1)
@ -51,8 +51,8 @@ int _d_switch_string(char[][] table, char[] ca)
for (i = 0; i < table.length; i++) for (i = 0; i < table.length; i++)
{ {
if (table[i].length == ca.length) if (table[i].length == ca.length)
{ c = memcmp(table[i], ca, ca.length); { cj = memcmp(table[i], ca, ca.length);
assert(c != 0); assert(cj != 0);
} }
} }
} }
@ -64,8 +64,8 @@ int _d_switch_string(char[][] table, char[] ca)
assert(i < table.length); assert(i < table.length);
if (table[i].length == ca.length) if (table[i].length == ca.length)
{ {
c = memcmp(table[i], ca, ca.length); cj = memcmp(table[i], ca, ca.length);
if (c == 0) if (cj == 0)
{ {
assert(i == result); assert(i == result);
break; break;
@ -95,6 +95,15 @@ int _d_switch_string(char[][] table, char[] ca)
printf("table[%d] = %d, '%s'\n", mid, pca.length, (char *)pca); printf("table[%d] = %d, '%s'\n", mid, pca.length, (char *)pca);
} }
*/ */
if (high &&
ca.length >= table[0].length &&
ca.length <= table[high - 1].length)
{
// Looking for 0 length string, which would only be at the beginning
if (ca.length == 0)
return 0;
char c1 = ca[0];
// Do binary search // Do binary search
while (low < high) while (low < high)
@ -103,6 +112,9 @@ int _d_switch_string(char[][] table, char[] ca)
pca = table[mid]; pca = table[mid];
c = ca.length - pca.length; c = ca.length - pca.length;
if (c == 0) if (c == 0)
{
c = (byte)c1 - (byte)pca[0];
if (c == 0)
{ {
c = memcmp(ca, pca, ca.length); c = memcmp(ca, pca, ca.length);
if (c == 0) if (c == 0)
@ -110,6 +122,7 @@ int _d_switch_string(char[][] table, char[] ca)
return mid; return mid;
} }
} }
}
if (c < 0) if (c < 0)
{ {
high = mid; high = mid;
@ -119,6 +132,8 @@ int _d_switch_string(char[][] table, char[] ca)
low = mid + 1; low = mid + 1;
} }
} }
}
//printf("not found\n"); //printf("not found\n");
return -1; // not found return -1; // not found
} }
@ -145,19 +160,19 @@ int _d_switch_ustring(wchar[][] table, wchar[] ca)
assert(ca.length >= 0); assert(ca.length >= 0);
// Make sure table[] is sorted correctly // Make sure table[] is sorted correctly
int i; int j;
for (i = 1; i < table.length; i++) for (j = 1; j < table.length; j++)
{ {
int len1 = table[i - 1].length; int len1 = table[j - 1].length;
int len2 = table[i].length; int len2 = table[j].length;
assert(len1 <= len2); assert(len1 <= len2);
if (len1 == len2) if (len1 == len2)
{ {
int c; int c;
c = memcmp(table[i - 1], table[i], len1 * wchar.size); c = memcmp(table[j - 1], table[j], len1 * wchar.size);
assert(c < 0); // c==0 means a duplicate assert(c < 0); // c==0 means a duplicate
} }
} }

71
ti_Ag.d Normal file
View file

@ -0,0 +1,71 @@
import string;
// byte[]
class TypeInfo_Ag : TypeInfo
{
uint getHash(void *p)
{ byte[] s = *(byte[]*)p;
uint len = s.length;
byte *str = s;
uint hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 9;
hash += *(ubyte *)str;
return hash;
case 2:
hash *= 9;
hash += *(ushort *)str;
return hash;
case 3:
hash *= 9;
hash += (*(ushort *)str << 8) +
((ubyte *)str)[2];
return hash;
default:
hash *= 9;
hash += *(uint *)str;
str += 4;
len -= 4;
break;
}
}
return hash;
}
int equals(void *p1, void *p2)
{
byte[] s1 = *(byte[]*)p1;
byte[] s2 = *(byte[]*)p2;
return s1.length == s2.length &&
memcmp((byte *)s1, (byte *)s2, s1.length) == 0;
}
int compare(void *p1, void *p2)
{
char[] s1 = *(char[]*)p1;
char[] s2 = *(char[]*)p2;
return string.cmp(s1, s2);
}
int tsize()
{
return (byte[]).size;
}
}

38
ti_cdouble.d Normal file
View file

@ -0,0 +1,38 @@
// cdouble
class TypeInfo_r : TypeInfo
{
uint getHash(void *p)
{
return ((uint *)p)[0] + ((uint *)p)[1] +
((uint *)p)[2] + ((uint *)p)[3];
}
int equals(void *p1, void *p2)
{
return *(cdouble *)p1 == *(cdouble *)p2;
}
int compare(void *p1, void *p2)
{
cdouble a = *(cdouble *) p1;
cdouble b = *(cdouble *) p2;
return a < b ? -1 : a > b ? 1 : 0;
}
int tsize()
{
return cdouble.size;
}
void swap(void *p1, void *p2)
{
cdouble t;
t = *(cdouble *)p1;
*(cdouble *)p1 = *(cdouble *)p2;
*(cdouble *)p2 = t;
}
}

37
ti_cfloat.d Normal file
View file

@ -0,0 +1,37 @@
// cfloat
class TypeInfo_q : TypeInfo
{
uint getHash(void *p)
{
return ((uint *)p)[0] + ((uint *)p)[1];
}
int equals(void *p1, void *p2)
{
return *(cfloat *)p1 == *(cfloat *)p2;
}
int compare(void *p1, void *p2)
{
cfloat a = *(cfloat *) p1;
cfloat b = *(cfloat *) p2;
return a < b ? -1 : a > b ? 1 : 0;
}
int tsize()
{
return cfloat.size;
}
void swap(void *p1, void *p2)
{
cfloat t;
t = *(cfloat *)p1;
*(cfloat *)p1 = *(cfloat *)p2;
*(cfloat *)p2 = t;
}
}

39
ti_creal.d Normal file
View file

@ -0,0 +1,39 @@
// creal
class TypeInfo_c : TypeInfo
{
uint getHash(void *p)
{
return ((uint *)p)[0] + ((uint *)p)[1] +
((uint *)p)[2] + ((uint *)p)[3] +
((uint *)p)[4];
}
int equals(void *p1, void *p2)
{
return *(creal *)p1 == *(creal *)p2;
}
int compare(void *p1, void *p2)
{
creal a = *(creal *) p1;
creal b = *(creal *) p2;
return a < b ? -1 : a > b ? 1 : 0;
}
int tsize()
{
return creal.size;
}
void swap(void *p1, void *p2)
{
creal t;
t = *(creal *)p1;
*(creal *)p1 = *(creal *)p2;
*(creal *)p2 = t;
}
}

View file

@ -5,7 +5,7 @@ class TypeInfo_d : TypeInfo
{ {
uint getHash(void *p) uint getHash(void *p)
{ {
return *(double *)p; return ((uint *)p)[0] + ((uint *)p)[1];
} }
int equals(void *p1, void *p2) int equals(void *p1, void *p2)

View file

@ -5,7 +5,7 @@ class TypeInfo_f : TypeInfo
{ {
uint getHash(void *p) uint getHash(void *p)
{ {
return *(float *)p; return *(uint *)p;
} }
int equals(void *p1, void *p2) int equals(void *p1, void *p2)

35
ti_idouble.d Normal file
View file

@ -0,0 +1,35 @@
// idouble
class TypeInfo_p : TypeInfo
{
uint getHash(void *p)
{
return ((uint *)p)[0] + ((uint *)p)[1];
}
int equals(void *p1, void *p2)
{
return *(idouble *)p1 == *(idouble *)p2;
}
int compare(void *p1, void *p2)
{
return *(double *)p1 - *(double *)p2;
}
int tsize()
{
return idouble.size;
}
void swap(void *p1, void *p2)
{
idouble t;
t = *(idouble *)p1;
*(idouble *)p1 = *(idouble *)p2;
*(idouble *)p2 = t;
}
}

35
ti_ifloat.d Normal file
View file

@ -0,0 +1,35 @@
// ifloat
class TypeInfo_o : TypeInfo
{
uint getHash(void *p)
{
return *(uint *)p;
}
int equals(void *p1, void *p2)
{
return *(ifloat *)p1 == *(ifloat *)p2;
}
int compare(void *p1, void *p2)
{
return *(float *)p1 - *(float *)p2;
}
int tsize()
{
return ifloat.size;
}
void swap(void *p1, void *p2)
{
ifloat t;
t = *(ifloat *)p1;
*(ifloat *)p1 = *(ifloat *)p2;
*(ifloat *)p2 = t;
}
}

35
ti_ireal.d Normal file
View file

@ -0,0 +1,35 @@
// ireal
class TypeInfo_j : TypeInfo
{
uint getHash(void *p)
{
return ((uint *)p)[0] + ((uint *)p)[1] + ((ushort *)p)[4];
}
int equals(void *p1, void *p2)
{
return *(ireal *)p1 == *(ireal *)p2;
}
int compare(void *p1, void *p2)
{
return *(real *)p1 - *(real *)p2;
}
int tsize()
{
return ireal.size;
}
void swap(void *p1, void *p2)
{
ireal t;
t = *(ireal *)p1;
*(ireal *)p1 = *(ireal *)p2;
*(ireal *)p2 = t;
}
}

View file

@ -5,7 +5,7 @@ class TypeInfo_l : TypeInfo
{ {
uint getHash(void *p) uint getHash(void *p)
{ {
return *(long *)p; return *(uint *)p + ((uint *)p)[1];
} }
int equals(void *p1, void *p2) int equals(void *p1, void *p2)
@ -15,7 +15,11 @@ class TypeInfo_l : TypeInfo
int compare(void *p1, void *p2) int compare(void *p1, void *p2)
{ {
return *(long *)p1 - *(long *)p2; if (*(long *)p1 < *(long *)p2)
return -1;
else if (*(long *)p1 > *(long *)p2)
return 1;
return 0;
} }
int tsize() int tsize()

35
ti_real.d Normal file
View file

@ -0,0 +1,35 @@
// real
class TypeInfo_e : TypeInfo
{
uint getHash(void *p)
{
return ((uint *)p)[0] + ((uint *)p)[1] + ((ushort *)p)[4];
}
int equals(void *p1, void *p2)
{
return *(real *)p1 == *(real *)p2;
}
int compare(void *p1, void *p2)
{
return *(real *)p1 - *(real *)p2;
}
int tsize()
{
return real.size;
}
void swap(void *p1, void *p2)
{
real t;
t = *(real *)p1;
*(real *)p1 = *(real *)p2;
*(real *)p2 = t;
}
}

View file

@ -5,7 +5,7 @@ class TypeInfo_m : TypeInfo
{ {
uint getHash(void *p) uint getHash(void *p)
{ {
return *(ulong *)p; return *(uint *)p + ((uint *)p)[1];
} }
int equals(void *p1, void *p2) int equals(void *p1, void *p2)
@ -15,7 +15,11 @@ class TypeInfo_m : TypeInfo
int compare(void *p1, void *p2) int compare(void *p1, void *p2)
{ {
return *(ulong *)p1 - *(ulong *)p2; if (*(ulong *)p1 < *(ulong *)p2)
return -1;
else if (*(ulong *)p1 > *(ulong *)p2)
return 1;
return 0;
} }
int tsize() int tsize()

View file

@ -17,7 +17,7 @@ class TypeInfo_u : TypeInfo
return *(wchar *)p1 - *(wchar *)p2; return *(wchar *)p1 - *(wchar *)p2;
} }
wchar tsize() int tsize()
{ {
return wchar.size; return wchar.size;
} }

View file

@ -34,7 +34,7 @@ int main(char[][] args)
OutBuffer b = new OutBuffer(); // outbuffer OutBuffer b = new OutBuffer(); // outbuffer
ctype.tolower('A'); // ctype ctype.tolower('A'); // ctype
RegExp r = new RegExp(null, null); // regexp RegExp r = new RegExp(null, null); // regexp
rand(); random.rand();
int a[]; int a[];
a.reverse; // adi a.reverse; // adi
a.sort; // qsort a.sort; // qsort

View file

@ -257,9 +257,8 @@ struct WIN32_FIND_DATA {
char cAlternateFileName[ 14 ]; char cAlternateFileName[ 14 ];
} }
export: export
{
BOOL CloseHandle(HANDLE hObject); BOOL CloseHandle(HANDLE hObject);
HANDLE CreateFileA(char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, HANDLE CreateFileA(char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition,
@ -280,6 +279,7 @@ DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
BOOL WriteFile(HANDLE hFile, void *lpBuffer, DWORD nNumberOfBytesToWrite, BOOL WriteFile(HANDLE hFile, void *lpBuffer, DWORD nNumberOfBytesToWrite,
DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped);
DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize); DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
}
export export