Skip to content

Instantly share code, notes, and snippets.

@DavidEGrayson
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidEGrayson/06cf7ea73f82a05490ba to your computer and use it in GitHub Desktop.
Save DavidEGrayson/06cf7ea73f82a05490ba to your computer and use it in GitHub Desktop.
Safe signed multiplication test suite
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
// Multiplies two 64-bit signed ints if possible.
// Returns 0 on success, and puts the product of x and y into the result.
// Returns 1 if there was an overflow.
int int64_mult(int64_t x, int64_t y, int64_t * result)
{
*result = 0;
if (x > 0 && y > 0 && x > INT64_MAX / y) return 1;
if (x < 0 && y > 0 && x < INT64_MIN / y) return 1;
if (x > 0 && y < 0 && y < INT64_MIN / x) return 1;
if (x < 0 && y < 0 && (x <= INT64_MIN || y <= INT64_MIN || -x > INT64_MAX / -y))
return 1;
*result = x * y;
return 0;
}
void test_int64_mult_success(int64_t x, int64_t y, int64_t expected)
{
int64_t result;
// x * y
if (int64_mult(x, y, &result))
{
fprintf(stderr, "unexpected overflow: %lld %lld\n", x, y);
}
if (result != expected)
{
fprintf(stderr, "wrong result: %lld %lld %lld %lld\n", x, y, expected, result);
}
// y * x should be the same
if (int64_mult(y, x, &result))
{
fprintf(stderr, "unexpected overflow: %lld %lld\n", y, x);
}
if (result != expected)
{
fprintf(stderr, "wrong result: %lld %lld %lld %lld\n", y, x, expected, result);
}
}
void test_int64_mult_error(int64_t x, int64_t y)
{
int64_t result;
// x * y
if (int64_mult(x, y, &result) == 0)
{
fprintf(stderr, "unexpected success: %lld %lld\n", x, y);
}
// y * x shoul be the same
if (int64_mult(y, x, &result) == 0)
{
fprintf(stderr, "unexpected success: %lld %lld\n", y, x);
}
}
int main()
{
// min, min
test_int64_mult_error(INT64_MIN, INT64_MIN);
// min, min/100
test_int64_mult_error(INT64_MIN, INT64_MIN / 100);
// min, 0
test_int64_mult_error(INT64_MIN, -2);
test_int64_mult_error(INT64_MIN, -1);
test_int64_mult_success(INT64_MIN, 0, 0);
test_int64_mult_success(INT64_MIN, 1, INT64_MIN);
test_int64_mult_error(INT64_MIN, 2);
// min, max/100
test_int64_mult_error(INT64_MIN, INT64_MAX / 100);
// min, max
test_int64_mult_error(INT64_MIN, INT64_MAX);
// min/100, min/100
test_int64_mult_error(INT64_MIN / 100, INT64_MIN / 100);
// min/100, 0
test_int64_mult_error(INT64_MIN / 100, -101);
test_int64_mult_success(INT64_MIN / 100, -100, 0x7ffffffffffffff8);
test_int64_mult_success(INT64_MIN / 100, -99, 0x7eb851eb851eb84a);
test_int64_mult_success(INT64_MIN / 100, 0, 0);
test_int64_mult_success(INT64_MIN / 100, 100, -0x7ffffffffffffff8);
test_int64_mult_error(INT64_MIN / 100, 101);
// min/100, max/100
test_int64_mult_error(INT64_MIN / 100, INT64_MAX / 100);
// min/100, max
test_int64_mult_error(INT64_MIN / 100, INT64_MAX);
// 0, 0
test_int64_mult_success(0, 0, 0);
test_int64_mult_success(0, 1, 0);
test_int64_mult_success(1, 1, 1);
test_int64_mult_success(1, 3, 3);
test_int64_mult_success(3, 3, 9);
// 0, max/100
test_int64_mult_error(INT64_MAX / 100, -101);
test_int64_mult_success(INT64_MAX / 100, -100, -0x7ffffffffffffff8);
test_int64_mult_success(INT64_MAX / 100, -99, -0x7eb851eb851eb84a);
test_int64_mult_success(INT64_MAX / 100, 0, 0);
test_int64_mult_success(INT64_MAX / 100, 100, 0x7ffffffffffffff8);
test_int64_mult_error(INT64_MAX / 100, 101);
// 0, max
test_int64_mult_error(-2, INT64_MAX);
test_int64_mult_success(-1, INT64_MAX, -INT64_MAX);
test_int64_mult_success(0, INT64_MAX, 0);
test_int64_mult_success(1, INT64_MAX, INT64_MAX);
test_int64_mult_error(2, INT64_MAX);
// max/100, max
test_int64_mult_error(INT64_MAX / 100, INT64_MAX);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment