|
- #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)
|