瀏覽代碼

core: fix a few implicit 64-to-32-bit casts in the real methods.

legacy
Sam Hocevar gary 13 年之前
父節點
當前提交
52e44ef8be
共有 1 個文件被更改,包括 26 次插入15 次删除
  1. +26
    -15
      src/real.cpp

+ 26
- 15
src/real.cpp 查看文件

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To // modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See // Public License, Version 2, as published by Sam Hocevar. See
@@ -12,6 +12,14 @@
# include "config.h" # include "config.h"
#endif #endif


#if defined WIN32 && !defined _XBOX
# define _USE_MATH_DEFINES /* for M_PI */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef near /* Fuck Microsoft */
# undef far /* Fuck Microsoft again */
#endif

#include <new> #include <new>
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
@@ -80,8 +88,8 @@ real::real(double d)
break; break;
} }


m_mantissa[0] = u.x >> 20; m_mantissa[0] = (uint32_t)(u.x >> 20);
m_mantissa[1] = u.x << 12; m_mantissa[1] = (uint32_t)(u.x << 12);
memset(m_mantissa + 2, 0, (BIGITS - 2) * sizeof(m_mantissa[0])); memset(m_mantissa + 2, 0, (BIGITS - 2) * sizeof(m_mantissa[0]));
} }


@@ -239,7 +247,7 @@ real real::operator +(real const &x) const
else if (i - bigoff == 0) else if (i - bigoff == 0)
carry += (uint64_t)1 << (BIGIT_BITS - off); carry += (uint64_t)1 << (BIGIT_BITS - off);


ret.m_mantissa[i] = carry; ret.m_mantissa[i] = (uint32_t)carry;
carry >>= BIGIT_BITS; carry >>= BIGIT_BITS;
} }


@@ -250,7 +258,8 @@ real real::operator +(real const &x) const
for (int i = 0; i < BIGITS; i++) for (int i = 0; i < BIGITS; i++)
{ {
uint32_t tmp = ret.m_mantissa[i]; uint32_t tmp = ret.m_mantissa[i];
ret.m_mantissa[i] = (carry << (BIGIT_BITS - 1)) | (tmp >> 1); ret.m_mantissa[i] = ((uint32_t)carry << (BIGIT_BITS - 1))
| (tmp >> 1);
carry = tmp & 1u; carry = tmp & 1u;
} }
ret.m_signexp++; ret.m_signexp++;
@@ -289,6 +298,7 @@ real real::operator -(real const &x) const


ret.m_signexp = m_signexp; ret.m_signexp = m_signexp;


/* int64_t instead of uint64_t to preserve sign through shifts */
int64_t carry = 0; int64_t carry = 0;
for (int i = 0; i < bigoff; i++) for (int i = 0; i < bigoff; i++)
{ {
@@ -312,7 +322,7 @@ real real::operator -(real const &x) const
else if (i - bigoff == 0) else if (i - bigoff == 0)
carry -= (uint64_t)1 << (BIGIT_BITS - off); carry -= (uint64_t)1 << (BIGIT_BITS - off);


ret.m_mantissa[i] = carry; ret.m_mantissa[i] = (uint32_t)carry;
carry >>= BIGIT_BITS; carry >>= BIGIT_BITS;
carry |= carry << BIGIT_BITS; carry |= carry << BIGIT_BITS;
} }
@@ -422,8 +432,9 @@ real real::operator *(real const &x) const
carry--; carry--;
for (int i = 0; i < BIGITS; i++) for (int i = 0; i < BIGITS; i++)
{ {
uint32_t tmp = ret.m_mantissa[i]; uint32_t tmp = (uint32_t)ret.m_mantissa[i];
ret.m_mantissa[i] = (carry << (BIGIT_BITS - 1)) | (tmp >> 1); ret.m_mantissa[i] = ((uint32_t)carry << (BIGIT_BITS - 1))
| (tmp >> 1);
carry = tmp & 1u; carry = tmp & 1u;
} }
e++; e++;
@@ -555,7 +566,7 @@ real re(real const &x)
/* Use the system's float inversion to approximate 1/x */ /* Use the system's float inversion to approximate 1/x */
union { float f; uint32_t x; } u = { 1.0f }, v = { 1.0f }; union { float f; uint32_t x; } u = { 1.0f }, v = { 1.0f };
v.x |= x.m_mantissa[0] >> 9; v.x |= x.m_mantissa[0] >> 9;
v.f = 1.0 / v.f; v.f = 1.0f / v.f;


real ret; real ret;
ret.m_mantissa[0] = v.x << 9; ret.m_mantissa[0] = v.x << 9;
@@ -598,7 +609,7 @@ real sqrt(real const &x)
union { float f; uint32_t x; } u = { 1.0f }, v = { 2.0f }; union { float f; uint32_t x; } u = { 1.0f }, v = { 2.0f };
v.x -= ((x.m_signexp & 1) << 23); v.x -= ((x.m_signexp & 1) << 23);
v.x |= x.m_mantissa[0] >> 9; v.x |= x.m_mantissa[0] >> 9;
v.f = 1.0 / sqrtf(v.f); v.f = 1.0f / sqrtf(v.f);


real ret; real ret;
ret.m_mantissa[0] = v.x << 9; ret.m_mantissa[0] = v.x << 9;
@@ -980,7 +991,7 @@ real fmod(real const &x, real const &y)


real sin(real const &x) real sin(real const &x)
{ {
bool switch_sign = x.m_signexp & 0x80000000u; int switch_sign = x.m_signexp & 0x80000000u;


real absx = fmod(fabs(x), real::R_PI * 2); real absx = fmod(fabs(x), real::R_PI * 2);
if (absx > real::R_PI) if (absx > real::R_PI)
@@ -1041,7 +1052,7 @@ real tan(real const &x)
return cos(y) / sin(y); return cos(y) / sin(y);
} }


static real asinacos(real const &x, bool is_asin, bool is_negative) static inline real asinacos(real const &x, int is_asin, int is_negative)
{ {
/* Strategy for asin(): in [-0.5..0.5], use a Taylor series around /* Strategy for asin(): in [-0.5..0.5], use a Taylor series around
* zero. In [0.5..1], use asin(x) = π/2 - 2*asin(sqrt((1-x)/2)), and * zero. In [0.5..1], use asin(x) = π/2 - 2*asin(sqrt((1-x)/2)), and
@@ -1049,7 +1060,7 @@ static real asinacos(real const &x, bool is_asin, bool is_negative)
* Strategy for acos(): use acos(x) = π/2 - asin(x) and try not to * Strategy for acos(): use acos(x) = π/2 - asin(x) and try not to
* lose the precision around x=1. */ * lose the precision around x=1. */
real absx = fabs(x); real absx = fabs(x);
bool around_zero = (absx < (real::R_1 / 2)); int around_zero = (absx < (real::R_1 / 2));


if (!around_zero) if (!around_zero)
absx = sqrt((real::R_1 - absx) / 2); absx = sqrt((real::R_1 - absx) / 2);
@@ -1086,12 +1097,12 @@ static real asinacos(real const &x, bool is_asin, bool is_negative)


real asin(real const &x) real asin(real const &x)
{ {
return asinacos(x, true, x.m_signexp >> 31); return asinacos(x, 1, x.m_signexp >> 31);
} }


real acos(real const &x) real acos(real const &x)
{ {
return asinacos(x, false, x.m_signexp >> 31); return asinacos(x, 0, x.m_signexp >> 31);
} }


real atan(real const &x) real atan(real const &x)


||||||
x
 
000:0
Loading…
取消
儲存