80 lines
2.2 KiB
C
80 lines
2.2 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* ft_safe_long_math.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: thrieg <thrieg@student.42mulhouse.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2024/11/08 11:11:17 by alier #+# #+# */
|
|
/* Updated: 2025/02/16 19:04:26 by thrieg ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include <limits.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
|
|
/*
|
|
* Does saturate and never overflows/underflows.
|
|
* Sets `errno` to `ERANGE` if the operation would
|
|
* have caused an overflow/underflow.
|
|
*/
|
|
long safe_long_add(long a, long b)
|
|
{
|
|
if (b >= 0 && a > LONG_MAX - b)
|
|
{
|
|
errno = ERANGE;
|
|
return (LONG_MAX);
|
|
}
|
|
else if (b < 0 && a < LONG_MIN - b)
|
|
{
|
|
errno = ERANGE;
|
|
return (LONG_MIN);
|
|
}
|
|
return (a + b);
|
|
}
|
|
|
|
/*
|
|
* Does saturate and never overflows/underflows.
|
|
* Sets `errno` to `ERANGE` if the operation would
|
|
* have caused an overflow/underflow.
|
|
*/
|
|
long safe_long_sub(long a, long b)
|
|
{
|
|
if (b >= 0 && a < LONG_MIN + b)
|
|
{
|
|
errno = ERANGE;
|
|
return (LONG_MIN);
|
|
}
|
|
else if (b < 0 && a > LONG_MAX + b)
|
|
{
|
|
errno = ERANGE;
|
|
return (LONG_MAX);
|
|
}
|
|
return (a - b);
|
|
}
|
|
|
|
/*
|
|
* Does saturate and never overflows/underflows.
|
|
* Sets `errno` to `ERANGE` if the operation would
|
|
* have caused an overflow/underflow.
|
|
*/
|
|
long safe_long_mul(long a, long b)
|
|
{
|
|
if (b > 0)
|
|
{
|
|
if (a > 0 && a > LONG_MAX / b)
|
|
return (errno = ERANGE, LONG_MAX);
|
|
else if (a < 0 && a < LONG_MIN / b)
|
|
return (errno = ERANGE, LONG_MIN);
|
|
}
|
|
else if (b < 0)
|
|
{
|
|
if (a < 0 && a < LONG_MAX / b)
|
|
return (errno = ERANGE, LONG_MAX);
|
|
else if ((-LONG_MAX > LONG_MIN && b < -1) && a > LONG_MIN / b)
|
|
return (errno = ERANGE, LONG_MIN);
|
|
}
|
|
return (a * b);
|
|
}
|