Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping signed integer ranges to unsigned

I'm facing a problem where signed integers should be converted to unsigneds, preserving their range and order.

Given the following definition:

#include <limits>

#define MIN(X) std::numeric_limits<X>::min();
#define MAX(X) std::numeric_limits<X>::max();

What is the fastest and correct way to map the signed range [MIN(T), MAX(T)] to the unsigned range [0, MAX(U)]?

where:

T is a signed integer type

U is an unsigned integer type

sizeof(T) == sizeof(U)

I tried various bit twiddling and numeric methods to come up with a solution, without success.

like image 988
plasmacel Avatar asked Jul 03 '15 09:07

plasmacel


1 Answers

unsigned int signedToUnsigned(signed int s) {
  unsigned int u =  1U + std::numeric_limits<int>::max();
  u += s;
  return u;
}

Live example here

This will add signed_max + 1 to signed int to ensure [MIN(int), MAX(int)] is mapped to [0, MAX(unsigned int)]


Why would this answer work and map correctly:

When you add a signed integral number to an unsigned, the signed number is promoted to unsigned type. From Section 4.7 [conv.integral]

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

like image 193
Mohit Jain Avatar answered Sep 24 '22 01:09

Mohit Jain