| @@ -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[1] = u.x << 12; | |||||
| m_mantissa[0] = (uint32_t)(u.x >> 20); | |||||
| 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]; | |||||
| ret.m_mantissa[i] = (carry << (BIGIT_BITS - 1)) | (tmp >> 1); | |||||
| uint32_t tmp = (uint32_t)ret.m_mantissa[i]; | |||||
| 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) | ||||