1
2/*
3 *  M_APM  -  mapmutl2.c
4 *
5 *  Copyright (C) 2002 - 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: mapmutl2.c,v 1.7 2007/12/03 02:00:04 mike Exp $
23 *
24 *      This file contains various utility functions
25 *
26 *      $Log: mapmutl2.c,v $
27 *      Revision 1.7  2007/12/03 02:00:04  mike
28 *      Update license
29 *
30 *      Revision 1.6  2003/07/21 20:53:10  mike
31 *      Modify error messages to be in a consistent format.
32 *
33 *      Revision 1.5  2003/05/04 18:14:32  mike
34 *      move generic error handling function into a dedicated module
35 *
36 *      Revision 1.4  2003/03/31 22:02:22  mike
37 *      call generic error handling function
38 *
39 *      Revision 1.3  2002/11/03 21:19:40  mike
40 *      Updated function parameters to use the modern style
41 *
42 *      Revision 1.2  2002/05/17 22:29:46  mike
43 *      update some comments
44 *
45 *      Revision 1.1  2002/05/17 22:28:27  mike
46 *      Initial revision
47 */
48
49#include "m_apm_lc.h"
50
51/****************************************************************************/
52int	m_apm_sign(M_APM atmp)
53{
54return(atmp->m_apm_sign);
55}
56/****************************************************************************/
57int	m_apm_exponent(M_APM atmp)
58{
59if (atmp->m_apm_sign == 0)
60  return(0);
61else
62  return(atmp->m_apm_exponent - 1);
63}
64/****************************************************************************/
65int	m_apm_significant_digits(M_APM atmp)
66{
67return(atmp->m_apm_datalength);
68}
69/****************************************************************************/
70int	m_apm_is_integer(M_APM atmp)
71{
72if (atmp->m_apm_sign == 0)
73  return(1);
74
75if (atmp->m_apm_exponent >= atmp->m_apm_datalength)
76  return(1);
77else
78  return(0);
79}
80/****************************************************************************/
81int 	m_apm_is_even(M_APM aa)
82{
83int     ii, jj;
84
85if (aa->m_apm_sign == 0)
86  return(1);
87
88ii = aa->m_apm_datalength;
89jj = aa->m_apm_exponent;
90
91if (jj < ii)
92  {
93   M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_is_even\', Non-integer input");
94   return(0);
95  }
96
97if (jj > ii)
98  return(1);
99
100ii = ((ii + 1) >> 1) - 1;
101ii = (int)aa->m_apm_data[ii];
102
103if ((jj & 1) != 0)      /* exponent is odd */
104  ii = ii / 10;
105
106if ((ii & 1) == 0)
107  return(1);
108else
109  return(0);
110}
111/****************************************************************************/
112int 	m_apm_is_odd(M_APM bb)
113{
114if (m_apm_is_even(bb))
115  return(0);
116else
117  return(1);
118}
119/****************************************************************************/
120void	M_set_to_zero(M_APM z)
121{
122z->m_apm_datalength = 1;
123z->m_apm_sign       = 0;
124z->m_apm_exponent   = 0;
125z->m_apm_data[0]    = 0;
126}
127/****************************************************************************/
128void	m_apm_negate(M_APM d, M_APM s)
129{
130m_apm_copy(d,s);
131if (d->m_apm_sign != 0)
132    d->m_apm_sign = -(d->m_apm_sign);
133}
134/****************************************************************************/
135void	m_apm_absolute_value(M_APM d, M_APM s)
136{
137m_apm_copy(d,s);
138if (d->m_apm_sign != 0)
139    d->m_apm_sign = 1;
140}
141/****************************************************************************/
142void	m_apm_copy(M_APM dest, M_APM src)
143{
144int	j;
145void	*vp;
146
147j = (src->m_apm_datalength + 1) >> 1;
148if (j > dest->m_apm_malloclength)
149  {
150   if ((vp = MAPM_REALLOC(dest->m_apm_data, (j + 32))) == NULL)
151     {
152      /* fatal, this does not return */
153
154      M_apm_log_error_msg(M_APM_FATAL, "\'m_apm_copy\', Out of memory");
155     }
156
157   dest->m_apm_malloclength = j + 28;
158   dest->m_apm_data = (UCHAR *)vp;
159  }
160
161dest->m_apm_datalength = src->m_apm_datalength;
162dest->m_apm_exponent   = src->m_apm_exponent;
163dest->m_apm_sign       = src->m_apm_sign;
164
165memcpy(dest->m_apm_data, src->m_apm_data, j);
166}
167/****************************************************************************/
168int	m_apm_compare(M_APM ltmp, M_APM rtmp)
169{
170int	llen, rlen, lsign, rsign, i, j, lexp, rexp;
171
172llen  = ltmp->m_apm_datalength;
173rlen  = rtmp->m_apm_datalength;
174
175lsign = ltmp->m_apm_sign;
176rsign = rtmp->m_apm_sign;
177
178lexp  = ltmp->m_apm_exponent;
179rexp  = rtmp->m_apm_exponent;
180
181if (rsign == 0)
182  return(lsign);
183
184if (lsign == 0)
185  return(-rsign);
186
187if (lsign == -rsign)
188  return(lsign);
189
190/* signs are the same, check the exponents */
191
192if (lexp > rexp)
193  goto E1;
194
195if (lexp < rexp)
196  goto E2;
197
198/* signs and exponents are the same, check the data */
199
200if (llen < rlen)
201  j = (llen + 1) >> 1;
202else
203  j = (rlen + 1) >> 1;
204
205for (i=0; i < j; i++)
206  {
207   if (ltmp->m_apm_data[i] > rtmp->m_apm_data[i])
208     goto E1;
209
210   if (ltmp->m_apm_data[i] < rtmp->m_apm_data[i])
211     goto E2;
212  }
213
214if (llen == rlen)
215   return(0);
216else
217  {
218   if (llen > rlen)
219     goto E1;
220   else
221     goto E2;
222  }
223
224E1:
225
226if (lsign == 1)
227  return(1);
228else
229  return(-1);
230
231E2:
232
233if (lsign == 1)
234  return(-1);
235else
236  return(1);
237}
238/****************************************************************************/
239/*
240 *
241 *	convert a signed long int to ASCII in base 10
242 *
243 */
244void    M_long_2_ascii(char *output, long input)
245{
246long    t, m;
247int     i, j;
248char    *p, tbuf[64];
249
250m = input;
251p = output;
252i = 0;
253t = 2147000000L;          /* something < 2^31 */
254
255if ((m > t) || (m < -t))  /* handle the bigger numbers with 'sprintf'. */
256  {			  /* let them worry about wrap-around problems */
257   sprintf(p, "%ld", m);  /* at 'LONG_MIN', etc.                       */
258  }
259else
260  {
261   if (m < 0)             /* handle the sign */
262     {
263      *p++ = '-';
264      m = -m;
265     }
266
267   while (TRUE)           /* build the digits in reverse order */
268     {
269      t = m / 10;
270      j = (int)(m - (10 * t));
271      tbuf[i++] = (char)(j + '0');
272      m = t;
273
274      if (t == 0)
275        break;
276     }
277
278   while (TRUE)           /* fill output string in the correct order */
279     {
280      *p++ = tbuf[--i];
281      if (i == 0)
282        break;
283     }
284
285   *p = '\0';
286  }
287}
288/****************************************************************************/
289/*
290 *      this function will convert a string to lowercase
291 */
292char    *M_lowercase(char *s)
293{
294char    *p;
295
296p = s;
297
298while (TRUE)
299  {
300   if (*p >= 'A' && *p <= 'Z')
301     *p += 'a' - 'A';
302
303   if (*p++ == '\0')  break;
304  }
305return(s);
306}
307/****************************************************************************/
308/*    returns char position of first occurence of s2 in s1
309	  or -1 if no match found
310*/
311int     M_strposition(char *s1, char *s2)
312{
313register char  ch1, ch2;
314char           *p0, *p1, *p2;
315int            ct;
316
317ct = -1;
318p0 = s1;
319
320if (*s2 == '\0')  return(-1);
321
322while (TRUE)
323  {
324   ct++;
325   p1  = p0;
326   p2  = s2;
327   ch2 = *p2;
328
329   while (TRUE)                    /* scan until first char matches */
330     {
331      if ((ch1 = *p1) == '\0')  return(-1);
332      if (ch1 == ch2)           break;
333      p1++;
334      ct++;
335     }
336
337   p2++;                           /* check remainder of 2 strings */
338   p1++;
339   p0 = p1;
340
341   while (TRUE)
342     {
343      if ((ch2 = *p2) == '\0')  return(ct);
344      if (*p1 != ch2)           break;
345      p1++;
346      p2++;
347     }
348  }
349}
350/****************************************************************************/
351