From 52b50689d2c078786bde1e58d6cd5be9d3af0a7c Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Tue, 10 Apr 2012 23:23:21 +0200 Subject: [PATCH] move fixed point number class to separate file --- Raytracer/CMakeLists.txt | 4 +- Raytracer/fixed.cc | 29 ++++++++++ Raytracer/fixed.h | 119 +++++++++++++++++++++++++++++++++++++++ Raytracer/raytracer2.cc | 111 +++--------------------------------- 4 files changed, 160 insertions(+), 103 deletions(-) create mode 100644 Raytracer/fixed.cc create mode 100644 Raytracer/fixed.h diff --git a/Raytracer/CMakeLists.txt b/Raytracer/CMakeLists.txt index f89561a790..938741b3ad 100644 --- a/Raytracer/CMakeLists.txt +++ b/Raytracer/CMakeLists.txt @@ -9,7 +9,9 @@ add_executable(Raytracer MACOSX_BUNDLE raytracer.cc ) add_executable(Raytracer2 MACOSX_BUNDLE - raytracer2.cc + raytracer2.cc + fixed.h + fixed.cc ) diff --git a/Raytracer/fixed.cc b/Raytracer/fixed.cc new file mode 100644 index 0000000000..49be5413d9 --- /dev/null +++ b/Raytracer/fixed.cc @@ -0,0 +1,29 @@ +#include "fixed.h" + +long fixed::nMul = 0, fixed::nIMul = 0, fixed::nDiv = 0, fixed::nSqrt = 0; + +fixed sqrt(fixed f) +{ + COUNT_OP(fixed::nSqrt); + + const int FRACBITS = 16; /* Must be even! */ + const int ITERS = 15 + (FRACBITS >> 1); + + unsigned long root, remHi, remLo, testDiv, count; + root = 0; /* Clear root */ + remHi = 0; /* Clear high part of partial remainder */ + remLo = f.val; /* Get argument into low part of partial remainder */ + count = ITERS; /* Load loop counter */ + + do { + remHi = (remHi << 2) | (remLo >> 30); remLo <<= 2; /* get 2 bits of arg */ + root <<= 1; /* Get ready for the next bit in the root */ + testDiv = (root << 1) + 1; /* Test radical */ + if (remHi >= testDiv) { + remHi -= testDiv; + root += 1; + } + } while (count-- != 0); + + return fixed(root, fixed::raw()); +} diff --git a/Raytracer/fixed.h b/Raytracer/fixed.h new file mode 100644 index 0000000000..ab453fe3d5 --- /dev/null +++ b/Raytracer/fixed.h @@ -0,0 +1,119 @@ +#ifndef FIXED_H +#define FIXED_H + +#include + +inline std::int32_t muls(std::int16_t x, std::int16_t y) +{ + return (std::int32_t)x*y; +} + +inline std::uint32_t mulu(std::uint16_t x, std::uint16_t y) +{ + //return (std::uint32_t)x * y; + std::uint32_t res; + __asm("mulu %1, %0" : "=d"(res) : "d"(x), "0"(y)); + return res; +} + +inline std::int32_t mulsu(std::int16_t x, std::uint16_t y) +{ + //return (std::int32_t)a * (std::uint32_t)b; + std::int32_t res; + __asm("mulu %1, %0" : "=d"(res) : "d"(x), "0"(y)); + if(x < 0) + res -= ((std::uint32_t)y) << 16; + return res; +} + +#define COUNT_OP(var) ++var + +class fixed +{ + std::int32_t val; + +public: + class raw {}; + fixed(std::int32_t val, raw r) : val(val) {} + + fixed() : val(0) {} + fixed(int x) : val((long)x << 16) {} + fixed(float f) : val(f * 65536) {} + + //operator int() { return val >> 16; } + + fixed operator+(fixed o) const { return fixed(val + o.val, raw()); } + fixed operator-(fixed o) const { return fixed(val - o.val, raw()); } + fixed operator*(fixed o) const { + COUNT_OP(nMul); + //return fixed((static_cast(val) * o.val) >> 16, raw()); + int16_t a = val >> 16; + int16_t c = o.val >> 16; + + uint16_t b = val; + uint16_t d = o.val; + + return fixed(((a*c) << 16) + + mulsu(a,d) + mulsu(c,b) + + (mulu(b,d) >> 16),raw()); + + } + fixed operator/(fixed o) const { COUNT_OP(nDiv); return fixed((static_cast(val) << 16) / o.val, raw()); } + + fixed operator-() const { return fixed(-val, raw()); } + + fixed& operator+=(fixed o) { val += o.val; return *this; } + fixed& operator-=(fixed o) { val -= o.val; return *this; } + fixed& operator*=(fixed o) { return (*this = *this * o); } + + bool operator== (fixed o) const { return val == o.val; } + bool operator!= (fixed o) const { return val != o.val; } + bool operator> (fixed o) const { return val > o.val; } + bool operator< (fixed o) const { return val < o.val; } + bool operator>= (fixed o) const { return val >= o.val; } + bool operator<= (fixed o) const { return val <= o.val; } + + friend fixed sqrt(fixed f); + friend fixed floor(fixed f); + friend fixed operator*(fixed f, int x); + friend fixed operator*(int x, fixed f); + friend int floor_to_int(fixed f); + + static long nMul; + static long nIMul; + static long nDiv; + static long nSqrt; +}; + +/*fixed operator*(fixed f, int x) { return fixed(f.val * x, fixed::raw()); } +fixed operator*(int x, fixed f) { return fixed(f.val * x, fixed::raw()); }*/ +inline fixed operator*(fixed f, int c) +{ + std::int16_t a = f.val >> 16; + + std::uint16_t b = f.val; + + COUNT_OP(fixed::nIMul); + return fixed(((a*c) << 16) + + mulsu(c,b),fixed::raw()); +} +inline fixed operator*(int x, fixed f) { return f*x; } + +inline fixed operator*(fixed f, float x) { return f*fixed(x); } +inline fixed operator*(float x, fixed f) { return f*fixed(x); } + + + +fixed sqrt(fixed f); + +inline fixed floor(fixed f) +{ + return fixed(f.val & 0xFFFF0000L, fixed::raw()); +} + +inline int floor_to_int(fixed f) +{ + return f.val >> 16; +} + +#endif // FIXED_H diff --git a/Raytracer/raytracer2.cc b/Raytracer/raytracer2.cc index 861795ba34..ea888a3c01 100644 --- a/Raytracer/raytracer2.cc +++ b/Raytracer/raytracer2.cc @@ -21,6 +21,7 @@ QDGlobals qd; #endif +#include "fixed.h" #include #include @@ -31,103 +32,9 @@ QDGlobals qd; using std::sqrt; using std::floor; -class fixed -{ - long val; - -public: - class raw {}; - fixed(long val, raw r) : val(val) {} - - fixed() : val(0) {} - fixed(int x) : val((long)x << 16) {} - fixed(float f) : val(f * 65536) {} - - //operator int() { return val >> 16; } - - fixed operator+(fixed o) const { return fixed(val + o.val, raw()); } - fixed operator-(fixed o) const { return fixed(val - o.val, raw()); } - fixed operator*(fixed o) const { return fixed((static_cast(val) * o.val) >> 16, raw()); } - fixed operator/(fixed o) const { return fixed((static_cast(val) << 16) / o.val, raw()); } - - fixed operator-() const { return fixed(-val, raw()); } - - fixed& operator+=(fixed o) { val += o.val; return *this; } - fixed& operator-=(fixed o) { val -= o.val; return *this; } - fixed& operator*=(fixed o) { return (*this = *this * o); } - - bool operator== (fixed o) const { return val == o.val; } - bool operator!= (fixed o) const { return val != o.val; } - bool operator> (fixed o) const { return val > o.val; } - bool operator< (fixed o) const { return val < o.val; } - bool operator>= (fixed o) const { return val >= o.val; } - bool operator<= (fixed o) const { return val <= o.val; } - - friend fixed sqrt(fixed f); - friend fixed floor(fixed f); - friend fixed operator*(fixed f, int x); - friend fixed operator*(int x, fixed f); - friend int floor_to_int(fixed f); -}; - -fixed operator*(fixed f, int x) { return fixed(f.val * x, fixed::raw()); } -fixed operator*(int x, fixed f) { return fixed(f.val * x, fixed::raw()); } - -fixed operator*(fixed f, float x) { return f*fixed(x); } -fixed operator*(float x, fixed f) { return f*fixed(x); } -fixed sqrt(fixed f) -{ -#if 1 - const int FRACBITS = 16; /* Must be even! */ - const int ITERS = 15 + (FRACBITS >> 1); - - unsigned long root, remHi, remLo, testDiv, count; - root = 0; /* Clear root */ - remHi = 0; /* Clear high part of partial remainder */ - remLo = f.val; /* Get argument into low part of partial remainder */ - count = ITERS; /* Load loop counter */ - - do { - remHi = (remHi << 2) | (remLo >> 30); remLo <<= 2; /* get 2 bits of arg */ - root <<= 1; /* Get ready for the next bit in the root */ - testDiv = (root << 1) + 1; /* Test radical */ - if (remHi >= testDiv) { - remHi -= testDiv; - root += 1; - } - } while (count-- != 0); - - return fixed(root, fixed::raw()); -#else - - fixed lower = 0; - fixed upper = 181; // 181.019 - while(lower != upper) - { - fixed mid(lower.val/2 + upper.val/2, fixed::raw()); - fixed s = mid*mid; - if(s <= f) - lower = mid; - if(s >= f) - upper = mid; - } - return lower; -#endif -} - -fixed floor(fixed f) -{ - return fixed(f.val & 0xFFFF0000L, fixed::raw()); -} - -int floor_to_int(fixed f) -{ - return f.val >> 16; -} - -int floor_to_int(float f) +inline int floor_to_int(float f) { return static_cast(std::floor(f)); } @@ -169,8 +76,8 @@ public: template bool hitSphere(vec3 p0, vec3 dir, T& t) { - const vec3 center(0.0f, 0.0f, -6.0f); - const T r = 1.0f; + const vec3 center(0.0f, 1.0f, -6.0f); + const T r = 2.0f; vec3 p0c(p0 - center); /* @@ -202,8 +109,8 @@ T ray(int n, vec3 p0, vec3 dir) static const vec3 light = vec3(-2,4,3).normalize(); if(1){ - const vec3 center(0.0f, 0.0f, -6.0f); - const T r = 1.0f; + const vec3 center(0.0f, 1.0f, -6.0f); + const T r = 2.0f; vec3 p0c(p0 - center); /* @@ -226,7 +133,7 @@ T ray(int n, vec3 p0, vec3 dir) { vec3 p = p0 + dir * t; - vec3 dir2 = p - center; + vec3 dir2 = (p - center) * (T(1)/r); T l = dir2*dir; @@ -290,7 +197,6 @@ struct rand1 int main() { WindowPtr win; - Debugger(); #if !TARGET_API_MAC_CARBON InitGraf(&qd.thePort); InitFonts(); @@ -366,7 +272,8 @@ int main() char buf[256]; unsigned char* pstr = (unsigned char*)buf; - std::sprintf(buf+1, "pps = %d", (int)( (long)r.right * r.bottom * 60 / (endTime - startTime) )); + std::sprintf(buf+1, "pps = %d %ld %ld %ld %ld", (int)( (long)r.right * r.bottom * 60 / (endTime - startTime) ), + fixed::nMul, fixed::nIMul, fixed::nDiv, fixed::nSqrt); buf[0] = std::strlen(buf+1); SetRect(&r, 10, 10, 10 + StringWidth(pstr) + 10, 30);