t-matrix22.c revision 1.1.1.1 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 }
208