5
* Copyright (C) 1999 - 2007 Michael C. Ring
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.
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.
18
* This software is provided "as is" without express or implied warranty.
23
* This file contains the functions that implement the sin (5x)
24
* and cos (4x) multiple angle relations
29
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
31
static M_APM M_work1 = NULL;
32
static M_APM M_work2 = NULL;
33
static int M_add_firsttime = TRUE;
35
/****************************************************************************/
38
if (M_add_firsttime == FALSE)
42
M_add_firsttime = TRUE;
45
/****************************************************************************/
46
void m_apm_add(M_APM r, M_APM a, M_APM b)
48
int j, carry, sign, aexp, bexp, adigits, bdigits;
52
M_add_firsttime = FALSE;
53
M_work1 = m_apm_init();
54
M_work2 = m_apm_init();
57
if (a->m_apm_sign == 0)
63
if (b->m_apm_sign == 0)
69
if (a->m_apm_sign == 1 && b->m_apm_sign == -1)
72
m_apm_subtract(r,a,b);
77
if (a->m_apm_sign == -1 && b->m_apm_sign == 1)
80
m_apm_subtract(r,b,a);
85
sign = a->m_apm_sign; /* signs are the same, result will be same */
87
aexp = a->m_apm_exponent;
88
bexp = b->m_apm_exponent;
90
m_apm_copy(M_work1, a);
91
m_apm_copy(M_work2, b);
94
* scale by at least 1 factor of 10 in case the MSB carrys
99
M_apm_scale(M_work1, 2); /* shift 2 digits == 1 byte for efficiency */
100
M_apm_scale(M_work2, 2);
106
M_apm_scale(M_work1, 2);
107
M_apm_scale(M_work2, (aexp + 2 - bexp));
109
else /* aexp < bexp */
111
M_apm_scale(M_work2, 2);
112
M_apm_scale(M_work1, (bexp + 2 - aexp));
116
adigits = M_work1->m_apm_datalength;
117
bdigits = M_work2->m_apm_datalength;
119
if (adigits >= bdigits)
121
m_apm_copy(r, M_work1);
122
j = (bdigits + 1) >> 1;
128
r->m_apm_data[j] += carry + M_work2->m_apm_data[j];
130
if (r->m_apm_data[j] >= 100)
132
r->m_apm_data[j] -= 100;
144
m_apm_copy(r, M_work2);
145
j = (adigits + 1) >> 1;
151
r->m_apm_data[j] += carry + M_work1->m_apm_data[j];
153
if (r->m_apm_data[j] >= 100)
155
r->m_apm_data[j] -= 100;
166
r->m_apm_sign = sign;
170
/****************************************************************************/
171
void m_apm_subtract(M_APM r, M_APM a, M_APM b)
173
int itmp, j, flag, icompare, sign, aexp, bexp,
174
borrow, adigits, bdigits;
178
M_add_firsttime = FALSE;
179
M_work1 = m_apm_init();
180
M_work2 = m_apm_init();
183
if (b->m_apm_sign == 0)
189
if (a->m_apm_sign == 0)
192
r->m_apm_sign = -(r->m_apm_sign);
196
if (a->m_apm_sign == 1 && b->m_apm_sign == -1)
204
if (a->m_apm_sign == -1 && b->m_apm_sign == 1)
212
/* now, the signs are the same */
213
/* make a positive working copy */
215
m_apm_absolute_value(M_work1, a);
216
m_apm_absolute_value(M_work2, b);
218
/* are they the same?? if so, the result is zero */
220
if ((icompare = m_apm_compare(M_work1, M_work2)) == 0)
226
if (icompare == 1) /* |a| > |b| (do A-B) */
229
sign = a->m_apm_sign;
231
else /* |b| > |a| (do B-A) */
234
sign = -(a->m_apm_sign);
237
aexp = M_work1->m_apm_exponent;
238
bexp = M_work2->m_apm_exponent;
241
M_apm_scale(M_work2, (aexp - bexp));
244
M_apm_scale(M_work1, (bexp - aexp));
246
adigits = M_work1->m_apm_datalength;
247
bdigits = M_work2->m_apm_datalength;
249
if (adigits > bdigits)
250
M_apm_pad(M_work2, adigits);
252
if (adigits < bdigits)
253
M_apm_pad(M_work1, bdigits);
255
if (flag) /* perform A-B, M_work1 - M_work2 */
257
m_apm_copy(r, M_work1);
258
j = (r->m_apm_datalength + 1) >> 1;
264
itmp = (int)r->m_apm_data[j] - ((int)M_work2->m_apm_data[j] + borrow);
268
r->m_apm_data[j] = (UCHAR)itmp;
273
r->m_apm_data[j] = (UCHAR)(100 + itmp);
281
else /* perform B-A, M_work2 - M_work1 */
283
m_apm_copy(r, M_work2);
284
j = (r->m_apm_datalength + 1) >> 1;
290
itmp = (int)r->m_apm_data[j] - ((int)M_work1->m_apm_data[j] + borrow);
294
r->m_apm_data[j] = (UCHAR)itmp;
299
r->m_apm_data[j] = (UCHAR)(100 + itmp);
308
r->m_apm_sign = sign;
312
/****************************************************************************/
316
MAPM operator+(const MAPM &a,const MAPM &b)
317
{MAPM ret;m_apm_add(ret.val(),a.cval(),b.cval());return ret;}
318
MAPM operator-(const MAPM &a,const MAPM &b)
319
{MAPM ret;m_apm_subtract(ret.val(),a.cval(),b.cval());return ret;}