GMS 2.3+ How do I check for overflow, to avoid assigning a value that is too large for a int64?

I wanted to know if GMS has simple way of detecting values that are too large for converting a double , that is floored, into a int64 type?

I looked at the wiki of IEEE 754 : 2008 and it mentions that if you have in the exponent binaray section of the double, a value of
7ff with a fractional value of 0, it is interpreted as infinity, which I would assume represents overflow to a programming language.
I honestly do not know. So I tried searching in the GMS online manual ," checking for overflow ", or "integer overflow " and the online manual
failed me due to its design faults ( as in it wont let me see the remaining search results past the ones it is showing ).

So I was looking for a better way of checking for overflow, like a GML built-in function.

Does anyone know?
 

kburkhart84

Firehammer Games
I don't think there is an actual function...you would just have to directly check if the value is greater than some reasonable max....but then you have to allow a buffer of values for it to be beyond that but not technically overflowed.

What are you doing that you even need numbers so high that you worry about this though?
 

GMWolf

aka fel666
From a float, to an int64?
Just check if the float is greater than 9223372036854775807.

Caveat: you can't represent the above number as a float. But it should work fine as the float you are comparing can't either. As long as the comparison is float against float (you don't convert to int first) it should be fine.
 
I don't think there is an actual function...you would just have to directly check if the value is greater than some reasonable max....but then you have to allow a buffer of values for it to be beyond that but not technically overflowed.

What are you doing that you even need numbers so high that you worry about this though?
I am building some tools to help me understand how the binary system works in GMS, because its different than programming in C using djgpp. The 1st tool, represents a 8 byte value in the form of binary lights that are on or off, the byte value of each of the 8 bytes, the hexadecimal representation of each of the 8 bytes, and a text box that allows me to enter a number that gets interpreted into what it looks like in those previous formats. This also includes smaller integer sizes than 64-bit ints, with the a feature for showing the sign bit and the interpretation in binary and hexadecimal.

2nd tool deals with double values and the epsilon values. Specifically I want to know how a epsilon value works, when I compare two different doubles, how does the epsilon value change how a if statement evaluates if their equal or not. This is all displayed in the same way my int64 tool works.

3rd tool shows what a text string looks like when each of its letters ( only 8 letters ) are broken down into individual CHR$ values, their binary representation as a single bytes, and their hexadecimal represention.

Also, there is a binary mask that is used in int64 tool

Obviously I do not need to check for values when I am using the 3rd tool that I am inventing , but I do need it
for user inputs for the 1st and 2nd tool that I am building.

Right now I am working on the 1st tool - the int64 display. That would be my best explanation.

This is what it looks like, so far - Im not done yet :
toolscreen_shot1.png
 
Last edited:
From a float, to an int64?
Just check if the float is greater than 9223372036854775807.

Caveat: you can't represent the above number as a float. But it should work fine as the float you are comparing can't either. As long as the comparison is float against float (you don't convert to int first) it should be fine.
Im converting a double to an int64 to use the binary representation of a int64.
 

chamaeleon

Member
GML:
var n = -2732745.23767;

var s = fp_sign(n);            // Get sign bit value
var e = fp_exponent(n);        // Get exponent value
var m = fp_mantissa(n);        // Get mantissa bit value
var mv = fp_mantissa_value(m); // Get mantissa floating point value
var r = fp_bits(n);            // Convert a real number to int64 bits

show_debug_message("raw bits            = " + bitstring(r, 63));
show_debug_message("sign                = " + string(s));
show_debug_message("exponent            = " + string(e));
show_debug_message("exponent bits       = " + bitstring(e, 10));
show_debug_message("mantissa bit value  = " + string(m));
show_debug_message("mantissa bits       = " + bitstring(m, 51));
show_debug_message("mantissa real value = " + string_format(mv, 0, 16));
show_debug_message("Original double     = " + string_format(n, 0, 16));
show_debug_message("Recomputed double   = " + string_format(power(-1, s) * power(2, (e-1023)) * (1+mv), 0, 16));
GML:
conversion_buffer = buffer_create(8, buffer_u8, 1);

function bitstring(n, bitwidth) {
    var bits = "";
    for (var bit = bitwidth; bit >= 0; bit--) {
        bits += ((n & (1 << bit)) != 0) ? "1" : "0";
    }
    return bits;
}

function real2int(n) {
    buffer_seek(global.conversion_buffer, buffer_seek_start, 0);
    buffer_write(global.conversion_buffer, buffer_f64, real(n));
    buffer_seek(global.conversion_buffer, buffer_seek_start, 0);
    var val = buffer_read(global.conversion_buffer, buffer_u64);
    return val;
}

function fp_bits(n) {
    var val = real2int(n);
    return val;
}

function fp_sign(n) {
    var val = real2int(n);
    return ((val >> 63) & 1) != 0;
}

function fp_exponent(n) {
    var val = real2int(n);
    val = ((val & $7fffffffffffffff) >> 52);
    return val;
}

function fp_mantissa(n) {    
    var val = real2int(n);
    val = (val & ((1<<53)-1));
    return val;
}

function fp_mantissa_value(m) {
    var val = 0;
    for (var i = 0; i < 52; i++) {
        if (m & (1 << (51-i))) val += power(2, -(i+1));
    }
    return val;
}
Code:
raw bits            = 1100000101000100110110010110010010011110011010111111100001110111
sign                = 1
exponent            = 1044
exponent bits       = 10000010100
mantissa bit value  = 1364926084675703
mantissa bits       = 0100110110010110010010011110011010111111100001110111
mantissa real value = 0.3030744732236863
Original double     = -2732745.2376700001768768
Recomputed double   = -2732745.2376700001768768
 
Last edited:

chamaeleon

Member
@chamaeleon - Thanks for the help. Would you happen to know if an int64 has a signed bit that is used, or do all int64 types can only be positive in GML?
GMS only has a concept of signed integers, there is no unsigned integer type exposed to manipulate. The highest bit in an int64 is the sign bit, the remaining 63 bits are for the value (together the sign bit and the 63 bits representing values between (-2^63) to (2^63-1) using 2-complement).

Edit: I know buffer read/write includes specifying signed/unsigned integer types, but as far as I know, once you have a value in a GMS variable from buffer operations that specify an unsigned type, it is treated as a signed integer.
 
Last edited:
GMS only has a concept of signed integers, there is no unsigned integer type exposed to manipulate. The highest bit in an int64 is the sign bit, the remaining 63 bits are for the value (together the sign bit and the 63 bits representing values between (-2^63) to (2^63-1) using 2-complement).

Edit: I know buffer read/write includes specifying signed/unsigned integer types, but as far as I know, once you have a value in a GMS variable from buffer operations that specify an unsigned type, it is treated as a signed integer.
So if enter in the value 0x80ffffffffffffff ( in base 10 - and I am not going to write all those numbers ) which is greater than 0x7fffffffffffffff how does it get rejected so the double is not converted into an int64? I thought I would have to test for the values that are mentioned in IEEE standard to see if infinity is true, for overflow. I dont see anything about underflow.... other than some variations of NaN.
 

chamaeleon

Member
So if enter in the value 0x80ffffffffffffff ( in base 10 - and I am not going to write all those numbers ) which is greater than 0x7fffffffffffffff how does it get rejected so the double is not converted into an int64? I thought I would have to test for the values that are mentioned in IEEE standard to see if infinity is true, for overflow. I dont see anything about underflow.... other than some variations of NaN.
GML:
var n = 0x80ffffffffffffff;
show_debug_message(n);
show_debug_message(typeof(n));

var buf = buffer_create(8, buffer_u8, 1);
buffer_write(buf, buffer_u64, n);
buffer_seek(buf, buffer_seek_start, 0);
var m = buffer_read(buf, buffer_f64);
show_debug_message(string_format(m, 0, 16));
buffer_delete(buf);
Code:
-9151314442816847873
int64
-0.0000000000000000
Other bit patterns for n should yield nan, inf, -inf, and whatever else there might be. I'm not sure if underflow is one of them. I have not looked at the spec in decades.
 
Last edited:

Juju

Member
Yo, thanks for the shout-out @EvanSki. BIG's an implementation of bits of a couple big integer libraries. It separates out integers into 32-bit segments stored in an array of 64-bit integers. Nowadays I'd be tempted to build this as a proper struct constructor class doodangle, but big integers are arrays for the time being until I can find time to modernise the library.
 
Top