On Friday, June 3, 2016 at 2:38:33 PM UTC-5, luser droog wrote:
> On Friday, June 3, 2016 at 3:46:12 AM UTC-5, Barry Schwarz wrote:
> > On Thu, 2 Jun 2016 22:42:26 -0700 (PDT), luser droog
> > <
luser...@gmail.com> wrote:
> >
> > >On Friday, June 3, 2016 at 12:34:32 AM UTC-5, luser droog wrote:
> > >> It's alive! It's alive!
> > >>
> I'm confident that following the documentation will remove much of my
> need for this level of scrutiny.
A little more fleshed-out. 4-function calculator. Produces floating-point
results for division, but only accepts integer input.
//number.c
//$make number LDLIBS='-lmpfr -lgmp'
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <mpfr.h>
#include <gmp.h>
enum tag { NONE, Z, FR };
typedef union {
enum tag tag;
struct z {
enum tag tag;
mpz_t z;
} z;
struct fr {
enum tag tag;
mpfr_t fr;
} fr;
} u_number;
typedef u_number number[1];
typedef u_number *number_ptr;
void init_z(number_ptr z){
z->z.tag = Z;
mpz_init(z->z.z);
}
void init_fr(number_ptr fr){
fr->fr.tag = FR;
mpfr_init(fr->
fr.fr);
}
void promote(number_ptr n){
mpz_t t;
memcpy(&t, &n->z.z, sizeof t);
init_fr(n);
mpfr_set_z(n->
fr.fr, t, MPFR_RNDN);
mpz_clear(t);
}
#define op(func, C, A, B) \
if ((A)->tag==Z && (B)->tag==Z) { \
if (!strcmp(#func,"div")) { \
init_fr(C); \
promote(A); \
promote(B); \
mpfr_##func((C)->
fr.fr, (A)->
fr.fr, (B)->
fr.fr, MPFR_RNDN); \
} else { \
init_z(C); \
mpz_##func((C)->z.z, (A)->z.z, (B)->z.z); \
} \
} else if ((A)->tag==FR && (B)->tag==FR) { \
init_fr(C); \
mpfr_##func((C)->
fr.fr, (A)->
fr.fr, (B)->
fr.fr, MPFR_RNDN); \
}
void mpz_nothing(mpz_t c, const mpz_t a, const mpz_t b){
mpz_set_ui(c,0);
}
void mpfr_nothing(mpfr_t c, const mpfr_t a, const mpfr_t b, mpfr_rnd_t rnd){
mpfr_set_ui(c,0,rnd);
}
int main(){
number a, b, c;
char op[2];
init_z(a);
init_z(b);
gmp_scanf("%Zd %1s %Zd", a->z.z, op, b->z.z);
switch(*op){
case '+': op(add, c, a, b); break;
case '*': op(mul, c, a, b); break;
case '-': op(sub, c, a, b); break;
case '/': op(div, c, a, b); break;
default: op(nothing, c, a, b);
}
switch(c->tag){
case Z: gmp_printf("%Zd\n", c->z.z); break;
case FR: mpfr_printf("%Rf\n", c->
fr.fr); break;
}
}