This repository has been archived on 2024-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
dc/old-dc/arith.c

105 lines
3.9 KiB
C
Raw Normal View History

2023-09-23 13:26:21 -04:00
#define ARITH(fn, op) \
static inline int \
fn(ns_t * s) \
{ \
if (s->top > 0) \
{ \
--s->top; \
op(NS_PEEK(s), \
NS_PEEK(s), s->num[s->top+1]); \
return 0; \
} \
else \
{ \
fprintf(stderr, "dc: underflow\n"); \
return 1; \
} \
}
#define ARITH_ONE(fn, op) \
static inline int \
fn(ns_t * s) \
{ \
if (s->top > -1) \
{ \
op(NS_PEEK(s), \
NS_PEEK(s)); \
return 0; \
} \
else \
{ \
fprintf(stderr, "dc: underflow\n"); \
return 1; \
} \
}
#define ARITH_DIV(fn, op) \
static inline int fn(ns_t * s) \
{ \
if (s->top > 0) \
{ \
if (!(mpf_cmp_ui(NS_PEEK(s), 0) || \
mpf_cmp_ui(s->num[s->top-1], 0))) \
{ fprintf(stderr, "dc: divide by 0\n"); return 2; } \
else \
{ \
--s->top; op(NS_PEEK(s), NS_PEEK(s), s->num[s->top+1]); \
return 0; \
} \
} \
else \
{ fprintf(stderr, "dc: underflow\n"); return 1; } \
}
/* handles negative numbers and is multi-presision unlike mpf_exp_ui */
static inline int ns_exp(ns_t * s)
{
if (s->top > 0)
{
if (!(mpf_cmp_ui(NS_PEEK(s), 0) ||
mpf_cmp_ui(s->num[s->top-1], 0)))
{ fprintf(stderr, "dc: divide by 0\n"); return 2; }
else
{
mpf_t i;
mpf_t mpf;
if (mpf_cmp_ui(NS_PEEK(s), 0) == 0)
{ mpf_set_ui(NS_PEEK(s), 1); return 0; }
--s->top;
mpf_inits(i, mpf, NULL);
mpf_set(mpf, NS_PEEK(s));
mpf_set(i, s->num[s->top + 1]);
mpf_ceil(i, i);
mpf_sub_ui(i, i, 1);
if (mpf_cmp_ui(i, 0) > 0)
{
for (; mpf_cmp_ui(i, 0); mpf_sub_ui(i, i, 1))
{ mpf_mul(NS_PEEK(s), NS_PEEK(s), mpf); }
}
else
{
for (; mpf_cmp_ui(i, 0); mpf_add_ui(i, i, 1))
{ mpf_div(NS_PEEK(s), NS_PEEK(s), mpf); }
}
mpf_clears(i, mpf, NULL);
return 0;
}
{
}
}
else
{ fprintf(stderr, "dc: underflow\n"); return 1; }
__builtin_unreachable();
}
ARITH(ns_add, mpf_add)
ARITH(ns_sub, mpf_sub)
ARITH(ns_mul, mpf_mul)
ARITH_DIV(ns_div, mpf_div)
ARITH_DIV(ns_mod, mpf_div)
ARITH_ONE(ns_abs, mpf_abs)
ARITH_ONE(ns_sqrt, mpf_sqrt)
ARITH_ONE(ns_floor, mpf_floor)
ARITH_ONE(ns_ceil, mpf_ceil)