~ubuntu-branches/debian/sid/pgadmin3/sid

« back to all changes in this revision

Viewing changes to pgadmin/pgscript/utilities/m_apm/mapm_div.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gerfried Fuchs
  • Date: 2009-07-30 12:27:16 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730122716-fddbh42on721bbs2
Tags: 1.10.0-1
* New upstream release.
* Adjusted watch file to match release candidates.
* Updated to Standards-Version 3.8.2:
  - Moved to Section: database.
  - Add DEB_BUILD_OPTIONS support for parallel building.
  - Move from findstring to filter suggestion for DEB_BUILD_OPTIONS parsing.
* pgagent got split into its own separate source package by upstream.
* Exclude Docs.vcproj from installation.
* Move doc-base.enus from pgadmin3 to pgadmin3-data package, the files are
  in there too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* 
 
3
 *  M_APM  -  mapm_div.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
 *
 
23
 *      This file contains the basic division functions 
 
24
 *
 
25
 */
 
26
 
 
27
#include "pgAdmin3.h"
 
28
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
 
29
 
 
30
static  M_APM   M_div_worka;
 
31
static  M_APM   M_div_workb;
 
32
static  M_APM   M_div_tmp7;
 
33
static  M_APM   M_div_tmp8;
 
34
static  M_APM   M_div_tmp9;
 
35
 
 
36
static  int     M_div_firsttime = TRUE;
 
37
 
 
38
/****************************************************************************/
 
39
void    M_free_all_div()
 
40
{
 
41
if (M_div_firsttime == FALSE)
 
42
  {
 
43
   m_apm_free(M_div_worka);
 
44
   m_apm_free(M_div_workb);
 
45
   m_apm_free(M_div_tmp7);
 
46
   m_apm_free(M_div_tmp8);
 
47
   m_apm_free(M_div_tmp9);
 
48
 
 
49
   M_div_firsttime = TRUE;
 
50
  }
 
51
}
 
52
/****************************************************************************/
 
53
void    m_apm_integer_div_rem(M_APM qq, M_APM rr, M_APM aa, M_APM bb)
 
54
{
 
55
m_apm_integer_divide(qq, aa, bb);
 
56
m_apm_multiply(M_div_tmp7, qq, bb);
 
57
m_apm_subtract(rr, aa, M_div_tmp7);
 
58
}
 
59
/****************************************************************************/
 
60
void    m_apm_integer_divide(M_APM rr, M_APM aa, M_APM bb)
 
61
{
 
62
/*
 
63
 *    we must use this divide function since the 
 
64
 *    faster divide function using the reciprocal
 
65
 *    will round the result (possibly changing 
 
66
 *    nnm.999999...  -->  nn(m+1).0000 which would 
 
67
 *    invalidate the 'integer_divide' goal).
 
68
 */
 
69
 
 
70
M_apm_sdivide(rr, 4, aa, bb);
 
71
 
 
72
if (rr->m_apm_exponent <= 0)        /* result is 0 */
 
73
  {
 
74
   M_set_to_zero(rr);
 
75
  }
 
76
else
 
77
  {
 
78
   if (rr->m_apm_datalength > rr->m_apm_exponent)
 
79
     {
 
80
      rr->m_apm_datalength = rr->m_apm_exponent;
 
81
      M_apm_normalize(rr);
 
82
     }
 
83
  }
 
84
}
 
85
/****************************************************************************/
 
86
void    M_apm_sdivide(M_APM r, int places, M_APM a, M_APM b)
 
87
{
 
88
int     j, k, m, b0, sign, nexp, indexr, icompare, iterations;
 
89
long    trial_numer;
 
90
void    *vp;
 
91
 
 
92
if (M_div_firsttime)
 
93
  {
 
94
   M_div_firsttime = FALSE;
 
95
 
 
96
   M_div_worka = m_apm_init();
 
97
   M_div_workb = m_apm_init();
 
98
   M_div_tmp7  = m_apm_init();
 
99
   M_div_tmp8  = m_apm_init();
 
100
   M_div_tmp9  = m_apm_init();
 
101
  }
 
102
 
 
103
sign = a->m_apm_sign * b->m_apm_sign;
 
104
 
 
105
if (sign == 0)      /* one number is zero, result is zero */
 
106
  {
 
107
   if (b->m_apm_sign == 0)
 
108
     {
 
109
      M_apm_log_error_msg(M_APM_RETURN, "\'M_apm_sdivide\', Divide by 0");
 
110
     }
 
111
 
 
112
   M_set_to_zero(r);
 
113
   return;
 
114
  }
 
115
 
 
116
/*
 
117
 *  Knuth step D1. Since base = 100, base / 2 = 50.
 
118
 *  (also make the working copies positive)
 
119
 */
 
120
 
 
121
if (b->m_apm_data[0] >= 50)
 
122
  {
 
123
   m_apm_absolute_value(M_div_worka, a);
 
124
   m_apm_absolute_value(M_div_workb, b);
 
125
  }
 
126
else       /* 'normal' step D1 */
 
127
  {
 
128
   k = 100 / (b->m_apm_data[0] + 1);
 
129
   m_apm_set_long(M_div_tmp9, (long)k);
 
130
 
 
131
   m_apm_multiply(M_div_worka, M_div_tmp9, a);
 
132
   m_apm_multiply(M_div_workb, M_div_tmp9, b);
 
133
 
 
134
   M_div_worka->m_apm_sign = 1;
 
135
   M_div_workb->m_apm_sign = 1;
 
136
  }
 
137
 
 
138
/* setup trial denominator for step D3 */
 
139
 
 
140
b0 = 100 * (int)M_div_workb->m_apm_data[0];
 
141
 
 
142
if (M_div_workb->m_apm_datalength >= 3)
 
143
  b0 += M_div_workb->m_apm_data[1];
 
144
 
 
145
nexp = M_div_worka->m_apm_exponent - M_div_workb->m_apm_exponent;
 
146
 
 
147
if (nexp > 0)
 
148
  iterations = nexp + places + 1;
 
149
else
 
150
  iterations = places + 1;
 
151
 
 
152
k = (iterations + 1) >> 1;     /* required size of result, in bytes */
 
153
 
 
154
if (k > r->m_apm_malloclength)
 
155
  {
 
156
   if ((vp = MAPM_REALLOC(r->m_apm_data, (k + 32))) == NULL)
 
157
     {
 
158
      /* fatal, this does not return */
 
159
 
 
160
      M_apm_log_error_msg(M_APM_FATAL, "\'M_apm_sdivide\', Out of memory");
 
161
     }
 
162
  
 
163
   r->m_apm_malloclength = k + 28;
 
164
   r->m_apm_data = (UCHAR *)vp;
 
165
  }
 
166
 
 
167
/* clear the exponent in the working copies */
 
168
 
 
169
M_div_worka->m_apm_exponent = 0;
 
170
M_div_workb->m_apm_exponent = 0;
 
171
 
 
172
/* if numbers are equal, ratio == 1.00000... */
 
173
 
 
174
if ((icompare = m_apm_compare(M_div_worka, M_div_workb)) == 0)
 
175
  {
 
176
   iterations = 1;
 
177
   r->m_apm_data[0] = 10;
 
178
   nexp++;
 
179
  }
 
180
else                               /* ratio not 1, do the real division */
 
181
  {
 
182
   if (icompare == 1)                        /* numerator > denominator */
 
183
     {
 
184
      nexp++;                           /* to adjust the final exponent */
 
185
      M_div_worka->m_apm_exponent += 1;     /* multiply numerator by 10 */
 
186
     }
 
187
   else                                      /* numerator < denominator */
 
188
     {
 
189
      M_div_worka->m_apm_exponent += 2;    /* multiply numerator by 100 */
 
190
     }
 
191
 
 
192
   indexr = 0;
 
193
   m      = 0;
 
194
 
 
195
   while (TRUE)
 
196
     {
 
197
      /*
 
198
       *  Knuth step D3. Only use the 3rd -> 6th digits if the number
 
199
       *  actually has that many digits.
 
200
       */
 
201
 
 
202
      trial_numer = 10000L * (long)M_div_worka->m_apm_data[0];
 
203
      
 
204
      if (M_div_worka->m_apm_datalength >= 5)
 
205
        {
 
206
         trial_numer += 100 * M_div_worka->m_apm_data[1]
 
207
                            + M_div_worka->m_apm_data[2];
 
208
        }
 
209
      else
 
210
        {
 
211
         if (M_div_worka->m_apm_datalength >= 3)
 
212
           trial_numer += 100 * M_div_worka->m_apm_data[1];
 
213
        }
 
214
 
 
215
      j = (int)(trial_numer / b0);
 
216
 
 
217
      /* 
 
218
       *    Since the library 'normalizes' all the results, we need
 
219
       *    to look at the exponent of the number to decide if we 
 
220
       *    have a lead in 0n or 00.
 
221
       */
 
222
 
 
223
      if ((k = 2 - M_div_worka->m_apm_exponent) > 0)
 
224
        {
 
225
         while (TRUE)
 
226
           {
 
227
            j /= 10;
 
228
            if (--k == 0)
 
229
              break;
 
230
           }
 
231
        }
 
232
 
 
233
      if (j == 100)     /* qhat == base ??      */
 
234
        j = 99;         /* if so, decrease by 1 */
 
235
 
 
236
      m_apm_set_long(M_div_tmp8, (long)j);
 
237
      m_apm_multiply(M_div_tmp7, M_div_tmp8, M_div_workb);
 
238
 
 
239
      /*
 
240
       *    Compare our q-hat (j) against the desired number.
 
241
       *    j is either correct, 1 too large, or 2 too large
 
242
       *    per Theorem B on pg 272 of Art of Compter Programming,
 
243
       *    Volume 2, 3rd Edition.
 
244
       *    
 
245
       *    The above statement is only true if using the 2 leading
 
246
       *    digits of the numerator and the leading digit of the 
 
247
       *    denominator. Since we are using the (3) leading digits
 
248
       *    of the numerator and the (2) leading digits of the 
 
249
       *    denominator, we eliminate the case where our q-hat is 
 
250
       *    2 too large, (and q-hat being 1 too large is quite remote).
 
251
       */
 
252
 
 
253
      if (m_apm_compare(M_div_tmp7, M_div_worka) == 1)
 
254
        {
 
255
         j--;
 
256
         m_apm_subtract(M_div_tmp8, M_div_tmp7, M_div_workb);
 
257
         m_apm_copy(M_div_tmp7, M_div_tmp8);
 
258
        }
 
259
 
 
260
      /* 
 
261
       *  Since we know q-hat is correct, step D6 is unnecessary.
 
262
       *
 
263
       *  Store q-hat, step D5. Since D6 is unnecessary, we can 
 
264
       *  do D5 before D4 and decide if we are done.
 
265
       */
 
266
 
 
267
      r->m_apm_data[indexr++] = (UCHAR)j;    /* j == 'qhat' */
 
268
      m += 2;
 
269
 
 
270
      if (m >= iterations)
 
271
        break;
 
272
 
 
273
      /* step D4 */
 
274
 
 
275
      m_apm_subtract(M_div_tmp9, M_div_worka, M_div_tmp7);
 
276
 
 
277
      /*
 
278
       *  if the subtraction yields zero, the division is exact
 
279
       *  and we are done early.
 
280
       */
 
281
 
 
282
      if (M_div_tmp9->m_apm_sign == 0)
 
283
        {
 
284
         iterations = m;
 
285
         break;
 
286
        }
 
287
 
 
288
      /* multiply by 100 and re-save */
 
289
      M_div_tmp9->m_apm_exponent += 2;
 
290
      m_apm_copy(M_div_worka, M_div_tmp9);
 
291
     }
 
292
  }
 
293
 
 
294
r->m_apm_sign       = sign;
 
295
r->m_apm_exponent   = nexp;
 
296
r->m_apm_datalength = iterations;
 
297
 
 
298
M_apm_normalize(r);
 
299
}
 
300
/****************************************************************************/