LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
mat22_mul.c
浏览该文件的文档.
1/**
2 * Copyright (C) 2026 HJimmyK(Jericho Knox)
3 *
4 * This file is part of LAMMP.
5 *
6 * LAMMP is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License (LGPL) as published
8 * by the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed WITHOUT ANY WARRANTY.
12 *
13 * See <https://www.gnu.org/licenses/>.
14 */
15
16#include "../../../include/lammp/impl/signed.h"
17#include "../../../include/lammp/impl/tmp_alloc.h"
18#include "../../../include/lammp/lmmpn.h"
19#include "../../../include/lammp/impl/mparam.h"
20#include "../../../include/lammp/impl/mat22_mul.h"
21
22
25 const lmmp_mat22_t* matA,
26 const lmmp_mat22_t* matB,
27 mp_size_t* tn,
29) {
32 if (matA == matB) {
39 dst->n00 = LMMP_MAX((A00 + A00), (A01 + A10));
40 dst->n01 = LMMP_MAX((A00 + A01), (A01 + A11));
41 dst->n10 = LMMP_MAX((A10 + A00), (A11 + A10));
42 dst->n11 = LMMP_MAX((A10 + A01), (A11 + A11));
43 *tn = LMMP_MAX(LMMP_MAX(LMMP_MAX(dst->n00, dst->n01), dst->n10), dst->n11) + 1;
44 ++(dst->n00);
45 ++(dst->n01);
46 ++(dst->n10);
47 ++(dst->n11);
48 return 0;
49 } else {
51 *tn = (*maxa << 1) + 1;
52 dst->n00 = *tn;
53 dst->n01 = *tn;
54 dst->n10 = *tn;
55 dst->n11 = *tn;
56 return 1;
57 }
58 } else {
71 dst->n00 = LMMP_MAX((A00 + B00), (A01 + B10));
72 dst->n01 = LMMP_MAX((A00 + B01), (A01 + B11));
73 dst->n10 = LMMP_MAX((A10 + B00), (A11 + B10));
74 dst->n11 = LMMP_MAX((A10 + B01), (A11 + B11));
75 *tn = LMMP_MAX(LMMP_MAX(LMMP_MAX(dst->n00, dst->n01), dst->n10), dst->n11);
76 ++(dst->n00);
77 ++(dst->n01);
78 ++(dst->n10);
79 ++(dst->n11);
80 return 0;
81 } else {
83 *tn = *maxa + LMMP_MAX(LMMP_MAX(LMMP_MAX(B00, B01), B10), B11) + 1;
84 dst->n00 = *tn;
85 dst->n01 = *tn;
86 dst->n10 = *tn;
87 dst->n11 = *tn;
88 return 1;
89 }
90 }
91}
92
95 const lmmp_mat22_t* matA,
96 const lmmp_mat22_t* matB,
97 mp_ptr tp,
98 mp_size_t tn
99) {
100 lmmp_param_assert(matA != NULL && matB != NULL && dst != NULL);
101 lmmp_param_assert(tn > 0);
102 if (matA == matB) {
104 return;
105 }
106 TEMP_DECL;
107 if (tp == NULL)
108 tp = TALLOC_TYPE(tn * 2, mp_limb_t);
109#define p1 tp
110#define p2 tp + tn
112 pn1 = lmmp_mul_signed_(p1, matA->a00, matA->n00, matB->a00, matB->n00);
113 pn2 = lmmp_mul_signed_(p2, matA->a01, matA->n01, matB->a10, matB->n10);
114 dst->n00 = lmmp_add_signed_(dst->a00, p1, pn1, p2, pn2);
115 pn1 = lmmp_mul_signed_(p1, matA->a00, matA->n00, matB->a01, matB->n01);
116 pn2 = lmmp_mul_signed_(p2, matA->a01, matA->n01, matB->a11, matB->n11);
117 dst->n01 = lmmp_add_signed_(dst->a01, p1, pn1, p2, pn2);
118 pn1 = lmmp_mul_signed_(p1, matA->a10, matA->n10, matB->a00, matB->n00);
119 pn2 = lmmp_mul_signed_(p2, matA->a11, matA->n11, matB->a10, matB->n10);
120 dst->n10 = lmmp_add_signed_(dst->a10, p1, pn1, p2, pn2);
121 pn1 = lmmp_mul_signed_(p1, matA->a10, matA->n10, matB->a01, matB->n01);
122 pn2 = lmmp_mul_signed_(p2, matA->a11, matA->n11, matB->a11, matB->n11);
123 dst->n11 = lmmp_add_signed_(dst->a11, p1, pn1, p2, pn2);
124#undef p1
125#undef p2
126 TEMP_FREE;
127}
128
131 const lmmp_mat22_t* matA,
132 mp_ptr tp,
133 mp_size_t tn
134) {
135 TEMP_DECL;
136 if (tp == NULL)
137 tp = TALLOC_TYPE(tn * 2, mp_limb_t);
138#define p1 tp
139#define p2 tp + tn
141 pn1 = lmmp_sqr_signed_(p1, matA->a00, matA->n00);
142 pn2 = lmmp_mul_signed_(p2, matA->a01, matA->n01, matA->a10, matA->n10);
143 dst->n00 = lmmp_add_signed_(dst->a00, p1, pn1, p2, pn2);
144 pn1 = lmmp_mul_signed_(p1, matA->a00, matA->n00, matA->a01, matA->n01);
145 pn2 = lmmp_mul_signed_(p2, matA->a01, matA->n01, matA->a11, matA->n11);
146 dst->n01 = lmmp_add_signed_(dst->a01, p1, pn1, p2, pn2);
147 pn1 = lmmp_mul_signed_(p1, matA->a10, matA->n10, matA->a00, matA->n00);
148 pn2 = lmmp_mul_signed_(p2, matA->a11, matA->n11, matA->a10, matA->n10);
149 dst->n10 = lmmp_add_signed_(dst->a10, p1, pn1, p2, pn2);
150 pn1 = lmmp_mul_signed_(p1, matA->a10, matA->n10, matA->a01, matA->n01);
151 pn2 = lmmp_sqr_signed_(p2, matA->a11, matA->n11);
152 dst->n11 = lmmp_add_signed_(dst->a11, p1, pn1, p2, pn2);
153#undef p1
154#undef p2
155 TEMP_FREE;
156}
157
158/*
159 * Strassen 2x2 矩阵乘法的 Winograd 变体
160 *
161 * 输入矩阵:
162 * A = | A11 A12 |
163 * | A21 A22 |
164 * B = | B11 B12 |
165 * | B21 B22 |
166 *
167 * 输出矩阵 C = A * B:
168 * C = | C11 C12 |
169 * | C21 C22 |
170 *
171 *
172 * s1 = A22 + A12
173 * s2 = A22 - A21
174 * s3 = s2 + A12 = A22 - A21 + A12
175 * s4 = s3 - A11 = A22 - A21 + A12 - A11
176 *
177 * t1 = B22 + B12
178 * t2 = B22 - B21
179 * t3 = t2 + B12 = B22 - B21 + B12
180 * t4 = t3 - B11 = B22 - B21 + B12 - B11
181 *
182 * 7 个 Strassen 乘积项
183 * p1 = s1 * t1 = (A22 + A12 ) * (B22 + B12 )
184 * p2 = s2 * t2 = (A22 - A21 ) * (B22 - B21 )
185 * p3 = s3 * t3 = (A22 - A21 + A12) * (B22 - B21 + B12)
186 * p4 = A11 * B11
187 * p5 = A12 * B21
188 * p6 = s4 * B12
189 * p7 = A21 * t4
190 *
191 * U1 = p3 + p5
192 * U2 = p1 - U1
193 * U3 = U1 - p2
194 *
195 * result:
196 * C11 = p4 + p5
197 * C12 = U3 - p6
198 * C21 = U2 - p7
199 * C22 = p2 + U2
200 *
201 * 平方版本(A*A):所有乘法替换为平方/自身相乘,流程一致。
202 */
203
206 const lmmp_mat22_t* matA,
207 const lmmp_mat22_t* matB,
208 mp_ptr tp,
209 mp_size_t tn,
211) {
212 lmmp_param_assert(matA != NULL && matB != NULL && dst != NULL);
213 lmmp_param_assert(tn > 0 && maxa > 0);
214 if (matA == matB) {
216 return;
217 }
219 ++tn;
220 if (tp == NULL)
221 tp = BALLOC_TYPE(tn * 7, mp_limb_t);
222
223#define A11 (matA->a00)
224#define A12 (matA->a01)
225#define A21 (matA->a10)
226#define A22 (matA->a11)
227#define B11 (matB->a00)
228#define B12 (matB->a01)
229#define B21 (matB->a10)
230#define B22 (matB->a11)
231#define A11n (matA->n00)
232#define A12n (matA->n01)
233#define A21n (matA->n10)
234#define A22n (matA->n11)
235#define B11n (matB->n00)
236#define B12n (matB->n01)
237#define B21n (matB->n10)
238#define B22n (matB->n11)
239
240#define s1 (dst->a00)
241#define s2 (dst->a01)
242#define s3 (dst->a10)
243#define s4 (dst->a11)
244#define t1 (dst->a00 + maxa)
245#define t2 (dst->a01 + maxa)
246#define t3 (dst->a10 + maxa)
247#define t4 (dst->a11 + maxa)
248#define p1 (tp)
249#define p2 (tp + tn)
250#define p3 (tp + 2 * tn)
251#define p4 (tp + 3 * tn)
252#define p5 (tp + 4 * tn)
253#define p6 (tp + 5 * tn)
254#define p7 (tp + 6 * tn)
255 mp_ssize_t n1, n2, n3, n4, n5, n6, n7, n8;
264
265 n1 = lmmp_mul_signed_(p1, s1, n1, t1, n5);
266 n5 = lmmp_mul_signed_(p2, s2, n2, t2, n6);
267 n2 = lmmp_mul_signed_(p3, s3, n3, t3, n7);
272
273#undef s1
274#undef s2
275#undef s3
276#undef s4
277#undef t1
278#undef t2
279#undef t3
280#undef t4
281
282#define p1n n1
283#define p2n n5
284#define p3n n2
285#define p4n n7
286#define p5n n6
287#define p6n n3
288#define p7n n4
289
290#undef A11
291#undef A12
292#undef A21
293#undef A22
294#undef B11
295#undef B12
296#undef B21
297#undef B22
298#undef A11n
299#undef A12n
300#undef A21n
301#undef A22n
302#undef B11n
303#undef B12n
304#undef B21n
305#undef B22n
306
307#define C11 (dst->a00)
308#define C12 (dst->a01)
309#define C21 (dst->a10)
310#define C22 (dst->a11)
311#define C11n (dst->n00)
312#define C12n (dst->n01)
313#define C21n (dst->n10)
314#define C22n (dst->n11)
315
317#define U1 p5 // U1 = p3 + p5
318#define U2 p1 // U2 = p1 - U1
319#define U3 U1 // U3 = U1 - p2
320#define U1n p5n
321#define U2n p1n
322#define U3n n8
326
331
332#undef C11
333#undef C12
334#undef C21
335#undef C22
336#undef C11n
337#undef C12n
338#undef C21n
339#undef C22n
340#undef U1
341#undef U2
342#undef U3
343#undef U1n
344#undef U2n
345#undef U3n
346
347#undef p1
348#undef p2
349#undef p3
350#undef p4
351#undef p5
352#undef p6
353#undef p7
354}
355
359 ++tn;
360 if (tp == NULL)
361 tp = BALLOC_TYPE(tn * 7, mp_limb_t);
362
363#define A11 (mat->a00)
364#define A12 (mat->a01)
365#define A21 (mat->a10)
366#define A22 (mat->a11)
367#define A11n (mat->n00)
368#define A12n (mat->n01)
369#define A21n (mat->n10)
370#define A22n (mat->n11)
371
372#define s1 (dst->a00)
373#define s2 (dst->a01)
374#define s3 (dst->a10)
375#define s4 (dst->a11)
376#define p1 (tp)
377#define p2 (tp + tn)
378#define p3 (tp + 2 * tn)
379#define p4 (tp + 3 * tn)
380#define p5 (tp + 4 * tn)
381#define p6 (tp + 5 * tn)
382#define p7 (tp + 6 * tn)
383 mp_ssize_t n1, n2, n3, n4, n5, n6, n7, n8;
388
396
397#undef s1
398#undef s2
399#undef s3
400#undef s4
401
402#define p1n n1
403#define p2n n5
404#define p3n n2
405#define p4n n7
406#define p5n n6
407#define p6n n3
408#define p7n n4
409
410#undef A11
411#undef A12
412#undef A21
413#undef A22
414#undef A11n
415#undef A12n
416#undef A21n
417#undef A22n
418
419#define C11 (dst->a00)
420#define C12 (dst->a01)
421#define C21 (dst->a10)
422#define C22 (dst->a11)
423#define C11n (dst->n00)
424#define C12n (dst->n01)
425#define C21n (dst->n10)
426#define C22n (dst->n11)
427
429#define U1 p5 // U1 = p3 + p5
430#define U2 p1 // U2 = p1 - U1
431#define U3 U1 // U3 = U1 - p2
432#define U1n p5n
433#define U2n p1n
434#define U3n n8
438
443
444#undef C11
445#undef C12
446#undef C21
447#undef C22
448#undef C11n
449#undef C12n
450#undef C21n
451#undef C22n
452#undef U1
453#undef U2
454#undef U3
455#undef U1n
456#undef U2n
457#undef U3n
458
459#undef p1
460#undef p2
461#undef p3
462#undef p4
463#undef p5
464#undef p6
465#undef p7
466}
mp_limb_t * mp_ptr
Definition lmmp.h:80
uint64_t mp_size_t
Definition lmmp.h:77
int64_t mp_ssize_t
Definition lmmp.h:79
#define LMMP_MAX(h, i)
Definition lmmp.h:353
uint64_t mp_limb_t
Definition lmmp.h:76
#define LMMP_ABS(x)
Definition lmmp.h:349
#define lmmp_param_assert(x)
Definition lmmp.h:401
#define s1
#define C11n
#define s4
#define C22n
#define U2n
#define s3
#define p6n
#define s2
#define C12n
#define t4
#define p6
#define A22n
void lmmp_mat22_mul_strassen_(lmmp_mat22_t *dst, const lmmp_mat22_t *matA, const lmmp_mat22_t *matB, mp_ptr tp, mp_size_t tn, mp_size_t maxa)
计算(稠密)2x2矩阵和(稠密)2x2矩阵的乘积(STRASSEN算法)
Definition mat22_mul.c:204
#define B12n
int lmmp_mat22_mul_size_(lmmp_mat22_t *dst, const lmmp_mat22_t *matA, const lmmp_mat22_t *matB, mp_size_t *tn, mp_size_t *maxa)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition mat22_mul.c:23
void lmmp_mat22_mul_basecase_(lmmp_mat22_t *dst, const lmmp_mat22_t *matA, const lmmp_mat22_t *matB, mp_ptr tp, mp_size_t tn)
计算2x2矩阵和2x2矩阵的乘积
Definition mat22_mul.c:93
#define B21
#define t1
#define B21n
#define A22
#define B12
#define t3
void lmmp_mat22_sqr_strassen_(lmmp_mat22_t *dst, const lmmp_mat22_t *mat, mp_ptr tp, mp_size_t tn)
计算(稠密)2x2矩阵平方(STRASSEN算法)
Definition mat22_mul.c:356
#define U3n
#define A11n
#define A12
#define C12
#define U3
#define p1n
#define B22n
#define p2
#define A21n
#define p4n
#define A21
#define t2
#define A11
#define U1
#define C21n
#define C22
void lmmp_mat22_sqr_basecase_(lmmp_mat22_t *dst, const lmmp_mat22_t *matA, mp_ptr tp, mp_size_t tn)
计算2x2矩阵平方
Definition mat22_mul.c:129
#define A12n
#define B22
#define p3
#define B11
#define p3n
#define C21
#define C11
#define p5n
#define p1
#define p7
#define U1n
#define p7n
#define U2
#define p2n
#define p5
#define p4
#define B11n
#define MAT22_SQR_STRASSEN_THRESHOLD
Definition mparam.h:95
#define MAT22_MUL_STRASSEN_THRESHOLD
Definition mparam.h:92
#define tp
#define n
static mp_ssize_t lmmp_sqr_signed_(mp_ptr dst, mp_srcptr numa, mp_ssize_t na)
计算带符号数的平方
Definition signed.h:168
static mp_ssize_t lmmp_add_signed_(mp_ptr dst, mp_srcptr numa, mp_ssize_t na, mp_srcptr numb, mp_ssize_t nb)
计算带符号数的加法
Definition signed.h:35
static mp_ssize_t lmmp_mul_signed_(mp_ptr dst, mp_srcptr numa, mp_ssize_t na, mp_srcptr numb, mp_ssize_t nb)
计算带符号数的乘法
Definition signed.h:143
#define TEMP_DECL
Definition tmp_alloc.h:131
#define TEMP_FREE
Definition tmp_alloc.h:150
#define TALLOC_TYPE(n, type)
Definition tmp_alloc.h:148
#define TEMP_B_DECL
Definition tmp_alloc.h:132
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:146
#define TEMP_B_FREE
Definition tmp_alloc.h:159