Tizen 2.1 base
[external/gmp.git] / tests / mpn / t-matrix22.c
1 /* Tests matrix22_mul.
2
3 Copyright 2008 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "gmp.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26
27 struct matrix {
28   mp_size_t alloc;
29   mp_size_t n;
30   mp_ptr e00, e01, e10, e11;
31 };
32
33 static void
34 matrix_init (struct matrix *M, mp_size_t n)
35 {
36   mp_ptr p = refmpn_malloc_limbs (4*(n+1));
37   M->e00 = p; p += n+1;
38   M->e01 = p; p += n+1;
39   M->e10 = p; p += n+1;
40   M->e11 = p;
41   M->alloc = n + 1;
42   M->n = 0;
43 }
44
45 static void
46 matrix_clear (struct matrix *M)
47 {
48   refmpn_free_limbs (M->e00);
49 }
50
51 static void
52 matrix_copy (struct matrix *R, const struct matrix *M)
53 {
54   R->n = M->n;
55   MPN_COPY (R->e00, M->e00, M->n);
56   MPN_COPY (R->e01, M->e01, M->n);
57   MPN_COPY (R->e10, M->e10, M->n);
58   MPN_COPY (R->e11, M->e11, M->n);
59 }
60
61 /* Used with same size, so no need for normalization. */
62 static int
63 matrix_equal_p (const struct matrix *A, const struct matrix *B)
64 {
65   return (A->n == B->n
66           && mpn_cmp (A->e00, B->e00, A->n) == 0
67           && mpn_cmp (A->e01, B->e01, A->n) == 0
68           && mpn_cmp (A->e10, B->e10, A->n) == 0
69           && mpn_cmp (A->e11, B->e11, A->n) == 0);
70 }
71
72 static void
73 matrix_random(struct matrix *M, mp_size_t n, gmp_randstate_ptr rands)
74 {
75   M->n = n;
76   mpn_random (M->e00, n);
77   mpn_random (M->e01, n);
78   mpn_random (M->e10, n);
79   mpn_random (M->e11, n);
80 }
81
82 #define MUL(rp, ap, an, bp, bn) do { \
83     if (an > bn)                     \
84       mpn_mul (rp, ap, an, bp, bn);  \
85     else                             \
86       mpn_mul (rp, bp, bn, ap, an);  \
87   } while(0)
88
89 static void
90 ref_matrix22_mul (struct matrix *R,
91                   const struct matrix *A,
92                   const struct matrix *B, mp_ptr tp)
93 {
94   mp_size_t an, bn, n;
95   mp_ptr r00, r01, r10, r11, a00, a01, a10, a11, b00, b01, b10, b11;
96
97   if (A->n >= B->n)
98     {
99       r00 = R->e00; a00 = A->e00; b00 = B->e00;
100       r01 = R->e01; a01 = A->e01; b01 = B->e01;
101       r10 = R->e10; a10 = A->e10; b10 = B->e10;
102       r11 = R->e11; a11 = A->e11; b11 = B->e11;
103       an = A->n, bn = B->n;
104     }
105   else
106     {
107       /* Transpose */
108       r00 = R->e00; a00 = B->e00; b00 = A->e00;
109       r01 = R->e10; a01 = B->e10; b01 = A->e10;
110       r10 = R->e01; a10 = B->e01; b10 = A->e01;
111       r11 = R->e11; a11 = B->e11; b11 = A->e11;
112       an = B->n, bn = A->n;
113     }
114   n = an + bn;
115   R->n = n + 1;
116
117   mpn_mul (r00, a00, an, b00, bn);
118   mpn_mul (tp, a01, an, b10, bn);
119   r00[n] = mpn_add_n (r00, r00, tp, n);
120
121   mpn_mul (r01, a00, an, b01, bn);
122   mpn_mul (tp, a01, an, b11, bn);
123   r01[n] = mpn_add_n (r01, r01, tp, n);
124
125   mpn_mul (r10, a10, an, b00, bn);
126   mpn_mul (tp, a11, an, b10, bn);
127   r10[n] = mpn_add_n (r10, r10, tp, n);
128
129   mpn_mul (r11, a10, an, b01, bn);
130   mpn_mul (tp, a11, an, b11, bn);
131   r11[n] = mpn_add_n (r11, r11, tp, n);
132 }
133
134 static void
135 one_test (const struct matrix *A, const struct matrix *B, int i)
136 {
137   struct matrix R;
138   struct matrix P;
139   mp_ptr tp;
140
141   matrix_init (&R, A->n + B->n + 1);
142   matrix_init (&P, A->n + B->n + 1);
143
144   tp = refmpn_malloc_limbs (mpn_matrix22_mul_itch (A->n, B->n));
145
146   ref_matrix22_mul (&R, A, B, tp);
147   matrix_copy (&P, A);
148   mpn_matrix22_mul (P.e00, P.e01, P.e10, P.e11, A->n,
149                     B->e00, B->e01, B->e10, B->e11, B->n, tp);
150   P.n = A->n + B->n + 1;
151   if (!matrix_equal_p (&R, &P))
152     {
153       fprintf (stderr, "ERROR in test %d\n", i);
154       gmp_fprintf (stderr, "A = (%Nx, %Nx\n      %Nx, %Nx)\n"
155                    "B = (%Nx, %Nx\n      %Nx, %Nx)\n"
156                    "R = (%Nx, %Nx (expected)\n      %Nx, %Nx)\n"
157                    "P = (%Nx, %Nx (incorrect)\n      %Nx, %Nx)\n",
158                    A->e00, A->n, A->e01, A->n, A->e10, A->n, A->e11, A->n,
159                    B->e00, B->n, B->e01, B->n, B->e10, B->n, B->e11, B->n,
160                    R.e00, R.n, R.e01, R.n, R.e10, R.n, R.e11, R.n,
161                    P.e00, P.n, P.e01, P.n, P.e10, P.n, P.e11, P.n);
162       abort();
163     }
164   refmpn_free_limbs (tp);
165   matrix_clear (&R);
166   matrix_clear (&P);
167 }
168
169 #define MAX_SIZE (2+2*MATRIX22_STRASSEN_THRESHOLD)
170
171 int
172 main (int argc, char **argv)
173 {
174   struct matrix A;
175   struct matrix B;
176
177   gmp_randstate_ptr rands;
178   mpz_t bs;
179   int i;
180
181   tests_start ();
182   rands = RANDS;
183
184   matrix_init (&A, MAX_SIZE);
185   matrix_init (&B, MAX_SIZE);
186   mpz_init (bs);
187
188   for (i = 0; i < 1000; i++)
189     {
190       mp_size_t an, bn;
191       mpz_urandomb (bs, rands, 32);
192       an = 1 + mpz_get_ui (bs) % MAX_SIZE;
193       mpz_urandomb (bs, rands, 32);
194       bn = 1 + mpz_get_ui (bs) % MAX_SIZE;
195
196       matrix_random (&A, an, rands);
197       matrix_random (&B, bn, rands);
198
199       one_test (&A, &B, i);
200     }
201   mpz_clear (bs);
202   matrix_clear (&A);
203   matrix_clear (&B);
204
205   tests_end ();
206   return 0;
207 }