How to safely use int64 type

As part of a hdf5 related project, I have tried to initialize some int64 variables (hdf5’s hid_t), in C++ or in m-code, and pass them back en forth between C++ functions and the m_code interpreter. The issue is that when numbers are larger than what double can reliably store, the variables get messed up.

I don’t know if I am doing something wrong, if there is an intrinsic limitation to this approach, or if there is a bug.

I defined a ping_int64 function, that just tries to return the original int64 variable. Here is the definition:

#include <octave/oct.h>

DEFUN_DLD(ping_int64, args, nargout,
          "-*- texinfo -*-\n\
@deftypefn {} {@var{out} =} ping_int64 (@var{in})\n\
@seealso{}\n\
@end deftypefn")
{
  octave_value_list retval;
  int nargin = args.length ();

  if (nargin != 1)
    print_usage ();

  int64_t out = args(0).xint64_value ("IN should be a scalar int64 val");
  
  return retval.append (octave_int64 (out));
}

Here is what I observe:

octave:2> a = intmax ("int64")
a = 9223372036854775807
octave:3> b = ping_int64 (a)
b = -9223372036854775808

Any hint would be appreciated.

This is actually a clang warning (e.g.:
http://buildbot.octave.org:8010/#/builders/9/builds/2258/steps/6/logs/stdio
)

../src/liboctave/numeric/lo-mappers.cc:186:15: warning: implicit conversion from 'long' to 'double' changes value from 9223372036854775807 to 9223372036854775808 [-Wimplicit-const-int-float-conversion]
      if (x > std::numeric_limits<octave_idx_type>::max ())
            ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/liboctave/numeric/lo-mappers.cc:198:15: warning: implicit conversion from 'long' to 'float' changes value from 9223372036854775807 to 9223372036854775808 [-Wimplicit-const-int-float-conversion]
      if (x > std::numeric_limits<octave_idx_type>::max ())
            ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/liboctave/numeric/lo-mappers.cc:221:15: warning: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Wimplicit-const-int-float-conversion]
      if (x > std::numeric_limits<int>::max ())
            ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 warnings generated.

The code looks like it should work to me. But I compiled it and had the same issue. Might need to run in the debugger and see where the problem is occurring. Is it with the call to xint64_value() or later with the octave_int64() call?


Okay, I did a quick debugging run and the number is wrong coming out of xint64_value(). Stepping through the code, it is already incorrect when the constructor for octave_int64 is called.

#0  octave_int<long>::octave_int (this=0x7f6b8e109c10, i=-9223372036854775808)
    at /home/rik/local/include/octave-7.0.0/octave/../octave/oct-inttypes.h:803

The code is

  octave_int (T i) : m_ival (i) { }

and i is already wrong

Thanks. I filed a bug report here:

https://savannah.gnu.org/bugs/index.php?60497