1 /*
2  * ORIGINAL
3  * https://crypto.stanford.edu/pbc/notes/pi/code.html
4  *
5  * COMMAND LINE DEFINES
6  *
7  * -DSTATIC
8  * Use static variables instead of locals.
9  *
10  * -DPRINTF
11  * Enable printf.
12  *
13  * -DTIMER
14  * Insert asm labels into source code at timing points.
15  *
16  */
17 
18 #ifdef __Z88DK
19    #include <intrinsic.h>
20    #ifdef PRINTF
21       #pragma output CLIB_OPT_PRINTF = 0x01
22    #endif
23 #endif
24 
25 #ifdef STATIC
26    #undef  STATIC
27    #define STATIC              static
28 #else
29    #define STATIC
30 #endif
31 
32 #ifdef PRINTF
33    #undef  PRINTF
34    #define PRINTF(a,b)         printf(a,b)
35 #else
36    STATIC  int dummy;
37    #define PRINTF(a,b)         (dummy=b)
38 #endif
39 
40 #ifdef TIMER
41    #define TIMER_START()       __asm__("TIMER_START:")
42    #define TIMER_STOP()        __asm__("TIMER_STOP:")
43 #else
44    #define TIMER_START()
45    #define TIMER_STOP()
46 #endif
47 
48 
49 #include <stdio.h>
50 #include <stdint.h>
51 #include <stdlib.h>
52 
main()53 int main()
54 {
55    static uint16_t r[2800 + 1];
56 
57    STATIC uint16_t i, k;
58    STATIC uint16_t b;
59    STATIC uint32_t d;
60    STATIC uint16_t c;
61 
62 TIMER_START();
63 
64    c = 0;
65 
66    for (i = 0; i < 2800; ++i)
67       r[i] = 2000;
68 
69    for (k = 2800; k > 0; k -= 14)
70    {
71       d = 0;
72       i = k;
73 
74       while (1)
75       {
76          d += (uint32_t)(r[i]) * 10000UL;
77          b = i * 2 - 1;
78 
79          r[i] = d % (uint32_t)(b);
80          d /= (uint32_t)(b);
81 
82          if (--i == 0) break;
83 
84          d *= (uint32_t)(i);
85       }
86 
87       PRINTF("%.4d", c + (uint16_t)(d / 10000UL));
88       c = d % 10000UL;
89    }
90 
91 TIMER_STOP();
92 
93    return 0;
94 }
95