"Fossies" - the Fresh Open Source Software Archive

Member "mapm_4.9.5a/mapmutil.c" (21 Feb 2010, 12990 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 "mapmutil.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /* 
    3  *  M_APM  -  mapmutil.c
    4  *
    5  *  Copyright (C) 1999 - 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: mapmutil.c,v 1.26 2007/12/03 01:58:49 mike Exp $
   23  *
   24  *      This file contains various utility functions needed by the 
   25  *  library in addition to some basic user callable functions.
   26  *
   27  *      $Log: mapmutil.c,v $
   28  *      Revision 1.26  2007/12/03 01:58:49  mike
   29  *      Update license
   30  *
   31  *      Revision 1.25  2003/07/21 20:51:34  mike
   32  *      Modify error messages to be in a consistent format.
   33  *
   34  *      Revision 1.24  2003/03/31 22:03:54  mike
   35  *      call generic error handling function
   36  *
   37  *      Revision 1.23  2002/11/04 20:47:02  mike
   38  *      change m_apm_init so it compiles clean with a real C++ compiler
   39  *
   40  *      Revision 1.22  2002/11/03 22:50:58  mike
   41  *      Updated function parameters to use the modern style
   42  *
   43  *      Revision 1.21  2002/05/17 22:26:49  mike
   44  *      move some functions into another file
   45  *
   46  *      Revision 1.20  2002/02/12 20:21:53  mike
   47  *      eliminate unneeded working arrays in _scale
   48  *      by processing the scaling operation in reverse
   49  *
   50  *      Revision 1.19  2001/07/24 18:29:18  mike
   51  *      add util function to get address of
   52  *      the div/rem lookup tables
   53  *
   54  *      Revision 1.18  2001/07/20 16:14:05  mike
   55  *      optimize normalize yet again
   56  *
   57  *      Revision 1.17  2001/07/17 18:17:56  mike
   58  *      another optimization to _normalize
   59  *
   60  *      Revision 1.16  2001/07/16 22:33:43  mike
   61  *      update free_all_util
   62  *
   63  *      Revision 1.15  2001/07/16 19:56:26  mike
   64  *      add function M_free_all_util
   65  *
   66  *      Revision 1.14  2001/07/16 18:10:21  mike
   67  *      optimize M_apm_normalize when moving multiple '00' bytes
   68  *
   69  *      Revision 1.13  2001/02/11 22:36:43  mike
   70  *      modify parameters to REALLOC
   71  *
   72  *      Revision 1.12  2001/01/23 21:17:38  mike
   73  *      add dedicated long->ascii conversion (instead of sprintf)
   74  *
   75  *      Revision 1.11  2000/08/22 20:21:54  mike
   76  *      fix m_apm_exponent with exactly 0 as the input
   77  *
   78  *      Revision 1.10  2000/08/22 00:01:26  mike
   79  *      add zero check in is_integer
   80  *
   81  *      Revision 1.9  2000/08/21 23:34:44  mike
   82  *      add new function _is_integer
   83  *
   84  *      Revision 1.8  2000/08/01 22:29:02  mike
   85  *      add sizeof int function call
   86  *
   87  *      Revision 1.7  2000/05/19 16:21:03  mike
   88  *      delete M_check_dec_places, no longer needed
   89  *
   90  *      Revision 1.6  2000/04/04 17:06:37  mike
   91  *      initialize C++ refcount struct element to 1
   92  *
   93  *      Revision 1.5  2000/02/03 22:49:56  mike
   94  *      use MAPM_* generic memory function
   95  *
   96  *      Revision 1.4  1999/09/18 03:06:41  mike
   97  *      fix m_apm_exponent
   98  *
   99  *      Revision 1.3  1999/09/18 02:59:11  mike
  100  *      added new functions
  101  *
  102  *      Revision 1.2  1999/05/15 02:21:14  mike
  103  *      add check for number of decimal places
  104  *
  105  *      Revision 1.1  1999/05/10 20:56:31  mike
  106  *      Initial revision
  107  */
  108 
  109 #include "m_apm_lc.h"
  110 
  111 static  UCHAR   *M_mul_div = NULL;
  112 static  UCHAR   *M_mul_rem = NULL;
  113 
  114 static  UCHAR   M_mul_div_10[100];
  115 static  UCHAR   M_mul_rem_10[100];
  116 
  117 static  int M_util_firsttime = TRUE;
  118 static  int     M_firsttime3 = TRUE;
  119 
  120 static  M_APM   M_work_0_5;
  121 
  122 static  char    *M_init_error_msg = "\'m_apm_init\', Out of memory";
  123 
  124 /****************************************************************************/
  125 M_APM   m_apm_init()
  126 {
  127 M_APM   atmp;
  128 
  129 if (M_firsttime3)
  130   {
  131    M_firsttime3 = FALSE;
  132    M_init_util_data();
  133    M_init_trig_globals();
  134   }
  135 
  136 if ((atmp = (M_APM)MAPM_MALLOC(sizeof(M_APM_struct))) == NULL)
  137   {
  138    /* fatal, this does not return */
  139 
  140    M_apm_log_error_msg(M_APM_FATAL, M_init_error_msg);
  141   }
  142 
  143 atmp->m_apm_id           = M_APM_IDENT;
  144 atmp->m_apm_malloclength = 80;
  145 atmp->m_apm_datalength   = 1;
  146 atmp->m_apm_refcount     = 1;           /* not for us, for MAPM C++ class */
  147 atmp->m_apm_exponent     = 0;
  148 atmp->m_apm_sign         = 0;
  149 
  150 if ((atmp->m_apm_data = (UCHAR *)MAPM_MALLOC(84)) == NULL)
  151   {
  152    /* fatal, this does not return */
  153 
  154    M_apm_log_error_msg(M_APM_FATAL, M_init_error_msg);
  155   }
  156 
  157 atmp->m_apm_data[0] = 0;
  158 return(atmp);
  159 }
  160 /****************************************************************************/
  161 void    m_apm_free(M_APM atmp)
  162 {
  163 if (atmp->m_apm_id == M_APM_IDENT)
  164   {
  165    atmp->m_apm_id = 0x0FFFFFF0L;
  166    MAPM_FREE(atmp->m_apm_data);
  167    MAPM_FREE(atmp);
  168   }
  169 else
  170   {
  171    M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_free\', Invalid M_APM variable");
  172   }
  173 }
  174 /****************************************************************************/
  175 void    M_free_all_util()
  176 {
  177 if (M_util_firsttime == FALSE)
  178   {
  179    m_apm_free(M_work_0_5);
  180    M_util_firsttime = TRUE;
  181   }
  182 
  183 if (M_firsttime3 == FALSE)
  184   {
  185    MAPM_FREE(M_mul_div);
  186    MAPM_FREE(M_mul_rem);
  187   
  188    M_mul_div    = NULL;
  189    M_mul_rem    = NULL;
  190    M_firsttime3 = TRUE;
  191   }
  192 }
  193 /****************************************************************************/
  194 /*
  195  *      just a dummy wrapper to keep some compilers from complaining
  196  */
  197 int     M_get_sizeof_int()
  198 {
  199 return(sizeof(int));
  200 }
  201 /****************************************************************************/
  202 void    M_init_util_data()
  203 {
  204 int k;
  205 UCHAR   ndiv, nrem;
  206 
  207 if (M_mul_div != NULL)
  208   return;
  209 
  210 M_mul_div = (UCHAR *)MAPM_MALLOC(10000 * sizeof(UCHAR));
  211 M_mul_rem = (UCHAR *)MAPM_MALLOC(10000 * sizeof(UCHAR));
  212 
  213 if (M_mul_div == NULL || M_mul_rem == NULL)
  214   {
  215    /* fatal, this does not return */
  216 
  217    M_apm_log_error_msg(M_APM_FATAL, "\'M_init_util_data\', Out of memory");
  218   }
  219 
  220 ndiv = 0;
  221 nrem = 0;
  222 
  223 for (k=0; k < 100; k++)
  224   {
  225    M_mul_div_10[k] = ndiv;
  226    M_mul_rem_10[k] = nrem;
  227 
  228    if (++nrem == 10)
  229      {
  230       nrem = 0;
  231       ndiv++;
  232      }
  233   }
  234 
  235 ndiv = 0;
  236 nrem = 0;
  237 
  238 for (k=0; k < 10000; k++)
  239   {
  240    M_mul_div[k] = ndiv;
  241    M_mul_rem[k] = nrem;
  242 
  243    if (++nrem == 100)
  244      {
  245       nrem = 0;
  246       ndiv++;
  247      }
  248   }
  249 }
  250 /****************************************************************************/
  251 void    M_get_div_rem_addr(UCHAR **ndivp, UCHAR **nremp)
  252 {
  253 *ndivp = M_mul_div;
  254 *nremp = M_mul_rem;
  255 }
  256 /****************************************************************************/
  257 void    M_get_div_rem(int tbl_lookup, UCHAR *ndiv, UCHAR *nrem)
  258 {
  259 *ndiv = M_mul_div[tbl_lookup];
  260 *nrem = M_mul_rem[tbl_lookup];
  261 }
  262 /****************************************************************************/
  263 void    M_get_div_rem_10(int tbl_lookup, UCHAR *ndiv, UCHAR *nrem)
  264 {
  265 *ndiv = M_mul_div_10[tbl_lookup];
  266 *nrem = M_mul_rem_10[tbl_lookup];
  267 }
  268 /****************************************************************************/
  269 void    m_apm_round(M_APM btmp, int places, M_APM atmp) 
  270 {
  271 int ii;
  272 
  273 if (M_util_firsttime)
  274   {
  275    M_util_firsttime = FALSE;
  276 
  277    M_work_0_5 = m_apm_init();
  278    m_apm_set_string(M_work_0_5, "5");
  279   }
  280 
  281 ii = places + 1;
  282 
  283 if (atmp->m_apm_datalength <= ii)
  284   {
  285    m_apm_copy(btmp,atmp);
  286    return;
  287   }
  288 
  289 M_work_0_5->m_apm_exponent = atmp->m_apm_exponent - ii;
  290 
  291 if (atmp->m_apm_sign > 0)
  292   m_apm_add(btmp, atmp, M_work_0_5);
  293 else
  294   m_apm_subtract(btmp, atmp, M_work_0_5);
  295 
  296 btmp->m_apm_datalength = ii;
  297 M_apm_normalize(btmp);
  298 }
  299 /****************************************************************************/
  300 void    M_apm_normalize(M_APM atmp)
  301 {
  302 int i, index, datalength, exponent;
  303 UCHAR   *ucp, numdiv, numrem, numrem2;
  304 
  305 if (atmp->m_apm_sign == 0)
  306   return;
  307 
  308 datalength = atmp->m_apm_datalength;
  309 exponent   = atmp->m_apm_exponent;
  310 
  311 /* make sure trailing bytes/chars are 0                */
  312 /* the following function will adjust the 'datalength' */
  313 /* we want the original value and will fix it later    */
  314 
  315 M_apm_pad(atmp, (datalength + 3));
  316 
  317 while (TRUE)            /* remove lead-in '0' if any */
  318   {
  319    M_get_div_rem_10((int)atmp->m_apm_data[0], &numdiv, &numrem);
  320 
  321    if (numdiv >= 1)      /* number is normalized, done here */
  322      break;
  323 
  324    index = (datalength + 1) >> 1;
  325 
  326    if (numrem == 0)      /* both nibbles are 0, we can move full bytes */
  327      {
  328       i = 0;
  329       ucp = atmp->m_apm_data;
  330 
  331       while (TRUE)   /* find out how many '00' bytes we can move */
  332         {
  333      if (*ucp != 0)
  334        break;
  335 
  336          ucp++;
  337      i++;
  338     }
  339 
  340       memmove(atmp->m_apm_data, ucp, (index + 1 - i));
  341       datalength -= 2 * i;
  342       exponent -= 2 * i;
  343      }
  344    else
  345      {
  346       for (i=0; i < index; i++)
  347         {
  348          M_get_div_rem_10((int)atmp->m_apm_data[i+1], &numdiv, &numrem2);
  349          atmp->m_apm_data[i] = 10 * numrem + numdiv;
  350      numrem = numrem2;
  351         }
  352    
  353       datalength--;
  354       exponent--;
  355      }
  356   }
  357 
  358 while (TRUE)            /* remove trailing '0' if any */
  359   {
  360    index = ((datalength + 1) >> 1) - 1;
  361 
  362    if ((datalength & 1) == 0)   /* back-up full bytes at a time if the */
  363      {              /* current length is an even number    */
  364       ucp = atmp->m_apm_data + index;
  365       if (*ucp == 0)
  366         {
  367      while (TRUE)
  368        {
  369         datalength -= 2;
  370         index--;
  371         ucp--;
  372 
  373         if (*ucp != 0)
  374           break;
  375        }
  376     }
  377      }
  378 
  379    M_get_div_rem_10((int)atmp->m_apm_data[index], &numdiv, &numrem);
  380 
  381    if (numrem != 0)     /* last digit non-zero, all done */
  382      break;
  383 
  384    if ((datalength & 1) != 0)   /* if odd, then first char must be non-zero */
  385      {
  386       if (numdiv != 0)
  387         break;
  388      }
  389 
  390    if (datalength == 1)
  391      {
  392       atmp->m_apm_sign = 0;
  393       exponent = 0;
  394       break;
  395      }
  396      
  397    datalength--;
  398   }
  399 
  400 atmp->m_apm_datalength = datalength;
  401 atmp->m_apm_exponent   = exponent;
  402 }
  403 /****************************************************************************/
  404 void    M_apm_scale(M_APM ctmp, int count)
  405 {
  406 int ii, numb, ct;
  407 UCHAR   *chp, numdiv, numdiv2, numrem;
  408 void    *vp;
  409 
  410 ct = count;
  411 
  412 ii = (ctmp->m_apm_datalength + ct + 1) >> 1;
  413 if (ii > ctmp->m_apm_malloclength)
  414   {
  415    if ((vp = MAPM_REALLOC(ctmp->m_apm_data, (ii + 32))) == NULL)
  416      {
  417       /* fatal, this does not return */
  418 
  419       M_apm_log_error_msg(M_APM_FATAL, "\'M_apm_scale\', Out of memory");
  420      }
  421    
  422    ctmp->m_apm_malloclength = ii + 28;
  423    ctmp->m_apm_data = (UCHAR *)vp;
  424   }
  425 
  426 if ((ct & 1) != 0)          /* move odd number first */
  427   {
  428    ct--;
  429    chp = ctmp->m_apm_data;
  430    ii  = ((ctmp->m_apm_datalength + 1) >> 1) - 1;
  431 
  432    if ((ctmp->m_apm_datalength & 1) == 0)
  433      {
  434       /*
  435        *   original datalength is even:
  436        *
  437        *   uv  wx  yz   becomes  -->   0u  vw  xy  z0
  438        */
  439 
  440       numdiv = 0;
  441 
  442       while (TRUE)
  443         {
  444          M_get_div_rem_10((int)chp[ii], &numdiv2, &numrem);
  445 
  446      chp[ii + 1] = 10 * numrem + numdiv;
  447      numdiv = numdiv2;
  448 
  449      if (ii == 0)
  450        break;
  451 
  452          ii--;
  453     }
  454 
  455       chp[0] = numdiv2;
  456      }
  457    else
  458      {
  459       /*
  460        *   original datalength is odd:
  461        *
  462        *   uv  wx  y0   becomes  -->   0u  vw  xy
  463        */
  464 
  465       M_get_div_rem_10((int)chp[ii], &numdiv2, &numrem);
  466 
  467       if (ii == 0)
  468         {
  469          chp[0] = numdiv2;
  470         }
  471       else
  472         {
  473          while (TRUE)
  474            {
  475             M_get_div_rem_10((int)chp[ii - 1], &numdiv, &numrem);
  476 
  477         chp[ii] = 10 * numrem + numdiv2;
  478         numdiv2 = numdiv;
  479 
  480         if (--ii == 0)
  481           break;
  482        }
  483 
  484          chp[0] = numdiv;
  485         }
  486      }
  487 
  488    ctmp->m_apm_exponent++;
  489    ctmp->m_apm_datalength++;
  490   }
  491 
  492 /* ct is even here */
  493 
  494 if (ct > 0)
  495   {
  496    numb = (ctmp->m_apm_datalength + 1) >> 1;
  497    ii   = ct >> 1;
  498    
  499    memmove((ctmp->m_apm_data + ii), ctmp->m_apm_data, numb);
  500    memset(ctmp->m_apm_data, 0, ii);
  501    
  502    ctmp->m_apm_datalength += ct;
  503    ctmp->m_apm_exponent += ct;
  504   }
  505 }
  506 /****************************************************************************/
  507 void    M_apm_pad(M_APM ctmp, int new_length)
  508 {
  509 int num1, numb, ct;
  510 UCHAR   numdiv, numrem;
  511 void    *vp;
  512 
  513 ct = new_length;
  514 if (ctmp->m_apm_datalength >= ct)
  515   return;
  516   
  517 numb = (ct + 1) >> 1;
  518 if (numb > ctmp->m_apm_malloclength)
  519   {
  520    if ((vp = MAPM_REALLOC(ctmp->m_apm_data, (numb + 32))) == NULL)
  521      {
  522       /* fatal, this does not return */
  523 
  524       M_apm_log_error_msg(M_APM_FATAL, "\'M_apm_pad\', Out of memory");
  525      }
  526    
  527    ctmp->m_apm_malloclength = numb + 28;
  528    ctmp->m_apm_data = (UCHAR *)vp;
  529   }
  530 
  531 num1 = (ctmp->m_apm_datalength + 1) >> 1;
  532 
  533 if ((ctmp->m_apm_datalength & 1) != 0)
  534   {
  535    M_get_div_rem_10((int)ctmp->m_apm_data[num1 - 1], &numdiv, &numrem);
  536    ctmp->m_apm_data[num1 - 1] = 10 * numdiv;
  537   }
  538 
  539 memset((ctmp->m_apm_data + num1), 0, (numb - num1));
  540 ctmp->m_apm_datalength = ct;
  541 }
  542 /****************************************************************************/
  543 
  544 /*
  545       debug_dsp(cc)
  546       M_APM cc;
  547       {
  548 static char buffer[8192];
  549 
  550 m_apm_to_string(buffer, -1, cc);
  551 printf("(dsp func) = [%s]\n",buffer);
  552 
  553       }
  554 */
  555