Math-Ryu

 view release on metacpan or  search on metacpan

Ryu.xs  view on Meta::CPAN


  if(s[0] == '-') {
    is_neg = 1;
    s++;
  }

  /* If the given argument contains a decimal point, then that *
   * decimal point will immediately follow the first digit.    *
   * Otherwise, the argument does not contain a decimal point. */
  if(s[1] == '.') pointpos = 1;

  if(pointpos) {
    /*** STRING CONTAINS A DECIMAL POINT ***/
    Newxz(man_str, MAN_BUF, char);
    if(man_str == NULL) croak("Failed (in 'if' block) to allocate memory for man_str in fmtpy function");
    Newxz(exp_str, EXP_BUF, char);
    if(exp_str == NULL) croak("Failed (in 'if' block) to allocate memory for exp_str in fmtpy function");

    /* Split into mantissa and exponent around 'E'         *
     * The input string (s) has the 'E' replaced by a NULL *
     * and the exponent portion of s is copied to exp_str  */
    len = strlen(s);
    for(i = 0; i < len; i++) {
      if(seen) { /* will be set when 'E' is encountered' */
        exp_str[i - seen] = s[i];
      }
      else if(s[i] == 'E') {
        seen = i + 1;
        s[i] = '\0';
      }
    }
    exp_str[i - seen] = '\0';
    exponent = atoi(exp_str);

    if(exponent > 0 && exponent < MAX_DEC_DIG) {
      len = strlen(s);
      zero_pad = exponent - ((int)len - 2);
      if(zero_pad >= 0 && (zero_pad + len < MAX_DEC_DIG + 1)) {
        /* Return, eg, '1.23E15' as '1230000000000000.0' */
        if(is_neg) man_str[0] = '-';
        man_str[0 + is_neg] = s[0];
        for(i = 2; i < len; i++) {
          man_str[i + is_neg - 1] = s[i];
        }
        for(dec = 0; dec < zero_pad; dec++) {
          man_str[i + is_neg - 1] = '0';
          i++;
        }
        man_str[i + is_neg - 1] = '.';
        man_str[i + is_neg] = '0';
        man_str[i + is_neg + 1] = '\0';

        outsv = newSVpv(man_str, 0);
        Safefree(man_str);
        Safefree(exp_str);
        if(is_neg) s--;
        return outsv;
      }
      else if(zero_pad < 0) {
        /* We want, eg,  1.23625E2 to be returned as "123.625". *
         * This involves relocation of the decimal point.       */
        len = strlen(s);
        zero_pad--;
        if(is_neg) man_str[0] = '-';
        man_str[0 + is_neg] = s[0];
        man_str[1 + is_neg] = s[2]; /* s[1] is the decimal point */
        dec = 1; /* set to 0 when the decimal point is encountered */
        for(i = 2; i < len; i++) {
           if(i == zero_pad + len) {
             man_str[i + is_neg] = '.';
             dec--;
           }
           else man_str[i + is_neg] = s[i + dec];
        }

        man_str[i + is_neg] = '\0';

        outsv = newSVpv(man_str, 0);
        Safefree(man_str);
        Safefree(exp_str);
        if(is_neg) s--;
        return outsv;
      }
    }

    len = strlen(s); /* now different to when initially set     *
                      * because 'E' has been replaced with '\0' */
    if(exponent < -4 || exponent >= 0) {
       if(is_neg) man_str[0] = '-';
      for(i = 0; i < len; i++) man_str[i + is_neg] = s[i];
      if(!exponent) {
        man_str[i + is_neg] = '\0';
        outsv = newSVpv(man_str, 0);
        Safefree(man_str);
        Safefree(exp_str);
        if(is_neg) s--;
        return outsv;
      }
      man_str[i + is_neg] = 'e';
      len = strlen(exp_str);
      if(exponent > 0) {
        man_str[i + 1 + is_neg] = '+';
        dec = (int)i + 2 + is_neg;
        for(i = 0; i < len; i ++) man_str[dec + i] = exp_str[i];
        man_str[dec + i] = '\0';
        outsv = newSVpv(man_str, 0);
        Safefree(man_str);
        Safefree(exp_str);
        if(is_neg) s--;
        return outsv;
      }
      /* exponent < -4 */
      dec = (int)i + 1 + is_neg;
      if(len == 2) {
        man_str[dec] = '-';
        man_str[dec + 1] = '0';
        man_str[dec + 2] = exp_str[1];
        man_str[dec + 3] = '\0';
      }
      else {
        for(i = 0; i < len; i++) man_str[dec + i] = exp_str[i];



( run in 0.613 second using v1.01-cache-2.11-cpan-5511b514fd6 )