Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / libgmp / mpn / tests / tst-addsub.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "gmp.h"
4 #include "gmp-impl.h"
5
6 #define ADD 1
7 #define SUB 2
8
9 #ifndef METHOD
10 #define METHOD ADD
11 #endif
12
13 #if METHOD == ADD
14 #define REFCALL refmpn_add_n
15 #define TESTCALL mpn_add_n
16 #endif
17
18 #if METHOD == SUB
19 #define REFCALL refmpn_sub_n
20 #define TESTCALL mpn_sub_n
21 #endif
22
23 mp_limb_t refmpn_add_n ();
24 mp_limb_t refmpn_sub_n ();
25
26 #define SIZE 100
27
28 main (argc, argv)
29      int argc;
30      char **argv;
31 {
32   mp_size_t alloc_size, max_size, size, i, cumul_size;
33   mp_ptr s1, s2, dx, dy;
34   int s1_align, s2_align, d_align;
35   long pass, n_passes;
36   mp_limb_t cx, cy;
37
38   max_size = SIZE;
39   n_passes = 1000000;
40
41   argc--; argv++;
42   if (argc)
43     {
44       max_size = atol (*argv);
45       argc--; argv++;
46     }
47
48   alloc_size = max_size + 32;
49   s1 = malloc (alloc_size * BYTES_PER_MP_LIMB);
50   s2 = malloc (alloc_size * BYTES_PER_MP_LIMB);
51   dx = malloc (alloc_size * BYTES_PER_MP_LIMB);
52   dy = malloc (alloc_size * BYTES_PER_MP_LIMB);
53
54   cumul_size = 0;
55   for (pass = 0; pass < n_passes; pass++)
56     {
57       cumul_size += size;
58       if (cumul_size >= 1000000)
59         {
60           cumul_size -= 1000000;
61           printf ("%d ", pass); fflush (stdout);
62         }
63       s1_align = random () % 32;
64       s2_align = random () % 32;
65       d_align = random () % 32;
66
67       size = random () % max_size + 1;
68
69       mpn_random2 (s1 + s1_align, size);
70       mpn_random2 (s2 + s2_align, size);
71
72       for (i = 0; i < alloc_size; i++)
73         dx[i] = dy[i] = i + 0x9876500;
74
75       cx = TESTCALL (dx + d_align, s1 + s1_align, s2 + s2_align, size);
76       cy = REFCALL (dy + d_align, s1 + s1_align, s2 + s2_align, size);
77
78       if (cx != cy || mpn_cmp (dx, dy, alloc_size) != 0)
79         abort ();
80     }
81
82   printf ("%d passes OK\n", n_passes);
83   exit (0);
84 }
85
86 mp_limb_t
87 #if __STDC__
88 refmpn_add_n (mp_ptr res_ptr,
89               mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
90 #else
91 refmpn_add_n (res_ptr, s1_ptr, s2_ptr, size)
92      register mp_ptr res_ptr;
93      register mp_srcptr s1_ptr;
94      register mp_srcptr s2_ptr;
95      mp_size_t size;
96 #endif
97 {
98   register mp_limb_t x, y, cy;
99   register mp_size_t j;
100
101   /* The loop counter and index J goes from -SIZE to -1.  This way
102      the loop becomes faster.  */
103   j = -size;
104
105   /* Offset the base pointers to compensate for the negative indices.  */
106   s1_ptr -= j;
107   s2_ptr -= j;
108   res_ptr -= j;
109
110   cy = 0;
111   do
112     {
113       y = s2_ptr[j];
114       x = s1_ptr[j];
115       y += cy;                  /* add previous carry to one addend */
116       cy = (y < cy);            /* get out carry from that addition */
117       y = x + y;                /* add other addend */
118       cy = (y < x) + cy;        /* get out carry from that add, combine */
119       res_ptr[j] = y;
120     }
121   while (++j != 0);
122
123   return cy;
124 }
125
126 mp_limb_t
127 #if __STDC__
128 refmpn_sub_n (mp_ptr res_ptr,
129                mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
130 #else
131 refmpn_sub_n (res_ptr, s1_ptr, s2_ptr, size)
132      register mp_ptr res_ptr;
133      register mp_srcptr s1_ptr;
134      register mp_srcptr s2_ptr;
135      mp_size_t size;
136 #endif
137 {
138   register mp_limb_t x, y, cy;
139   register mp_size_t j;
140
141   /* The loop counter and index J goes from -SIZE to -1.  This way
142      the loop becomes faster.  */
143   j = -size;
144
145   /* Offset the base pointers to compensate for the negative indices.  */
146   s1_ptr -= j;
147   s2_ptr -= j;
148   res_ptr -= j;
149
150   cy = 0;
151   do
152     {
153       y = s2_ptr[j];
154       x = s1_ptr[j];
155       y += cy;                  /* add previous carry to subtrahend */
156       cy = (y < cy);            /* get out carry from that addition */
157       y = x - y;                /* main subtract */
158       cy = (y > x) + cy;        /* get out carry from the subtract, combine */
159       res_ptr[j] = y;
160     }
161   while (++j != 0);
162
163   return cy;
164 }