1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-06-24 02:57:12 +02:00
Files
bin
cbp
config
external
include
modules
shared
source
Base
Entity
Library
Chrono
Crypt
IO
Numeric
Decimal.cpp
Decimal.hpp
LongInt.cpp
LongInt.hpp
Math.cpp
Math.hpp
Random.cpp
Random.hpp
System
Utils
Chrono.cpp
Chrono.hpp
Crypt.cpp
Crypt.hpp
IO.cpp
IO.hpp
Numeric.cpp
Numeric.hpp
String.cpp
String.hpp
System.cpp
System.hpp
Utils.cpp
Utils.hpp
Misc
Command.cpp
Command.hpp
Constants.cpp
Core.cpp
Core.hpp
CoreEntity.cpp
CoreEvents.cpp
CoreFuncs.cpp
CoreUtils.cpp
Exports.cpp
Logger.cpp
Logger.hpp
Main.cpp
Register.cpp
Routine.cpp
Routine.hpp
SqBase.hpp
.gitignore
LICENSE
README.md
SqMod/source/Library/Numeric/Decimal.cpp
2016-06-05 03:54:15 +03:00

287 lines
10 KiB
C++

// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/Decimal.hpp"
#include "Library/Numeric/LongInt.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
const Int64 Decimal::s_Factors[] = {
static_cast< Int64 >(std::pow(10, 0)),
static_cast< Int64 >(std::pow(10, 1)),
static_cast< Int64 >(std::pow(10, 2)),
static_cast< Int64 >(std::pow(10, 3)),
static_cast< Int64 >(std::pow(10, 4)),
static_cast< Int64 >(std::pow(10, 5)),
static_cast< Int64 >(std::pow(10, 6)),
static_cast< Int64 >(std::pow(10, 7)),
static_cast< Int64 >(std::pow(10, 8)),
static_cast< Int64 >(std::pow(10, 9)),
static_cast< Int64 >(std::pow(10, 10)),
static_cast< Int64 >(std::pow(10, 11)),
static_cast< Int64 >(std::pow(10, 12)),
static_cast< Int64 >(std::pow(10, 13)),
static_cast< Int64 >(std::pow(10, 14)),
static_cast< Int64 >(std::pow(10, 15)),
static_cast< Int64 >(std::pow(10, 16)),
static_cast< Int64 >(std::pow(10, 17)),
static_cast< Int64 >(std::pow(10, 18)),
static_cast< Int64 >(std::pow(10, 19)),
static_cast< Int64 >(std::pow(10, 20)),
static_cast< Int64 >(std::pow(10, 21)),
static_cast< Int64 >(std::pow(10, 22)),
static_cast< Int64 >(std::pow(10, 23)),
static_cast< Int64 >(std::pow(10, 24)),
static_cast< Int64 >(std::pow(10, 25)),
static_cast< Int64 >(std::pow(10, 26)),
static_cast< Int64 >(std::pow(10, 27)),
static_cast< Int64 >(std::pow(10, 28)),
static_cast< Int64 >(std::pow(10, 29)),
static_cast< Int64 >(std::pow(10, 30)),
static_cast< Int64 >(std::pow(10, 31)),
static_cast< Int64 >(std::pow(10, 32)),
static_cast< Int64 >(std::pow(10, 33)),
static_cast< Int64 >(std::pow(10, 34)),
static_cast< Int64 >(std::pow(10, 35)),
static_cast< Int64 >(std::pow(10, 36)),
static_cast< Int64 >(std::pow(10, 37)),
static_cast< Int64 >(std::pow(10, 38)),
static_cast< Int64 >(std::pow(10, 39)),
static_cast< Int64 >(std::pow(10, 40)),
static_cast< Int64 >(std::pow(10, 41)),
static_cast< Int64 >(std::pow(10, 42)),
static_cast< Int64 >(std::pow(10, 43)),
static_cast< Int64 >(std::pow(10, 44)),
static_cast< Int64 >(std::pow(10, 45)),
static_cast< Int64 >(std::pow(10, 46)),
static_cast< Int64 >(std::pow(10, 47)),
static_cast< Int64 >(std::pow(10, 48)),
static_cast< Int64 >(std::pow(10, 49)),
static_cast< Int64 >(std::pow(10, 40)),
static_cast< Int64 >(std::pow(10, 51)),
static_cast< Int64 >(std::pow(10, 52)),
static_cast< Int64 >(std::pow(10, 53)),
static_cast< Int64 >(std::pow(10, 54)),
static_cast< Int64 >(std::pow(10, 55)),
static_cast< Int64 >(std::pow(10, 56)),
static_cast< Int64 >(std::pow(10, 57)),
static_cast< Int64 >(std::pow(10, 58)),
static_cast< Int64 >(std::pow(10, 59)),
static_cast< Int64 >(std::pow(10, 60)),
static_cast< Int64 >(std::pow(10, 61)),
static_cast< Int64 >(std::pow(10, 62)),
static_cast< Int64 >(std::pow(10, 63)),
};
// ------------------------------------------------------------------------------------------------
SQInteger Decimal::Typename(HSQUIRRELVM vm)
{
static const SQChar name[] = _SC("SqDecimal");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
void Decimal::ValidatePrecision(Uint8 precision)
{
if (precision >= (sizeof(s_Factors) / sizeof(Int64)))
{
STHROWF("Out of range precision: %u >= %u", precision, (sizeof(s_Factors) / sizeof(Int64)));
}
}
// ------------------------------------------------------------------------------------------------
Int64 Decimal::Convert(const Decimal & dec) const
{
// Do they already have the same precision
if (m_Precision == dec.m_Precision)
{
return dec.m_Value;
}
// Return the value converted to the new precision
return (dec.m_Value / s_Factors[dec.m_Precision]) * s_Factors[m_Precision];
}
// ------------------------------------------------------------------------------------------------
Int32 Decimal::Compare(const Decimal & o) const
{
// Convert ti the same precision
const Int64 b = Convert(o);
// Perform the comparison
if (m_Value == b)
{
return 0;
}
else if (m_Value > b)
{
return 1;
}
else
{
return -1;
}
}
// ------------------------------------------------------------------------------------------------
Decimal::Decimal(CSStr value)
: m_Value(0), m_Precision(0)
{
// Is there anything to parse at least?
if (!value)
{
STHROWF("Invalid decimal string: null");
}
// Skip whitespace characters
while (std::isspace(*value))
{
++value;
}
// Do we still have anything left to parse?
if (*value == '\0')
{
return; // Leave default values
}
// Is there anything before the separator?
if (*value == '.')
{
// Extract the amount of precision required
m_Precision = std::strlen(++value);
// Extract the value as is
m_Value = std::strtoul(value, nullptr, 10);
// Leave the remaining value to default
return;
}
// Find the fraction separator
CSStr point = std::strchr(value, '.');
// Was there a fraction separator found?
if (!point)
{
// Extract the value as is
m_Value = std::strtoul(value, nullptr, 10);
// Leave the remaining value to default
return;
}
// Extract the amount of precision required
m_Precision = ConvTo< Uint8 >::From(std::strlen(++point));
// Validate the obtained precision
ValidatePrecision(m_Precision);
// Copy the value upto the the separator
std::strncpy(GetTempBuff(), value, point - value - 1)[point - value - 1] = '\0';
// Extract the value itself
m_Value = (std::strtoul(GetTempBuff(), nullptr, 10) * s_Factors[m_Precision]);
m_Value += std::strtoul(point, nullptr, 10);
}
// ------------------------------------------------------------------------------------------------
Decimal::Decimal(SQInteger value, Uint8 precision)
: m_Value(0), m_Precision(precision)
{
// Validate the specified precision
ValidatePrecision(m_Precision);
// Assign the specified value
m_Value = (s_Factors[m_Precision] * value);
}
#ifndef _SQ64
// ------------------------------------------------------------------------------------------------
Decimal::Decimal(Int64 value, Uint8 precision)
: m_Value(0), m_Precision(precision)
{
// Validate the specified precision
ValidatePrecision(m_Precision);
// Assign the specified value
m_Value = (s_Factors[m_Precision] * value);
}
#endif // _SQ64
// ------------------------------------------------------------------------------------------------
CSStr Decimal::ToString() const
{
// Generate the string into the temporary buffer
MakeString(GetTempBuff(), GetTempBuffSize());
// Return the resulted string
return GetTempBuff();
}
// ------------------------------------------------------------------------------------------------
SLongInt Decimal::GetConverted(const Decimal & dec) const
{
return SLongInt(Convert(dec));
}
// ------------------------------------------------------------------------------------------------
SLongInt Decimal::GetFactor() const
{
return SLongInt(s_Factors[m_Precision]);
}
// ------------------------------------------------------------------------------------------------
SLongInt Decimal::GetUnbiased() const
{
return SLongInt(m_Value);
}
// ------------------------------------------------------------------------------------------------
void Decimal::MakeString(CStr buffer, Uint32 size) const
{
const Int64 after = m_Value % s_Factors[m_Precision];
const Int64 before = (m_Value - after) / s_Factors[m_Precision];
// Generate the format string
if (std::snprintf(buffer, size, "%lld.%0*lld", before, m_Precision, after) < 0)
{
buffer[0] = '\0'; // At least make sure the string is null terminated
}
}
// ------------------------------------------------------------------------------------------------
static Decimal Sq_DecimalFromLong(const SLongInt & value, Uint8 precision)
{
return Decimal(value.GetNum(), precision);
}
// ================================================================================================
void Register_Decimal(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqDecimal"), Class< Decimal >(vm, _SC("SqDecimal"))
// Constructors
.Ctor()
.Ctor< CSStr >()
.Ctor< SQInteger, Uint8 >()
// Core Meta-methods
.Func(_SC("_tostring"), &Decimal::ToString)
.SquirrelFunc(_SC("_typename"), &Decimal::Typename)
.Func(_SC("_cmp"), &Decimal::Cmp)
// Core Functions
.Func(_SC("tofloat"), &Decimal::GetSqFloat)
// Meta-methods
.Func< Decimal (Decimal::*)(const Decimal &) const >(_SC("_add"), &Decimal::operator +)
.Func< Decimal (Decimal::*)(const Decimal &) const >(_SC("_sub"), &Decimal::operator -)
.Func< Decimal (Decimal::*)(const Decimal &) const >(_SC("_mul"), &Decimal::operator *)
.Func< Decimal (Decimal::*)(const Decimal &) const >(_SC("_div"), &Decimal::operator /)
// Properties
.Prop(_SC("Factor"), &Decimal::GetFactor)
.Prop(_SC("Unbiased"), &Decimal::GetUnbiased)
.Prop(_SC("Precision"), &Decimal::GetPrecision)
.Prop(_SC("Abs"), &Decimal::GetAbs)
.Prop(_SC("Float"), &Decimal::GetSqFloat)
.Prop(_SC("Float32"), &Decimal::GetFloat32)
.Prop(_SC("Float64"), &Decimal::GetFloat64)
.Prop(_SC("Str"), &Decimal::ToString)
// Functions
.Func(_SC("Convert"), &Decimal::GetConverted)
// Static Functions
.StaticFunc(_SC("Long"), &Sq_DecimalFromLong)
.StaticFunc(_SC("FromLong"), &Sq_DecimalFromLong)
);
}
} // Namespace:: SqMod