Attached is a patch against Int128.xs from version Math-Int128-0.12 that allows the module to build and pass all tests on Windows with gcc-4.7.0.
For reasons that I don't understand, it's (apparently) ok to do 'SvI128(aTHX_ other)' and 'SvU128(aTHX_ other)' in both the CODE and PREINIT sections, and it's ok to do both 'SvI128x(self)' and 'SvU128x(self)' in the PREINIT section ... but, on Windows, you cannot do either 'SvI128x(self)' or 'SvU128x(self)' in the *CODE* section. (If you do that, you get a crash with no useful error messages.)
Now, you'll notice that there are still CODE sections in the patched Int128.xs that do both 'SvI128x(self)' and 'SvU128x(self)'. I expect that these are simply "crashes waiting to happen". I patched enough merely to allow all tests to pass.
Perhaps there's a better fix than that provided by my patch. For one thing, I've turned mu128_sub into an awful state that badly needs to be rewritten ... but it's getting late.
And I wouldn't like to guarantee that my patched versions always do the right thing, either ;-)
If you can see something in SvI128x() and SvU128x() that account for this behaviour (and can be fixed) then I would think that would be a better approach.
I notice that mu128_pow assigns SvU128() and SvU128x() to int128_t variables. I expect the assignment should be to uint128_t variables ? And is the third argument (rev) to mu128_pow invariably &PL_sv_no ? If so why do you SvTRUE(rev) ?
Hope there's something here that helps, at least ;-)
Cheers,
Rob
--- Int128.xs_orig 2013-07-25 12:14:18 +1000
+++ Int128.xs 2013-07-25 22:51:32 +1000
@@ -908,29 +908,27 @@
SV *other
SV *rev
PREINIT:
- int128_t up;
- int128_t down;
+ int128_t a = SvI128x(self);
+ int128_t b = SvI128(aTHX_ other);
CODE:
if (SvOK(rev)) {
if (SvTRUE(rev)) {
- up = SvI128(aTHX_ other);
- down = SvI128x(self);
+ if (!a)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVi128(aTHX_ b / a);
}
else {
- up = SvI128x(self);
- down = SvI128(aTHX_ other);
+ if (!b)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVi128(aTHX_ a / b);
}
- if (!down)
- croak_string(aTHX_ div_by_0_error);
- RETVAL = newSVi128(aTHX_ up/down);
}
else {
- down = SvI128(aTHX_ other);
- if (!down)
+ if (!b)
croak_string(aTHX_ div_by_0_error);
- RETVAL = self;
+ a /= b;
+ RETVAL = newSVi128(aTHX_ a);
SvREFCNT_inc(RETVAL);
- SvI128x(self) /= down;
}
OUTPUT:
RETVAL
@@ -941,29 +939,25 @@
SV *other
SV *rev
PREINIT:
- int128_t up;
- int128_t down;
+ int128_t a = SvI128x(self);
+ int128_t b = SvI128(aTHX_ other);
CODE:
if (SvOK(rev)) {
if (SvTRUE(rev)) {
- up = SvI128(aTHX_ other);
- down = SvI128x(self);
+ if (!a)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVi128(aTHX_ b % a);
}
else {
- up = SvI128x(self);
- down = SvI128(aTHX_ other);
+ if (!b)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVi128(aTHX_ a % b);
}
- if (!down)
- croak_string(aTHX_ div_by_0_error);
- RETVAL = newSVi128(aTHX_ up % down);
}
else {
- down = SvI128(aTHX_ other);
- if (!down)
+ if (!b)
croak_string(aTHX_ div_by_0_error);
- RETVAL = self;
- SvREFCNT_inc(RETVAL);
- SvI128x(self) %= down;
+
}
OUTPUT:
RETVAL
@@ -1087,8 +1081,12 @@
mi128_eqn(self, other, ...)
SV *self
SV *other
+PREINIT:
+ int128_t a = SvI128x(self);
+ int128_t b = SvI128(aTHX_ other);
CODE:
- RETVAL = ( SvI128x(self) == SvI128(aTHX_ other)
+ printf("starting _eqn\n");
+ RETVAL = ( a == b
? &PL_sv_yes
: &PL_sv_no );
OUTPUT:
@@ -1315,22 +1313,29 @@
SV *other
SV *rev
PREINIT:
- uint128_t a, b;
+ uint128_t a = SvU128x(self);
+ uint128_t b = SvU128(aTHX_ other);
CODE:
- if (SvTRUE(rev)) {
- a = SvU128(aTHX_ other);
- b = SvU128x(self);
- }
- else {
- a = SvU128x(self);
- b = SvU128(aTHX_ other);
- }
- if (may_die_on_overflow && (b > a)) overflow(aTHX_ sub_error);
- if (SvOK(rev))
+ if(SvOK(rev)) {
+ if(SvTRUE(rev)) {
+ if (may_die_on_overflow && (a > b)) overflow(aTHX_ sub_error);
+ RETVAL = newSVu128(aTHX_ b - a);
+ }
+ else {
+ if (may_die_on_overflow && (b > a)) overflow(aTHX_ sub_error);
RETVAL = newSVu128(aTHX_ a - b);
+ }
+ }
else {
RETVAL = SvREFCNT_inc(self);
- SvU128x(self) = a - b;
+ if(SvTRUE(rev)) {
+ if (may_die_on_overflow && (a > b)) overflow(aTHX_ sub_error);
+ SvU128x(self) = b - a;
+ }
+ else {
+ if (may_die_on_overflow && (b > a)) overflow(aTHX_ sub_error);
+ SvU128x(self) = a - b;
+ }
}
OUTPUT:
RETVAL
@@ -1355,35 +1360,34 @@
OUTPUT:
RETVAL
+
SV *
mu128_div(self, other, rev)
SV *self
SV *other
SV *rev
PREINIT:
- uint128_t up;
- uint128_t down;
+ uint128_t a = SvU128x(self);
+ uint128_t b = SvU128(aTHX_ other);
CODE:
if (SvOK(rev)) {
if (SvTRUE(rev)) {
- up = SvU128(aTHX_ other);
- down = SvU128x(self);
+ if (!a)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVu128(aTHX_ b / a);
}
else {
- up = SvU128x(self);
- down = SvU128(aTHX_ other);
+ if (!b)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVu128(aTHX_ a / b);
}
- if (!down)
- croak_string(aTHX_ div_by_0_error);
- RETVAL = newSVu128(aTHX_ up/down);
}
else {
- down = SvU128(aTHX_ other);
- if (!down)
+ if (!b)
croak_string(aTHX_ div_by_0_error);
- RETVAL = self;
+ a /= b;
+ RETVAL = newSVi128(aTHX_ a);
SvREFCNT_inc(RETVAL);
- SvU128x(self) /= down;
}
OUTPUT:
RETVAL
@@ -1394,29 +1398,27 @@
SV *other
SV *rev
PREINIT:
- uint128_t up;
- uint128_t down;
+ uint128_t a = SvU128x(self);
+ uint128_t b = SvU128(aTHX_ other);
CODE:
if (SvOK(rev)) {
if (SvTRUE(rev)) {
- up = SvU128(aTHX_ other);
- down = SvU128x(self);
+ if (!a)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVu128(aTHX_ b % a);
}
else {
- up = SvU128x(self);
- down = SvU128(aTHX_ other);
+ if (!b)
+ croak_string(aTHX_ div_by_0_error);
+ RETVAL = newSVu128(aTHX_ a % b);
}
- if (!down)
- croak_string(aTHX_ div_by_0_error);
- RETVAL = newSVu128(aTHX_ up % down);
}
else {
- down = SvU128(aTHX_ other);
- if (!down)
+ if (!b)
croak_string(aTHX_ div_by_0_error);
- RETVAL = self;
+ a %= b;
+ RETVAL = newSVu128(aTHX_ a);
SvREFCNT_inc(RETVAL);
- SvU128x(self) %= down;
}
OUTPUT:
RETVAL
@@ -1478,16 +1480,9 @@
PREINIT:
int sign;
uint128_t r;
- int128_t a, b;
+ int128_t a = SvU128x(self);
+ int128_t b = SvU128(aTHX_ other);
CODE:
- if (SvTRUE(rev)) {
- a = SvU128(aTHX_ other);
- b = SvU128x(self);
- }
- else {
- a = SvU128x(self);
- b = SvU128(aTHX_ other);
- }
r = powU128(aTHX_ a, b);
if (SvOK(rev))
RETVAL = newSVu128(aTHX_ r);
@@ -1524,8 +1519,11 @@
mu128_eqn(self, other, ...)
SV *self
SV *other
+PREINIT:
+ uint128_t a = SvU128x(self);
+ uint128_t b = SvU128(aTHX_ other);
CODE:
- RETVAL = ( SvU128x(self) == SvU128(aTHX_ other)
+ RETVAL = ( a == b
? &PL_sv_yes
: &PL_sv_no );
OUTPUT: