~ubuntu-branches/ubuntu/karmic/libxfont/karmic

« back to all changes in this revision

Viewing changes to src/Type1/arith.c

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2007-07-18 16:46:59 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20070718164659-h894n91b3dynfwi2
Tags: 1:1.3.0-0ubuntu1
* New upstream release.
* debian/control:
  - Maintainer field updated
* debian/copyright:
  - Added packaging copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
113
113
The two multiplicands must be positive.
114
114
*/
115
115
 
116
 
void 
 
116
static void 
117
117
DLmult(doublelong *product, unsigned long u, unsigned long v)
118
118
{
119
119
#ifdef LONG64
157
157
}
158
158
 
159
159
/*
160
 
:h2.DLdiv() - Divide Two Longs by One Long, Yielding Two Longs
161
 
 
162
 
Both the dividend and the divisor must be positive.
163
 
*/
164
 
 
165
 
void 
166
 
DLdiv(doublelong *quotient,  /* also where dividend is, originally     */
167
 
      unsigned long divisor)
168
 
{
169
 
#ifdef LONG64
170
 
/* printf("DLdiv(%lx %lx)\n", quotient, divisor); */
171
 
        *quotient /= divisor;
172
 
/* printf("DLdiv returns %lx\n", *quotient); */
173
 
#else
174
 
       register unsigned long u1u2 = quotient->high;
175
 
       register unsigned long u3u4 = quotient->low;
176
 
       register long u3;     /* single digit of dividend                     */
177
 
       register int v1,v2;   /* divisor in registers                         */
178
 
       register long t;      /* signed copy of u1u2                          */
179
 
       register int qhat;    /* guess at the quotient digit                  */
180
 
       register unsigned long q3q4;  /* low two digits of quotient           */
181
 
       register int shift;   /* holds the shift value for normalizing        */
182
 
       register int j;       /* loop variable                                */
183
 
 
184
 
/* printf("DLdiv(%x %x, %x)\n", quotient->high, quotient->low, divisor); */
185
 
       /*
186
 
       * Knuth's algorithm works if the dividend is smaller than the
187
 
       * divisor.  We can get to that state quickly:
188
 
       */
189
 
       if (u1u2 >= divisor) {
190
 
               quotient->high = u1u2 / divisor;
191
 
               u1u2 %= divisor;
192
 
       }
193
 
       else
194
 
               quotient->high = 0;
195
 
 
196
 
       if (divisor <= MAXSHORT) {
197
 
 
198
 
               /*
199
 
               * This is the case where the divisor is contained in one
200
 
               * 'short'.  It is worthwhile making this fast:
201
 
               */
202
 
               u1u2 = ASSEMBLE(u1u2, HIGHDIGIT(u3u4));
203
 
               q3q4 = u1u2 / divisor;
204
 
               u1u2 %= divisor;
205
 
               u1u2 = ASSEMBLE(u1u2, LOWDIGIT(u3u4));
206
 
               quotient->low = ASSEMBLE(q3q4, u1u2 / divisor);
207
 
               return;
208
 
       }
209
 
 
210
 
 
211
 
       /*
212
 
       * At this point the divisor is a true 'long' so we must use
213
 
       * Knuth's algorithm.
214
 
       *
215
 
       * Step D1: Normalize divisor and dividend (this makes our 'qhat'
216
 
       *        guesses more accurate):
217
 
       */
218
 
       for (shift=0; !SIGNBITON(divisor); shift++, divisor <<= 1) { ; }
219
 
       shift--;
220
 
       divisor >>= 1;
221
 
 
222
 
       if ((u1u2 >> (LONGSIZE - shift)) != 0 && shift != 0)
223
 
               Abort("DLdiv:  dividend too large");
224
 
       u1u2 = (u1u2 << shift) + ((shift == 0) ? 0 : u3u4 >> (LONGSIZE - shift));
225
 
       u3u4 <<= shift;
226
 
 
227
 
       /*
228
 
       * Step D2:  Begin Loop through digits, dividing u1,u2,u3 by v1,v2,
229
 
       *           then shifting U left by 1 digit:
230
 
       */
231
 
       v1 = HIGHDIGIT(divisor);
232
 
       v2 = LOWDIGIT(divisor);
233
 
       q3q4 = 0;
234
 
       u3 = HIGHDIGIT(u3u4);
235
 
 
236
 
       for (j=0; j < 2; j++) {
237
 
 
238
 
               /*
239
 
               * Step D3:  make a guess (qhat) at the next quotient denominator:
240
 
               */
241
 
               qhat = (HIGHDIGIT(u1u2) == v1) ? MAXSHORT : u1u2 / v1;
242
 
               /*
243
 
               * At this point Knuth would have us further refine our
244
 
               * guess, since we know qhat is too big if
245
 
               *
246
 
               *      v2 * qhat > ASSEMBLE(u1u2 % v, u3)
247
 
               *
248
 
               * That would make sense if u1u2 % v was easy to find, as it
249
 
               * would be in assembly language.  I ignore this step, and
250
 
               * repeat step D6 if qhat is too big.
251
 
               */
252
 
 
253
 
               /*
254
 
               * Step D4: Multiply v1,v2 times qhat and subtract it from
255
 
               * u1,u2,u3:
256
 
               */
257
 
               u3 -= qhat * v2;
258
 
               /*
259
 
               * The high digit of u3 now contains the "borrow" for the
260
 
               * rest of the substraction from u1,u2.
261
 
               * Sometimes we can lose the sign bit with the above.
262
 
               * If so, we have to force the high digit negative:
263
 
               */
264
 
               t = HIGHDIGIT(u3);
265
 
               if (t > 0)
266
 
                       t |= -1 << SHORTSIZE;
267
 
               t += u1u2 - qhat * v1;
268
 
/* printf("..>divide step qhat=%x t=%x u3=%x u1u2=%x v1=%x v2=%x\n",
269
 
                             qhat, t, u3, u1u2, v1, v2); */
270
 
               while (t < 0) {  /* Test is Step D5.                          */
271
 
 
272
 
                       /*
273
 
                       * D6: Oops, qhat was too big.  Add back in v1,v2 and
274
 
                       * decrease qhat by 1:
275
 
                       */
276
 
                       u3 = LOWDIGIT(u3) + v2;
277
 
                       t += HIGHDIGIT(u3) + v1;
278
 
                       qhat--;
279
 
/* printf("..>>qhat correction t=%x u3=%x qhat=%x\n", t, u3, qhat); */
280
 
               }
281
 
               /*
282
 
               * Step D7:  shift U left one digit and loop:
283
 
               */
284
 
               u1u2 = t;
285
 
               if (HIGHDIGIT(u1u2) != 0)
286
 
                       Abort("divide algorithm error");
287
 
               u1u2 = ASSEMBLE(u1u2, LOWDIGIT(u3));
288
 
               u3 = LOWDIGIT(u3u4);
289
 
               q3q4 = ASSEMBLE(q3q4, qhat);
290
 
       }
291
 
       quotient->low = q3q4;
292
 
/* printf("DLdiv returns %x %x\n", quotient->high, quotient->low); */
293
 
#endif /* !LONG64 */
294
 
       return;
295
 
}
296
 
 
297
 
/*
298
 
:h3.DLadd() - Add Two Double Longs
299
 
 
300
 
In this case, the doublelongs may be signed.  The algorithm takes the
301
 
piecewise sum of the high and low longs, with the possibility that the
302
 
high should be incremented if there is a carry out of the low.  How to
303
 
tell if there is a carry?  Alex Harbury suggested that if the sum of
304
 
the lows is less than the max of the lows, there must have been a
305
 
carry.  Conversely, if there was a carry, the sum of the lows must be
306
 
less than the max of the lows.  So, the test is "if and only if".
307
 
*/
308
 
 
309
 
void 
310
 
DLadd(doublelong *u, /* u = u + v                                    */
311
 
      doublelong *v)
312
 
{
313
 
#ifdef LONG64
314
 
/* printf("DLadd(%lx %lx)\n", *u, *v); */
315
 
       *u = *u + *v;
316
 
/* printf("DLadd returns %lx\n", *u); */
317
 
#else
318
 
       register unsigned long lowmax = MAX(u->low, v->low);
319
 
 
320
 
/* printf("DLadd(%x %x, %x %x)\n", u->high, u->low, v->high, v->low); */
321
 
       u->high += v->high;
322
 
       u->low += v->low;
323
 
       if (lowmax > u->low)
324
 
               u->high++;
325
 
#endif
326
 
}
327
 
/*
328
 
:h3.DLsub() - Subtract Two Double Longs
329
 
 
330
 
Testing for a borrow is even easier.  If the v.low is greater than
331
 
u.low, there must be a borrow.
332
 
*/
333
 
 
334
 
void 
335
 
DLsub(doublelong *u, /* u = u - v                                    */
336
 
      doublelong *v)
337
 
{
338
 
#ifdef LONG64
339
 
/* printf("DLsub(%lx %lx)\n", *u, *v); */
340
 
       *u = *u - *v;
341
 
/* printf("DLsub returns %lx\n", *u); */
342
 
#else
343
 
/* printf("DLsub(%x %x, %x %x)\n", u->high, u->low, v->high, v->low);*/
344
 
       u->high -= v->high;
345
 
       if (v->low > u->low)
346
 
               u->high--;
347
 
       u->low -= v->low;
348
 
#endif
349
 
}
350
 
/*
351
160
:h3.DLrightshift() - Macro to Shift Double Long Right by N
352
161
*/
353
162
 
401
210
  return ((negative) ? -ret : ret);
402
211
#endif
403
212
}
404
 
 
405
 
/*
406
 
:h3.FPdiv() - Divide Two Fractional Pel Values
407
 
 
408
 
These values may be signed.  The function returns the quotient.
409
 
*/
410
 
 
411
 
fractpel 
412
 
FPdiv(fractpel dividend, fractpel divisor)
413
 
{
414
 
       doublelong w;         /* result will be built here                    */
415
 
       int negative = FALSE; /* flag for sign bit                            */
416
 
#ifdef LONG64
417
 
       register fractpel ret;
418
 
#endif
419
 
 
420
 
       if (dividend < 0) {
421
 
               dividend = -dividend;
422
 
               negative = TRUE;
423
 
       }
424
 
       if (divisor < 0) {
425
 
               divisor = -divisor;
426
 
               negative = !negative;
427
 
       }
428
 
#ifndef LONG64
429
 
       w.low = dividend << FRACTBITS;
430
 
       w.high = dividend >> (LONGSIZE - FRACTBITS);
431
 
       DLdiv(&w, divisor);
432
 
       if (w.high != 0 || SIGNBITON(w.low)) {
433
 
               w.low = TOFRACTPEL(MAXSHORT);
434
 
       }
435
 
       return( (negative) ? -w.low : w.low);
436
 
#else
437
 
       w = ((long)dividend) << FRACTBITS;
438
 
       DLdiv(&w, divisor);
439
 
       if (w & 0xffffffff80000000L ) {
440
 
               ret = TOFRACTPEL(MAXSHORT);
441
 
       }
442
 
       else
443
 
               ret = (fractpel)w;
444
 
       return( (negative) ? -ret : ret);
445
 
#endif
446
 
}
447
 
 
448
 
/*
449
 
:h3.FPstarslash() - Multiply then Divide
450
 
 
451
 
Borrowing a chapter from the language Forth, it is useful to define
452
 
an operator that first multiplies by one constant then divides by
453
 
another, keeping the intermediate result in extended precision.
454
 
*/
455
 
 
456
 
fractpel 
457
 
FPstarslash(fractpel a,   /* result = a * b / c                              */
458
 
            fractpel b, 
459
 
            fractpel c)
460
 
{
461
 
       doublelong w;         /* result will be built here                    */
462
 
       int negative = FALSE;
463
 
#ifdef LONG64
464
 
       register fractpel ret;
465
 
#endif
466
 
 
467
 
       if (a < 0) { a = -a; negative = TRUE; }
468
 
       if (b < 0) { b = -b; negative = !negative; }
469
 
       if (c < 0) { c = -c; negative = !negative; }
470
 
 
471
 
       DLmult(&w, a, b);
472
 
       DLdiv(&w, c);
473
 
#ifndef LONG64
474
 
       if (w.high != 0 || SIGNBITON(w.low)) {
475
 
               w.low = TOFRACTPEL(MAXSHORT);
476
 
       }
477
 
       return((negative) ? -w.low : w.low);
478
 
#else
479
 
       if (w & 0xffffffff80000000L ) {
480
 
               ret = TOFRACTPEL(MAXSHORT);
481
 
       }
482
 
       else
483
 
               ret = (fractpel)w;
484
 
       return( (negative) ? -ret : ret);
485
 
#endif
486
 
}