Subversion Repositories spk

Rev

Rev 273 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#ifndef CONVERSION_INCLUDED
#define CONVERSION_INCLUDED

#include <cmath>
/*

        conversion from:
                int to double 
                int (modulo 100000) to int (modulo 0xFFFF)
        double to int rounding is done "to nearest" - hence the assembler and not simple static cast

*/

namespace conversion
{
#ifdef _WIN64
        // Constants for conversions
        constexpr double MULTIPLIER_BOB_TO_BOD = 0.65536; // == 65535 / 100000
        constexpr double MULTIPLIER_BOD_TO_BOB = 0.65536; // == 65535 / 100000
        constexpr double MULTIPLIER_DOUBLE_TO_INT = 1.52587890625E-05; // == 1 / 65535

        // Divide and round a double value
        inline double divideAndRound(double value) {
                return std::round(value / MULTIPLIER_DOUBLE_TO_INT);
        }

        // Convert double to int with rounding
        inline int double2int(double d) {
                return static_cast<int>(divideAndRound(d));
        }

        // Convert vertex from bob to bod
        inline int vertex_bob2bod(int i) {
                return static_cast<int>(i / MULTIPLIER_BOB_TO_BOD + 0.5);
        }

        // Convert vertex from bod to bob
        inline int vertex_bod2bob(int i) {
                return static_cast<int>(std::round(i * MULTIPLIER_BOD_TO_BOB));
        }

        /*
        static inline double __fastcall divideAndRound(double value) {
                const double MULTIPLIER = 1.52587890625E-05; // == 1 / 65535

                value /= MULTIPLIER;
                return std::round(value);
        }

        static inline int __stdcall double2int(double d)
        {
                return static_cast<int>(divideAndRound(d));
        }

        static int __stdcall vertex_bob2bod(int i)
        {
                // bod = i / 0.65535
                static double MULTIPLIER = 0.65536; // == 65535 / 100000
                return static_cast<int>(i / MULTIPLIER + 0.5f);
        }

        static inline int __stdcall vertex_bod2bob(int i)
        {
                // bob = i * 0.65535
                static double MULTIPLIER = 0.65536; // == 65535 / 100000

                double result = MULTIPLIER * i;
                return static_cast<int>(std::round(result));
        }
        */
#else

__declspec(naked)
static 
int __stdcall vertex_bob2bod(int i)
{
        // bod = i / 0.65535
        static double MULTIPLIER = 0.65536; // == 65535 / 100000
        __asm {
                fld MULTIPLIER
                fidivr dword ptr [esp + 4]
                fistp dword ptr [esp + 4]
                mov eax, dword ptr [esp + 4]
                ret 4
        }
}

/*inline 
int __stdcall vertex_bob2bod(int i)
{
        static double MULTIPLIER = 0.65535; // == 65535 / 100000 
        return (int)(i / MULTIPLIER);
}*/


__declspec(naked)
inline 
int __stdcall vertex_bod2bob(int i)
{
        // bob = i * 0.65535
        static double MULTIPLIER = 0.65536; // == 65535 / 100000
        __asm {
                fld MULTIPLIER
                fimul dword ptr [esp + 4]
                fistp dword ptr [esp + 4]
                mov eax, dword ptr [esp + 4]
                ret 4
        }
}

__declspec(naked)
inline 
int __stdcall double2int(double d)
{
        static const double MULTIPLIER=1.52587890625E-05; // == 1 / 65535
        
        // int = right / multiplier 
        __asm{
                fld qword ptr [esp + 4]
                fdiv MULTIPLIER
                fistp dword ptr [esp + 4]
                mov eax, dword ptr [esp + 4]
                ret 8
        }
}
/*
inline 
int __stdcall double2int(double d)
{
        static const double MULTIPLIER=1.52587890625E-05; // == 1 / 65535
        
        return (int)(d / MULTIPLIER);
        
}*/
#endif

} // namespace conversion

#endif // !defined(CONVERSION_INCLUDED)