LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
ele_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
10static inline void swap_num_node(num_node_ptr restrict a, num_node_ptr restrict b) {
11 num_node temp = *a;
12 *a = *b;
13 *b = temp;
14}
15
16// 向上调整最小堆(插入元素后维护堆性质:len小的在上)
17static inline void heapifyUp(num_heap* restrict pq, size_t index) {
18 size_t parent = (index - 1) / 2;
19
20 // 最小堆:当前节点len < 父节点len 时交换
21 while (index > 0 && pq->head[index].n < pq->head[parent].n) {
22 swap_num_node(&pq->head[index], &pq->head[parent]);
23 index = parent;
24 parent = (index - 1) / 2;
25 }
26}
27
28// 向下调整最小堆
29static inline void heapifyDown(num_heap* restrict pq, size_t index) {
30 if (pq->size == 0) {
31 return;
32 }
33 lmmp_debug_assert(index < pq->size);
34
35 while (1) {
36 size_t smallest = index;
37 size_t left = 2 * index + 1;
38 size_t right = 2 * index + 2;
39
40 if (left < pq->size && pq->head[left].n < pq->head[smallest].n) {
41 smallest = left;
42 }
43 if (right < pq->size && pq->head[right].n < pq->head[smallest].n) {
44 smallest = right;
45 }
46
47 if (smallest == index) {
48 break;
49 }
50
51 swap_num_node(&pq->head[index], &pq->head[smallest]);
52 index = smallest;
53 }
54}
55
56void lmmp_num_heap_push_(num_heap* restrict pq, mp_ptr elem, mp_size_t n) {
57 lmmp_param_assert(pq->size < pq->cap);
58 pq->head[pq->size].num = elem;
59 pq->head[pq->size].n = n;
60 pq->size++;
61 heapifyUp(pq, pq->size - 1);
62}
63
64bool lmmp_num_heap_pop_(num_heap* restrict pq, num_node_ptr restrict outElem) {
65 if (pq->size == 0) {
66 outElem->num = NULL;
67 outElem->n = 0;
68 return false;
69 }
70 *outElem = pq->head[0];
71 pq->head[0] = pq->head[pq->size - 1];
72 --(pq->size);
73 heapifyDown(pq, 0);
74 return true;
75}
76
77mp_ptr lmmp_num_heap_mul_(num_heap* restrict pq, mp_size_t* restrict rn) {
78 num_node numa, numb;
79 numa.num = NULL;
80 numb.num = NULL;
81 numa.n = 0;
82 numb.n = 0;
83
84 while (lmmp_num_heap_pop_(pq, &numa)) {
85 if (!lmmp_num_heap_pop_(pq, &numb)) {
86 break;
87 }
88 mp_ptr restrict prod = ALLOC_TYPE(numa.n + numb.n, mp_limb_t);
89 lmmp_mul_(prod, numb.num, numb.n, numa.num, numa.n);
90 lmmp_free(numa.num);
91 lmmp_free(numb.num);
92 numa.num = prod;
93 numa.n += numb.n;
94 numa.n -= numa.num[numa.n - 1] == 0 ? 1 : 0;
95 lmmp_num_heap_push_(pq, numa.num, numa.n);
96 }
97 *rn = numa.n;
98 return numa.num;
99}
100
101mp_size_t lmmp_elem_mul_ulong_(mp_ptr restrict dst, const ulongp restrict limbs, mp_size_t n, mp_ptr restrict tp) {
103 lmmp_debug_assert(n > 0);
104 dst[0] = limbs[0];
105 mp_size_t rn = 1;
106 for (mp_size_t i = 1; i < n; i++) {
107 dst[rn] = lmmp_mul_1_(dst, dst, rn, limbs[i]);
108 rn++;
109 rn -= dst[rn - 1] == 0 ? 1 : 0;
110 }
111 return rn;
112 }
113 mp_size_t halfn = n / 2;
114 mp_size_t n1 = lmmp_elem_mul_ulong_(tp, limbs, halfn, dst);
115 mp_size_t n2 = lmmp_elem_mul_ulong_(tp + halfn, limbs + halfn, n - halfn, dst + halfn);
116 if (n1 > n2)
117 lmmp_mul_(dst, tp, n1, tp + halfn, n2);
118 else
119 lmmp_mul_(dst, tp + halfn, n2, tp, n1);
120 n = n1 + n2;
121 n -= dst[n - 1] == 0 ? 1 : 0;
122 return n;
123}
static void heapifyDown(num_heap *restrict pq, size_t index)
Definition ele_mul.c:29
static void swap_num_node(num_node_ptr restrict a, num_node_ptr restrict b)
Definition ele_mul.c:10
void lmmp_num_heap_push_(num_heap *restrict pq, mp_ptr elem, mp_size_t n)
Definition ele_mul.c:56
bool lmmp_num_heap_pop_(num_heap *restrict pq, num_node_ptr restrict outElem)
Definition ele_mul.c:64
mp_ptr lmmp_num_heap_mul_(num_heap *restrict pq, mp_size_t *restrict rn)
Definition ele_mul.c:77
mp_size_t lmmp_elem_mul_ulong_(mp_ptr restrict dst, const ulongp restrict limbs, mp_size_t n, mp_ptr restrict tp)
Definition ele_mul.c:101
static void heapifyUp(num_heap *restrict pq, size_t index)
Definition ele_mul.c:17
mp_size_t n
Definition ele_mul.h:42
mp_ptr num
Definition ele_mul.h:41
mp_limb_t * mp_ptr
Definition lmmp.h:215
uint64_t mp_size_t
Definition lmmp.h:212
#define lmmp_debug_assert(x)
Definition lmmp.h:387
void lmmp_free(void *ptr)
内存释放函数(调用lmmp_heap_free_fn)
Definition memory.c:204
uint64_t mp_limb_t
Definition lmmp.h:211
#define lmmp_param_assert(x)
Definition lmmp.h:398
void lmmp_mul_(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_limb_t lmmp_mul_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数乘以单limb操作 [dst,na] = [numa,na] * x
#define ELEM_MUL_BASECASE_THRESHOLD
Definition mparam.h:127
#define tp
uint64_t * ulongp
Definition numth.h:45
#define ALLOC_TYPE(n, type)
Definition tmp_alloc.h:112