////////////////////////////////////////////////////////////////////// // // Quotient header // // File: quotient.h // Description : quotient template class declaration and inlined implementation // // History: // -:Created by Anton Knyazev // ////////////////////////////////////////////////////////////////////// #ifndef quotient_h #define quotient_h #pragma once // warning: all comparisons assume quotent's y>=0, use fixsign() to ensure this is the case template class quotient_tpl { public: quotient_tpl() {} quotient_tpl(type_min) { x=-1;y=0; } quotient_tpl(type_max) { x=1;y=0; } explicit quotient_tpl(ftype _x,ftype _y=1) { x=_x;y=_y; } quotient_tpl(const quotient_tpl& src) { x=src.x;y=src.y; } template quotient_tpl(const quotient_tpl& src) { x=src.x;y=src.y; } template quotient_tpl& set(ftype1 nx,ftype2 ny) { (*this=nx)/=ny; return *this; } quotient_tpl& operator=(const quotient_tpl& src) { x=src.x;y=src.y; return *this; } template quotient_tpl& operator=(const quotient_tpl& src) { x=src.x;y=src.y; return *this; } quotient_tpl& operator=(ftype src) { x=src;y=1; return *this; } quotient_tpl& fixsign() { int sgny=::sgnnz(y); x*=sgny; y*=sgny; return *this; } ftype val() { return y!=0 ? x/y : 0; } quotient_tpl operator-() const { return quotient_tpl(-x,y); } quotient_tpl operator*(ftype op) const { return quotient_tpl(x*op,y); } quotient_tpl operator/(ftype op) const { return quotient_tpl(x,y*op); } quotient_tpl operator+(ftype op) const { return quotient_tpl(x+y*op,y); } quotient_tpl operator-(ftype op) const { return quotient_tpl(x-y*op,y); } quotient_tpl& operator*=(ftype op) { x*=op; return *this; } quotient_tpl& operator/=(ftype op) { y*=op; return *this; } quotient_tpl& operator+=(ftype op) { x+=op*y; return *this; } quotient_tpl& operator-=(ftype op) { x-=op*y; return *this; } bool operator==(ftype op) const { return x==op*y; } bool operator!=(ftype op) const { return x!=op*y; } bool operator<(ftype op) const { return x-op*y<0; } bool operator>(ftype op) const { return x-op*y>0; } bool operator<=(ftype op) const { return x-op*y<=0; } bool operator>=(ftype op) const { return x-op*y>=0; } int sgn() { return ::sgn(x); } int sgnnz() { return ::sgnnz(x); } int isneg() { return ::isneg(x); } int isnonneg() { return ::isnonneg(x); } int isin01() { return ::isneg(fabs_tpl(x*2-y)-fabs_tpl(y)); } ftype x,y; }; template<> inline quotient_tpl::quotient_tpl(type_min) { x=-1;y=1E-15f; } template<> inline quotient_tpl::quotient_tpl(type_max) { x=1;y=1E-15f; } template<> inline quotient_tpl::quotient_tpl(type_min) { x=-1;y=1E-50f; } template<> inline quotient_tpl::quotient_tpl(type_max) { x=1;y=1E-50f; } template quotient_tpl operator*(const quotient_tpl &op1,const quotient_tpl &op2) { return quotient_tpl(op1.x*op2.x,op1.y*op2.y); } template quotient_tpl operator/(const quotient_tpl &op1,const quotient_tpl &op2) { return quotient_tpl(op1.x*op2.y,op1.y*op2.x); } template quotient_tpl operator+(const quotient_tpl &op1,const quotient_tpl &op2) { return /*op1.y==op2.y ? quotient_tpl(op1.x+op2.x,op1.y) :*/ quotient_tpl(op1.x*op2.y+op2.x*op1.y, op1.y*op2.y); } template quotient_tpl operator-(const quotient_tpl &op1,const quotient_tpl &op2) { return /*op1.y==op2.y ? quotient_tpl(op1.x-op2.x,op1.y) :*/ quotient_tpl(op1.x*op2.y-op2.x*op1.y, op1.y*op2.y); } template quotient_tpl& operator*=(quotient_tpl &op1,const quotient_tpl &op2) { op1.x*=op2.x; op1.y*=op2.y; return op1; } template quotient_tpl& operator/=(quotient_tpl &op1,const quotient_tpl &op2) { op1.x*=op2.y; op1.y*=op2.x; return op1; } template quotient_tpl& operator+=(quotient_tpl &op1,const quotient_tpl &op2) { /*if (op1.y==op2.y) op1.x+=op2.x; else*/ { op1.x=op1.x*op2.y+op2.x*op1.y; op1.y*=op2.y; } return op1; } template quotient_tpl& operator-=(quotient_tpl &op1,const quotient_tpl &op2) { /*if (op1.y==op2.y) op1.x-=op2.x; else*/ { op1.x=op1.x*op2.y-op2.x*op1.y; op1.y*=op2.y; } return op1; } template quotient_tpl operator*(ftype op, const quotient_tpl &q) { return quotient_tpl(q.x*op,q.y); } template quotient_tpl operator/(ftype op, const quotient_tpl &q) { return quotient_tpl(q.x,q.y*op); } template quotient_tpl operator+(ftype op, const quotient_tpl &q) { return quotient_tpl(op*q.y+q.x,q.y); } template quotient_tpl operator-(ftype op, const quotient_tpl &q) { return quotient_tpl(op*q.y-q.x,q.y); } template bool operator==(ftype op1, const quotient_tpl &op2) { return op1*op2.y==op2.x; } template bool operator!=(ftype op1, const quotient_tpl &op2) { return op1*op2.y!=op2.x; } template bool operator<(ftype op1, const quotient_tpl &op2) { return op1*op2.y-op2.x<0; } template bool operator>(ftype op1, const quotient_tpl &op2) { return op1*op2.y-op2.x>0; } template bool operator<=(ftype op1, const quotient_tpl &op2) { return op1*op2.y-op2.x<=0; } template bool operator>=(ftype op1, const quotient_tpl &op2) { return op1*op2.y-op2.x>=0; } template bool operator==(const quotient_tpl &op1, const quotient_tpl &op2) { return op1.x*op2.y==op2.x*op1.y; } template bool operator!=(const quotient_tpl &op1, const quotient_tpl &op2) { return op1.x*op2.y!=op2.x*op1.y; } template bool operator<(const quotient_tpl &op1, const quotient_tpl &op2) { return op1.x*op2.y-op2.x*op1.y < 0; } template bool operator>(const quotient_tpl &op1, const quotient_tpl &op2) { return op1.x*op2.y-op2.x*op1.y > 0; } template bool operator<=(const quotient_tpl &op1, const quotient_tpl &op2) { return op1.x*op2.y-op2.x*op1.y <= 0; } template bool operator>=(const quotient_tpl &op1, const quotient_tpl &op2) { return op1.x*op2.y-op2.x*op1.y >= 0; } template int sgn(const quotient_tpl &op) { return sgn(op.x); } template int sgnnz(const quotient_tpl &op) { return sgnnz(op.x); } template int isneg(const quotient_tpl &op) { return isneg(op.x); } template int isnonneg(const quotient_tpl &op) { return isnonneg(op.x); } template int sgn_safe(const quotient_tpl &op) { return sgn(op.x)*sgnnz(op.y); } template int sgnnz_safe(const quotient_tpl &op) { return sgnnz(op.x)*sgnnz(op.y); } template int isneg_safe(const quotient_tpl &op) { return isneg(op.x)^isneg(op.y); } template int isnonneg_safe(const quotient_tpl &op) { return isnonneg(op.x)*isnonneg(op.y); } template quotient_tpl fabs_tpl(const quotient_tpl op) { return quotient_tpl(fabs_tpl(op.x),fabs_tpl(op.y)); } template quotient_tpl max(const quotient_tpl &op1,const quotient_tpl &op2) { int mask1=isneg(op2.x*op1.y-op1.x*op2.y), mask2=mask1^1; return quotient_tpl(op1.x*mask1+op2.x*mask2, op1.y*mask1+op2.y*mask2); } template quotient_tpl min(const quotient_tpl &op1,const quotient_tpl &op2) { int mask1=isneg(op1.x*op2.y-op2.x*op1.y), mask2=mask1^1; return quotient_tpl(op1.x*mask1+op2.x*mask2, op1.y*mask1+op2.y*mask2); } template quotient_tpl fake_atan2(ftype y,ftype x) { quotient_tpl res; ftype src[2] = { x,y }; int ix=isneg(x),iy=isneg(y),iflip=isneg(fabs_tpl(x)-fabs_tpl(y)); res.x = src[iflip^1]*(1-iflip*2)*sgnnz(src[iflip]); res.y = fabs_tpl(src[iflip]); res += (iy*2+(ix^iy)+(iflip^ix^iy))*2; return res; } typedef quotient_tpl quotientf; typedef quotient_tpl quotient; typedef quotient_tpl quotienti; #endif