LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
elem_mul.c
浏览该文件的文档.
1/*
2 * LAMMP - Copyright (C) 2025-2026 HJimmyK(Jericho Knox)
3 * This file is part of lammp, under the GNU LGPL v2 license.
4 * See LICENSE in the project root for the full license text.
5 */
6
7#include "../../../include/lammp/impl/ele_mul.h"
8#include "../../../include/lammp/impl/mparam.h"
9#include "../../../include/lammp/lmmpn.h"
10#include "../../../include/lammp/matrix.h"
11
12#define COPY(tp, src, n) \
13 tp = ALLOC_TYPE(n, mp_limb_t); \
14 lmmp_copy(tp, src, n)
15
16#define POP_THRESHOLD 5
17
19 lmmp_param_assert(dst != NULL && vec != NULL);
20 lmmp_param_assert(vec->n > 0);
21
22 num_heap heap;
23 lmmp_num_heap_init_(&heap, vec->n);
24
25 mp_size_t mpn = 1, len;
26 mp_ptr tp;
29 mp1[0] = 1;
30 bool imp = true; // true 表示当前mp1存储连乘结果
31
32 bool sign = true;
33 for (size_t i = 0; i < vec->n; ++i) {
34 if (vec->num[i] == NULL || vec->len[i] == 0) {
35 *dst = NULL;
36 return 0;
37 } else if (vec->len[i] < 0) {
38 sign = !sign;
39 }
40 len = LMMP_ABS(vec->len[i]);
41 if (len > VEC_ELEMMUL_MP_THRESHOLD || (len + mpn > VEC_ELEMMUL_MP_THRESHOLD)) {
42 COPY(tp, vec->num[i], len);
43 lmmp_num_heap_push_(&heap, tp, len);
44 } else {
45 if (imp) {
46 if (mpn >= len)
47 lmmp_mul_basecase_(mp2, mp1, mpn, vec->num[i], len);
48 else
49 lmmp_mul_basecase_(mp2, vec->num[i], len, mp1, mpn);
50 mpn += len;
51 mpn -= mp2[mpn - 1] == 0 ? 1 : 0;
52 imp = false;
53 } else {
54 if (mpn >= len)
55 lmmp_mul_basecase_(mp1, mp2, mpn, vec->num[i], len);
56 else
57 lmmp_mul_basecase_(mp1, vec->num[i], len, mp2, mpn);
58 mpn += len;
59 mpn -= mp1[mpn - 1] == 0 ? 1 : 0;
60 imp = true;
61 }
62 }
64 if (imp) {
65 lmmp_num_heap_push_(&heap, mp1, mpn);
67 mpn = 1;
68 mp1[0] = 1;
69 } else {
70 lmmp_num_heap_push_(&heap, mp2, mpn);
72 mpn = 1;
73 mp2[0] = 1;
74 }
75 }
76 }
77 if (imp) {
78 if (!(mpn == 1 && mp1[0] == 1))
79 lmmp_num_heap_push_(&heap, mp1, mpn);
80 else
81 lmmp_free(mp1);
82 lmmp_free(mp2);
83 } else {
84 if (!(mpn == 1 && mp2[0] == 1))
85 lmmp_num_heap_push_(&heap, mp2, mpn);
86 else
87 lmmp_free(mp2);
88 lmmp_free(mp1);
89 }
90
91 tp = lmmp_num_heap_mul_(&heap, &mpn);
93 *dst = tp;
94 return sign ? mpn : -mpn;
95}
96
97mp_size_t lmmp_limb_elem_mul_(mp_ptr* dst, const mp_limb_t* restrict limb, mp_size_t n) {
98 lmmp_param_assert(dst != NULL && limb != NULL);
99 lmmp_param_assert(n > 0);
100 mp_ptr mp = ALLOC_TYPE(n, mp_limb_t);
102
103 n = lmmp_elem_mul_ulong_(mp, (const ulongp)limb, n, tp);
104 *dst = mp;
105 lmmp_free(tp);
106 return n;
107}
108
110 lmmp_debug_assert(dst != NULL && slimb != NULL);
111 lmmp_debug_assert(n > 0);
112 TEMP_DECL;
113 ulongp limbs = TALLOC_TYPE(n, ulong);
114 bool sign = true;
115 for (mp_size_t i = 0; i < n; ++i) {
116 if (slimb[i] < 0) {
117 sign = !sign;
118 limbs[i] = -slimb[i];
119 } else {
120 limbs[i] = slimb[i];
121 }
122 }
123 mp_ptr mp = ALLOC_TYPE(n, mp_limb_t);
125
126 n = lmmp_elem_mul_ulong_(mp, limbs, n, tp);
127 *dst = mp;
128 TEMP_FREE;
129 return sign ? n : -n;
130}
void lmmp_num_heap_push_(num_heap *pq, mp_ptr elem, mp_size_t n)
入队
mp_size_t lmmp_elem_mul_ulong_(mp_ptr dst, const ulongp limbs, mp_size_t n, mp_ptr tp)
计算limbs数组的累乘积
static void lmmp_num_heap_init_(num_heap *restrict pq, size_t capa)
初始化优先队列
Definition ele_mul.h:58
static void lmmp_num_heap_free_(num_heap *restrict pq)
释放优先队列
Definition ele_mul.h:72
mp_ptr lmmp_num_heap_mul_(num_heap *pq, mp_size_t *rn)
将队列中所有元素相乘
mp_size_t lmmp_limb_elem_mul_(mp_ptr *dst, const mp_limb_t *restrict limb, mp_size_t n)
Definition elem_mul.c:97
mp_ssize_t lmmp_slimb_elem_mul_(mp_ptr *dst, const mp_slimb_t *restrict slimb, mp_size_t n)
Definition elem_mul.c:109
#define POP_THRESHOLD
Definition elem_mul.c:16
mp_ssize_t lmmp_vec_elem_mul_(mp_ptr *dst, const lmmp_vecn_t *vec)
计算向量的累乘
Definition elem_mul.c:18
#define COPY(tp, src, n)
Definition elem_mul.c:12
mp_limb_t * mp_ptr
Definition lmmp.h:215
uint64_t mp_size_t
Definition lmmp.h:212
int64_t mp_slimb_t
Definition lmmp.h:213
#define lmmp_debug_assert(x)
Definition lmmp.h:387
void lmmp_free(void *ptr)
内存释放函数(调用lmmp_heap_free_fn)
Definition memory.c:204
int64_t mp_ssize_t
Definition lmmp.h:214
uint64_t mp_limb_t
Definition lmmp.h:211
#define LMMP_ABS(x)
Definition lmmp.h:346
#define lmmp_param_assert(x)
Definition lmmp.h:398
void lmmp_mul_basecase_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
基础乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
mp_ptr * num
Definition matrix.h:81
size_t n
Definition matrix.h:83
mp_ssize_t * len
Definition matrix.h:82
#define VEC_ELEMMUL_MP_THRESHOLD
Definition mparam.h:95
#define tp
uint64_t * ulongp
Definition numth.h:45
uint64_t ulong
Definition numth.h:36
#define TEMP_DECL
Definition tmp_alloc.h:72
#define ALLOC_TYPE(n, type)
Definition tmp_alloc.h:112
#define TEMP_FREE
Definition tmp_alloc.h:93
#define TALLOC_TYPE(n, type)
Definition tmp_alloc.h:91