// Factorial. (2.01)
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
// Utility.
_Bool sign_different_p(int a, int b)
{
return (a ^ b) < 0;
}
_Bool mul_overflow_p(int a, int b)
{
if (a == 0 || b == 0)
return 0;
if (sign_different_p(a, b))
return (a < 0) ? INT_MIN/b > a : INT_MIN/a > b;
else
return (a < 0) ? INT_MAX/a > b : INT_MAX/a < b;
}
_Bool mul_overflow(int a, int b, int *result)
{
if (mul_overflow_p(a, b))
return 1;
*result = a * b;
return 0;
}
// Main.
int factorial(int n)
{
if (n < 0)
{
errno = EDOM;
return -1;
}
int result = 1;
while (n > 1)
{
if (mul_overflow(n, result, &result))
{
errno = ERANGE;
return -1;
}
n -= 1;
}
return result;
}
int main(void)
{
for (int i = -1; i < 14; i++)
{
int result = factorial(i);
if (result < 0)
else
printf("%2d! : %d\n", i
, result
); }
return 0;
}
Ly8gRmFjdG9yaWFsLiAoMi4wMSkKCiNpbmNsdWRlIDxsaW1pdHMuaD4KI2luY2x1ZGUgPGVycm5vLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CgovLyBVdGlsaXR5LgoKX0Jvb2wgc2lnbl9kaWZmZXJlbnRfcChpbnQgYSwgaW50IGIpCnsKICAgIHJldHVybiAoYSBeIGIpIDwgMDsKfQoKX0Jvb2wgbXVsX292ZXJmbG93X3AoaW50IGEsIGludCBiKQp7CiAgICBpZiAoYSA9PSAwIHx8IGIgPT0gMCkKICAgICAgICByZXR1cm4gMDsKICAgIGlmIChzaWduX2RpZmZlcmVudF9wKGEsIGIpKQogICAgICAgIHJldHVybiAoYSA8IDApID8gSU5UX01JTi9iID4gYSA6IElOVF9NSU4vYSA+IGI7CiAgICBlbHNlCiAgICAgICAgcmV0dXJuIChhIDwgMCkgPyBJTlRfTUFYL2EgPiBiIDogSU5UX01BWC9hIDwgYjsKfQoKX0Jvb2wgbXVsX292ZXJmbG93KGludCBhLCBpbnQgYiwgaW50ICpyZXN1bHQpCnsKICAgIGlmIChtdWxfb3ZlcmZsb3dfcChhLCBiKSkKICAgICAgICByZXR1cm4gMTsKICAgICpyZXN1bHQgPSBhICogYjsKICAgIHJldHVybiAwOwp9CgovLyBNYWluLgoKaW50IGZhY3RvcmlhbChpbnQgbikKewogICAgaWYgKG4gPCAwKQogICAgewogICAgICAgIGVycm5vID0gRURPTTsKICAgICAgICByZXR1cm4gLTE7CiAgICB9CgogICAgaW50IHJlc3VsdCA9IDE7CgogICAgd2hpbGUgKG4gPiAxKQogICAgewogICAgICAgIGlmIChtdWxfb3ZlcmZsb3cobiwgcmVzdWx0LCAmcmVzdWx0KSkKICAgICAgICB7CiAgICAgICAgICAgIGVycm5vID0gRVJBTkdFOwogICAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgfQogICAgICAgIG4gLT0gMTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7Cn0KCmludCBtYWluKHZvaWQpCnsKICAgIGZvciAoaW50IGkgPSAtMTsgaSA8IDE0OyBpKyspCiAgICB7CiAgICAgICAgaW50IHJlc3VsdCA9IGZhY3RvcmlhbChpKTsKICAgICAgICBpZiAocmVzdWx0IDwgMCkKICAgICAgICAgICAgcHJpbnRmKCIlMmQhIDogJXNcbiIsIGksIHN0cmVycm9yKGVycm5vKSk7CiAgICAgICAgZWxzZQogICAgICAgICAgICBwcmludGYoIiUyZCEgOiAlZFxuIiwgaSwgcmVzdWx0KTsKICAgIH0KICAgIHJldHVybiAwOwp9