1 /* biginit.c - C routines for bignumbers */
2 
3 /*
4 Note: This is NOT the biginit.c file that come the standard BigNum library,
5 but is a customized version specific to Fractint.  The biggest difference
6 is in the allocations of memory for the big numbers.
7 */
8 
9 #include <string.h>
10 #ifdef __APPLE__
11 #include <malloc/malloc.h>
12 #elif !defined(BIG_ANSI_C)
13 #include <malloc.h>
14 #endif
15   /* see Fractint.c for a description of the "include"  hierarchy */
16 #include "port.h"
17 #include "prototyp.h"
18 #include "fractype.h"
19 
20 /* appears to me that avoiding the start of extraseg is unnecessary. If
21    correct, later we can eliminate ENDVID here. */
22 #ifdef ENDVID
23 #undef ENDVID
24 #endif
25 #define ENDVID 0
26 
27 /* globals */
28 #ifdef BIG_BASED
29 _segment bignum_seg;
30 #endif
31 int bnstep, bnlength, intlength, rlength, padding, shiftfactor, decimals;
32 int bflength, rbflength, bfdecimals;
33 
34 /* used internally by bignum.c routines */
35 static bn_t bnroot=BIG_NULL;
36 static bn_t stack_ptr; /* memory allocator base after global variables */
37 bn_t bntmp1, bntmp2, bntmp3, bntmp4, bntmp5, bntmp6; /* rlength  */
38 bn_t bntmpcpy1, bntmpcpy2;                           /* bnlength */
39 
40 /* used by other routines */
41 bn_t bnxmin, bnxmax, bnymin, bnymax, bnx3rd, bny3rd;        /* bnlength */
42 bn_t bnxdel, bnydel, bnxdel2, bnydel2, bnclosenuff;         /* bnlength */
43 bn_t bntmpsqrx, bntmpsqry, bntmp;                           /* rlength  */
44 _BNCMPLX /* bnold, bnnew, */ bnparm, bnsaved;               /* bnlength */
45 _BNCMPLX bnold, bnnew;                                       /* rlength */
46 bn_t bn_pi;                                           /* TAKES NO SPACE */
47 
48 bf_t bftmp1, bftmp2, bftmp3, bftmp4, bftmp5, bftmp6;     /* rbflength+2 */
49 bf_t bftmpcpy1, bftmpcpy2;                               /* rbflength+2 */
50 bf_t bfxdel, bfydel, bfxdel2, bfydel2, bfclosenuff;      /* rbflength+2 */
51 bf_t bftmpsqrx, bftmpsqry;                               /* rbflength+2 */
52 _BFCMPLX /* bfold,  bfnew, */ bfparm, bfsaved;            /* bflength+2 */
53 _BFCMPLX bfold,  bfnew;                                  /* rbflength+2 */
54 bf_t bf_pi;                                           /* TAKES NO SPACE */
55 bf_t big_pi;                                              /* bflength+2 */
56 
57 /* for testing only */
58 
59 /* used by other routines */
60 bf_t bfxmin, bfxmax, bfymin, bfymax, bfx3rd, bfy3rd;      /* bflength+2 */
61 bf_t bfsxmin, bfsxmax, bfsymin, bfsymax, bfsx3rd, bfsy3rd;/* bflength+2 */
62 bf_t bfparms[10];                                    /* (bflength+2)*10 */
63 bf_t bftmp;
64 
65 bf_t bf10tmp;                                              /* dec+4 */
66 
67 #define LOG10_256 2.4082399653118
68 #define LOG_256   5.5451774444795
69 
70 static int save_bf_vars(void);
71 static int restore_bf_vars(void);
72 
73 /*********************************************************************/
74 /* given bnlength, calc_lengths will calculate all the other lengths */
calc_lengths(void)75 void calc_lengths(void)
76     {
77 #if 0
78 #ifdef USE_BIGNUM_C_CODE
79     bnstep = 2;
80 #else /* use 80x86 asm code */
81     if (cpu >= 386)
82         bnstep = 4;
83     else /* cpu <= 286 */
84         bnstep = 2;
85 #endif
86 #else
87         bnstep = 4;  /* use 4 in all cases */
88 #endif
89 
90     if (bnlength % bnstep != 0)
91         bnlength = (bnlength / bnstep + 1) * bnstep;
92     if (bnlength == bnstep)
93         padding = bnlength;
94     else
95         padding = 2*bnstep;
96     rlength = bnlength + padding;
97 
98     /* This shiftfactor assumes non-full multiplications will be performed.*/
99     /* Change to bnlength-intlength for full multiplications.              */
100     shiftfactor = padding - intlength;
101 
102     bflength = bnlength+bnstep; /* one extra step for added precision */
103     rbflength = bflength + padding;
104     bfdecimals = (int)((bflength-2)*LOG10_256);
105     }
106 
107 /************************************************************************/
108 /* intended only to be called from init_bf_dec() or init_bf_length().   */
109 /* initialize bignumber global variables                                */
110 
111 long maxptr = 0;
112 long startstack = 0;
113 long maxstack = 0;
114 int bf_save_len = 0;
115 
116 /* ??? for some strange reason, msc 7.0 hangs here without this pragma. ??? */
117 #ifndef XFRACT
118 #pragma optimize( "", off )
119 #endif
init_bf_2(void)120 static void init_bf_2(void)
121     {
122     int i;
123     long ptr;
124     save_bf_vars(); /* copy corners values for conversion */
125 
126     calc_lengths();
127 
128     /* allocate all the memory at once within the same segment (DOS) */
129 #if defined(BIG_FAR) || defined(BIG_ANSI_C)
130     bnroot = (bf_t)MK_FP(extraseg,ENDVID); /* ENDVID is to avoid videotable */
131 #else /* BASED or NEAR  */
132     bnroot = (bf_t)ENDVID;  /* ENDVID is to avoid videotable */
133 #endif
134 #ifdef BIG_BASED
135     bignum_seg = (_segment)extraseg;
136 #endif
137     /* at present time one call would suffice, but this logic allows
138        multiple kinds of alternate math eg long double */
139     if((i = find_alternate_math(fractype, BIGNUM)) > -1)
140        bf_math = alternatemath[i].math;
141     else if((i = find_alternate_math(fractype, BIGFLT)) > -1)
142        bf_math = alternatemath[i].math;
143     else
144        bf_math = 1; /* maybe called from cmdfiles.c and fractype not set */
145 
146     floatflag=1;
147 
148     /* Now split up the memory among the pointers */
149     /* internal pointers */
150     ptr        = 0;
151     bntmp1     = bnroot+ptr; ptr += rlength;
152     bntmp2     = bnroot+ptr; ptr += rlength;
153     bntmp3     = bnroot+ptr; ptr += rlength;
154     bntmp4     = bnroot+ptr; ptr += rlength;
155     bntmp5     = bnroot+ptr; ptr += rlength;
156     bntmp6     = bnroot+ptr; ptr += rlength;
157 
158     bftmp1     = bnroot+ptr; ptr += rbflength+2;
159     bftmp2     = bnroot+ptr; ptr += rbflength+2;
160     bftmp3     = bnroot+ptr; ptr += rbflength+2;
161     bftmp4     = bnroot+ptr; ptr += rbflength+2;
162     bftmp5     = bnroot+ptr; ptr += rbflength+2;
163     bftmp6     = bnroot+ptr; ptr += rbflength+2;
164 
165     bftmpcpy1  = bnroot+ptr; ptr += (rbflength+2)*2;
166     bftmpcpy2  = bnroot+ptr; ptr += (rbflength+2)*2;
167 
168     bntmpcpy1  = bnroot+ptr; ptr += (rlength*2);
169     bntmpcpy2  = bnroot+ptr; ptr += (rlength*2);
170 
171     if (bf_math == BIGNUM)
172     {
173     bnxmin     = bnroot+ptr; ptr += bnlength;
174     bnxmax     = bnroot+ptr; ptr += bnlength;
175     bnymin     = bnroot+ptr; ptr += bnlength;
176     bnymax     = bnroot+ptr; ptr += bnlength;
177     bnx3rd     = bnroot+ptr; ptr += bnlength;
178     bny3rd     = bnroot+ptr; ptr += bnlength;
179     bnxdel     = bnroot+ptr; ptr += bnlength;
180     bnydel     = bnroot+ptr; ptr += bnlength;
181     bnxdel2    = bnroot+ptr; ptr += bnlength;
182     bnydel2    = bnroot+ptr; ptr += bnlength;
183     bnold.x    = bnroot+ptr; ptr += rlength;
184     bnold.y    = bnroot+ptr; ptr += rlength;
185     bnnew.x    = bnroot+ptr; ptr += rlength;
186     bnnew.y    = bnroot+ptr; ptr += rlength;
187     bnsaved.x  = bnroot+ptr; ptr += bnlength;
188     bnsaved.y  = bnroot+ptr; ptr += bnlength;
189     bnclosenuff= bnroot+ptr; ptr += bnlength;
190     bnparm.x   = bnroot+ptr; ptr += bnlength;
191     bnparm.y   = bnroot+ptr; ptr += bnlength;
192     bntmpsqrx  = bnroot+ptr; ptr += rlength;
193     bntmpsqry  = bnroot+ptr; ptr += rlength;
194     bntmp      = bnroot+ptr; ptr += rlength;
195     }
196     if (bf_math == BIGFLT)
197     {
198     bfxdel     = bnroot+ptr; ptr += bflength+2;
199     bfydel     = bnroot+ptr; ptr += bflength+2;
200     bfxdel2    = bnroot+ptr; ptr += bflength+2;
201     bfydel2    = bnroot+ptr; ptr += bflength+2;
202     bfold.x    = bnroot+ptr; ptr += rbflength+2;
203     bfold.y    = bnroot+ptr; ptr += rbflength+2;
204     bfnew.x    = bnroot+ptr; ptr += rbflength+2;
205     bfnew.y    = bnroot+ptr; ptr += rbflength+2;
206     bfsaved.x  = bnroot+ptr; ptr += bflength+2;
207     bfsaved.y  = bnroot+ptr; ptr += bflength+2;
208     bfclosenuff= bnroot+ptr; ptr += bflength+2;
209     bfparm.x   = bnroot+ptr; ptr += bflength+2;
210     bfparm.y   = bnroot+ptr; ptr += bflength+2;
211     bftmpsqrx  = bnroot+ptr; ptr += rbflength+2;
212     bftmpsqry  = bnroot+ptr; ptr += rbflength+2;
213     bftmp      = bnroot+ptr; ptr += rbflength+2;
214     }
215     big_pi     = bnroot+ptr; ptr += bflength+2; /* needed by both BIGNUM & BIGFLT */
216     bf10tmp    = bnroot+ptr; ptr += bfdecimals+4;
217 
218     /* ptr needs to be 16-bit aligned on some systems */
219     ptr = (ptr+1)&~1;
220 
221     stack_ptr  = bnroot + ptr;
222     startstack = ptr;
223 
224     /* max stack offset from bnroot */
225     maxstack = (long)0x10000l-(bflength+2)*22-ENDVID;
226 
227     /* sanity check */
228     /* leave room for NUMVARS variables allocated from stack */
229     /* also leave room for the safe area at top of segment */
230     if(ptr + NUMVARS*(bflength+2) > maxstack)
231        {
232        char msg[80];
233        char nmsg[80];
234        static FCODE fmsg[] = {"Requested precision of %d too high, aborting"};
235        far_strcpy(nmsg,fmsg);
236        sprintf(msg,nmsg,decimals);
237        stopmsg(0,msg);
238        goodbye();
239        }
240 
241     /* room for 6 corners + 6 save corners + 10 params at top of extraseg */
242     /* this area is safe - use for variables that are used outside fractal*/
243     /* generation - e.g. zoom box variables */
244     ptr  = maxstack;
245     bfxmin     = bnroot+ptr; ptr += bflength+2;
246     bfxmax     = bnroot+ptr; ptr += bflength+2;
247     bfymin     = bnroot+ptr; ptr += bflength+2;
248     bfymax     = bnroot+ptr; ptr += bflength+2;
249     bfx3rd     = bnroot+ptr; ptr += bflength+2;
250     bfy3rd     = bnroot+ptr; ptr += bflength+2;
251     for(i=0;i<10;i++)
252        {
253        bfparms[i]  = bnroot+ptr; ptr += bflength+2;
254        }
255     bfsxmin    = bnroot+ptr; ptr += bflength+2;
256     bfsxmax    = bnroot+ptr; ptr += bflength+2;
257     bfsymin    = bnroot+ptr; ptr += bflength+2;
258     bfsymax    = bnroot+ptr; ptr += bflength+2;
259     bfsx3rd    = bnroot+ptr; ptr += bflength+2;
260     bfsy3rd    = bnroot+ptr; ptr += bflength+2;
261     /* end safe vars */
262 
263     /* good citizens initialize variables */
264     if(bf_save_len)  /* leave save area */
265        far_memset(bnroot+(bf_save_len+2)*22,0,(unsigned)(startstack-(bf_save_len+2)*22));
266     else /* first time through - nothing saved */
267        {
268        /* high variables */
269        far_memset(bnroot+maxstack,0,(bflength+2)*22);
270        /* low variables */
271        far_memset(bnroot,0,(unsigned)startstack);
272        }
273 
274     restore_bf_vars();
275 
276     /* Initialize the value of pi.  Needed for trig functions. */
277     /* init_big_pi(); */
278 /* call to init_big_pi() has been moved to fractal setup routine */
279 /* so as to use only when necessary. */
280 
281     }
282 
283 
284 /**********************************************************/
285 /* save current corners and parameters to start of bnroot */
286 /* to preserve values across calls to init_bf()           */
save_bf_vars(void)287 static int save_bf_vars(void)
288    {
289    int ret;
290    unsigned int mem;
291    if(bnroot != BIG_NULL)
292       {
293       mem = (bflength+2)*22;  /* 6 corners + 6 save corners + 10 params */
294       bf_save_len = bflength;
295       far_memcpy(bnroot,bfxmin,mem);
296       /* scrub old high area */
297       far_memset(bfxmin,0,mem);
298       ret = 0;
299       }
300    else
301       {
302       bf_save_len = 0;
303       ret = -1;
304       }
305    return(ret);
306    }
307 
308 /************************************************************************/
309 /* copy current corners and parameters from save location               */
restore_bf_vars(void)310 static int restore_bf_vars(void)
311    {
312    bf_t ptr;
313    int i;
314    if(bf_save_len == 0)
315       return(-1);
316    ptr  = bnroot;
317    convert_bf(bfxmin,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
318    convert_bf(bfxmax,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
319    convert_bf(bfymin,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
320    convert_bf(bfymax,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
321    convert_bf(bfx3rd,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
322    convert_bf(bfy3rd,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
323    for(i=0;i<10;i++)
324       {
325       convert_bf(bfparms[i],ptr,bflength,bf_save_len);
326       ptr += bf_save_len+2;
327       }
328    convert_bf(bfsxmin,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
329    convert_bf(bfsxmax,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
330    convert_bf(bfsymin,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
331    convert_bf(bfsymax,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
332    convert_bf(bfsx3rd,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
333    convert_bf(bfsy3rd,ptr,bflength,bf_save_len); ptr += bf_save_len+2;
334 
335    /* scrub save area */
336    far_memset(bnroot,0,(bf_save_len+2)*22);
337    return(0);
338    }
339 
340 /*******************************************/
341 /* free corners and parameters save memory */
free_bf_vars()342 void free_bf_vars()
343    {
344    bf_save_len = bf_math = 0;
345    bnstep=bnlength=intlength=rlength=padding=shiftfactor=decimals=0;
346    bflength=rbflength=bfdecimals=0;
347    maxptr = startstack = maxstack = 0;
348    }
349 
350 #ifndef XFRACT
351 #pragma optimize( "", on )
352 #endif
353 
354 /************************************************************************/
355 /* Memory allocator routines start here.                                */
356 /************************************************************************/
357 /* Allocates a bn_t variable on stack                                   */
alloc_stack(size_t size)358 bn_t alloc_stack(size_t size)
359    {
360    long stack_addr;
361    if(bf_math == 0)
362       {
363       static FCODE msg[] = {"alloc_stack called with bf_math==0"};
364       stopmsg(0,msg);
365       return(0);
366       }
367    stack_addr = (long)(stack_ptr-bnroot)+size; /* +ENDVID, part of bnroot */
368 
369    if(stack_addr > maxstack)
370       {
371       static FCODE msg[] = {"Aborting, Out of Bignum Stack Space"};
372       stopmsg(0,msg);
373       goodbye();
374       }
375    /* keep track of max ptr */
376    if(stack_addr > maxptr)
377       maxptr = stack_addr;
378    stack_ptr += size;   /* increment stack pointer */
379    return(stack_ptr - size);
380    }
381 
382 /************************************************************************/
383 /* Returns stack pointer offset so it can be saved.                            */
save_stack(void)384 int save_stack(void)
385    {
386    return(stack_ptr - bnroot);
387    }
388 
389 /************************************************************************/
390 /* Restores stack pointer, effectively freeing local variables          */
391 /*    allocated since save_stack()                                   */
restore_stack(int old_offset)392 void restore_stack(int old_offset)
393    {
394    stack_ptr  = bnroot+old_offset;
395    }
396 
397 /************************************************************************/
398 /* Memory allocator routines end here.                                  */
399 /************************************************************************/
400 
401 /************************************************************************/
402 /* initialize bignumber global variables                                */
403 /*   dec = decimal places after decimal point                           */
404 /*   intl = bytes for integer part (1, 2, or 4)                         */
405 
init_bf_dec(int dec)406 void init_bf_dec(int dec)
407     {
408     if(bfdigits)
409        decimals=bfdigits;   /* blindly force */
410     else
411        decimals = dec;
412     if(bailout > 10)    /* arbitrary value */
413        /* using 2 doesn't gain much and requires another test */
414        intlength = 4;
415     else if (fractype == FPMANDELZPOWER || fractype == FPJULIAZPOWER ||
416              fractype == DIVIDEBROT5)
417        intlength = 4; /* 2 leaves artifacts in the center of the lakes */
418     /* the bailout tests need greater dynamic range */
419     else if(bailoutest == Real || bailoutest == Imag || bailoutest == And ||
420             bailoutest == Manr)
421        intlength = 2;
422     else
423        intlength = 1;
424     /* conservative estimate */
425     bnlength = intlength + (int)(decimals/LOG10_256) + 1; /* round up */
426     init_bf_2();
427     }
428 
429 /************************************************************************/
430 /* initialize bignumber global variables                                */
431 /*   bnl = bignumber length                                             */
432 /*   intl = bytes for integer part (1, 2, or 4)                         */
init_bf_length(int bnl)433 void init_bf_length(int bnl)
434     {
435     bnlength = bnl;
436 
437     if(bailout > 10)    /* arbitrary value */
438        /* using 2 doesn't gain much and requires another test */
439        intlength = 4;
440     else if (fractype == FPMANDELZPOWER || fractype == FPJULIAZPOWER ||
441              fractype == DIVIDEBROT5)
442        intlength = 4; /* 2 leaves artifacts in the center of the lakes */
443     /* the bailout tests need greater dynamic range */
444     else if(bailoutest == Real || bailoutest == Imag || bailoutest == And ||
445             bailoutest == Manr)
446        intlength = 2;
447     else
448        intlength = 1;
449     /* conservative estimate */
450     decimals = (int)((bnlength-intlength)*LOG10_256);
451     init_bf_2();
452     }
453 
454 
init_big_pi(void)455 void init_big_pi(void)
456     {
457     /* What, don't you recognize the first 700 digits of pi, */
458     /* in base 256, in reverse order?                        */
459     int length, pi_offset;
460     static BFCODE pi_table[] = {
461          0x44, 0xD5, 0xDB, 0x69, 0x17, 0xDF, 0x2E, 0x56, 0x87, 0x1A,
462          0xA0, 0x8C, 0x6F, 0xCA, 0xBB, 0x57, 0x5C, 0x9E, 0x82, 0xDF,
463          0x00, 0x3E, 0x48, 0x7B, 0x31, 0x53, 0x60, 0x87, 0x23, 0xFD,
464          0xFA, 0xB5, 0x3D, 0x32, 0xAB, 0x52, 0x05, 0xAD, 0xC8, 0x1E,
465          0x50, 0x2F, 0x15, 0x6B, 0x61, 0xFD, 0xDF, 0x16, 0x75, 0x3C,
466          0xF8, 0x22, 0x32, 0xDB, 0xF8, 0xE9, 0xA5, 0x8E, 0xCC, 0xA3,
467          0x1F, 0xFB, 0xFE, 0x25, 0x9F, 0x67, 0x79, 0x72, 0x2C, 0x40,
468          0xC6, 0x00, 0xA1, 0xD6, 0x0A, 0x32, 0x60, 0x1A, 0xBD, 0xC0,
469          0x79, 0x55, 0xDB, 0xFB, 0xD3, 0xB9, 0x39, 0x5F, 0x0B, 0xD2,
470          0x0F, 0x74, 0xC8, 0x45, 0x57, 0xA8, 0xCB, 0xC0, 0xB3, 0x4B,
471          0x2E, 0x19, 0x07, 0x28, 0x0F, 0x66, 0xFD, 0x4A, 0x33, 0xDE,
472          0x04, 0xD0, 0xE3, 0xBE, 0x09, 0xBD, 0x5E, 0xAF, 0x44, 0x45,
473          0x81, 0xCC, 0x2C, 0x95, 0x30, 0x9B, 0x1F, 0x51, 0xFC, 0x6D,
474          0x6F, 0xEC, 0x52, 0x3B, 0xEB, 0xB2, 0x39, 0x13, 0xB5, 0x53,
475          0x6C, 0x3E, 0xAF, 0x6F, 0xFB, 0x68, 0x63, 0x24, 0x6A, 0x19,
476          0xC2, 0x9E, 0x5C, 0x5E, 0xC4, 0x60, 0x9F, 0x40, 0xB6, 0x4F,
477          0xA9, 0xC1, 0xBA, 0x06, 0xC0, 0x04, 0xBD, 0xE0, 0x6C, 0x97,
478          0x3B, 0x4C, 0x79, 0xB6, 0x1A, 0x50, 0xFE, 0xE3, 0xF7, 0xDE,
479          0xE8, 0xF6, 0xD8, 0x79, 0xD4, 0x25, 0x7B, 0x1B, 0x99, 0x80,
480          0xC9, 0x72, 0x53, 0x07, 0x9B, 0xC0, 0xF1, 0x49, 0xD3, 0xEA,
481          0x0F, 0xDB, 0x48, 0x12, 0x0A, 0xD0, 0x24, 0xD7, 0xD0, 0x37,
482          0x3D, 0x02, 0x9B, 0x42, 0x72, 0xDF, 0xFE, 0x1B, 0x06, 0x77,
483          0x3F, 0x36, 0x62, 0xAA, 0xD3, 0x4E, 0xA6, 0x6A, 0xC1, 0x56,
484          0x9F, 0x44, 0x1A, 0x40, 0x73, 0x20, 0xC1, 0x85, 0xD8, 0x75,
485          0x6F, 0xE0, 0xBE, 0x5E, 0x8B, 0x3B, 0xC3, 0xA5, 0x84, 0x7D,
486          0xB4, 0x9F, 0x6F, 0x45, 0x19, 0x86, 0xEE, 0x8C, 0x88, 0x0E,
487          0x43, 0x82, 0x3E, 0x59, 0xCA, 0x66, 0x76, 0x01, 0xAF, 0x39,
488          0x1D, 0x65, 0xF1, 0xA1, 0x98, 0x2A, 0xFB, 0x7E, 0x50, 0xF0,
489          0x3B, 0xBA, 0xE4, 0x3B, 0x7A, 0x13, 0x6C, 0x0B, 0xEF, 0x6E,
490          0xA3, 0x33, 0x51, 0xAB, 0x28, 0xA7, 0x0F, 0x96, 0x68, 0x2F,
491          0x54, 0xD8, 0xD2, 0xA0, 0x51, 0x6A, 0xF0, 0x88, 0xD3, 0xAB,
492          0x61, 0x9C, 0x0C, 0x67, 0x9A, 0x6C, 0xE9, 0xF6, 0x42, 0x68,
493          0xC6, 0x21, 0x5E, 0x9B, 0x1F, 0x9E, 0x4A, 0xF0, 0xC8, 0x69,
494          0x04, 0x20, 0x84, 0xA4, 0x82, 0x44, 0x0B, 0x2E, 0x39, 0x42,
495          0xF4, 0x83, 0xF3, 0x6F, 0x6D, 0x0F, 0xC5, 0xAC, 0x96, 0xD3,
496          0x81, 0x3E, 0x89, 0x23, 0x88, 0x1B, 0x65, 0xEB, 0x02, 0x23,
497          0x26, 0xDC, 0xB1, 0x75, 0x85, 0xE9, 0x5D, 0x5D, 0x84, 0xEF,
498          0x32, 0x80, 0xEC, 0x5D, 0x60, 0xAC, 0x7C, 0x48, 0x91, 0xA9,
499          0x21, 0xFB, 0xCC, 0x09, 0xD8, 0x61, 0x93, 0x21, 0x28, 0x66,
500          0x1B, 0xE8, 0xBF, 0xC4, 0xAF, 0xB9, 0x4B, 0x6B, 0x98, 0x48,
501          0x8F, 0x3B, 0x77, 0x86, 0x95, 0x28, 0x81, 0x53, 0x32, 0x7A,
502          0x5C, 0xCF, 0x24, 0x6C, 0x33, 0xBA, 0xD6, 0xAF, 0x1E, 0x93,
503          0x87, 0x9B, 0x16, 0x3E, 0x5C, 0xCE, 0xF6, 0x31, 0x18, 0x74,
504          0x5D, 0xC5, 0xA9, 0x2B, 0x2A, 0xBC, 0x6F, 0x63, 0x11, 0x14,
505          0xEE, 0xB3, 0x93, 0xE9, 0x72, 0x7C, 0xAF, 0x86, 0x54, 0xA1,
506          0xCE, 0xE8, 0x41, 0x11, 0x34, 0x5C, 0xCC, 0xB4, 0xB6, 0x10,
507          0xAB, 0x2A, 0x6A, 0x39, 0xCA, 0x55, 0x40, 0x14, 0xE8, 0x63,
508          0x62, 0x98, 0x48, 0x57, 0x94, 0xAB, 0x55, 0xAA, 0xF3, 0x25,
509          0x55, 0xE6, 0x60, 0x5C, 0x60, 0x55, 0xDA, 0x2F, 0xAF, 0x78,
510          0x27, 0x4B, 0x31, 0xBD, 0xC1, 0x77, 0x15, 0xD7, 0x3E, 0x8A,
511          0x1E, 0xB0, 0x8B, 0x0E, 0x9E, 0x6C, 0x0E, 0x18, 0x3A, 0x60,
512          0xB0, 0xDC, 0x79, 0x8E, 0xEF, 0x38, 0xDB, 0xB8, 0x18, 0x79,
513          0x41, 0xCA, 0xF0, 0x85, 0x60, 0x28, 0x23, 0xB0, 0xD1, 0xC5,
514          0x13, 0x60, 0xF2, 0x2A, 0x39, 0xD5, 0x30, 0x9C, 0xB5, 0x59,
515          0x5A, 0xC2, 0x1D, 0xA4, 0x54, 0x7B, 0xEE, 0x4A, 0x15, 0x82,
516          0x58, 0xCD, 0x8B, 0x71, 0x58, 0xB6, 0x8E, 0x72, 0x8F, 0x74,
517          0x95, 0x0D, 0x7E, 0x3D, 0x93, 0xF4, 0xA3, 0xFE, 0x58, 0xA4,
518          0x69, 0x4E, 0x57, 0x71, 0xD8, 0x20, 0x69, 0x63, 0x16, 0xFC,
519          0x8E, 0x85, 0xE2, 0xF2, 0x01, 0x08, 0xF7, 0x6C, 0x91, 0xB3,
520          0x47, 0x99, 0xA1, 0x24, 0x99, 0x7F, 0x2C, 0xF1, 0x45, 0x90,
521          0x7C, 0xBA, 0x96, 0x7E, 0x26, 0x6A, 0xED, 0xAF, 0xE1, 0xB8,
522          0xB7, 0xDF, 0x1A, 0xD0, 0xDB, 0x72, 0xFD, 0x2F, 0xAC, 0xB5,
523          0xDF, 0x98, 0xA6, 0x0B, 0x31, 0xD1, 0x1B, 0xFB, 0x79, 0x89,
524          0xD9, 0xD5, 0x16, 0x92, 0x17, 0x09, 0x47, 0xB5, 0xB5, 0xD5,
525          0x84, 0x3F, 0xDD, 0x50, 0x7C, 0xC9, 0xB7, 0x29, 0xAC, 0xC0,
526          0x6C, 0x0C, 0xE9, 0x34, 0xCF, 0x66, 0x54, 0xBE, 0x77, 0x13,
527          0xD0, 0x38, 0xE6, 0x21, 0x28, 0x45, 0x89, 0x6C, 0x4E, 0xEC,
528          0x98, 0xFA, 0x2E, 0x08, 0xD0, 0x31, 0x9F, 0x29, 0x22, 0x38,
529          0x09, 0xA4, 0x44, 0x73, 0x70, 0x03, 0x2E, 0x8A, 0x19, 0x13,
530          0xD3, 0x08, 0xA3, 0x85, 0x88, 0x6A, 0x3F, 0x24,
531          /* . */  0x03, 0x00, 0x00, 0x00
532               /*  <- up to intlength 4 -> */
533               /* or bf_t int length of 2 + 2 byte exp  */
534          };
535 
536     length = bflength+2; /* 2 byte exp */
537     pi_offset = sizeof pi_table - length;
538     _fmemcpy(big_pi, pi_table + pi_offset, length);
539 
540     /* notice that bf_pi and bn_pi can share the same memory space */
541     bf_pi = big_pi;
542     bn_pi = big_pi + (bflength-2) - (bnlength-intlength);
543     return;
544     }
545