Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/maths/Fixed.h
/* Copyright (C) 2013 Wildfire Games. | /* Copyright (C) 2020 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
Show All 16 Lines | |||||
#ifndef NDEBUG | #ifndef NDEBUG | ||||
#define USE_FIXED_OVERFLOW_CHECKS | #define USE_FIXED_OVERFLOW_CHECKS | ||||
#endif | #endif | ||||
#if MSC_VERSION | #if MSC_VERSION | ||||
// i32*i32 -> i64 multiply: MSVC x86 doesn't optimise i64 multiplies automatically, so use the intrinsic | // i32*i32 -> i64 multiply: MSVC x86 doesn't optimise i64 multiplies automatically, so use the intrinsic | ||||
#include <intrin.h> | #include <intrin.h> | ||||
#define FIXED_MUL_I64_I32_I32(a, b) (__emul((a), (b))) | #define MUL_I64_I32_I32(a, b)\ | ||||
(__emul((a), (b))) | |||||
#define SQUARE_U64_FIXED(a)\ | |||||
static_cast<u64>(__emul((a).GetInternalValue(), (a).GetInternalValue())) | |||||
#else | #else | ||||
#define FIXED_MUL_I64_I32_I32(a, b) ((i64)(a) * (i64)(b)) | #define MUL_I64_I32_I32(a, b)\ | ||||
static_cast<i64>(a) * static_cast<i64>(b) | |||||
#define SQUARE_U64_FIXED(a)\ | |||||
static_cast<u64>(static_cast<i64>((a).GetInternalValue()) * static_cast<i64>((a).GetInternalValue())) | |||||
#endif | #endif | ||||
//define overflow macros | //define overflow macros | ||||
#ifndef USE_FIXED_OVERFLOW_CHECKS | #ifndef USE_FIXED_OVERFLOW_CHECKS | ||||
#define CheckSignedSubtractionOverflow(type, left, right, overflowWarning, underflowWarning) | #define CheckSignedSubtractionOverflow(type, left, right, overflowWarning, underflowWarning) | ||||
#define CheckSignedAdditionOverflow(type, left, right, overflowWarning, underflowWarning) | #define CheckSignedAdditionOverflow(type, left, right, overflowWarning, underflowWarning) | ||||
#define CheckCastOverflow(var, targetType, overflowWarning, underflowWarning) | #define CheckCastOverflow(var, targetType, overflowWarning, underflowWarning) | ||||
▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | public: | ||||
CFixed Absolute() const { return CFixed(abs(value)); } | CFixed Absolute() const { return CFixed(abs(value)); } | ||||
/** | /** | ||||
* Multiply by a CFixed. Likely to overflow if both numbers are large, | * Multiply by a CFixed. Likely to overflow if both numbers are large, | ||||
* so we use an ugly name instead of operator* to make it obvious. | * so we use an ugly name instead of operator* to make it obvious. | ||||
*/ | */ | ||||
CFixed Multiply(CFixed n) const | CFixed Multiply(CFixed n) const | ||||
{ | { | ||||
i64 t = FIXED_MUL_I64_I32_I32(value, n.value); | i64 t = MUL_I64_I32_I32(value, n.value); | ||||
t >>= fract_bits; | t >>= fract_bits; | ||||
CheckCastOverflow(t, T, L"Overflow in CFixed::Multiply(CFixed n)", L"Underflow in CFixed::Multiply(CFixed n)") | CheckCastOverflow(t, T, L"Overflow in CFixed::Multiply(CFixed n)", L"Underflow in CFixed::Multiply(CFixed n)") | ||||
return CFixed((T)t); | return CFixed((T)t); | ||||
} | } | ||||
/** | /** | ||||
* Multiply the value by itself. Might overflow. | * Multiply the value by itself. Might overflow. | ||||
*/ | */ | ||||
CFixed Square() const | CFixed Square() const | ||||
{ | { | ||||
return (*this).Multiply(*this); | return (*this).Multiply(*this); | ||||
} | } | ||||
/** | /** | ||||
* Compute this*m/d. Must not have d == 0. Won't overflow if the result can be represented as a CFixed. | * Compute this*m/d. Must not have d == 0. Won't overflow if the result can be represented as a CFixed. | ||||
*/ | */ | ||||
CFixed MulDiv(CFixed m, CFixed d) const | CFixed MulDiv(CFixed m, CFixed d) const | ||||
{ | { | ||||
i64 t = FIXED_MUL_I64_I32_I32(value, m.value) / (i64)d.value; | i64 t = MUL_I64_I32_I32(value, m.value) / static_cast<i64>(d.value); | ||||
CheckCastOverflow(t, T, L"Overflow in CFixed::Multiply(CFixed n)", L"Underflow in CFixed::Multiply(CFixed n)") | CheckCastOverflow(t, T, L"Overflow in CFixed::Multiply(CFixed n)", L"Underflow in CFixed::Multiply(CFixed n)") | ||||
return CFixed((T)t); | return CFixed((T)t); | ||||
} | } | ||||
CFixed Sqrt() const | CFixed Sqrt() const | ||||
{ | { | ||||
if (value <= 0) | if (value <= 0) | ||||
return CFixed(0); | return CFixed(0); | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator