| [117] | 1 | /* +++Date last modified: 05-Jul-1997 */ | 
|---|
 | 2 |  | 
|---|
 | 3 | #include <string.h> | 
|---|
 | 4 | #include "basicmath-snipmath.h" | 
|---|
 | 5 |  | 
|---|
 | 6 | #define BITSPERLONG 32 | 
|---|
 | 7 |  | 
|---|
 | 8 | #define TOP2BITS(x) ((x & (3L << (BITSPERLONG-2))) >> (BITSPERLONG-2)) | 
|---|
 | 9 |  | 
|---|
 | 10 |  | 
|---|
 | 11 | /* usqrt: | 
|---|
 | 12 |     ENTRY x: unsigned long | 
|---|
 | 13 |     EXIT  returns floor(sqrt(x) * pow(2, BITSPERLONG/2)) | 
|---|
 | 14 |  | 
|---|
 | 15 |     Since the square root never uses more than half the bits | 
|---|
 | 16 |     of the input, we use the other half of the bits to contain | 
|---|
 | 17 |     extra bits of precision after the binary point. | 
|---|
 | 18 |  | 
|---|
 | 19 |     EXAMPLE | 
|---|
 | 20 |         suppose BITSPERLONG = 32 | 
|---|
 | 21 |         then    usqrt(144) = 786432 = 12 * 65536 | 
|---|
 | 22 |                 usqrt(32) = 370727 = 5.66 * 65536 | 
|---|
 | 23 |  | 
|---|
 | 24 |     NOTES | 
|---|
 | 25 |         (1) change BITSPERLONG to BITSPERLONG/2 if you do not want | 
|---|
 | 26 |             the answer scaled.  Indeed, if you want n bits of | 
|---|
 | 27 |             precision after the binary point, use BITSPERLONG/2+n. | 
|---|
 | 28 |             The code assumes that BITSPERLONG is even. | 
|---|
 | 29 |         (2) This is really better off being written in assembly. | 
|---|
 | 30 |             The line marked below is really a "arithmetic shift left" | 
|---|
 | 31 |             on the double-long value with r in the upper half | 
|---|
 | 32 |             and x in the lower half.  This operation is typically | 
|---|
 | 33 |             expressible in only one or two assembly instructions. | 
|---|
 | 34 |         (3) Unrolling this loop is probably not a bad idea. | 
|---|
 | 35 |  | 
|---|
 | 36 |     ALGORITHM | 
|---|
 | 37 |         The calculations are the base-two analogue of the square | 
|---|
 | 38 |         root algorithm we all learned in grammar school.  Since we're | 
|---|
 | 39 |         in base 2, there is only one nontrivial trial multiplier. | 
|---|
 | 40 |  | 
|---|
 | 41 |         Notice that absolutely no multiplications or divisions are performed. | 
|---|
 | 42 |         This means it'll be fast on a wide range of processors. | 
|---|
 | 43 | */ | 
|---|
 | 44 |  | 
|---|
 | 45 | void usqrt(unsigned long x, struct int_sqrt *q) | 
|---|
 | 46 | { | 
|---|
 | 47 |       unsigned long a = 0L;                   /* accumulator      */ | 
|---|
 | 48 |       unsigned long r = 0L;                   /* remainder        */ | 
|---|
 | 49 |       unsigned long e = 0L;                   /* trial product    */ | 
|---|
 | 50 |  | 
|---|
 | 51 |       int i; | 
|---|
 | 52 |  | 
|---|
 | 53 |       for (i = 0; i < BITSPERLONG; i++)   /* NOTE 1 */ | 
|---|
 | 54 |       { | 
|---|
 | 55 |             r = (r << 2) + TOP2BITS(x); x <<= 2; /* NOTE 2 */ | 
|---|
 | 56 |             a <<= 1; | 
|---|
 | 57 |             e = (a << 1) + 1; | 
|---|
 | 58 |             if (r >= e) | 
|---|
 | 59 |             { | 
|---|
 | 60 |                   r -= e; | 
|---|
 | 61 |                   a++; | 
|---|
 | 62 |             } | 
|---|
 | 63 |       } | 
|---|
 | 64 |       memcpy(q, &a, sizeof(long)); | 
|---|
 | 65 | } | 
|---|
 | 66 |  | 
|---|
 | 67 | #ifdef TEST | 
|---|
 | 68 |  | 
|---|
 | 69 | #include <stdio.h> | 
|---|
 | 70 | #include <stdlib.h> | 
|---|
 | 71 |  | 
|---|
 | 72 | main(void) | 
|---|
 | 73 | { | 
|---|
 | 74 |       int i; | 
|---|
 | 75 |       unsigned long l = 0x3fed0169L; | 
|---|
 | 76 |       struct int_sqrt q; | 
|---|
 | 77 |  | 
|---|
 | 78 |       for (i = 0; i < 101; ++i) | 
|---|
 | 79 |       { | 
|---|
 | 80 |             usqrt(i, &q); | 
|---|
 | 81 |             printf("sqrt(%3d) = %2d, remainder = %2d\n", | 
|---|
 | 82 |                   i, q.sqrt, q.frac); | 
|---|
 | 83 |       } | 
|---|
 | 84 |       usqrt(l, &q); | 
|---|
 | 85 |       printf("\nsqrt(%lX) = %X, remainder = %X\n", l, q.sqrt, q.frac); | 
|---|
 | 86 |       return 0; | 
|---|
 | 87 | } | 
|---|
 | 88 |  | 
|---|
 | 89 | #endif /* TEST */ | 
|---|