#define NS_DEFAULT (2 << 11) /* 4096 */ #define MAX_PREC 4 #define PRINT_FORMAT "%.Ff" #define PRINTLINE_FORMAT PRINT_FORMAT "\n" #define PERROR_RETURN(str,ret) do { perror(str); return ret; } while (1) #define NS_EXPAND(s) \ do \ { \ if (s->top + 2 >= (ssize_t) s->max) \ { \ if (ns_expand(s, s->max << 2)) \ { return 1; } \ if (!s->num) \ { return 1; } \ } \ ++s->top; \ } while (0) #define NS_DEINT(s)\ #define NS_PEEK(s) s->num[s->top] #define NS_PEEKN(s,n) s->num[s->top + n] typedef struct { ssize_t max; ssize_t top; /* top < NS_MAX */ mpf_t * num; } ns_t; /* number stack */ static ns_t * ns_init(ssize_t max) { ssize_t i; ns_t * s = (ns_t *) malloc(sizeof(ns_t)); if (!s) { PERROR_RETURN(PROGN, NULL); } s->num = malloc(max * sizeof(mpf_t)); if (!s->num) { PERROR_RETURN(PROGN, NULL); } s->max = max; s->top = -1; for (i = 0; i < s->max; ++i) { mpf_init(s->num[i]); } return s; } static void ns_free(ns_t * s) { ssize_t i; /* fprintf(stderr, "Freeing %ld blocks\n", s->max); */ for (i = 0; i < s->max; ++i) { mpf_clear(s->num[i]); } free(s->num); free(s); } int ns_expand(ns_t * s, ssize_t newmax) { /* fprintf(stderr, "Expanding to %ld blocks\n", newmax); */ assert(newmax > s->max); s->num = realloc(s->num, (size_t) newmax * sizeof(mpf_t)); if (!s->num) { PERROR_RETURN(PROGN, 1); } else { ssize_t i; for (i = s->max; i < newmax; ++i) { mpf_init(s->num[i]); } s->max = newmax; return 0; } } static int ns_push(ns_t * s, mpf_t val) { NS_EXPAND(s); mpf_set(NS_PEEK(s), val); return 0; } static mpf_t * ns_pop(ns_t * s) { if (s->top > -1) { return &s->num[s->top--]; } else { fprintf(stderr, PROGN ": underflow\n"); return NULL; } } static void ns_printline_all(ns_t * s) { ssize_t i; #ifdef FOR_HUMANS for (i = 0; i <= s->top; ++i) #else for (i = s->top; i >= 0; --i) #endif /* FOR_HUMANS */ { gmp_printf(PRINTLINE_FORMAT, s->num[i]); } } static inline void ns_printline_peek(ns_t * s) { if (s->top > -1) { gmp_printf(PRINTLINE_FORMAT, NS_PEEK(s)); } } static inline int ns_print_peek(ns_t * s) { if (s->top > -1) { gmp_printf(PRINT_FORMAT, NS_PEEK(s)); return 0; } else { return 1; } } static inline void ns_clear(ns_t * s) { s->top = -1; } static inline int ns_reverse(ns_t * s) { if (s->top > 0) { mpf_swap(NS_PEEK(s), s->num[s->top-1]); return 0; } else { return 1; } } static inline int ns_dup(ns_t * s) { return ns_push(s, NS_PEEK(s)); } /* FIXME REMOVE TEST FUNCTION !!! */ static inline int ns_ndup(ns_t * s) { int ret = 0; mpf_t dupn; if (ns_pop(s) == NULL) { return 1; } for (mpf_set(dupn, NS_PEEKN(s,1)); !ret && mpf_cmp_ui(dupn,1); mpf_sub_ui(dupn,dupn,1)) { ret += ns_dup(s); } return ret; } #include "arith.c"