packages feed

trade-journal-0.0.1: src/Journal/mpfr_printf.c

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <mpfr.h>

int stream_out_mpq(
  mpq_t      quant,
  size_t     precision,
  int        zeros_prec /* = -1 */,
  mpfr_rnd_t rnd /* = GMP_RNDN */,
  char **    bufPtr)
{
  static const size_t extend_by_digits = 6U;

  mpfr_t tempfb;
  mpfr_t tempfnum;
  mpfr_t tempfden;

  mpfr_init(tempfb);
  mpfr_init(tempfnum);
  mpfr_init(tempfden);

  // Convert the rational number to a floating-point, extending the
  // floating-point to a large enough size to get a precise answer.

  mp_prec_t num_prec =
    (mpfr_prec_t)mpz_sizeinbase(mpq_numref(quant), 2);
  num_prec += extend_by_digits*64;
  if (num_prec < MPFR_PREC_MIN)
    num_prec = MPFR_PREC_MIN;

  mpfr_set_prec(tempfnum, num_prec);
  mpfr_set_z(tempfnum, mpq_numref(quant), rnd);

  mp_prec_t den_prec =
    (mpfr_prec_t)mpz_sizeinbase(mpq_denref(quant), 2);
  den_prec += extend_by_digits*64;
  if (den_prec < MPFR_PREC_MIN)
    den_prec = MPFR_PREC_MIN;

  mpfr_set_prec(tempfden, den_prec);
  mpfr_set_z(tempfden, mpq_denref(quant), rnd);

  mpfr_set_prec(tempfb, num_prec + den_prec);
  mpfr_div(tempfb, tempfnum, tempfden, rnd);

  if (mpfr_asprintf(bufPtr, "%.*RNf", precision, tempfb) < 0) {
    mpfr_clear(tempfb);
    mpfr_clear(tempfnum);
    mpfr_clear(tempfden);
    return -1;
  }

  char * buf = *bufPtr;

  if (zeros_prec >= 0) {
    size_t index = strlen(buf);
    size_t point = 0;
    for (size_t i = 0; i < index; i++) {
      if (buf[i] == '.') {
        point = i;
        break;
      }
    }
    if (point > 0) {
      while (--index >= (point + 1 + (size_t)zeros_prec) &&
             buf[index] == '0')
        buf[index] = '\0';
      if (index >= (point + (size_t)zeros_prec) &&
          buf[index] == '.')
        buf[index] = '\0';
    }
  }

  mpfr_clear(tempfb);
  mpfr_clear(tempfnum);
  mpfr_clear(tempfden);

  return 0;
}

void rational_to_str(
  signed long num,
  unsigned long den,
  unsigned int rnd_mode,
  size_t prec,
  char ** bufPtr)
{
  mpq_t val;
  mpq_init(val);
  mpq_set_si(val, num, den);
  stream_out_mpq(val, prec, -1, rnd_mode, bufPtr);
  mpq_clear(val);
}