#ifdef __MINGW32__
#ifndef __USE_MINGW_ANSI_STDIO
#define __USE_MINGW_ANSI_STDIO 1
#endif
#endif
#define PERL_NO_GET_CONTEXT 1
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "math_decimal64_include.h"
typedef _Decimal64 D64;
int nnum = 0; /* flag that is incremented whenever _atodecimal is handed something non-numeric */
long long add_on[54] = {1ll,2ll, 4ll, 8ll, 16ll, 32ll, 64ll, 128ll, 256ll, 512ll, 1024ll, 2048ll,
4096ll, 8192ll, 16384ll, 32768ll, 65536ll, 131072ll, 262144ll, 524288ll,
1048576ll, 2097152ll, 4194304ll, 8388608ll, 16777216ll, 33554432ll,
67108864ll, 134217728ll, 268435456ll, 536870912ll, 1073741824ll,
2147483648ll, 4294967296ll, 8589934592ll, 17179869184ll, 34359738368ll,
68719476736ll, 137438953472ll, 274877906944ll, 549755813888ll,
1099511627776ll, 2199023255552ll, 4398046511104ll, 8796093022208ll,
17592186044416ll, 35184372088832ll, 70368744177664ll, 140737488355328ll,
281474976710656ll, 562949953421312ll, 1125899906842624ll, 2251799813685248ll,
4503599627370496ll, 9007199254740992ll};
_Decimal64 _exp10 (int power) {
_Decimal64 ret = 1.DD;
if(power < 0) {
while(power < -100) {
ret *= 1e-100DD;
power += 100;
}
while(power < -10) {
ret *= 1e-10DD;
power += 10;
}
while(power) {
ret *= 1e-1DD;
power++;
}
}
else {
while(power > 100) {
ret *= 1e100DD;
power -= 100;
}
while(power > 10) {
ret *= 1e10DD;
power -= 10;
}
while(power) {
ret *= 1e1DD;
power--;
}
}
return ret;
}
int _is_nan(_Decimal64 x) {
if(x == x) return 0;
return 1;
}
int _is_inf(_Decimal64 x) {
if(x != x) return 0; /* NaN */
if(x == 0.0DD) return 0; /* Zero */
if(x/x != x/x) {
if(x < 0.0DD) return -1;
else return 1;
}
return 0; /* Finite Real */
}
/* Replaced */
/*
//int _is_neg_zero(_Decimal64 x) {
// char * buffer;
//
// if(x != 0.0DD) return 0;
//
// Newx(buffer, 2, char);
// sprintf(buffer, "%.0f", (double)x);
//
// if(strcmp(buffer, "-0")) {
// Safefree(buffer);
// return 0;
// }
//
// Safefree(buffer);
// return 1;
//}
*/
int _is_neg_zero(_Decimal64 d64) {
int n = sizeof(_Decimal64);
void * p = &d64;
/*****************************************************
We perform the following oddness because of gcc's
buggy optimization of signed zero _Decimal64.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80692
******************************************************/
if(d64 != 0.0DD) {
if(d64 * -1.0DD == 0.0DD) return 1; /* it's a -0 */
return 0; /* it's not zero */
}
#ifdef WE_HAVE_BENDIAN /* Big Endian architecture */
if(((unsigned char*)p)[0] >= 128) return 1;
#else
if(((unsigned char*)p)[n - 1] >= 128) return 1;
#endif
return 0;
}
SV * _is_nan_NV(pTHX_ SV * x) {
if(SvNV(x) == SvNV(x)) return newSViv(0);
return newSViv(1);
}
SV * _is_inf_NV(pTHX_ SV * x) {
if(SvNV(x) != SvNV(x)) return 0; /* NaN */
if(SvNV(x) == 0.0) return newSViv(0); /* Zero */
if(SvNV(x)/SvNV(x) != SvNV(x)/SvNV(x)) {
if(SvNV(x) < 0.0) return newSViv(-1);
else return newSViv(1);
}
return newSVnv(0); /* Finite Real */
}
SV * _is_neg_zero_NV(pTHX_ SV * x) {
char buffer[3];
if(SvNV(x) != 0.0) return newSViv(0);
sprintf(buffer, "%.0f", (double)SvNV(x));
if(strcmp(buffer, "-0")) {
return newSViv(0);
}
return newSViv(1);
}
_Decimal64 _get_inf(int sign) {
if(sign < 0) return -1.0DD/0.0DD;
return 1.0DD/0.0DD;
}
_Decimal64 _get_nan(void) {
_Decimal64 inf = _get_inf(1);
return inf/inf;
}
_Decimal64 _atodecimal(pTHX_ char * s) {
/*
plagiarising code available at
https://www.ibm.com/developerworks/community/wikis/home?lang=en_US#!/wiki/Power%20Systems/page/POWER6%20Decimal%20Floating%20Point%20(DFP)
The aim is that nnum be incremented iff looks_like_number() would return false for the given string
*/
_Decimal64 top = 0.DD, bot = 0.DD, result = 0.DD, div = 10.DD;
int negative = 0, i = 0, exponent = 0, count = 0;
if(!strcmp(s, "0 but true")) return 0.DD;
while(s[0] == ' ' || s[0] == '\t' || s[0] == '\n' || s[0] == '\r' || s[0] == '\f') s++;
if(s[0] == '-') {
negative = -1;
s++;
}
else {
if(s[0] == '+') s++;
}
if((s[0] == 'i' || s[0] == 'I') && (s[1] == 'n' || s[1] == 'N') && (s[2] == 'f' || s[2] == 'F')) {
if((s[3] == 'i' || s[3] == 'I') && (s[4] == 'n' || s[4] == 'N') && (s[5] == 'i' || s[5] == 'I') &&
(s[6] == 't' || s[6] == 'T') && (s[7] == 'y' || s[7] == 'Y')) count = 5;
for(i = 3 + count;;i++) {
if(s[i] == 0) return _get_inf(negative);
if(s[i] != ' ' && s[i] != '\t' && s[i] != '\n' && s[i] != '\r' && s[i] != '\f') {
nnum++;
if(SvIV(get_sv("Math::Decimal64::NNW", 0)))
warn("string argument contains at least one non-numeric character");
return _get_inf(negative);
}
}
}
if((s[0] == 'n' || s[0] == 'N') && (s[1] == 'a' || s[1] == 'A') && (s[2] == 'n' || s[2] == 'N')) {
for(i = 3;;i++) {
if(s[i] == 0) return _get_nan();
if(s[i] != ' ' && s[i] != '\t' && s[i] != '\n' && s[i] != '\r' && s[i] != '\f') {
nnum++;
if(SvIV(get_sv("Math::Decimal64::NNW", 0)))
warn("string argument contains at least one non-numeric character");
return _get_nan();
}
}
}
/* Must be a digit or a decimal point */
if(!isdigit(s[0]) && s[0] != '.') {
nnum++;
if(SvIV(get_sv("Math::Decimal64::NNW", 0)))
warn("string argument contains at least one non-numeric character");
result = negative ? result * -1.DD : result;
return result;
}
for(; isdigit(*s); s++) {
top = top * 10.DD;
top = top + *s - '0';
}
if(s[0] == '.') {
s++;
for(i = 0; isdigit(s[i]) ;i++) {
bot += (_Decimal64)(s[i] - '0') / (_Decimal64)div;
div *= 10.DD;
}
}
result = top + bot;
if(negative) result *= -1.DD;
if(s[i] == 'e' || s[i] == 'E') {
s += i + 1;
if(*s == '-') {
s++;
for(i = 0; isdigit(s[i]);i++) exponent = (exponent * 10) + (s[i] - '0');
while(exponent > 398) {
result /= 10.DD;
exponent--;
}
result *= _exp10(-exponent);
/* Check for non-numeric trailing characters, and increment nnum */
/* (and return immediately) if we hit one */
for(;;i++) {
if(s[i] == 0) return result;
if(s[i] != ' ' && s[i] != '\t' && s[i] != '\n' && s[i] != '\r' && s[i] != '\f') {
nnum++;
if(SvIV(get_sv("Math::Decimal64::NNW", 0)))
warn("string argument contains at least one non-numeric character");
return result;
}
}
}
if(*s == '+') s++;
for(i = 0; isdigit(s[i]);i++) exponent = (exponent * 10) + (s[i] - '0');
while(exponent > 384) {
result *= 10.DD;
exponent--;
}
result *= _exp10(exponent);
/* Check for non-numeric trailing characters, and increment nnum */
/* (and return immediately) if we hit one */
for(;;i++) {
if(s[i] == 0) return result;
if(s[i] != ' ' && s[i] != '\t' && s[i] != '\n' && s[i] != '\r' && s[i] != '\f') {
nnum++;
if(SvIV(get_sv("Math::Decimal64::NNW", 0)))
warn("string argument contains at least one non-numeric character");
return result;
}
}
}
/* Check for non-numeric trailing characters, and increment nnum */
/* (and return immediately) if we hit one */
for(;;i++) {
if(s[i] == 0) return result;
if(s[i] != ' ' && s[i] != '\t' && s[i] != '\n' && s[i] != '\r' && s[i] != '\f') {
nnum++;
if(SvIV(get_sv("Math::Decimal64::NNW", 0)))
warn("string argument contains at least one non-numeric character");
return result;
}
}
}
SV * _DEC64_MAX(pTHX) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in DEC64_MAX function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = 9999999999999999e369DD;
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * _DEC64_MIN(pTHX) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in DEC64_MIN function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = 1e-398DD;
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * NaND64(pTHX) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in NaND64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = _get_nan();
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * InfD64(pTHX_ int sign) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in InfD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = _get_inf(sign);
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * ZeroD64(pTHX_ int sign) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in ZeroD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = 0.0DD;
if(sign < 0) *d64 *= -1;
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * UnityD64(pTHX_ int sign) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in UnityD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = 1.0DD;
if(sign < 0) *d64 *= -1;
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * Exp10(pTHX_ int power) {
_Decimal64 * d64;
SV * obj_ref, * obj;
/*
Remove this condition - and let the value be set to 0 or Inf
if(power < -398 || power > 384)
croak("Argument supplied to Exp10 function (%d) is out of allowable range", power);
*/
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in Exp10 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = 1.0DD;
if(power < 0) {
while(power < -100) {
*d64 *= 1e-100DD;
power += 100;
}
while(power < -10) {
*d64 *= 1e-10DD;
power += 10;
}
while(power) {
*d64 *= 1e-1DD;
power++;
}
}
else {
while(power > 100) {
*d64 *= 1e100DD;
power -= 100;
}
while(power > 10) {
*d64 *= 1e10DD;
power -= 10;
}
while(power) {
*d64 *= 1e1DD;
power--;
}
}
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * _testvalD64(pTHX_ int sign) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _testvalD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = 9307199254740993e-15DD;
if(sign < 0) *d64 *= -1;
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * _MEtoD64(pTHX_ char * mantissa, SV * exponent) {
_Decimal64 * d64;
SV * obj_ref, * obj;
int exp = (int)SvIV(exponent), i;
char * ptr;
long double man;
man = strtold(mantissa, &ptr);
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in MEtoD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = (_Decimal64)man;
if(exp < 0) {
for(i = 0; i > exp; --i) *d64 *= 0.1DD;
}
else {
for(i = 0; i < exp; ++i) *d64 *= 10.0DD;
}
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * NVtoD64(pTHX_ SV * x) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in NVtoD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = (_Decimal64)SvNV(x);
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * UVtoD64(pTHX_ SV * x) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in UVtoD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = (_Decimal64)SvUV(x);
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * IVtoD64(pTHX_ SV * x) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in IVtoD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = (_Decimal64)SvIV(x);
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * PVtoD64(pTHX_ char * x) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in PVtoD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
*d64 = _atodecimal(aTHX_ x);
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * STRtoD64(pTHX_ char * x) {
#ifdef STRTOD64_AVAILABLE
_Decimal64 * d64;
char * ptr;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in STRtoD64 function");
*d64 = strtod64(x, &ptr);
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
#else
croak("The strtod64 function has not been made available");
#endif
}
int have_strtod64(void) {
#ifdef STRTOD64_AVAILABLE
return 1;
#else
return 0;
#endif
}
SV * D64toNV(pTHX_ SV * d64) {
return newSVnv((NV)(*(INT2PTR(_Decimal64*, SvIVX(SvRV(d64))))));
}
void LDtoD64(pTHX_ SV * d64, SV * ld) {
if(sv_isobject(d64) && sv_isobject(ld)) {
const char *h1 = HvNAME(SvSTASH(SvRV(d64)));
const char *h2 = HvNAME(SvSTASH(SvRV(ld)));
if(strEQ(h1, "Math::Decimal64") && strEQ(h2, "Math::LongDouble")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(d64)))) = (_Decimal64)*(INT2PTR(long double *, SvIVX(SvRV(ld))));
}
else croak("Invalid object supplied to Math::Decimal64::LDtoD64");
}
else croak("Invalid argument supplied to Math::Decimal64::LDtoD64");
}
void D64toLD(pTHX_ SV * ld, SV * d64) {
if(sv_isobject(d64) && sv_isobject(ld)) {
const char *h1 = HvNAME(SvSTASH(SvRV(d64)));
const char *h2 = HvNAME(SvSTASH(SvRV(ld)));
if(strEQ(h1, "Math::Decimal64") && strEQ(h2, "Math::LongDouble")) {
*(INT2PTR(long double *, SvIVX(SvRV(ld)))) = (long double)*(INT2PTR(_Decimal64 *, SvIVX(SvRV(d64))));
}
else croak("Invalid object supplied to Math::Decimal64::D64toLD");
}
else croak("Invalid argument supplied to Math::Decimal64::D64toLD");
}
void DESTROY(pTHX_ SV * rop) {
Safefree(INT2PTR(_Decimal64 *, SvIVX(SvRV(rop))));
}
void _assignME(pTHX_ SV * a, char * mantissa, SV * c) {
char * ptr;
long double man;
int exp = (int)SvIV(c), i;
man = strtold(mantissa, &ptr);
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = (_Decimal64)man;
if(exp < 0) {
for(i = 0; i > exp; --i) *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) *= 0.1DD;
}
else {
for(i = 0; i < exp; ++i) *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) *= 10.0DD;
}
}
void assignPV(pTHX_ SV * a, char * s) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = _atodecimal(aTHX_ s);
}
void assignIV(pTHX_ SV * a, SV * val) {
if(sv_isobject(a)) {
const char * h = HvNAME(SvSTASH(SvRV(a)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = (_Decimal64)SvIV(val);
}
else croak("Invalid object supplied to Math::Decimal64::assignIV function");
}
else croak("Invalid argument supplied to Math::Decimal64::assignIV function");
}
void assignUV(pTHX_ SV * a, SV * val) {
if(sv_isobject(a)) {
const char * h = HvNAME(SvSTASH(SvRV(a)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = (_Decimal64)SvUV(val);
}
else croak("Invalid object supplied to Math::Decimal64::assignUV function");
}
else croak("Invalid argument supplied to Math::Decimal64::assignUV function");
}
void assignNV(pTHX_ SV * a, SV * val) {
if(sv_isobject(a)) {
const char * h = HvNAME(SvSTASH(SvRV(a)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = (_Decimal64)SvNV(val);
}
else croak("Invalid object supplied to Math::Decimal64::assignNV function");
}
else croak("Invalid argument supplied to Math::Decimal64::assignNV function");
}
void assignD64(pTHX_ SV * a, SV * val) {
if(sv_isobject(a) && sv_isobject(val)) {
const char * h = HvNAME(SvSTASH(SvRV(a)));
const char * hh = HvNAME(SvSTASH(SvRV(val)));
if(strEQ(h, "Math::Decimal64") && strEQ(hh, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(val))));
}
else croak("Invalid object supplied to Math::Decimal64::assignD64 function");
}
else croak("Invalid argument supplied to Math::Decimal64::assignD64 function");
}
void assignNaN(pTHX_ SV * a) {
if(sv_isobject(a)) {
const char * h = HvNAME(SvSTASH(SvRV(a)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = _get_nan();
}
else croak("Invalid object supplied to Math::Decimal64::assignNaN function");
}
else croak("Invalid argument supplied to Math::Decimal64::assignNaN function");
}
void assignInf(pTHX_ SV * a, int sign) {
if(sv_isobject(a)) {
const char * h = HvNAME(SvSTASH(SvRV(a)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) = _get_inf(sign);
}
else croak("Invalid object supplied to Math::Decimal64::assignInf function");
}
else croak("Invalid argument supplied to Math::Decimal64::assignInf function");
}
SV * _overload_add(pTHX_ SV * a, SV * b, SV * third) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _overload_add function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
if(SvUOK(b)) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) + (D64)SvUVX(b);
return obj_ref;
}
if(SvIOK(b)) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) + (D64)SvIVX(b);
return obj_ref;
}
if(SvPOK(b) && !SvNOK(b)) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) + _atodecimal(aTHX_ SvPV_nolen(b));
return obj_ref;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) + *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return obj_ref;
}
croak("Invalid object supplied to Math::Decimal64::_overload_add function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_add function");
}
SV * _overload_mul(pTHX_ SV * a, SV * b, SV * third) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _overload_mul function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
if(SvUOK(b)) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) * (D64)SvUVX(b);
return obj_ref;
}
if(SvIOK(b)) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) * (D64)SvIVX(b);
return obj_ref;
}
if(SvPOK(b) && !SvNOK(b)) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) * _atodecimal(aTHX_ SvPV_nolen(b));
return obj_ref;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) * *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return obj_ref;
}
croak("Invalid object supplied to Math::Decimal64::_overload_mul function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_mul function");
}
SV * _overload_sub(pTHX_ SV * a, SV * b, SV * third) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _overload_sub function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
if(SvUOK(b)) {
if(SWITCH_ARGS) *d64 = (D64)SvUVX(b) - *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
else *d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) - (D64)SvUVX(b);
return obj_ref;
}
if(SvIOK(b)) {
if(SWITCH_ARGS) *d64 = (D64)SvIVX(b) - *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
else *d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) - (D64)SvIVX(b);
return obj_ref;
}
if(SvPOK(b) && !SvNOK(b)) {
if(SWITCH_ARGS) *d64 = _atodecimal(aTHX_ SvPV_nolen(b)) - *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
else *d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) - _atodecimal(aTHX_ SvPV_nolen(b));
return obj_ref;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) - *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return obj_ref;
}
croak("Invalid object supplied to Math::Decimal64::_overload_sub function");
}
/* replaced by _overload_neg
if(SWITCH_ARGS) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) * -1.0DD;
return obj_ref;
}
*/
croak("Invalid argument supplied to Math::Decimal64::_overload_sub function");
}
SV * _overload_neg(pTHX_ SV * a, SV * b, SV * third) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _overload_sub function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) * -1.0DD;
return obj_ref;
}
SV * _overload_div(pTHX_ SV * a, SV * b, SV * third) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _overload_div function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
if(SvUOK(b)) {
if(SWITCH_ARGS) *d64 = (D64)SvUVX(b) / *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
else *d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) / (D64)SvUVX(b);
return obj_ref;
}
if(SvIOK(b)) {
if(SWITCH_ARGS) *d64 = (D64)SvIVX(b) / *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
else *d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) / (D64)SvIVX(b);
return obj_ref;
}
if(SvPOK(b) && !SvNOK(b)) {
if(SWITCH_ARGS) *d64 = _atodecimal(aTHX_ SvPV_nolen(b)) / *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
else *d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) / _atodecimal(aTHX_ SvPV_nolen(b));
return obj_ref;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) / *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return obj_ref;
}
croak("Invalid object supplied to Math::Decimal64::_overload_div function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_div function");
}
SV * _overload_add_eq(pTHX_ SV * a, SV * b, SV * third) {
SvREFCNT_inc(a);
if(SvUOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) += (D64)SvUVX(b);
return a;
}
if(SvIOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) += (D64)SvIVX(b);
return a;
}
if(SvPOK(b) && !SvNOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) += _atodecimal(aTHX_ SvPV_nolen(b));
return a;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) += *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return a;
}
SvREFCNT_dec(a);
croak("Invalid object supplied to Math::Decimal64::_overload_add_eq function");
}
SvREFCNT_dec(a);
croak("Invalid argument supplied to Math::Decimal64::_overload_add_eq function");
}
SV * _overload_mul_eq(pTHX_ SV * a, SV * b, SV * third) {
SvREFCNT_inc(a);
if(SvUOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) *= (D64)SvUVX(b);
return a;
}
if(SvIOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) *= (D64)SvIVX(b);
return a;
}
if(SvPOK(b) && !SvNOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) *= _atodecimal(aTHX_ SvPV_nolen(b));
return a;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) *= *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return a;
}
SvREFCNT_dec(a);
croak("Invalid object supplied to Math::Decimal64::_overload_mul_eq function");
}
SvREFCNT_dec(a);
croak("Invalid argument supplied to Math::Decimal64::_overload_mul_eq function");
}
SV * _overload_sub_eq(pTHX_ SV * a, SV * b, SV * third) {
SvREFCNT_inc(a);
if(SvUOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) -= (D64)SvUVX(b);
return a;
}
if(SvIOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) -= (D64)SvIVX(b);
return a;
}
if(SvPOK(b) && !SvNOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) -= _atodecimal(aTHX_ SvPV_nolen(b));
return a;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) -= *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return a;
}
SvREFCNT_dec(a);
croak("Invalid object supplied to Math::Decimal64::_overload_sub_eq function");
}
SvREFCNT_dec(a);
croak("Invalid argument supplied to Math::Decimal64::_overload_sub_eq function");
}
SV * _overload_div_eq(pTHX_ SV * a, SV * b, SV * third) {
SvREFCNT_inc(a);
if(SvUOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) /= (D64)SvUVX(b);
return a;
}
if(SvIOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) /= (D64)SvIVX(b);
return a;
}
if(SvPOK(b) && !SvNOK(b)) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) /= _atodecimal(aTHX_ SvPV_nolen(b));
return a;
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) /= *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))));
return a;
}
SvREFCNT_dec(a);
croak("Invalid object supplied to Math::Decimal64::_overload_div_eq function");
}
SvREFCNT_dec(a);
croak("Invalid argument supplied to Math::Decimal64::_overload_div_eq function");
}
SV * _overload_equiv(pTHX_ SV * a, SV * b, SV * third) {
if(SvUOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvIOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvPOK(b) && !SvNOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(1);
return newSViv(0);
}
croak("Invalid object supplied to Math::Decimal64::_overload_equiv function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_equiv function");
}
SV * _overload_not_equiv(pTHX_ SV * a, SV * b, SV * third) {
if(SvUOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) != (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvIOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) != (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvPOK(b) && !SvNOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) != _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(0);
return newSViv(1);
}
croak("Invalid object supplied to Math::Decimal64::_overload_not_equiv function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_not_equiv function");
}
SV * _overload_lt(pTHX_ SV * a, SV * b, SV * third) {
if(SvUOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvIOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvPOK(b) && !SvNOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(1);
return newSViv(0);
}
croak("Invalid object supplied to Math::Decimal64::_overload_lt function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_lt function");
}
SV * _overload_gt(pTHX_ SV * a, SV * b, SV * third) {
if(SvUOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvIOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvPOK(b) && !SvNOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(1);
return newSViv(0);
}
croak("Invalid object supplied to Math::Decimal64::_overload_gt function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_gt function");
}
SV * _overload_lte(pTHX_ SV * a, SV * b, SV * third) {
if(SvUOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) >= (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) <= (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvIOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) >= (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) <= (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvPOK(b) && !SvNOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) >= _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) <= _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) <= *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(1);
return newSViv(0);
}
croak("Invalid object supplied to Math::Decimal64::_overload_lte function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_lte function");
}
SV * _overload_gte(pTHX_ SV * a, SV * b, SV * third) {
if(SvUOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) <= (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) >= (D64)SvUVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvIOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) <= (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) >= (D64)SvIVX(b)) return newSViv(1);
return newSViv(0);
}
if(SvPOK(b) && !SvNOK(b)) {
if(SWITCH_ARGS) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) <= _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) >= _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1);
return newSViv(0);
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) >= *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(1);
return newSViv(0);
}
croak("Invalid object supplied to Math::Decimal64::_overload_gte function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_gte function");
}
SV * _overload_spaceship(pTHX_ SV * a, SV * b, SV * third) {
int reversal = 1;
if(SWITCH_ARGS) reversal = -1;
if(SvUOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > (D64)SvUVX(b)) return newSViv(1 * reversal);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < (D64)SvUVX(b)) return newSViv(-1 * reversal);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == (D64)SvUVX(b)) return newSViv(0);
return &PL_sv_undef; /* Math::Decimal64 object (1st arg) is a nan */
}
if(SvIOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > (D64)SvIVX(b)) return newSViv(1 * reversal);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < (D64)SvIVX(b)) return newSViv(-1 * reversal);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == (D64)SvIVX(b)) return newSViv(0);
return &PL_sv_undef; /* Math::Decimal64 object (1st arg) is a nan */
}
if(SvPOK(b) && !SvNOK(b)) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(1 * reversal);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(-1 * reversal);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == _atodecimal(aTHX_ SvPV_nolen(b))) return newSViv(0);
return &PL_sv_undef; /* Math::Decimal64 object (1st arg) is a nan */
}
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64")) {
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) < *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(-1);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) > *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(1);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) == *(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))) return newSViv(0);
return &PL_sv_undef; /* it's a nan */
}
croak("Invalid object supplied to Math::Decimal64::_overload_spaceship function");
}
croak("Invalid argument supplied to Math::Decimal64::_overload_spaceship function");
}
SV * _overload_copy(pTHX_ SV * a, SV * b, SV * third) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _overload_copy function");
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
SV * D64toD64(pTHX_ SV * a) {
_Decimal64 * d64;
SV * obj_ref, * obj;
if(sv_isobject(a)) {
const char *h = HvNAME(SvSTASH(SvRV(a)));
if(strEQ(h, "Math::Decimal64")) {
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in D64toD64 function");
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
croak("Invalid object supplied to Math::Decimal64::D64toD64 function");
}
croak("Invalid argument supplied to Math::Decimal64::D64toD64 function");
}
SV * _overload_true(pTHX_ SV * a, SV * b, SV * third) {
if(_is_nan(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))))) return newSViv(0);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) != 0.0DD) return newSViv(1);
return newSViv(0);
}
SV * _overload_not(pTHX_ SV * a, SV * b, SV * third) {
if(_is_nan(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))))) return newSViv(1);
if(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(a)))) != 0.0DD) return newSViv(0);
return newSViv(1);
}
SV * _overload_abs(pTHX_ SV * a, SV * b, SV * third) {
_Decimal64 * d64;
SV * obj_ref, * obj;
Newx(d64, 1, _Decimal64);
if(d64 == NULL) croak("Failed to allocate memory in _overload_abs function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
*d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(a))));
if(_is_neg_zero(*d64) || *d64 < 0 ) *d64 *= -1.0DD;
return obj_ref;
}
SV * _overload_inc(pTHX_ SV * p, SV * second, SV * third) {
SvREFCNT_inc(p);
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(p)))) += 1.0DD;
return p;
}
SV * _overload_dec(pTHX_ SV * p, SV * second, SV * third) {
SvREFCNT_inc(p);
*(INT2PTR(_Decimal64 *, SvIVX(SvRV(p)))) -= 1.0DD;
return p;
}
SV * _itsa(pTHX_ SV * a) {
if(SvUOK(a)) return newSVuv(1);
if(SvIOK(a)) return newSVuv(2);
if(SvNOK(a)) return newSVuv(3);
if(SvPOK(a)) return newSVuv(4);
if(sv_isobject(a)) {
const char *h = HvNAME(SvSTASH(SvRV(a)));
if(strEQ(h, "Math::Decimal64")) return newSVuv(64);
}
return newSVuv(0);
}
SV * is_NaND64(pTHX_ SV * b) {
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64"))
return newSViv(_is_nan(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))));
}
croak("Invalid argument supplied to Math::Decimal64::is_NaND64 function");
}
SV * is_InfD64(pTHX_ SV * b) {
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64"))
return newSViv(_is_inf(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(b))))));
}
croak("Invalid argument supplied to Math::Decimal64::is_InfD64 function");
}
SV * is_ZeroD64(pTHX_ SV * b) {
if(sv_isobject(b)) {
const char *h = HvNAME(SvSTASH(SvRV(b)));
if(strEQ(h, "Math::Decimal64"))
if (_is_neg_zero(*(INT2PTR(_Decimal64 *, SvIVX(SvRV(b)))))) return newSViv(-1);
if (*(INT2PTR(_Decimal64 *, SvIVX(SvRV(b)))) == 0.0DD) return newSViv(1);
return newSViv(0);
}
croak("Invalid argument supplied to Math::Decimal64::is_ZeroD64 function");
}
SV * _wrap_count(pTHX) {
return newSVuv(PL_sv_count);
}
SV * _get_xs_version(pTHX) {
return newSVpv(XS_VERSION, 0);
}
void _d64_bytes(pTHX_ SV * sv) {
dXSARGS;
_Decimal64 d64 = *(INT2PTR(_Decimal64 *, SvIVX(SvRV(sv))));
int i, n = sizeof(_Decimal64);
char buff[4];
void * p = &d64;
sp = mark;
#ifdef WE_HAVE_BENDIAN /* Big Endian architecture */
for (i = 0; i < n; i++) {
#else
for (i = n - 1; i >= 0; i--) {
#endif
sprintf(buff, "%02X", ((unsigned char*)p)[i]);
XPUSHs(sv_2mortal(newSVpv(buff, 0)));
}
PUTBACK;
XSRETURN(n);
}
void _bid_mant(pTHX_ SV * bin) {
dXSARGS;
int i, imax = av_len((AV*)SvRV(bin));
char buf[21];
long long val = 0ll;
extern long long add_on[54];
for(i = 0; i <= imax; i++)
if(SvIV(*(av_fetch((AV*)SvRV(bin), i, 0)))) val += add_on[i];
if(val > 9999999999999999ll) sprintf(buf, "%lld", 0ll);
else sprintf(buf, "%lld", val);
ST(0) = sv_2mortal(newSVpv(buf, 0));
XSRETURN(1);
}
SV * _endianness(pTHX) {
#if defined(WE_HAVE_BENDIAN)
return newSVpv("Big Endian", 0);
#elif defined(WE_HAVE_LENDIAN)
return newSVpv("Little Endian", 0);
#else
return &PL_sv_undef;
#endif
}
SV * _DPDtoD64(pTHX_ char * in) {
D64 * d64;
SV * obj_ref, * obj;
int i, n = sizeof(D64);
D64 out = 0.;
void *p = &out;
Newx(d64, 1, D64);
if(d64 == NULL) croak("Failed to allocate memory in DPDtoD64 function");
obj_ref = newSV(0);
obj = newSVrv(obj_ref, "Math::Decimal64");
for (i = n - 1; i >= 0; i--)
#ifdef WE_HAVE_BENDIAN
((unsigned char*)p)[i] = in[i];
#else
((unsigned char*)p)[i] = in[n - 1 - i];
#endif
*d64 = out;
sv_setiv(obj, INT2PTR(IV,d64));
SvREADONLY_on(obj);
return obj_ref;
}
/*
_assignDPD takes 2 args: a Math::Decimal64 object, and a
string that encodes the value to be assigned to that object
*/
void _assignDPD(pTHX_ SV * a, char * in) {
int i, n = sizeof(D64);
D64 out = 0.;
void *p = &out;
for (i = n - 1; i >= 0; i--)
#ifdef WE_HAVE_BENDIAN
((unsigned char*)p)[i] = in[i];
#else
((unsigned char*)p)[i] = in[n - 1 - i];
#endif
*(INT2PTR(D64 *, SvIVX(SvRV(a)))) = out;
}
int nnumflag(void) {
return nnum;
}
void clear_nnum(void) {
nnum = 0;
}
void set_nnum(int x) {
nnum = x;
}
int _lln(pTHX_ SV * x) {
if(looks_like_number(x)) return 1;
return 0;
}
MODULE = Math::Decimal64 PACKAGE = Math::Decimal64
PROTOTYPES: DISABLE
SV *
_is_nan_NV (x)
SV * x
CODE:
RETVAL = _is_nan_NV (aTHX_ x);
OUTPUT: RETVAL
SV *
_is_inf_NV (x)
SV * x
CODE:
RETVAL = _is_inf_NV (aTHX_ x);
OUTPUT: RETVAL
SV *
_is_neg_zero_NV (x)
SV * x
CODE:
RETVAL = _is_neg_zero_NV (aTHX_ x);
OUTPUT: RETVAL
SV *
_DEC64_MAX ()
CODE:
RETVAL = _DEC64_MAX (aTHX);
OUTPUT: RETVAL
SV *
_DEC64_MIN ()
CODE:
RETVAL = _DEC64_MIN (aTHX);
OUTPUT: RETVAL
SV *
NaND64 ()
CODE:
RETVAL = NaND64 (aTHX);
OUTPUT: RETVAL
SV *
InfD64 (sign)
int sign
CODE:
RETVAL = InfD64 (aTHX_ sign);
OUTPUT: RETVAL
SV *
ZeroD64 (sign)
int sign
CODE:
RETVAL = ZeroD64 (aTHX_ sign);
OUTPUT: RETVAL
SV *
UnityD64 (sign)
int sign
CODE:
RETVAL = UnityD64 (aTHX_ sign);
OUTPUT: RETVAL
SV *
Exp10 (power)
int power
CODE:
RETVAL = Exp10 (aTHX_ power);
OUTPUT: RETVAL
SV *
_testvalD64 (sign)
int sign
CODE:
RETVAL = _testvalD64 (aTHX_ sign);
OUTPUT: RETVAL
SV *
_MEtoD64 (mantissa, exponent)
char * mantissa
SV * exponent
CODE:
RETVAL = _MEtoD64 (aTHX_ mantissa, exponent);
OUTPUT: RETVAL
SV *
NVtoD64 (x)
SV * x
CODE:
RETVAL = NVtoD64 (aTHX_ x);
OUTPUT: RETVAL
SV *
UVtoD64 (x)
SV * x
CODE:
RETVAL = UVtoD64 (aTHX_ x);
OUTPUT: RETVAL
SV *
IVtoD64 (x)
SV * x
CODE:
RETVAL = IVtoD64 (aTHX_ x);
OUTPUT: RETVAL
SV *
PVtoD64 (x)
char * x
CODE:
RETVAL = PVtoD64 (aTHX_ x);
OUTPUT: RETVAL
SV *
STRtoD64 (x)
char * x
CODE:
RETVAL = STRtoD64 (aTHX_ x);
OUTPUT: RETVAL
int
have_strtod64 ()
SV *
D64toNV (d64)
SV * d64
CODE:
RETVAL = D64toNV (aTHX_ d64);
OUTPUT: RETVAL
void
LDtoD64 (d64, ld)
SV * d64
SV * ld
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
LDtoD64(aTHX_ d64, ld);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
D64toLD (ld, d64)
SV * ld
SV * d64
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
D64toLD(aTHX_ ld, d64);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
DESTROY (rop)
SV * rop
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
DESTROY(aTHX_ rop);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
_assignME (a, mantissa, c)
SV * a
char * mantissa
SV * c
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
_assignME(aTHX_ a, mantissa, c);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
assignPV (a, s)
SV * a
char * s
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
assignPV(aTHX_ a, s);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
assignIV (a, val)
SV * a
SV * val
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
assignIV(aTHX_ a, val);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
assignUV (a, val)
SV * a
SV * val
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
assignUV(aTHX_ a, val);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
assignNV (a, val)
SV * a
SV * val
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
assignNV(aTHX_ a, val);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
assignD64 (a, val)
SV * a
SV * val
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
assignD64(aTHX_ a, val);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
assignNaN (a)
SV * a
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
assignNaN(aTHX_ a);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
assignInf (a, sign)
SV * a
int sign
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
assignInf(aTHX_ a, sign);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
SV *
_overload_add (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_add (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_mul (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_mul (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_sub (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_sub (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_neg (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_neg (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_div (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_div (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_add_eq (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_add_eq (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_mul_eq (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_mul_eq (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_sub_eq (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_sub_eq (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_div_eq (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_div_eq (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_equiv (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_equiv (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_not_equiv (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_not_equiv (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_lt (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_lt (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_gt (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_gt (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_lte (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_lte (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_gte (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_gte (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_spaceship (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_spaceship (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_copy (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_copy (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
D64toD64 (a)
SV * a
CODE:
RETVAL = D64toD64 (aTHX_ a);
OUTPUT: RETVAL
SV *
_overload_true (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_true (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_not (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_not (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_abs (a, b, third)
SV * a
SV * b
SV * third
CODE:
RETVAL = _overload_abs (aTHX_ a, b, third);
OUTPUT: RETVAL
SV *
_overload_inc (p, second, third)
SV * p
SV * second
SV * third
CODE:
RETVAL = _overload_inc (aTHX_ p, second, third);
OUTPUT: RETVAL
SV *
_overload_dec (p, second, third)
SV * p
SV * second
SV * third
CODE:
RETVAL = _overload_dec (aTHX_ p, second, third);
OUTPUT: RETVAL
SV *
_itsa (a)
SV * a
CODE:
RETVAL = _itsa (aTHX_ a);
OUTPUT: RETVAL
SV *
is_NaND64 (b)
SV * b
CODE:
RETVAL = is_NaND64 (aTHX_ b);
OUTPUT: RETVAL
SV *
is_InfD64 (b)
SV * b
CODE:
RETVAL = is_InfD64 (aTHX_ b);
OUTPUT: RETVAL
SV *
is_ZeroD64 (b)
SV * b
CODE:
RETVAL = is_ZeroD64 (aTHX_ b);
OUTPUT: RETVAL
SV *
_wrap_count ()
CODE:
RETVAL = _wrap_count (aTHX);
OUTPUT: RETVAL
SV *
_get_xs_version ()
CODE:
RETVAL = _get_xs_version (aTHX);
OUTPUT: RETVAL
void
_d64_bytes (sv)
SV * sv
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
_d64_bytes(aTHX_ sv);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
_bid_mant (bin)
SV * bin
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
_bid_mant(aTHX_ bin);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
SV *
_endianness ()
CODE:
RETVAL = _endianness (aTHX);
OUTPUT: RETVAL
SV *
_DPDtoD64 (in)
char * in
CODE:
RETVAL = _DPDtoD64 (aTHX_ in);
OUTPUT: RETVAL
void
_assignDPD (a, in)
SV * a
char * in
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
_assignDPD(aTHX_ a, in);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
int
nnumflag ()
void
clear_nnum ()
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
clear_nnum();
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
set_nnum (x)
int x
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
set_nnum(x);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
int
_lln (x)
SV * x
CODE:
RETVAL = _lln (aTHX_ x);
OUTPUT: RETVAL