Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine integer types that are twice the width as `int` and `unsigned`?

Tags:

c

int

portability

Values of intermediate multiplication typically need twice the number of bits as inputs.

 // Example
int foo(int a, int b, int carry, int rem) {
  int2x c;  // Some type that is twice as wide at `int`
  c = (int2x)a * b + carry;
  return (int) (c % rem);
}

Considering the potential for padding, (which appears to limit sizeof() usefulness) and non-2`s complement integers (which limits bit dibbling), ...

Does the following always create the needed type?
If not, how to code at least a reasonable solution, even if not entirely portable?


#include <limits.h>
#include <stdint.h>

#if LONG_MAX/2/INT_MAX - 2 == INT_MAX
  typedef long int2x;
  typedef unsigned long unsigned2x;
#elif LLONG_MAX/2/INT_MAX - 2 == INT_MAX
  typedef long long int2x;
  typedef unsigned long long unsigned2x;
#elif INTMAX_MAX/2/INT_MAX - 2 == INT_MAX
  typedef intmax_t int2x;
  typedef uintmax_t unsigned2x;
#else
  #error int2x/unsigned2x not available
#endif

[Edit]
Qualify:"always", if long, long long and intmax_t, do not work it is OK to #error.
What I want to know is if at least 1 of long, long long, or intmax_t will work, will int2x be correctly typed?

Notes: The above assumes xxx_MAX are some odd power-of-2 minus 1. Maybe a good assumption? The above works on at least 2 platforms, but that is hardly a great portability test.

like image 929
chux - Reinstate Monica Avatar asked Sep 22 '14 20:09

chux - Reinstate Monica


1 Answers

The assumption that all *_MAX constants are of the form (2^n)-1 is valid. See 6.2.6 Representations of Types, and particularly 6.2.6.2 Integer types, where the representations of unsigned integer types and the positive values of signed integer types are fully defined as pure binary, thus yielding a maximum which is one less than a power of two.

like image 133
R.. GitHub STOP HELPING ICE Avatar answered Sep 20 '22 13:09

R.. GitHub STOP HELPING ICE