21

Is it possible to create a templated function that checks if a primitive data type can fit a value of potentially different primitive data type? Let's limit the scope to integer types for the moment.

More precisely: Is it possible to create a "one fit all" templated functions yet without getting compiler warnings (boolean expression always true/false, signed/unsigned comparison, unused variable) and without disabling compiler warning checks? The functions should also limit as much as possible checks at runtime (all trivial cases should be excluded at compile time). If possible, I would prefer avoiding using extensions from C++11 and the like (unless a "quick" replacement for "old" C++ exists).

Note: "value" is not known at compile time, only its type.

Example of expected behaviour:

int main(int argc, char** argv) {
    for (int i = 1; i < argc; i++) {
        const int value = atoi(argv[i]);
        std::cout << value << ": ";
        std::cout << CanTypeFitValue<int8_t>(value) << " ";
        std::cout << CanTypeFitValue<uint8_t>(value) << " ";
        std::cout << CanTypeFitValue<int16_t>(value) << " ";
        std::cout << CanTypeFitValue<uint16_t>(value) << " ";
        std::cout << CanTypeFitValue<int32_t>(value) << " ";
        std::cout << CanTypeFitValue<uint32_t>(value) << " ";
        std::cout << CanTypeFitValue<int64_t>(value) << " ";
        std::cout << CanTypeFitValue<uint64_t>(value) << std::endl;
        }
    
}

Output:

./a.out 6 1203032847 2394857 -13423 9324 -192992929

6: 1 1 1 1 1 1 1 1

1203032847: 0 0 0 0 1 1 1 1

2394857: 0 0 0 0 1 1 1 1

-13423: 0 0 1 0 1 0 1 0

9324: 0 0 1 1 1 1 1 1

-192992929: 0 0 0 0 1 0 1 0

Test your code here or here.

Check the assembly generated here.

This question was inspired by this post

phuclv
  • 37,963
  • 15
  • 156
  • 475
Antonio
  • 19,451
  • 13
  • 99
  • 197

7 Answers7

13

Using numeric_limits and types defined in stdint.h

More compact that my first solution, same efficiency.

Drawback: one additional header to be included.

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

using std::numeric_limits;

template <typename T, typename U>
    bool CanTypeFitValue(const U value) {
        const intmax_t botT = intmax_t(numeric_limits<T>::min() );
        const intmax_t botU = intmax_t(numeric_limits<U>::min() );
        const uintmax_t topT = uintmax_t(numeric_limits<T>::max() );
        const uintmax_t topU = uintmax_t(numeric_limits<U>::max() );
        return !( (botT > botU && value < static_cast<U> (botT)) || (topT < topU && value > static_cast<U> (topT)) );        
    }

Assembly code generated (you can change T and U types)

Correctness test


Note: a constexpr version was written, but apparently it has some problems. See here and here.
Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • The assembly is _slightly_ longer if you go from `int` to `short`, but... wow. I'm impressed. You do lose `constexpr` unfortunately, but if it's important, it's easy to add that back. – Mooing Duck Jun 22 '13 at 19:11
  • @MooingDuck Thanks! :) I cannot see though in which way for the case int->short assembly generated is longer. And, sorry for asking so openly, do you think also the question could get a thump up? – Antonio Jun 22 '13 at 19:24
  • already gave you +1. [Here, I got it constexpr](http://coliru.stacked-crooked.com/view?id=4174e9e1a48a87b35434a325cb10207c-803889f054654ad4b92ce24ea171578e). (By longer I meant that `CanTypeFitValue(int);` is 3 ops instead of just two) – Mooing Duck Jun 22 '13 at 19:34
  • @MooingDuck I meant +1 to the question, not the answer. Anyway thanks. How could it be only 2 ops? Thanks for constexpr version! I will edit the answer to include it! – Antonio Jun 22 '13 at 19:50
  • If its converting to the same type or a bigger type, the value always fits, so that's zero ops. For the other cases, it checks if `(ull)(value-min)<(ull)(max-min)`, and precalculates `(ull)(max-min)`. If the value is -10, and converting to a `signed char`, then `value-min = (-10)-(-128) = 118`, and `max-min = (127)-(-128) = 255`, and since `118<255`, it's valid. If value was -200, then `value-min = (-200)-(-128) = -72`. When cast to an `unsigned long long` (zero ops), that becomes ~1.84e+19, which is well over 255, and thus out of range. Obviously when `min==0` then it can skip the first op. – Mooing Duck Jun 22 '13 at 20:24
  • @MooingDuck I still do not understand: if I convert from int to unsigned char, it does only one op, if I convert from int to signed char it does just one op more, and I cannot see how it could be less than that... – Antonio Jun 22 '13 at 21:16
  • it's pretty tricky, I suggest making that a separate question. "Can someone explain how this assembly works and why it's generated from this C++?" – Mooing Duck Jun 22 '13 at 22:25
  • @MooingDuck But to me the assembly code generated is clear! I don't understand how you could reduce the ops. You speak about a cast of a negative number to `unsigned long long` that does not happen... – Antonio Jun 22 '13 at 22:33
  • 1
    we must have had a communication error, I believe your code has the minimm number of ops. Casting from `int` to `unsigned` and similar merely changes which instructions are generated by the compiler, casts does not take an op. – Mooing Duck Jun 22 '13 at 22:44
  • Note that for casting to `long long` and `unsigned long long` the compiler generates more instructions, because the two instructions do not cover the case when it cannot be upcast. I coded a C++ version of what the compiler is generating for the general case [here](http://coliru.stacked-crooked.com/view?id=353ca277f2c7729fba4b8f07d4bee4e7-4f34a5fd633ef9f45cb08f8e23efae0a), and it incorrectly says that `unsigned long long` and `signed long long` both hold all values. Your code does not have this error. – Mooing Duck Jun 22 '13 at 22:58
  • I threw in a cast to intmax_t on the numeric_limits::min( ) and a cast to uintmax_t on numeric_limits::max( ) to get rid of the warnings. We know the intmax_t can hold the smallest integeral and uintmax_t can hold the largest and there should be no risk – Beached Jun 06 '16 at 01:50
  • @Beached Which kind of warning were you getting? With which compiler? – Antonio Jun 08 '16 at 07:15
  • @Antonio when T is unsigned I got a signed/unsigned comparison warning. So std::numeric_limits::min() <= (intmax_t)std::numeric_limits::min() became (intmax_t)std::numeric_limits::min( ) <= (intmax_t)std::numeric_limits::min() And the same but uintmax_t for the max's. The max min is 0 which is in the range of all integrals so casting to a signed will provable not change the value and with max the min max is >0 so a cast to uintmax_t is provably not going to change the value. – Beached Jun 09 '16 at 00:01
  • @Beached I have removed the constexpr version, it has some problems. Which compiler are you using by the way? – Antonio Jun 09 '16 at 13:51
  • 1
    @Antonio the big three, msvc 2015.2, clang 3.8, and gcc 5.2 – Beached Jun 09 '16 at 22:49
  • 1
    Even though I have been using this version here for a couple of years (thanks, by the way), I can confirm it does generate warnings when building on MSVC 2015. I just tested a x64 build and it will warn if the source value is uint64_t and dest is int. Also, I'd suggest you to edit your answer and put a link to stefan's. His awesome answer handles non integral types correctly. And, much like yours, can easily be transformed into constexpr – user1593842 Aug 16 '17 at 17:55
9

Using the features of C++14 (leave out constexpr for C++11 compatibility) and use of templates, this is what I came up with:

https://ideone.com/OSc9CI (updated version: now also accepts unsigned to signed, short and beautiful)

This basically uses std::enable_if extensively with type_traits std::is_unsigned and std::is_integral. Best to read from bottom up (as the decision tree builds up from there).

Obviously this is nearly all done compile time, so assembly should be fairly small.

This solution can handle integral and floating point target types as well as integral and floating point original types.

If the check isn't trivial (i.e. bounds of data type have to be checked), the actual_type value n is casted to typename std::common_type<target, actual_type>::type statically.

Every decision is_integral and is_unsigned and is_same is done at compile time, so no overhead from this at runtime. The check boils down to some lower_bound(target) <= value and / or value <= upper_bound(target) after the types are casted to a common type (to avoid warnings and prevent overflows).

#include <cmath> // necessary to check for floats too
#include <cstdint> // for testing only
#include <iomanip> // for testing only
#include <iostream> // for testing only
#include <limits> // necessary to check ranges
#include <type_traits> // necessary to check type properties (very efficient, compile time!)

// the upper bound must always be checked
template <typename target_type, typename actual_type>
constexpr bool test_upper_bound(const actual_type n)
{
   typedef typename std::common_type<target_type, actual_type>::type common_type;
   const auto c_n = static_cast<common_type>(n);
   const auto t_max = static_cast<common_type>(std::numeric_limits<target_type>::max());
   return ( c_n <= t_max );
}

// the lower bound is only needed to be checked explicitely in non-trivial cases, see the next three functions
template <typename target_type, typename actual_type>
constexpr typename std::enable_if<!(std::is_unsigned<target_type>::value) && !(std::is_unsigned<actual_type>::value), bool>::type
test_lower_bound(const actual_type n)
{
   typedef typename std::common_type<target_type, actual_type>::type common_type;
   const auto c_n = static_cast<common_type>(n);
   const auto t_min_as_t = std::numeric_limits<target_type>::lowest();
   const auto t_min = static_cast<common_type>(t_min_as_t);
   return (c_n >= t_min);
}

// for signed target types where the actual type is unsigned, the lower bound is trivially satisfied.
template <typename target_type, typename actual_type>
constexpr typename std::enable_if<!(std::is_unsigned<target_type>::value) &&(std::is_unsigned<actual_type>::value), bool>::type
test_lower_bound(const actual_type n)
{
    return true;
}
    
// for unsigned target types, the sign of n musn't be negative
// but that's not an issue with unsigned actual_type
template <typename target_type, typename actual_type>
constexpr typename std::enable_if<std::is_integral<target_type>::value &&
                        std::is_unsigned<target_type>::value &&
                        std::is_integral<actual_type>::value &&
                        std::is_unsigned<actual_type>::value, bool>::type
test_lower_bound(const actual_type)
{
   return true;
}

// for unsigned target types, the sign of n musn't be negative
template <typename target_type, typename actual_type>
constexpr typename std::enable_if<std::is_integral<target_type>::value &&
                        std::is_unsigned<target_type>::value &&
                        (!std::is_integral<actual_type>::value ||
                         !std::is_unsigned<actual_type>::value), bool>::type
test_lower_bound(const actual_type n)
{
   return ( n >= 0 );
}

// value may be integral if the target type is non-integral
template <typename target_type, typename actual_type>
constexpr typename std::enable_if<!std::is_integral<target_type>::value, bool>::type
test_integrality(const actual_type)
{
   return true;
}

// value must be integral if the target type is integral
template <typename target_type, typename actual_type>
constexpr typename std::enable_if<std::is_integral<target_type>::value, bool>::type
test_integrality(const actual_type n)
{
   return ( (std::abs(n - std::floor(n)) < 1e-8) || (std::abs(n - std::ceil(n)) < 1e-8) );
}

// perform check only if non-trivial
template <typename target_type, typename actual_type>
constexpr typename std::enable_if<!std::is_same<target_type, actual_type>::value, bool>::type
CanTypeFitValue(const actual_type n)
{
   return test_upper_bound<target_type>(n) &&
          test_lower_bound<target_type>(n) &&
          test_integrality<target_type>(n);
}


// trivial case: actual_type == target_type
template <typename actual_type>
constexpr bool CanTypeFitValue(const actual_type)
{
   return true;
}

int main()
{
   int ns[] = {6, 1203032847, 2394857, -13423, 9324, -192992929};
   for ( const auto n : ns )
   {
      std::cout << std::setw(10) << n << "\t";
      std::cout << " " << CanTypeFitValue<int8_t>(n);
      std::cout << " " << CanTypeFitValue<uint8_t>(n);
      std::cout << " " << CanTypeFitValue<int16_t>(n);
      std::cout << " " << CanTypeFitValue<uint16_t>(n);
      std::cout << " " << CanTypeFitValue<int32_t>(n);
      std::cout << " " << CanTypeFitValue<uint32_t>(n);
      std::cout << " " << CanTypeFitValue<int64_t>(n);
      std::cout << " " << CanTypeFitValue<uint64_t>(n);
      std::cout << " " << CanTypeFitValue<float>(n);
      std::cout << " " << CanTypeFitValue<double>(n);
      std::cout << "\n";
   }
   std::cout << "\n";
   unsigned long long uss[] = {6, 1201146189143ull, 2397, 23};
   for ( const auto n : uss )
   {
      std::cout << std::setw(10) << n << "\t";
      std::cout << " " << CanTypeFitValue<int8_t>(n);
      std::cout << " " << CanTypeFitValue<uint8_t>(n);
      std::cout << " " << CanTypeFitValue<int16_t>(n);
      std::cout << " " << CanTypeFitValue<uint16_t>(n);
      std::cout << " " << CanTypeFitValue<int32_t>(n);
      std::cout << " " << CanTypeFitValue<uint32_t>(n);
      std::cout << " " << CanTypeFitValue<int64_t>(n);
      std::cout << " " << CanTypeFitValue<uint64_t>(n);
      std::cout << " " << CanTypeFitValue<float>(n);
      std::cout << " " << CanTypeFitValue<double>(n);
      std::cout << "\n";
   }
   std::cout << "\n";
   float fs[] = {0.0, 0.5, -0.5, 1.0, -1.0, 1e10, -1e10};
   for ( const auto f : fs )
   {
      std::cout << std::setw(10) << f << "\t";
      std::cout << " " << CanTypeFitValue<int8_t>(f);
      std::cout << " " << CanTypeFitValue<uint8_t>(f);
      std::cout << " " << CanTypeFitValue<int16_t>(f);
      std::cout << " " << CanTypeFitValue<uint16_t>(f);
      std::cout << " " << CanTypeFitValue<int32_t>(f);
      std::cout << " " << CanTypeFitValue<uint32_t>(f);
      std::cout << " " << CanTypeFitValue<int64_t>(f);
      std::cout << " " << CanTypeFitValue<uint64_t>(f);
      std::cout << " " << CanTypeFitValue<float>(f);
      std::cout << " " << CanTypeFitValue<double>(f);
      std::cout << "\n";
   }
}

This (new) version quickly decides (at compile time!) if checks are needed (concerning upper bound, lower bound and integrality) and uses the correct version (to avoid warnings about stupid >= 0 comparisons with unsigned types) (also at compile time). E.g. the integrality does not need to be checked if the target is float, the lower bound does not need to be checked if both types are unsigned etc.

The most obvious optimization (having equal types), is done with std::is_same.

This approach can also be extended to used-defined types with specialized templates. Checks such as std::is_integral will be negative on those types.

You can check that the assembler output is fairly small (except for the obvious case of floats) here or by invoking g++ with -S.

stefan
  • 10,215
  • 4
  • 49
  • 90
  • Interesting! So can you tell something more about the scope of your function? I mean, it solves the problem for integers and on top of that... – Antonio Jun 27 '13 at 11:47
  • @Antonio can you please clarify your comment? Or was it about "this solves the problem for floats as well"? – stefan Jun 27 '13 at 12:07
  • Yeah, if it is just that, please put it in a short summary – Antonio Jun 27 '13 at 12:10
  • @Antonio I thought that's what I did. Did you check the updated answer yet? – stefan Jun 27 '13 at 12:11
  • No I hadn't :) Ok, thanks for the update!, will read thoroughly within the end of the week... – Antonio Jun 27 '13 at 12:16
  • @Antonio I added a pseudo code that hopefully visualizes the code. – stefan Jun 27 '13 at 12:50
  • @Antonio: I've rewritten my code (and the answer). It probably is much more intuitive now and does not use a massive decision tree. Please let me know if you like this or if you have question or remarks. – stefan Jun 28 '13 at 20:21
  • Hi Stefan, thanks for your efforts. I was thinking that many cases could be reduced to one if you used my answer to handle the case where both entries are integer, and where both entries are floating point with a very similar version (just in that case we do not need to check more than max value). I also suggest that you double check the assembly code generated using the link I provided (just put only one function instantiation in the main to see its code), just to guarantee it's always limited to 0-1-2 operations. – Antonio Jun 28 '13 at 21:02
  • @Antonio There you go, updated. I'd say that's pretty much optimal. Floats are evil. – stefan Jun 28 '13 at 22:11
  • @Antonio Thanks for awarding me with the bounty. It's great to get such appreciation for having fun ;-) – stefan Jul 01 '13 at 08:16
  • 1
    Awesome answer. Produces pretty much the same assembly code as the accepted answer but can also handle non integral types. And by simply moving the value you assign to `c_n` in `test_upper_bound` directly to the return statement, your version can become `constexpr` (at least in c++14). Awesome! – user1593842 Aug 16 '17 at 18:04
  • @stefan I tried the solution using the following input: CanTypeFitValue(uint32_t(120)), which returns 0 even though 120 fits into an `int8_t`. The assembler in this case is `xorl %eax, %eax`, so it will always return 0. – maxbachmann May 08 '21 at 09:38
  • @maxbachmann given that this answer is eight years old, I won't go into debugging now. If you are convinced it doesn't work, please try to find out why and propose a fix. – stefan May 08 '21 at 15:05
  • 1
    @maxbachmann This is indeed an issue. It happens because the common type of int8_t and uint32_t is uint32_t, which messes with the check for the lower bound. I've updated the answer. – stefan May 10 '21 at 07:31
5

Certainly

template <typename T, typename U>
constexpr bool CanTypeFitValue(const U value)
{return ((value>U(0))==(T(value)>T(0))) && U(T(value))==value;}

//      (         part1         ) && (      part2      )

Basically, this has two parts. The first part confirms that if a sign change happens (casting unsigned to signed or vice-versa, that the sign information isn't lost. The second part simply checks if value is cast to a T and back, that it retains it's value, and no bits have been lost.

FYI I'm not certain this is enough to tell if the value is maintained, but can't immediately think of a case with primitives that would fail. Both my answer and Casey's answer should work on user-defined numeric-like types so long as they provide conversion operators both ways between T and U.

Here's proof that it passes the tests you post in the question.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • 3
    Antonio, despite the word `constexpr`, all the solutions I see on this page work just fine with runtime variables too. You might mistunderstand what `constexpr` does. – Mooing Duck Jun 21 '13 at 16:54
4

I've used something similar in the past to determine if T can represent the value u of type U exactly (replace constexpr with inline make this C++03):

template <typename T, typename U>
constexpr bool CanTypeRepresentValue(const U value) {
    return ((value > U()) == (static_cast<T>(value) > T())) &&
           (value == static_cast<U>(static_cast<T>(value)));
}

This should work well for conversions between integer types, but conversions between integer and floating-point types - or conversions from a floating-point type to a narrow floating-point type - are rife with undefined behavior and need a lot of range checking.

Casey
  • 41,449
  • 7
  • 95
  • 125
  • 2
    `value` doesn't *need* to be known at compile time - use of `constexpr` here just makes it possible to compute the result at compile time if it is. – Casey Jun 21 '13 at 17:24
  • Edited your example into my [ideone code](http://ideone.com/C5iael), had to use `cin` instead of `argc`/`argv` (If you can pass command line arguments at ideone, I don't know how.) – Casey Jun 21 '13 at 17:31
  • Let's say both variables are `int`, the compiler will understand **at compile time** that the expression is binded to be true? – Antonio Jun 22 '13 at 08:29
  • 2
    @Antonio Sure. But don't take my word for it, [see for yourself at gcc.godbolt.org](http://goo.gl/4b8Qf). – Casey Jun 22 '13 at 12:24
  • Thanks for linking to this great website! Now hold on to your chair :) I have tried putting also my code with different data types (like `unsigned int` to `int`, `int` to `char`, and it produces **by far** smaller assembly code... I cannot get to paste it because the url get too long, even for google to create a short url... – Antonio Jun 22 '13 at 13:21
  • *"This should work at least for all arithmetic types..."* You probably meant the integral types. Conversions between different floating point types and floating point types to integral types are dangerous and can easily cause undefined behavior. – 303 Sep 16 '21 at 00:13
  • @303 Hard to tell if this was an innocent mistake, or just me being horribly wrong. (Correction: I looked at the old test code; this was me being horribly wrong.) – Casey Sep 17 '21 at 02:21
2

In C++20 just use std::in_range

std::cout << std::in_range<int8_t>(value)   << " "
          << std::in_range<uint8_t>(value)  << " "
          << std::in_range<int16_t>(value)  << " "
          << std::in_range<uint16_t>(value) << " "
          << std::in_range<int32_t>(value)  << " "
          << std::in_range<uint32_t>(value) << " "
          << std::in_range<int64_t>(value)  << " "
          << std::in_range<uint64_t>(value) << '\n';

Anything in the std namespace is standard and not some "extension"

phuclv
  • 37,963
  • 15
  • 156
  • 475
  • 1
    Very cool! Also the new comparison functions available are very nice, looking forward to their availability in the compilers! https://en.cppreference.com/w/cpp/utility/intcmp – Antonio Jul 19 '21 at 14:07
1

I propose a solution using numeric_limits

#include <limits>
using std::numeric_limits;

template <typename T, typename U>
    bool CanTypeFitValue(const U value) {
        if (numeric_limits<T>::is_signed == numeric_limits<U>::is_signed) {
            if (numeric_limits<T>::digits >= numeric_limits<U>::digits)
                return true;
            else
                return (static_cast<U>(numeric_limits<T>::min() ) <= value && static_cast<U>(numeric_limits<T>::max() ) >= value);
        }
        else {
            if (numeric_limits<T>::is_signed) {
                if (numeric_limits<T>::digits > numeric_limits<U>::digits) //Not >= in this case!
                    return true;
                else
                    return (static_cast<U>(numeric_limits<T>::max() ) >= value);
            }
            else ///U is signed, T is not
                if (value < static_cast<U> (0) )
                    return false;
                else
                    if (numeric_limits<T>::digits >= numeric_limits<U>::digits)
                        return true;
                    else
                        return (static_cast<U>(numeric_limits<T>::max() ) >= value);
        }
    }

Tested here (Sorry for using atoi :) ).

Antonio
  • 19,451
  • 13
  • 99
  • 197
  • That seems a wee bit over complicated – Mooing Duck Jun 21 '13 at 16:59
  • Your code [says I can cast `0.5` to an `int` safely](http://coliru.stacked-crooked.com/view?id=0733776dd63891e3ec5bdaf86ef7ae36-ad7854d9cfd7979d567ca413f0830b65) – Mooing Duck Jun 21 '13 at 17:06
  • 1
    @MooingDuck Antonio's did say "Let's limit the scope to integer types for the moment." in the OP. – Casey Jun 21 '13 at 17:34
  • oh, so it does. I misremembered that as limiting to primitives. – Mooing Duck Jun 21 '13 at 18:53
  • @MooingDuck Yeah, it's very complicated, but testing it [here](http://goo.gl/4b8Qf), it produces the smallest assembly code... I wonder if there is any way to obtain a methods that combines efficiency and conciseness... – Antonio Jun 22 '13 at 13:34
  • @MooingDuck Please check [new answer](http://stackoverflow.com/a/17251989/2436175) – Antonio Jun 22 '13 at 15:16
-1

The most explicit way is probably to use SFINAE and a function for each type. Something like this:

#include <limits>


template <typename T>
bool CanTypeFitValue(int) {
    return false;
}

template <typename T>
bool CanSignedNumericTypeFitValue(int value) {
    return (value >= std::numeric_limits<T>::min() && 
            value <= std::numeric_limits<T>::max());
}

template <typename T>
bool CanUnsignedNumericTypeFitValue(int value) {
    return (value >= 0 && 
            static_cast<unsigned>(value) <= std::numeric_limits<T>::max());
}

template <> bool CanTypeFitValue<int8_t>(int value) { 
    return CanSignedNumericTypeFitValue<int8_t>(value); 
}
template <> bool CanTypeFitValue<uint8_t>(int value) {
    return CanUnsignedNumericTypeFitValue<uint8_t>(value); 
}
// .....
//template <> bool CanTypeFitValue<SomeUserClass * > { 
//    return impl_details(value);
//};

It's also commonly used in STL/Boost etc.

The main idea is the function can be defined along with user defined type.

  • I suggest you read more carefully the question, and you try to compile your code with the links given. This will give warnings of comparing signed against unsigned when `T` is of `unsigned` type. It will probably not work because of this, especially for numbers close to the limit, like an unsigned int 4,000,000,000. Finally, it's not clear to me why you reduced the template parameters, forcing you to implement the function for any kind of input type for value. And you forgot to specify value as name of the input variable in the function. – Antonio Jun 24 '13 at 21:25
  • Yes you're right, this function will fail on input value close to the limits. I wrote this only to show the idea. – user2517908 Jun 24 '13 at 21:46
  • You have only followed up part of my comments. I also suggest that you test your code [here](http://coliru.stacked-crooked.com/view?id=563dadd8bd231acdfa7898188bbe33c8-ad7854d9cfd7979d567ca413f0830b65), leaving more or less unmodified the main function. You can then share your code, with the share button. – Antonio Jun 24 '13 at 22:12