0

I would like to convert unsigned int to uint64 inside C function. uint64 is defined in R package int64.

EDIT

This question is about conversion from C unsigned int data type to uint64 R language data type.

"int64 package has been developped so that 64 bit integer vectors are represented using only R data structures, i.e data is not represented as external pointers to some C++ object. Instead, each 64 bit integer is represented as a couple of regular 32 bit integers, each of them carrying half the bits of the underlying 64 bit integer. This was a choice by design so that 64 bit integer vectors can be serialized and used as data frame columns."

Wojciech Sobala
  • 7,431
  • 2
  • 21
  • 27

1 Answers1

1

An unsigned int is required to be able to store values between at least the range 0-65536. An int64_t (that's the portable version, from <stdint.h>) will be able to store values between -(263-1) and 263. There's a problem here, which is that an unsigned int might be 64 bits in length and might represent values outside the range of an int64_t (see §5.2.4.2.1 p1 of the C standard, and the section below).

Here's what the standard says:

6.3.1.3 Signed and unsigned integers

  1. When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
  2. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.60)
  3. Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

60) The rules describe arithmetic on the mathematical value, not the value of a given type of expression.


Ignoring an implementation-defined signal corresponding to a computational exception is undefined behaviour.

In the case of unsigned-to-signed conversions, I suggest defining your behaviour explicitly. Saturation is the easiest: When your unsigned int value is greater than INT64_MAX, the conversion would result in INT64_MAX. This looks something like x > INT64_MAX : INT64_MAX ? x. Wrapping LIA style (eg. unsigned int x = UINT_MAX; ++x == 0) is possible for int64_t because of the guarantee that int64_t won't contain padding, but more work is necessary to make portability guarantees. I suggest something like (x & INT64_MIN) > INT64_MAX ? -(x & INT64_MAX) : x & INT64_MAX, if you can find some assertion that your int64 will have the same representation as the C standard int64_t.

autistic
  • 1
  • 3
  • 35
  • 80