#ifndef UCS_LINEAR_FUNC_H_
#define UCS_LINEAR_FUNC_H_
#include <ucs/type/status.h>
#include <ucs/sys/compiler_def.h>
#include <math.h>
typedef struct {
double c;
double m;
} ucs_linear_func_t;
static UCS_F_ALWAYS_INLINE ucs_linear_func_t
ucs_linear_func_make(double c, double m)
{
ucs_linear_func_t result;
result.c = c;
result.m = m;
return result;
}
static UCS_F_ALWAYS_INLINE double
ucs_linear_func_apply(ucs_linear_func_t f, double x)
{
return f.c + (f.m * x);
}
static UCS_F_ALWAYS_INLINE ucs_linear_func_t
ucs_linear_func_add(ucs_linear_func_t func1, ucs_linear_func_t func2)
{
return ucs_linear_func_make(func1.c + func2.c, func1.m + func2.m);
}
static UCS_F_ALWAYS_INLINE ucs_linear_func_t
ucs_linear_func_add3(ucs_linear_func_t func1, ucs_linear_func_t func2,
ucs_linear_func_t func3)
{
return ucs_linear_func_add(ucs_linear_func_add(func1, func2), func3);
}
static inline ucs_linear_func_t
ucs_linear_func_sub(ucs_linear_func_t func1, ucs_linear_func_t func2)
{
return ucs_linear_func_make(func1.c - func2.c, func1.m - func2.m);
}
static inline void
ucs_linear_func_add_inplace(ucs_linear_func_t *func1, ucs_linear_func_t func2)
{
func1->m += func2.m;
func1->c += func2.c;
}
static inline ucs_linear_func_t
ucs_linear_func_compose(ucs_linear_func_t outer, ucs_linear_func_t inner)
{
return ucs_linear_func_make((outer.m * inner.c) + outer.c,
outer.m * inner.m);
}
static inline ucs_status_t
ucs_linear_func_intersect(ucs_linear_func_t func1, ucs_linear_func_t func2,
double *x_intersect)
{
double x;
x = (func2.c - func1.c) / (func1.m - func2.m);
if (isnan(x) || isinf(x)) {
return UCS_ERR_INVALID_PARAM;
}
*x_intersect = x;
return UCS_OK;
}
static inline void
ucs_linear_func_add_value_at(ucs_linear_func_t *func,
ucs_linear_func_t baseline_func, double baseline_x)
{
func->c += ucs_linear_func_apply(baseline_func, baseline_x);
}
static inline int
ucs_linear_func_is_equal(ucs_linear_func_t func1, ucs_linear_func_t func2,
double epsilon)
{
return (fabs(func1.m - func2.m) < epsilon) &&
(fabs(func1.c - func2.c) < epsilon);
}
#endif