baud@GATECH.EDU (Kurt Baudendistel) (10/10/88)
BUG REPORT 14 BEHAVIOR: fatal signal 4 received by compiler. COMPILER VERSION: GNU C++ compiler driver, version 1.25.0 INPUT FILES: Fix.cc Fix.h type.h COMMAND LINE: g++ -v -g -c Fix.cc /usr/local/lib/gcc-cpp+ -v -I . -I ./include -I /dsp/mcclellan/baud/c++/include -I /usr/local/lib/g++-include -undef -D__GNU__ -D__GNUG__ -Dvax -Dunix Fix.cc /tmp/cc013738.cpp GNU CPP version 1.25.0 /usr/local/lib/gcc-c++ /tmp/cc013738.cpp -quiet -dumpbase Fix.cc -noreg -version -G -o /tmp/cc013738.s g++: Program c++ got fatal signal 4. FILE NAMES: tm.h = tm-vax.h md = vax.md MACHINE: vax 11/780 with BRL UNIX (4.2 BSD) SOURCE FILES: ---------------------------------------------------------------------------- #include <Fix.h> #include <Obstack.h> #include <std.h> // default parameters uint16 Fix_default_length = 16; uint16 Fix_set_default_length(uint16 newlen) { uint16 oldlen = Fix_default_length; Fix_default_length = newlen; return oldlen; } // error handling void default_Fix_error_handler(char* msg) { cerr << "Fatal Fix error. " << msg << "\n"; abort(); } one_arg_error_handler_t Fix_error_handler = default_Fix_error_handler; one_arg_error_handler_t set_Fix_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = Fix_error_handler; Fix_error_handler = f; return old; } void Fix::error(char* msg) { (*Fix_error_handler)(msg); } // compare two equal-length reps inline static int docmp(uint16* x, uint16* y, int siz) { int diff = (int16 )*x - (int16 )*y; while ( siz-- && !diff ) diff = (int32 )(uint32 )*++x - (int32 )(uint32 )*++y; return diff; } // compare rep to zero inline static int docmpz(uint16* x, int siz) { while ( siz-- ) if ( *x++ ) return 1; return 0; } // allocate a new _Frep static _Fix new_Frep(int len, _Fix x = NULL ) { int siz = (len + 15) >> 4; unsigned allocsiz = sizeof(_Frep) + (siz - 1) * sizeof(uint16); _Fix z = (_Fix ) (malloc(allocsiz)); if (z == 0) (*Fix_error_handler)("Out of memory."); z->len = len; z->siz = siz; z->ref = 1; if ( x != NULL ) { uint16 *zs = z->s, *xs = x->s; int imax = z->siz <? x->siz; for ( int i=0; i < imax; i++ ) *zs++ = *xs++; if ( imax != z->siz ) for ( ; i < z->siz; i++ ) *zs++ = 0; mask(z); } return z; } // convert to a double double Fix::operator double() { double d = 0.0; for (int i = rep->siz - 1; i >= 0; --i) { d += rep->s[i]; d *= 1./32768.; } d *= 2.; return d >= 1. ? d : d - 2.; } // comparison functions int compare(Fix x, Fix y) { if ( x.rep->siz == y.rep->siz ) return docmp(x.rep->s, y.rep->s, x.rep->siz); else { int r; _Frep longer, shorter; if ( x.rep->siz > y.rep->siz ) { longer = x.rep; shorter = y.rep; r = 1; } else { longer = y.rep; shorter = x.rep; r = -1; } int diff = docmp(x.rep->s, y.rep->s, shorter->siz); if ( diff ) return diff; else if ( docmpz(&longer->s[shorter->siz], longer->siz-shorter->siz) ) return r; else return 0; } } // arithmetic functions _Fix add(_Fix x, _Fix y, _Fix r) { _Fix longer, shorter; if ( x->len >= y->len ) longer = x, shorter = y; else longer = y, shorter = x; if ( r == NULL ) r = new_Frep(longer->len); for ( int i=r->siz; i > longer->siz; i-- ) r->s[i] = 0; for ( ; i > shorter->siz; i-- ) r->s[i] = longer->s[i]; uint32 carry = 0, sum; for ( ; i >= 0; i-- ) { sum = carry + longer->s[i] + shorter->s[i]; carry = sum >> 16; r->s[i] = sum & _Fix_mask; } if ( (x->s[0] ^ sum) & (y->s[0] ^ sum) & _Fix_msb ) (*Fix_overflow_handler)(result); return r; } _Fix subtract(_Fix x, _Fix y, _Fix r) { _Fix longer, shorter; if ( x->len >= y->len ) longer = x, shorter = y; else longer = y, shorter = x; if ( r == NULL ) r = new_Frep(longer->len); for ( int i=r->siz; i > longer->siz; i-- ) r->s[i] = 0; for ( ; i > shorter->siz; i-- ) r->s[i] = longer->s[i]; uint32 carry = 0, sum; for ( ; i >= 0; i-- ) { sum = carry + longer->s[i] - shorter->s[i]; carry = sum >> 16 ? _Fix_borrow: 0; r->s[i] = sum & _Fix_mask; } if ( (x->s[0] ^ sum) & (y->s[0] ^ sum) & _Fix_msb ) (*Fix_overflow_handler)(result); return r; } Fix operator * (Fix x, Fix y) { _Frep result(x.rep->len + y.rep->len - 1); for ( int i=0; i < result->siz; i++ ) result->s[i] = 0; for ( i=x.rep->siz; i >= 0; i-- ) { int carry = 0; for ( int j=y.rep->siz; j >= 0; j-- ) { uint32 a = x.rep->s[i] * y.rep->s[i]; uint32 b = result->s[i+j+1] + ((a << 1) & 0xffff) + carry; result->s[i+j+1] = b & 0xffff; carry = ((a >> 15) & 0x1ffff) + (b >> 16); } result->s[i] = carry & 0xffff; if ( carry >> 16 ) for ( int k=i-1; k >=0; k-- ) result->s[i]--; } return Fix(result); } //?? Fix shift(Fix x, int y) { int xl = x.rep->len; if (xl == 0 || y == 0) { r = x; return; } int xrsame = x.rep == r.rep; int rsgn = x.rep->sgn; long ay = (y < 0)? -y : y; int bw = ay / I_SHIFT; int sw = ay % I_SHIFT; if (y > 0) { int rl = bw + xl + 1; r.setlength(rl); r.rep->sgn = rsgn; uint16* botr = r.rep->s; uint16* botx = (xrsame)? botr : x.rep->s; uint16* rs = &(botr[rl - 1]); uint16* xs = &(botx[xl - 1]); uint32 a = 0; while (xs >= botx) { a = up(a) | ((uint32)(*xs--) << sw); *rs-- = extract(down(a)); } *rs-- = extract(a); while (rs >= botr) *rs-- = 0; } else { int rl = xl - bw; if (rl <= 0) r.copy(_Fix_Zero); else { r.setlength(rl); r.rep->sgn = rsgn; int rw = I_SHIFT - sw; uint16* rs = r.rep->s; uint16* topr = &(rs[rl]); uint16* botx = (xrsame)? rs : x.rep->s; uint16* xs = &(botx[bw]); uint16* topx = &(botx[xl]); uint32 a = (uint32)(*xs++) >> sw; while (xs < topx) { a |= (uint32)(*xs++) << rw; *rs++ = extract(a); a = down(a); } *rs++ = extract(a); while (rs < topr) *rs++ = 0; } } r.checklength(); } //?? Fix Fix::operator -() { Fix x; x.copy(rep->s, rep->len, !rep->sgn); return x; } extern Obstack _libgxx_io_ob; extern char* _libgxx_io_oblast; //?? char* Itoa(Fix x, int base = 10, int width = 0) { if (_libgxx_io_oblast) _libgxx_io_ob.free(_libgxx_io_oblast); int wrksiz = (x.rep->len + 1) * I_SHIFT * 4 + 1 + width; _libgxx_io_ob.blank(wrksiz); _libgxx_io_oblast = (char*)(_libgxx_io_ob.finish()); char* obbase = _libgxx_io_oblast; char* e = obbase + wrksiz - 1; char* s = e; *--s = 0; int xsgn = sign(x); if (xsgn == 0) *--s = '0'; else { Fix z = abs(x); // split division by base into two parts: // first divide by biggest power of base that fits in an uint16, // then use straight signed div/mods from there. // find power int bpower = 1; uint16 b = base; uint16 maxb = I_MAXNUM / base; while (b < maxb) { b *= base; ++bpower; } int rem; for(;;) { divide(z, b, z, rem); if (z.rep->len == 0) { while (rem != 0) { char ch = rem % base; rem /= base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } break; } else { for (int i = 0; i < bpower; ++i) { char ch = rem % base; rem /= base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } } } } if (xsgn < 0) *--s = '-'; int w = e - s - 1; while (w++ < width) *--s = ' '; return s; } //?? istream& operator >> (istream& s, Fix y) { int got_one = 0; if (!s.readable()) { s.error(); return s; } if (_libgxx_io_oblast) _libgxx_io_ob.free(_libgxx_io_oblast); char sgn = 0; char ch; s >> WS; while (s.good()) { s.get(ch); if (ch == '-') { if (sgn == 0) { sgn = 1; _libgxx_io_ob.grow(ch); } else break; } else if (ch >= '0' && ch <= '9') { got_one = 1; _libgxx_io_ob.grow(ch); } else break; } char * p = (char*)(_libgxx_io_ob.finish(0)); _libgxx_io_oblast = p; if (s.good()) s.unget(ch); if (!got_one) s.error(); else y = atoI(p); return s; } ---------------------------------------------------------------------------- #ifndef _Fix_h #define _Fix_h 1 #include <stream.h> #include <stddef.h> #include <type.h> #include <Integer.h> #define _Fix_mask 0xffff #define _Fix_msb 0x8000 #define _Fix_borrow 0xffffffff #define _Fix_min_length 1 #define _Fix_max_length 65535 extern uint16 Fix_default_length; struct _Frep // internal Fix representation { uint16 len; // length in bits uint16 siz; // allocated storage int16 ref; // reference count uint16 s[1]; // represented as ushort array starting here }; typedef struct _Frep* _Fix; class Fix { _Fix rep; Fix(_Fix); void unique(); void copy(int, uint16*); friend int compare(_Fix, _Fix); friend void mask(_Fix); friend _Fix new_Frep(int, _Fix = NULL); friend _Fix add(_Fix, _Fix, _Fix = NULL); friend _Fix subtract(_Fix, _Fix, _Fix = NULL); friend _Fix multiply(_Fix, _Fix, _Fix = NULL); friend _Fix multiply(_Fix, long, _Fix = NULL); friend _Fix divide(_Fix, _Fix, _Fix = NULL); friend _Fix shift(_Fix, int, _Fix = NULL); public: Fix(); Fix(Fix&); Fix(double&); Fix(int); Fix(int, Fix&); Fix(int, double&); ~Fix(); Fix operator = (Fix&); Fix operator = (double&); friend int operator == (Fix&, Fix& ); friend int operator != (Fix&, Fix&); friend int operator < (Fix&, Fix&); friend int operator <= (Fix&, Fix&); friend int operator > (Fix&, Fix&); friend int operator >= (Fix&, Fix&); Fix operator - (); friend Fix operator + (Fix&, Fix&); friend Fix operator - (Fix&, Fix&); friend Fix operator * (Fix&, Fix&); friend Fix operator / (Fix&, Fix&); friend Fix operator * (Fix&, long); friend Fix operator % (Fix&, long); friend Fix operator << (Fix&, long); friend Fix operator >> (Fix&, long); friend Fix operator <? (Fix&, Fix&); // min friend Fix operator >? (Fix&, Fix&); // max Fix operator += (Fix&); Fix operator -= (Fix&); Fix operator *= (Fix&); Fix operator /= (Fix&); Fix operator *= (long); Fix operator %= (long); Fix operator <<=(long); Fix operator >>=(long); // builtin Fix functions friend Fix abs(Fix&); // absolute value friend int sgn(Fix&); // returns -1, 0, +1 // coercion & conversion friend Integer mantissa(Fix&); friend double value(Fix&); friend char* Ftoa(Fix&, int base = 10, int width = 0); friend Fix atoF(const char*); friend istream& operator >> (istream&, Fix&); friend ostream& operator << (ostream&, Fix&); // miscellany void error(char* msg); }; // error handlers extern void default_Fix_error_handler(char*); extern one_arg_error_handler_t Fix_error_handler; extern one_arg_error_handler_t set_Fix_error_handler(one_arg_error_handler_t f); //#ifdef __OPTIMIZE__ inline void Fix::unique() { if ( rep->ref > 1 ) { rep->ref--; rep = new_Frep(rep->len,rep); } } inline void Fix::copy(int l, uint16* t) { uint16 *s = rep->s; while ( l-- ) *s++ = *t++; } inline Fix::Fix() { rep = new_Frep(Fix_default_length); } inline Fix::Fix(int len) { if ( len < _Fix_min_length || len > _Fix_max_length ) error("illegal length in Fix declaration"); rep = new_Frep(len); } inline Fix::Fix(Fix& y) { rep = y.rep, rep->ref++; } inline Fix::Fix(int len, Fix& y) { if ( len < _Fix_min_length || len > _Fix_max_length ) error("illegal length in Fix declaration"); else if ( len == y.rep->len ) rep = y.rep, rep->ref++; else rep = new_Frep(len,y.rep); } inline Fix::~Fix() { if ( --rep->ref <= 0 ) delete rep; } inline Fix Fix::operator = (Fix& y) { if ( --rep->ref <= 0 ) delete rep; if ( rep->len == y.rep->len ) rep = y.rep, rep->ref++; else copy(rep->len,y.rep->s); return *this; } inline int operator == (Fix& x, Fix& y) { return compare(x.rep, y.rep) == 0; } inline int operator != (Fix& x, Fix& y) { return compare(x.rep, y.rep) != 0; } inline int operator < (Fix& x, Fix& y) { return compare(x.rep, y.rep) < 0; } inline int operator <= (Fix& x, Fix& y) { return compare(x.rep, y.rep) <= 0; } inline int operator > (Fix& x, Fix& y) { return compare(x.rep, y.rep) > 0; } inline int operator >= (Fix& x, Fix& y) { return compare(x.rep, y.rep) >= 0; } inline int sgn(Fix& x) { return (x.rep->len == 0) ? 0 : ( x.rep->s[0] & _Fix_msb ? 1 : -1 ); } inline Fix operator + (Fix& x, Fix& y) { _Fix r = add(x.rep, y.rep); return r; } inline Fix operator - (Fix& x, Fix& y) { _Fix r = subtract(x.rep, y.rep); return r; } inline Fix operator * (Fix& x, Fix& y) { _Fix r = multiply(x.rep, y.rep); return r; } inline Fix operator * (Fix& x, long y) { _Fix r = multiply(x.rep, y); return r; } inline Fix operator / (Fix& x, Fix& y) { _Fix r = divide(x.rep, y.rep); return r; } inline Fix Fix::operator += (Fix& y) { unique(); add(this->rep, y.rep, this->rep); return *this; } inline Fix Fix::operator -= (Fix& y) { unique(); subtract(this->rep, y.rep, this->rep); return *this; } inline Fix Fix::operator *= (Fix& y) { unique(); multiply(this->rep, y.rep, this->rep); return *this; } inline Fix Fix::operator *= (long y) { unique(); multiply(this->rep, y, this->rep); return *this; } inline Fix Fix::operator /= (Fix& y) { unique(); divide(this->rep, y.rep, this->rep); return *this; } inline Fix operator % (Fix& x, long y) { Fix r(x.rep->len + y, x); return r; } inline Fix Fix::operator %= (long y) { Fix r(rep->len + y, *this); return *this = r; } inline Fix operator << (Fix& x, long y) { _Fix rep = shift(x.rep, y); return rep; } inline Fix operator >> (Fix& x, long y) { _Fix rep = shift(x.rep, -y); return rep; } inline Fix Fix::operator <<= (long y) { unique(); shift(this->rep, y, this->rep); return *this; } inline Fix Fix::operator >>= (long y) { unique(); shift(this->rep, -y, this->rep); return *this; } inline Fix operator <? (Fix& x, Fix& y) { if (compare(x.rep, y.rep) <= 0) return x; else return y; } inline Fix operator >? (Fix& x, Fix& y) { if (compare(x.rep, y.rep) >= 0) return x; else return y; } inline Fix abs(Fix& y) { return y >= 0 ? y : -y; } inline ostream& operator << (ostream& s, Fix& y) { return s << Ftoa(y); } inline void mask (_Fix x) { x->s[x->siz - 1] &= 0xffff << (16 - x->len & 0x000f); } inline Fix atoF(const char* s) { return atof(s); } //#endif #endif ---------------------------------------------------------------------------- // // type.h : machine type definitions // #ifndef TYPEH #define TYPEH typedef short int int16; typedef long int int32; typedef unsigned short int uint16; typedef unsigned long int uint32; typedef unsigned int uint; typedef unsigned char byte; #endif ----------------------------------------------------------------------------