// 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