Index: source/maths/FixedVector2D.h =================================================================== --- source/maths/FixedVector2D.h +++ source/maths/FixedVector2D.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -103,8 +103,8 @@ // Do intermediate calculations with 64-bit ints to avoid overflows i32 x = X.GetInternalValue(); i32 y = Y.GetInternalValue(); - u64 xx = (u64)FIXED_MUL_I64_I32_I32(x, x); - u64 yy = (u64)FIXED_MUL_I64_I32_I32(y, y); + u64 xx = static_cast(FIXED_MUL_I64_I32_I32(x, x)); + u64 yy = static_cast(FIXED_MUL_I64_I32_I32(y, y)); u64 d2 = xx + yy; CheckUnsignedAdditionOverflow(d2, xx, L"Overflow in CFixedVector2D::Length() part 1") @@ -112,7 +112,7 @@ CheckU32CastOverflow(d, i32, L"Overflow in CFixedVector2D::Length() part 2") fixed r; - r.SetInternalValue((i32)d); + r.SetInternalValue(static_cast(d)); return r; } @@ -125,12 +125,12 @@ { i32 x = X.GetInternalValue(); // abs(x) <= 2^31 i32 y = Y.GetInternalValue(); - u64 xx = (u64)FIXED_MUL_I64_I32_I32(x, x); // xx <= 2^62 - u64 yy = (u64)FIXED_MUL_I64_I32_I32(y, y); + u64 xx = static_cast(FIXED_MUL_I64_I32_I32(x, x)); // xx <= 2^62 + u64 yy = static_cast(FIXED_MUL_I64_I32_I32(y, y)); u64 d2 = xx + yy; // d2 <= 2^63 (no overflow) i32 c = cmp.GetInternalValue(); - u64 c2 = (u64)FIXED_MUL_I64_I32_I32(c, c); + u64 c2 = static_cast(FIXED_MUL_I64_I32_I32(c, c)); if (d2 < c2) return -1; else if (d2 > c2) @@ -140,6 +140,29 @@ } /** + * Same as above, but avoids squaring the compared value + */ + int CompareLengthSquared(fixed cmpSquared) const + { + i32 x = X.GetInternalValue(); // abs(x) <= 2^31 + i32 y = Y.GetInternalValue(); + + u64 xx = static_cast(FIXED_MUL_I64_I32_I32(x, x)); // xx <= 2^62 + u64 yy = static_cast(FIXED_MUL_I64_I32_I32(y, y)); + u64 d2 = xx + yy; // d2 <= 2^63 (no overflow) + + //u64 c2 = static_cast(FIXED_MUL_I64_I32_I32(cmpSquared.GetInternalValue(), fixed::FromInt(1).GetInternalValue()); + u64 c2 = cmpSquared.GetInternalValue(); + c2 <<= fixed::fract_bits; + + if (d2 < c2) + return -1; + else if (d2 > c2) + return +1; + else + return 0; + } + /** * Returns -1, 0, +1 depending on whether length is less/equal/greater * than the argument's length. * Avoids sqrting and overflowing. @@ -148,11 +171,11 @@ { i32 x = X.GetInternalValue(); i32 y = Y.GetInternalValue(); - u64 d2 = (u64)FIXED_MUL_I64_I32_I32(x, x) + (u64)FIXED_MUL_I64_I32_I32(y, y); + u64 d2 = static_cast(FIXED_MUL_I64_I32_I32(x, x)) + static_cast(FIXED_MUL_I64_I32_I32(y, y)); i32 ox = other.X.GetInternalValue(); i32 oy = other.Y.GetInternalValue(); - u64 od2 = (u64)FIXED_MUL_I64_I32_I32(ox, ox) + (u64)FIXED_MUL_I64_I32_I32(oy, oy); + u64 od2 = static_cast(FIXED_MUL_I64_I32_I32(ox, ox)) + static_cast(FIXED_MUL_I64_I32_I32(oy, oy)); if (d2 < od2) return -1; @@ -208,7 +231,7 @@ CheckCastOverflow(sum, i32, L"Overflow in CFixedVector2D::Dot() part 2", L"Underflow in CFixedVector2D::Dot() part 2") fixed ret; - ret.SetInternalValue((i32)sum); + ret.SetInternalValue(static_cast(sum)); return ret; } Index: source/maths/tests/test_FixedVector2D.h =================================================================== --- source/maths/tests/test_FixedVector2D.h +++ source/maths/tests/test_FixedVector2D.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -66,6 +66,24 @@ TS_ASSERT_DELTA(v3.Length().ToDouble(), sqrt(2.0)*large.ToDouble(), 0.01); } + void test_CompareLength() + { + CFixedVector2D v1(fixed::FromInt(3), fixed::FromInt(4)); + TS_ASSERT_EQUALS(v1.CompareLength(fixed::FromInt(4)), 1); + TS_ASSERT_EQUALS(v1.CompareLength(fixed::FromInt(5)), 0); + TS_ASSERT_EQUALS(v1.CompareLength(fixed::FromInt(6)), -1); + + CFixedVector2D v2(fixed::FromInt(2), fixed::FromInt(3)); + CFixedVector2D v3(fixed::FromInt(4), fixed::FromInt(5)); + TS_ASSERT_EQUALS(v1.CompareLength(v2), 1); + TS_ASSERT_EQUALS(v1.CompareLength(v1), 0); + TS_ASSERT_EQUALS(v1.CompareLength(v3), -1); + + TS_ASSERT_EQUALS(v1.CompareLengthSquared(fixed::FromInt(24)), 1); + TS_ASSERT_EQUALS(v1.CompareLengthSquared(fixed::FromInt(25)), 0); + TS_ASSERT_EQUALS(v1.CompareLengthSquared(fixed::FromInt(26)), -1); + } + void test_Normalize() { CFixedVector2D v0 (fixed::FromInt(0), fixed::FromInt(0)); Index: source/simulation2/components/CCmpRangeManager.cpp =================================================================== --- source/simulation2/components/CCmpRangeManager.cpp +++ source/simulation2/components/CCmpRangeManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -1294,7 +1294,7 @@ return r; // angle = 0 goes in the positive Z direction - entity_pos_t precision = entity_pos_t::FromInt((int)TERRAIN_TILE_SIZE)/8; + entity_pos_t precisionSquared = (entity_pos_t::FromInt(static_cast(TERRAIN_TILE_SIZE)) / 8).Square(); CmpPtr cmpWaterManager(GetSystemEntity()); entity_pos_t waterLevel = cmpWaterManager ? cmpWaterManager->GetWaterLevel(pos.X, pos.Z) : entity_pos_t::Zero(); @@ -1323,7 +1323,7 @@ } // Loop until vectors come close enough - while ((maxVector - minVector).CompareLength(precision) > 0) + while ((maxVector - minVector).CompareLengthSquared(precisionSquared) > 0) { // difference still bigger than precision, bisect to get smaller difference entity_pos_t newDistance = (minDistance+maxDistance)/entity_pos_t::FromInt(2);