- Timestamp:
- Sep 21, 2011, 7:10:21 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/real.cpp
r965 r969 14 14 15 15 #include <cstring> 16 #include <cstdio> 16 17 17 18 #include "core.h" … … 22 23 { 23 24 24 template<> real4k::Real(float f)25 real::real(float f) 25 26 { 26 27 union { float f; uint32_t x; } u = { f }; 27 28 28 29 uint32_t sign = u.x & 0x80000000u; 29 int e = ((u.x >> 23) & 0xff) + (1 << 30) - (1 << 10);30 int e = ((u.x >> 23) & 0xff) + (1 << 30) - (1 << 7); 30 31 31 32 m_signexp = sign | e; 32 m_mantissa[0] = u.x << 17; 33 memset(m_mantissa + 1, 0, sizeof(m_mantissa) - sizeof(m_mantissa[0])); 33 m_mantissa[0] = u.x >> 7; 34 m_mantissa[1] = u.x << 9; 35 memset(m_mantissa + 2, 0, sizeof(m_mantissa) - sizeof(m_mantissa[0])); 34 36 } 35 37 36 template<> real4k::operator float() const38 real::operator float() const 37 39 { 38 40 union { float f; uint32_t x; } u; 39 41 40 u.x = m_mantissa[0] >> 17; 41 u.x |= ((m_signexp & 0x7fffffffu) - (1 << 30) + (1 << 10)) << 23; 42 u.x = m_mantissa[0] << 7; 43 u.x |= m_mantissa[1] >> 9; 44 u.x |= ((m_signexp & 0x7fffffffu) - (1 << 30) + (1 << 7)) << 23; 42 45 u.x |= m_signexp & 0x80000000u; 43 46 … … 45 48 } 46 49 50 real real::operator *(real const &x) const 51 { 52 real ret; 53 54 ret.m_signexp = (m_signexp ^ x.m_signexp) & 0x80000000u; 55 int e = (m_signexp & 0x7fffffffu) - (1 << 30) + 1 56 + (x.m_signexp & 0x7fffffffu) - (1 << 30) + 1; 57 58 /* Accumulate low order product; no need to store it, we just 59 * want the carry value */ 60 uint32_t carry = 0; 61 for (int i = 0; i < BIGITS; i++) 62 { 63 for (int j = 0; j < i + 1; j++) 64 carry += m_mantissa[BIGITS - 1 - j] 65 * x.m_mantissa[BIGITS - 1 + j - i]; 66 carry >>= 16; 67 } 68 69 for (int i = 0; i < BIGITS; i++) 70 { 71 for (int j = i + 1; j < BIGITS; j++) 72 carry += m_mantissa[BIGITS - 1 - j] 73 * x.m_mantissa[j - 1 - i]; 74 75 carry += m_mantissa[BIGITS - 1 - i]; 76 carry += x.m_mantissa[BIGITS - 1 - i]; 77 ret.m_mantissa[BIGITS - 1 - i] = carry & 0xffffu; 78 carry >>= 16; 79 } 80 81 /* Renormalise in case we overflowed the mantissa */ 82 if (carry) 83 { 84 carry--; 85 for (int i = 0; i < BIGITS; i++) 86 { 87 uint16_t tmp = ret.m_mantissa[i]; 88 ret.m_mantissa[i] = (carry << 15) | (tmp >> 1); 89 carry = tmp & 0x0001u; 90 } 91 e++; 92 } 93 94 ret.m_signexp |= e + (1 << 30) - 1; 95 96 return ret; 97 } 98 99 void real::print() const 100 { 101 printf("%x %08x ", m_signexp >> 31, (m_signexp << 1) >> 1); 102 for (int i = 0; i < BIGITS; i++) 103 printf("%04x ", m_mantissa[i]); 104 printf("\n"); 105 } 106 47 107 } /* namespace lol */ 48 108 -
trunk/src/real.h
r965 r969 22 22 { 23 23 24 template<int NBITS> class Real24 class real 25 25 { 26 static int const BIGITS = 10; 27 26 28 public: 27 inline Real<NBITS>() {}28 Real<NBITS>(float f);29 inline real() { } 30 real(float f); 29 31 30 32 operator float() const; 33 real operator *(real const &x) const; 34 35 void print() const; 31 36 32 37 private: 38 uint32_t m_size; 33 39 uint32_t m_signexp; 34 uint 32_t m_mantissa[(NBITS + 31) / 32];40 uint16_t m_mantissa[BIGITS]; 35 41 }; 36 37 typedef Real<4096> real4k;38 42 39 43 } /* namespace lol */ -
trunk/test/unit/real.cpp
r967 r969 26 26 LOLUNIT_TEST(test_real_from_float) 27 27 { 28 float x = real4k(0.0f); 29 float y = real4k(1.0f); 28 float x = real(0.0f); 29 float y = real(1.0f); 30 float z = real(1.5f); 30 31 31 32 LOLUNIT_ASSERT_EQUAL(x, 0.0f); 32 33 LOLUNIT_ASSERT_EQUAL(y, 1.0f); 34 LOLUNIT_ASSERT_EQUAL(z, 1.5f); 35 } 36 37 LOLUNIT_TEST(test_real_mul) 38 { 39 real x(1.25f); 40 real y(1.5f); 41 real z(1.99999f); 42 real w(-1.5f); 43 44 float m1 = x * x; 45 float m2 = y * y; 46 float m3 = z * z; 47 float m4 = w * w; 48 49 LOLUNIT_ASSERT_EQUAL(m1, 1.25f * 1.25f); 50 LOLUNIT_ASSERT_EQUAL(m2, 1.5f * 1.5f); 51 LOLUNIT_ASSERT_EQUAL(m3, 1.99999f * 1.99999f); 52 LOLUNIT_ASSERT_EQUAL(m4, -1.5f * -1.5f); 33 53 } 34 54 };
Note: See TracChangeset
for help on using the changeset viewer.