// ------------------------------------------------------------------------------------------------ #include "Library/Numeric/Math.hpp" // ------------------------------------------------------------------------------------------------ #include #include #include // ------------------------------------------------------------------------------------------------ namespace SqMod { // ------------------------------------------------------------------------------------------------ static SQInteger SqDiv(HSQUIRRELVM vm) { // The return type of the function #ifdef _SQ64 typedef typename std::conditional< std::is_same< SQInteger, signed long int >::value, std::ldiv_t, std::lldiv_t >::type DivT; #else typedef std::div_t DivT; #endif // _SQ64 // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation const DivT r = std::div(PopStackInteger(vm, 2), PopStackInteger(vm, 3)); // Create a new table on the stack sq_newtable(vm); // Push the quotient index sq_pushstring(vm, _SC("quot"), -1); // Push the quotient value sq_pushinteger(vm, r.quot); // Attempt to create the array element if (SQ_FAILED(sq_rawset(vm, -3))) { return sq_throwerror(vm, "Unable to insert the quotient element"); } // Push the remainder index sq_pushstring(vm, _SC("rem"), -1); // Push the remainder value sq_pushinteger(vm, r.rem); // Attempt to create the array element if (SQ_FAILED(sq_rawset(vm, -3))) { return sq_throwerror(vm, "Unable to insert the remainder element"); } // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqRemainder(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Are we both arguments floats? if ((sq_gettype(vm, 2) == OT_FLOAT) && sq_gettype(vm, 3) == OT_FLOAT) { // NOLINT(bugprone-branch-clone) sq_pushfloat(vm, std::remainder(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); } // Are we both arguments integers? else if ((sq_gettype(vm, 2) == OT_INTEGER) && sq_gettype(vm, 3) == OT_INTEGER) { // NOLINT(bugprone-branch-clone) sq_pushinteger(vm, static_cast< SQInteger >(std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3)))); } // Is the first argument float? else if ((sq_gettype(vm, 2) == OT_FLOAT)) { sq_pushfloat(vm, std::remainder(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); } // Is the first argument integer? else if ((sq_gettype(vm, 2) == OT_INTEGER)) { sq_pushinteger(vm, static_cast< SQInteger >(std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3)))); } // Default to both arguments as float so we don't loos precision from the float one else { sq_pushfloat(vm, std::remainder(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); } // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqFma(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 3) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::fma(PopStackFloat(vm, 2), PopStackFloat(vm, 3), PopStackFloat(vm, 4))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqMax(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::fmax(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqMin(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::fmin(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqDim(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::fdim(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqNan(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Attempt to generate the string value StackStrF val(vm, 2); // Have we failed to retrieve the string? if (SQ_FAILED(val.Proc(true))) { return val.mRes; // Propagate the error! } // Fetch the arguments from the stack and perform the requested operation #ifdef _SQ64 sq_pushfloat(vm, std::nan(val.mPtr)); #else sq_pushfloat(vm, std::nanf(val.mPtr)); #endif // _SQ64 // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqNanL(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Attempt to generate the string value StackStrF val(vm, 2); // Have we failed to retrieve the string? if (SQ_FAILED(val.Proc(true))) { return val.mRes; // Propagate the error! } // Fetch the arguments from the stack and perform the requested operation sq_pushinteger(vm, static_cast< SQInteger >(std::nanl(val.mPtr))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqExp(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::exp(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqExp2(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::exp2(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqExpm1(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::expm1(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqLog(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::log(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqLog10(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::log10(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqLog2(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::log2(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqLog1p(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::log1p(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqPow(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::pow(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqSqrt(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::sqrt(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqCbrt(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::cbrt(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqHypot(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::hypot(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqSin(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::sin(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqCos(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::cos(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqTan(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::tan(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqAsin(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::asin(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqAcos(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::acos(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqAtan(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::atan(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqAtan2(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::atan2(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqSinh(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::sinh(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqCosh(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::cosh(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqTanh(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::tanh(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqAsinh(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::asinh(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqAcosh(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::acosh(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqAtanh(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::atanh(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqErf(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::erf(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqErfc(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::erfc(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqTgamma(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::tgamma(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqLgamma(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::lgamma(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqCeil(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::ceil(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqFloor(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::floor(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqTrunc(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::trunc(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqRound(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::round(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqRoundI(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation if (sq_gettype(vm, 2) == OT_FLOAT) { sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackFloat(vm, 2)))); } else { sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackInteger(vm, 2)))); } // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqRoundL(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation if (sq_gettype(vm, 2) == OT_FLOAT) { sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackFloat(vm, 2)))); } else { sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackInteger(vm, 2)))); } // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqNearByInt(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::nearbyint(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqFrexp(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Where the exponent is retrieved int32_t expv = 0; // Fetch the arguments from the stack and perform the requested operation const SQFloat sigv = std::frexp(PopStackFloat(vm, 2), &expv); // Create a new table on the stack sq_newtable(vm); // Push the significand index sq_pushstring(vm, _SC("sig"), -1); // Push the significand value sq_pushfloat(vm, sigv); // Attempt to create the array element if (SQ_FAILED(sq_rawset(vm, -3))) { return sq_throwerror(vm, "Unable to insert the significand element"); } // Push the exponent index sq_pushstring(vm, _SC("exp"), -1); // Push the exponent value sq_pushinteger(vm, expv); // Attempt to create the array element if (SQ_FAILED(sq_rawset(vm, -3))) { return sq_throwerror(vm, "Unable to insert the exponent element"); } // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqLdexp(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::ldexp(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3)))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqModF(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Where the fractional part is retrieved SQFloat intv = 0; // Fetch the arguments from the stack and perform the requested operation const SQFloat fracv = std::modf(PopStackFloat(vm, 2), &intv); // Create a new table on the stack sq_newtable(vm); // Push the integral index sq_pushstring(vm, _SC("integral"), -1); // Push the integral value sq_pushfloat(vm, intv); // Attempt to create the array element if (SQ_FAILED(sq_rawset(vm, -3))) { return sq_throwerror(vm, "Unable to insert the integral element"); } // Push the fractional index sq_pushstring(vm, _SC("fractional"), -1); // Push the fractional value sq_pushfloat(vm, fracv); // Attempt to create the array element if (SQ_FAILED(sq_rawset(vm, -3))) { return sq_throwerror(vm, "Unable to insert the fractional element"); } // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqScalbn(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation #ifdef _SQ64 sq_pushfloat(vm, std::scalbln(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3)))); #else sq_pushfloat(vm, std::scalbn(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3)))); #endif // _SQ64 // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIlogb(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushinteger(vm, std::ilogb(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqLogb(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::logb(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqNextAfter(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::nextafter(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqNextForward(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::nexttoward(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqCopySign(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushfloat(vm, std::copysign(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqFpClassify(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushinteger(vm, std::fpclassify(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsFinite(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isfinite(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsInf(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isinf(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsNan(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isnan(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsNormal(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isnormal(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqSignBit(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::signbit(PopStackFloat(vm, 2))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsGreater(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isgreater(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsGreaterEqual(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isgreaterequal(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsLess(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isless(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsLessEqual(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::islessequal(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsLessGreater(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::islessgreater(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqIsUnordered(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 2) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the arguments from the stack and perform the requested operation sq_pushbool(vm, std::isunordered(PopStackFloat(vm, 2), PopStackFloat(vm, 3))); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqDigits1(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the integer value from the stack int64_t n = std::llabs(PopStackInteger(vm, 2)); // Start with 0 digits uint8_t d = 0; // Identify the number of digits while (n != 0) { n /= 10; ++d; } // Push the number of digits on the stack sq_pushinteger(vm, d); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ static SQInteger SqDigits0(HSQUIRRELVM vm) { // Do we have the correct number of arguments? if (sq_gettop(vm) <= 1) { return sq_throwerror(vm, "Wrong number of arguments"); } // Fetch the integer value from the stack int64_t n = std::llabs(PopStackInteger(vm, 2)); // Start with 0 digits uint8_t d = 0; // Identify the number of digits do { n /= 10; ++d; } while (n != 0); // Push the number of digits on the stack sq_pushinteger(vm, d); // Specify that we have a value on the stack return 1; } // ------------------------------------------------------------------------------------------------ SQFloat SqIToF(int64_t sigv, int64_t expv, int32_t padn, bool negf) { // The number of characters to add before the exponent CharT padb[64]; // Make sure the pad number is positive padn = ClampMin(padn, 0); // Is the number of pad characters out of range? if (static_cast< uint32_t >(padn) >= sizeof(padb)) { STHROWF("Pad characters out of range: {} >= {}", padn, sizeof(padb)); } // Write the padding characters std::memset(padb, '0', padn); // Add the null terminator padb[padn] = '\0'; // Now transform the resulted string to a floating point value if (negf) { #ifdef SQUSEDOUBLE return std::strtod(fmt::format("-{}.{}{}", sigv, padb, expv).c_str(), nullptr); #else return std::strtof(fmt::format("-{}.{}{}", sigv, padb, expv).c_str(), nullptr); #endif // SQUSEDOUBLE } else { #ifdef SQUSEDOUBLE return std::strtod(fmt::format("{}.{}{}", sigv, padb, expv).c_str(), nullptr); #else return std::strtof(fmt::format("{}.{}{}", sigv, padb, expv).c_str(), nullptr); #endif // SQUSEDOUBLE } } // ================================================================================================ void Register_Math(HSQUIRRELVM vm) { Table mns(vm); mns .SquirrelFunc(_SC("Div"), &SqDiv) .SquirrelFunc(_SC("Remainder"), &SqRemainder) .SquirrelFunc(_SC("Fma"), &SqFma) .SquirrelFunc(_SC("Max"), &SqMax) .SquirrelFunc(_SC("Min"), &SqMin) .SquirrelFunc(_SC("Dim"), &SqDim) .SquirrelFunc(_SC("Nan"), &SqNan) .SquirrelFunc(_SC("NanL"), &SqNanL) .SquirrelFunc(_SC("Exp"), &SqExp) .SquirrelFunc(_SC("Exp2"), &SqExp2) .SquirrelFunc(_SC("Expm1"), &SqExpm1) .SquirrelFunc(_SC("Log"), &SqLog) .SquirrelFunc(_SC("Log10"), &SqLog10) .SquirrelFunc(_SC("Log2"), &SqLog2) .SquirrelFunc(_SC("Log1p"), &SqLog1p) .SquirrelFunc(_SC("Pow"), &SqPow) .SquirrelFunc(_SC("Sqrt"), &SqSqrt) .SquirrelFunc(_SC("Cbrt"), &SqCbrt) .SquirrelFunc(_SC("Hypot"), &SqHypot) .SquirrelFunc(_SC("Sin"), &SqSin) .SquirrelFunc(_SC("Cos"), &SqCos) .SquirrelFunc(_SC("Tan"), &SqTan) .SquirrelFunc(_SC("Asin"), &SqAsin) .SquirrelFunc(_SC("Acos"), &SqAcos) .SquirrelFunc(_SC("Atan"), &SqAtan) .SquirrelFunc(_SC("Atan2"), &SqAtan2) .SquirrelFunc(_SC("Sinh"), &SqSinh) .SquirrelFunc(_SC("Cosh"), &SqCosh) .SquirrelFunc(_SC("Tanh"), &SqTanh) .SquirrelFunc(_SC("Asinh"), &SqAsinh) .SquirrelFunc(_SC("Acosh"), &SqAcosh) .SquirrelFunc(_SC("Atanh"), &SqAtanh) .SquirrelFunc(_SC("Erf"), &SqErf) .SquirrelFunc(_SC("Erfc"), &SqErfc) .SquirrelFunc(_SC("Tgamma"), &SqTgamma) .SquirrelFunc(_SC("Lgamma"), &SqLgamma) .SquirrelFunc(_SC("Ceil"), &SqCeil) .SquirrelFunc(_SC("Floor"), &SqFloor) .SquirrelFunc(_SC("Trunc"), &SqTrunc) .SquirrelFunc(_SC("Round"), &SqRound) .SquirrelFunc(_SC("RoundI"), &SqRoundI) .SquirrelFunc(_SC("RoundL"), &SqRoundL) .SquirrelFunc(_SC("NearByInt"), &SqNearByInt) .SquirrelFunc(_SC("Frexp"), &SqFrexp) .SquirrelFunc(_SC("Ldexp"), &SqLdexp) .SquirrelFunc(_SC("ModF"), &SqModF) .SquirrelFunc(_SC("Scalbn"), &SqScalbn) .SquirrelFunc(_SC("Ilogb"), &SqIlogb) .SquirrelFunc(_SC("Logb"), &SqLogb) .SquirrelFunc(_SC("NextAfter"), &SqNextAfter) .SquirrelFunc(_SC("NextForward"), &SqNextForward) .SquirrelFunc(_SC("CopySign"), &SqCopySign) .SquirrelFunc(_SC("FpClassify"), &SqFpClassify) .SquirrelFunc(_SC("IsFinite"), &SqIsFinite) .SquirrelFunc(_SC("IsInf"), &SqIsInf) .SquirrelFunc(_SC("IsNan"), &SqIsNan) .SquirrelFunc(_SC("IsNormal"), &SqIsNormal) .SquirrelFunc(_SC("SignBit"), &SqSignBit) .SquirrelFunc(_SC("IsGreater"), &SqIsGreater) .SquirrelFunc(_SC("IsGreaterEqual"), &SqIsGreaterEqual) .SquirrelFunc(_SC("IsLess"), &SqIsLess) .SquirrelFunc(_SC("IsLessEqual"), &SqIsLessEqual) .SquirrelFunc(_SC("IsLessGreater"), &SqIsLessGreater) .SquirrelFunc(_SC("IsUnordered"), &SqIsUnordered) .SquirrelFunc(_SC("Digits1"), &SqDigits1) .SquirrelFunc(_SC("Digits0"), &SqDigits0); RootTable(vm).Bind(_SC("SqMath"), mns); RootTable(vm).Func(_SC("IToF"), &SqIToF); } } // Namespace:: SqMod