/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : quotient template class declaration and inlined implementation #ifndef CRYINCLUDE_CRYPHYSICS_QUOTIENT_H #define CRYINCLUDE_CRYPHYSICS_QUOTIENT_H #pragma once #if ENABLE_CRY_PHYSICS // warning: all comparisons assume quotent's y>=0, use fixsign() to ensure this is the case #define sgnnz_result_type(F) int #define isneg_result_type(F) int 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 ILINE quotient_tpl& set(ftype1 nx, ftype2 ny) { (*this = nx) /= ny; return *this; } ILINE quotient_tpl& operator=(const quotient_tpl& src) { x = src.x; y = src.y; return *this; } template ILINE quotient_tpl& operator=(const quotient_tpl& src) { x = src.x; y = src.y; return *this; } ILINE quotient_tpl& operator=(ftype src) { x = src; y = 1; return *this; } ILINE quotient_tpl& fixsign() { int sgny = ::sgnnz(y); x *= sgny; y *= sgny; return *this; } ILINE ftype val() { return y != 0 ? x / y : 0; } ILINE quotient_tpl operator-() const { return quotient_tpl(-x, y); } ILINE quotient_tpl operator*(ftype op) const { quotient_tpl rvo(x * op, y); return rvo; } ILINE quotient_tpl operator/(ftype op) const { quotient_tpl rvo(x, y * op); return rvo; } ILINE quotient_tpl operator+(ftype op) const { quotient_tpl rvo(x + y * op, y); return rvo; } ILINE quotient_tpl operator-(ftype op) const { quotient_tpl rvo(x - y * op, y); return rvo; } ILINE quotient_tpl& operator*=(ftype op) { x *= op; return *this; } ILINE quotient_tpl& operator/=(ftype op) { y *= op; return *this; } ILINE quotient_tpl& operator+=(ftype op) { x += op * y; return *this; } ILINE quotient_tpl& operator-=(ftype op) { x -= op * y; return *this; } ILINE bool operator==(ftype op) const { return x == op * y; } ILINE bool operator!=(ftype op) const { return x != op * y; } ILINE bool operator<(ftype op) const { return x - op * y < 0; } ILINE bool operator>(ftype op) const { return x - op * y > 0; } ILINE bool operator<=(ftype op) const { return x - op * y <= 0; } ILINE bool operator>=(ftype op) const { return x - op * y >= 0; } ILINE int sgn() { return ::sgn(x); } ILINE sgnnz_result_type(ftype) sgnnz() { return ::sgnnz(x); } ILINE isneg_result_type(ftype) isneg() { return ::isneg(x); } ILINE int isnonneg() { return ::isnonneg(x); } ILINE isneg_result_type(ftype) isin01() { return ::isneg(fabs_tpl(x * 2 - y) - fabs_tpl(y)); } ftype x, y; }; inline float getmin(float) { return 1E-20f; } inline double getmin(double) { return 1E-80; } template<> inline quotient_tpl::quotient_tpl(type_min) { x = -1.f; y = 1E-20f; } template<> inline quotient_tpl::quotient_tpl(type_max) { x = 1.f; y = 1E-20f; } template<> inline quotient_tpl::quotient_tpl(type_min) { x = -1.; y = 1E-80; } template<> inline quotient_tpl::quotient_tpl(type_max) { x = 1.; y = 1E-80; } template ILINE quotient_tpl operator*(const quotient_tpl& op1, const quotient_tpl& op2) { quotient_tpl rvo(op1.x * op2.x, op1.y * op2.y); return rvo; } template ILINE quotient_tpl operator/(const quotient_tpl& op1, const quotient_tpl& op2) { quotient_tpl rvo(op1.x * op2.y, op1.y * op2.x); return rvo; } template ILINE quotient_tpl operator+(const quotient_tpl& op1, const quotient_tpl& op2) { /*op1.y==op2.y ? quotient_tpl(op1.x+op2.x,op1.y) :*/ quotient_tpl rvo(op1.x * op2.y + op2.x * op1.y, op1.y * op2.y); return rvo; } template ILINE quotient_tpl operator-(const quotient_tpl& op1, const quotient_tpl& op2) { /*op1.y==op2.y ? quotient_tpl(op1.x-op2.x,op1.y) :*/ quotient_tpl rvo(op1.x * op2.y - op2.x * op1.y, op1.y * op2.y); return rvo; } template ILINE quotient_tpl& operator*=(quotient_tpl& op1, const quotient_tpl& op2) { op1.x *= op2.x; op1.y *= op2.y; return op1; } template ILINE quotient_tpl& operator/=(quotient_tpl& op1, const quotient_tpl& op2) { op1.x *= op2.y; op1.y *= op2.x; return op1; } template ILINE 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 ILINE 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 ILINE quotient_tpl operator*(ftype op, const quotient_tpl& q) { return quotient_tpl(q.x * op, q.y); } template ILINE quotient_tpl operator/(ftype op, const quotient_tpl& q) { return quotient_tpl(q.x, q.y * op); } template ILINE quotient_tpl operator+(ftype op, const quotient_tpl& q) { return quotient_tpl(op * q.y + q.x, q.y); } template ILINE quotient_tpl operator-(ftype op, const quotient_tpl& q) { return quotient_tpl(op * q.y - q.x, q.y); } template ILINE bool operator==(ftype op1, const quotient_tpl& op2) { return op1 * op2.y == op2.x; } template ILINE bool operator!=(ftype op1, const quotient_tpl& op2) { return op1 * op2.y != op2.x; } template ILINE bool operator<(ftype op1, const quotient_tpl& op2) { return op1 * op2.y - op2.x < 0; } template ILINE bool operator>(ftype op1, const quotient_tpl& op2) { return op1 * op2.y - op2.x > 0; } template ILINE bool operator<=(ftype op1, const quotient_tpl& op2) { return op1 * op2.y - op2.x <= 0; } template ILINE bool operator>=(ftype op1, const quotient_tpl& op2) { return op1 * op2.y - op2.x >= 0; } template ILINE bool operator==(const quotient_tpl& op1, const quotient_tpl& op2) { return op1.x * op2.y == op2.x * op1.y; } template ILINE bool operator!=(const quotient_tpl& op1, const quotient_tpl& op2) { return op1.x * op2.y != op2.x * op1.y; } template ILINE bool operator<(const quotient_tpl& op1, const quotient_tpl& op2) { return op1.x * op2.y - op2.x * op1.y + getmin(op1.x) * (op1.x - op2.x) < 0; } template ILINE bool operator>(const quotient_tpl& op1, const quotient_tpl& op2) { return op1.x * op2.y - op2.x * op1.y + getmin(op1.x) * (op1.x - op2.x) > 0; } template ILINE bool operator<=(const quotient_tpl& op1, const quotient_tpl& op2) { return op1.x * op2.y - op2.x * op1.y + getmin(op1.x) * (op1.x - op2.x) <= 0; } template ILINE bool operator>=(const quotient_tpl& op1, const quotient_tpl& op2) { return op1.x * op2.y - op2.x * op1.y + getmin(op1.x) * (op1.x - op2.x) >= 0; } template ILINE int sgn(const quotient_tpl& op) { return sgn(op.x); } template ILINE sgnnz_result_type(ftype) sgnnz(const quotient_tpl &op) { return sgnnz(op.x); } template ILINE isneg_result_type(ftype) isneg(const quotient_tpl &op) { return isneg(op.x); } template ILINE int isnonneg(const quotient_tpl& op) { return isnonneg(op.x); } template ILINE int sgn_safe(const quotient_tpl& op) { return sgn(op.x) * sgnnz(op.y); } template ILINE sgnnz_result_type(ftype) sgnnz_safe(const quotient_tpl &op) { return sgnnz(op.x * op.y); } template ILINE isneg_result_type(ftype) isneg_safe(const quotient_tpl &op) { return isneg(op.x * op.y); } template ILINE int isnonneg_safe(const quotient_tpl& op) { return isnonneg(op.x) * isnonneg(op.y); } template ILINE quotient_tpl fabs_tpl(const quotient_tpl op) { return quotient_tpl(fabs_tpl(op.x), fabs_tpl(op.y)); } template ILINE 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); return op1 > op2 ? op1 : op2; } template ILINE 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); return op1 < op2 ? op1 : op2; } template ILINE 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 // ENABLE_CRY_PHYSICS #endif // CRYINCLUDE_CRYPHYSICS_QUOTIENT_H