"Fossies" - the Fresh Open Source Software Archive

Member "mapm_4.9.5a/mapm_fpf.c" (21 Feb 2010, 9269 Bytes) of package /linux/misc/old/mapm-4.9.5a.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mapm_fpf.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /* 
    3  *  M_APM  -  mapm_fpf.c
    4  *
    5  *  Copyright (C) 2001 - 2007   Michael C. Ring
    6  *
    7  *  Permission to use, copy, and distribute this software and its
    8  *  documentation for any purpose with or without fee is hereby granted,
    9  *  provided that the above copyright notice appear in all copies and
   10  *  that both that copyright notice and this permission notice appear
   11  *  in supporting documentation.
   12  *
   13  *  Permission to modify the software is granted. Permission to distribute
   14  *  the modified code is granted. Modifications are to be distributed by
   15  *  using the file 'license.txt' as a template to modify the file header.
   16  *  'license.txt' is available in the official MAPM distribution.
   17  *
   18  *  This software is provided "as is" without express or implied warranty.
   19  */
   20 
   21 /*
   22  *      $Id: mapm_fpf.c,v 1.10 2007/12/03 01:39:57 mike Exp $
   23  *
   24  *      This file contains the Fixed Point Formatting functions
   25  *
   26  *      $Log: mapm_fpf.c,v $
   27  *      Revision 1.10  2007/12/03 01:39:57  mike
   28  *      Update license
   29  *
   30  *      Revision 1.9  2003/07/21 20:15:12  mike
   31  *      Modify error messages to be in a consistent format.
   32  *
   33  *      Revision 1.8  2003/03/31 22:11:14  mike
   34  *      call generic error handling function
   35  *
   36  *      Revision 1.7  2002/11/05 23:31:00  mike
   37  *      use new set_to_zero call instead of copy
   38  *
   39  *      Revision 1.6  2002/11/03 22:33:24  mike
   40  *      Updated function parameters to use the modern style
   41  *
   42  *      Revision 1.5  2002/02/14 19:31:44  mike
   43  *      eliminate need for conditional compile
   44  *
   45  *      Revision 1.4  2001/08/26 22:35:50  mike
   46  *      no LCC conditional needed on fixpt_string
   47  *
   48  *      Revision 1.3  2001/08/26 22:11:10  mike
   49  *      add new 'stringexp' function
   50  *
   51  *      Revision 1.2  2001/08/25 22:30:09  mike
   52  *      fix LCC-WIN32 compile problem
   53  *
   54  *      Revision 1.1  2001/08/25 16:50:59  mike
   55  *      Initial revision
   56  */
   57 
   58 #include "m_apm_lc.h"
   59 #include <ctype.h>
   60 
   61 /****************************************************************************/
   62 char    *m_apm_to_fixpt_stringexp(int dplaces, M_APM atmp, 
   63                   char ch_radx, char ch_sep, int ct_sep)
   64 {
   65 int places, xp, dl, ii;
   66 char    *cpr;
   67 
   68 places = dplaces;
   69 
   70 dl = atmp->m_apm_datalength;
   71 xp = atmp->m_apm_exponent;
   72 
   73 if (places < 0)             /* show ALL digits */
   74   {
   75    if (xp < 0)
   76       ii = dl - xp;
   77    else
   78      {
   79       if (dl > xp)
   80         ii = dl;
   81       else
   82         ii = xp;
   83      }
   84   }
   85 else
   86   {
   87    ii = places;
   88       
   89    if (xp > 0)
   90      ii += xp;
   91   }
   92 
   93 if (ct_sep != 0 && ch_sep != 0 && xp > 0)
   94   ii += xp / ct_sep;
   95 
   96 if ((cpr = (char *)MAPM_MALLOC((ii + 32) * sizeof(char))) == NULL)
   97   return(NULL);
   98 
   99 m_apm_to_fixpt_stringex(cpr,places,atmp,ch_radx,ch_sep,ct_sep);
  100 
  101 return(cpr);
  102 }
  103 /****************************************************************************/
  104 void    m_apm_to_fixpt_stringex(char *s, int dplaces, M_APM atmp, 
  105                 char ch_radix, char ch_sep, int count_sep)
  106 {
  107 M_APM   btmp;
  108 char    ch, *cpd, *cps;
  109 int ii, jj, kk, ct, dl, xp, no_sep_flg, places;
  110 
  111 btmp       = M_get_stack_var();
  112 places     = dplaces;
  113 cpd        = s;
  114 no_sep_flg = FALSE;
  115 
  116 m_apm_absolute_value(btmp, atmp);   /* do conversion of positive number */
  117 
  118 if (ch_sep == 0 || count_sep == 0)  /* no separator char OR count */
  119   no_sep_flg = TRUE;
  120 
  121 /* determine how much memory to get for the temp string */
  122 
  123 dl = btmp->m_apm_datalength;
  124 xp = btmp->m_apm_exponent;
  125 
  126 if (places < 0)             /* show ALL digits */
  127   {
  128    if (xp < 0)
  129       ii = dl - xp;
  130    else
  131      {
  132       if (dl > xp)
  133         ii = dl;
  134       else
  135         ii = xp;
  136      }
  137   }
  138 else
  139   {
  140    ii = places;
  141       
  142    if (xp > 0)
  143      ii += xp;
  144   }
  145 
  146 if ((cps = (char *)MAPM_MALLOC((ii + 32) * sizeof(char))) == NULL)
  147   {
  148    /* fatal, this does not return */
  149 
  150    M_apm_log_error_msg(M_APM_FATAL, 
  151                        "\'m_apm_to_fixpt_stringex\', Out of memory");
  152   }
  153 
  154 m_apm_to_fixpt_string(cps, places, btmp);
  155 
  156 /*
  157  *  the converted string may be all 'zero', 0.0000...
  158  *  if so and the original number is negative,
  159  *  do NOT set the '-' sign of our output string.
  160  */
  161 
  162 if (atmp->m_apm_sign == -1)     /* if input number negative */
  163   {
  164    kk = 0;
  165    jj = 0;
  166 
  167    while (TRUE)
  168      {
  169       ch = cps[kk++];
  170       if ((ch == '\0') || (jj != 0))
  171         break;
  172 
  173       if (isdigit((int)ch))
  174         {
  175      if (ch != '0')
  176        jj = 1;
  177     }
  178      }
  179 
  180    if (jj)
  181      *cpd++ = '-';
  182   }
  183 
  184 ct = M_strposition(cps, ".");      /* find the default (.) radix char */
  185 
  186 if (ct == -1)              /* if not found .. */
  187   {
  188    strcat(cps, ".");               /* add one */
  189    ct = M_strposition(cps, ".");   /* and then find it */
  190   }
  191 
  192 if (places == 0)           /* int format, terminate at radix char */
  193   cps[ct] = '\0';
  194 else
  195   cps[ct] = ch_radix;          /* assign the radix char */
  196 
  197 /*
  198  *  if the number is small enough to not have any separator char's ...
  199  */
  200 
  201 if (ct <= count_sep)
  202   no_sep_flg = TRUE;
  203 
  204 if (no_sep_flg)
  205   {
  206    strcpy(cpd, cps);
  207   }
  208 else
  209   {
  210    jj = 0;
  211    kk = count_sep;
  212    ii = ct / count_sep;
  213 
  214    if ((ii = ct - ii * count_sep) == 0)
  215      ii = count_sep;
  216 
  217    while (TRUE)             /* write out the first 1,2  */
  218      {                  /* (up to count_sep) digits */
  219       *cpd++ = cps[jj++];
  220 
  221       if (--ii == 0)
  222         break;
  223      }
  224 
  225    while (TRUE)             /* write rest of the string   */
  226      {
  227       if (kk == count_sep)      /* write a new separator char */
  228         {
  229      if (jj != ct)          /* unless we're at the radix  */
  230        {
  231             *cpd++ = ch_sep;        /* note that this also disables */
  232         kk = 0;         /* the separator char AFTER     */
  233        }                /* the radix char               */
  234     }
  235 
  236       if ((*cpd++ = cps[jj++]) == '\0')
  237         break;
  238 
  239       kk++;
  240      }
  241   }
  242 
  243 MAPM_FREE(cps);
  244 M_restore_stack(1);
  245 }
  246 /****************************************************************************/
  247 void    m_apm_to_fixpt_string(char *ss, int dplaces, M_APM mtmp)
  248 {
  249 M_APM   ctmp;
  250 void    *vp;
  251 int places, i2, ii, jj, kk, xp, dl, numb;
  252 UCHAR   *ucp, numdiv, numrem;
  253 char    *cpw, *cpd, sbuf[128];
  254 
  255 ctmp   = M_get_stack_var();
  256 vp     = NULL;
  257 cpd    = ss;
  258 places = dplaces;
  259 
  260 /* just want integer portion if places == 0 */
  261 
  262 if (places == 0)
  263   {
  264    if (mtmp->m_apm_sign >= 0)
  265      m_apm_add(ctmp, mtmp, MM_0_5);
  266    else
  267      m_apm_subtract(ctmp, mtmp, MM_0_5);
  268 
  269    m_apm_to_integer_string(cpd, ctmp);
  270 
  271    M_restore_stack(1);
  272    return;
  273   }
  274 
  275 if (places > 0)
  276   M_apm_round_fixpt(ctmp, places, mtmp);
  277 else
  278   m_apm_copy(ctmp, mtmp);     /* show ALL digits */
  279 
  280 if (ctmp->m_apm_sign == 0)        /* result is 0 */
  281   {
  282    if (places < 0)
  283      {
  284       cpd[0] = '0';       /* "0.0" */
  285       cpd[1] = '.';
  286       cpd[2] = '0';
  287       cpd[3] = '\0';
  288      }
  289    else
  290      {
  291       memset(cpd, '0', (places + 2));   /* pre-load string with all '0' */
  292       cpd[1] = '.';
  293       cpd[places + 2] = '\0';
  294      }
  295 
  296    M_restore_stack(1);
  297    return;
  298   }
  299 
  300 xp   = ctmp->m_apm_exponent;
  301 dl   = ctmp->m_apm_datalength;
  302 numb = (dl + 1) >> 1;
  303 
  304 if (places < 0)
  305   {
  306    if (dl > xp)
  307      jj = dl + 16;
  308    else
  309      jj = xp + 16;
  310   }
  311 else
  312   {
  313    jj = places + 16;
  314    
  315    if (xp > 0)
  316      jj += xp;
  317   }
  318 
  319 if (jj > 112)
  320   {
  321    if ((vp = (void *)MAPM_MALLOC((jj + 16) * sizeof(char))) == NULL)
  322      {
  323       /* fatal, this does not return */
  324 
  325       M_apm_log_error_msg(M_APM_FATAL, 
  326                           "\'m_apm_to_fixpt_string\', Out of memory");
  327      }
  328 
  329    cpw = (char *)vp;
  330   }
  331 else
  332   {
  333    cpw = sbuf;
  334   }
  335 
  336 /*
  337  *  at this point, the number is non-zero and the the output
  338  *  string will contain at least 1 significant digit.
  339  */
  340 
  341 if (ctmp->m_apm_sign == -1)       /* negative number */
  342   {
  343    *cpd++ = '-';
  344   }
  345 
  346 ucp = ctmp->m_apm_data;
  347 ii  = 0;
  348 
  349 /* convert MAPM num to ASCII digits and store in working char array */
  350 
  351 while (TRUE)
  352   {
  353    M_get_div_rem_10((int)(*ucp++), &numdiv, &numrem);
  354 
  355    cpw[ii++] = numdiv + '0';
  356    cpw[ii++] = numrem + '0';
  357 
  358    if (--numb == 0)
  359      break;
  360   }
  361 
  362 i2 = ii;        /* save for later */
  363 
  364 if (places < 0)     /* show ALL digits */
  365   {
  366    places = dl - xp;
  367 
  368    if (places < 1)
  369      places = 1;
  370   }
  371 
  372 /* pad with trailing zeros if needed */
  373 
  374 kk = xp + places + 2 - ii;
  375 
  376 if (kk > 0)
  377   memset(&cpw[ii], '0', kk);
  378 
  379 if (xp > 0)          /* |num| >= 1, NO lead-in "0.nnn" */
  380   {
  381    ii = xp + places + 1;
  382    jj = 0;
  383 
  384    for (kk=0; kk < ii; kk++)
  385      {
  386       if (kk == xp)
  387         cpd[jj++] = '.';
  388 
  389       cpd[jj++] = cpw[kk];
  390      }
  391 
  392    cpd[ii] = '\0';
  393   }
  394 else            /* |num| < 1, have lead-in "0.nnn" */
  395   {
  396    jj = 2 - xp;
  397    ii = 2 + places;
  398    memset(cpd, '0', (ii + 1));  /* pre-load string with all '0' */
  399    cpd[1] = '.';        /* assign decimal point */
  400 
  401    for (kk=0; kk < i2; kk++)
  402      {
  403       cpd[jj++] = cpw[kk];
  404      }
  405 
  406    cpd[ii] = '\0';
  407   }
  408 
  409 if (vp != NULL)
  410   MAPM_FREE(vp);
  411 
  412 M_restore_stack(1);
  413 }
  414 /****************************************************************************/
  415 void    M_apm_round_fixpt(M_APM btmp, int places, M_APM atmp)
  416 {
  417 int xp, ii;
  418 
  419 xp = atmp->m_apm_exponent;
  420 ii = xp + places - 1;
  421 
  422 M_set_to_zero(btmp); /* assume number is too small so the net result is 0 */
  423 
  424 if (ii >= 0)
  425   {
  426    m_apm_round(btmp, ii, atmp);
  427   }
  428 else
  429   {
  430    if (ii == -1)    /* next digit is significant which may round up */
  431      {
  432       if (atmp->m_apm_data[0] >= 50)    /* digit >= 5, round up */
  433         {
  434          m_apm_copy(btmp, atmp);
  435      btmp->m_apm_data[0] = 10;
  436      btmp->m_apm_exponent += 1;
  437      btmp->m_apm_datalength = 1;
  438      M_apm_normalize(btmp);
  439     }
  440      }
  441   }
  442 }
  443 /****************************************************************************/
  444