LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
pow_win2.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/tmp_alloc.h"
8#include "../../../include/lammp/lmmpn.h"
9#include "../../../include/lammp/numth.h"
10
11#define mul_b(_i_) \
12 if (rsq) { \
13 if (b##_i_##n >= rn) \
14 lmmp_mul_(dst, b##_i_, b##_i_##n, sq, rn); \
15 else \
16 lmmp_mul_(dst, sq, rn, b##_i_, b##_i_##n); \
17 rn += b##_i_##n; \
18 rn -= (dst[rn - 1] == 0) ? 1 : 0; \
19 rsq = false; \
20 } else { \
21 if (b##_i_##n >= rn) \
22 lmmp_mul_(sq, b##_i_, b##_i_##n, dst, rn); \
23 else \
24 lmmp_mul_(sq, dst, rn, b##_i_, b##_i_##n); \
25 rn += b##_i_##n; \
26 rn -= (sq[rn - 1] == 0) ? 1 : 0; \
27 rsq = true; \
28 }
29
30mp_size_t lmmp_pow_win2_(mp_ptr restrict dst, mp_size_t rn, mp_srcptr restrict base, mp_size_t n, ulong exp) {
31 lmmp_param_assert(exp > 0);
32 lmmp_param_assert(n > 0);
33 lmmp_param_assert(dst != NULL);
35
36#define b1 base
37#define b1n n
38#define new_b(_i_) mp_ptr restrict b##_i_ = TALLOC_TYPE(b##_i_##n, mp_limb_t)
39
40 mp_size_t b2n = n << 1, b3n = b2n + n;
41 new_b(2);
42 new_b(3);
43
44 lmmp_sqr_(b2, b1, b1n);
45 b2n = b1n << 1;
46 b2n -= b2[b2n - 1] == 0 ? 1 : 0;
47 lmmp_mul_(b3, b2, b2n, b1, b1n);
48 b3n = b2n + b1n;
49 b3n -= b3[b3n - 1] == 0 ? 1 : 0;
50
51 bool rsq = true;
52 mp_ptr restrict sq = BALLOC_TYPE(rn, mp_limb_t);
53 rn = 1;
54 int i = 31, j;
55 while ((exp & (0x3ull << ((i--) * 2))) == 0);
56
57 /*
58 模拟一次,让最后一次计算结果恰好是dst,避免最后一次可能的拷贝
59 */
60 for (j = i + 1; j != -1; --j) {
61 int p = (exp & (0x3ull << (j * 2))) >> (j * 2);
62 if (p != 0)
63 rsq = !rsq;
64 }
65 if (rsq) {
66 dst[0] = 1;
67 rsq = false;
68 } else {
69 sq[0] = 1;
70 rsq = true;
71 }
72
73 for (++i; i != -1; --i) {
74 int p = (exp & (0x3ull << (i * 2))) >> (i * 2);
75 if (p == 0) {
76 ;
77 } else if (p == 1) {
78 mul_b(1)
79 } else if (p == 2) {
80 mul_b(2)
81 } else {
82 mul_b(3)
83 }
84
85 if (i > 0) {
86 if (rsq) {
87 lmmp_sqr_(dst, sq, rn);
88 rn <<= 1;
89 rn -= (dst[rn - 1] == 0) ? 1 : 0;
90 lmmp_sqr_(sq, dst, rn);
91 rn <<= 1;
92 rn -= (sq[rn - 1] == 0) ? 1 : 0;
93 } else {
94 lmmp_sqr_(sq, dst, rn);
95 rn <<= 1;
96 rn -= (sq[rn - 1] == 0) ? 1 : 0;
97 lmmp_sqr_(dst, sq, rn);
98 rn <<= 1;
99 rn -= (dst[rn - 1] == 0) ? 1 : 0;
100 }
101 }
102 }
103 lmmp_debug_assert(rsq == false);
104
105 TEMP_FREE;
106 return rn;
107
108#undef b1
109#undef b1n
110#undef new_b
111}
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
const mp_limb_t * mp_srcptr
Definition lmmp.h:216
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]
void lmmp_sqr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
大数平方操作 [dst,2*na] = [numa,na]^2
Definition sqr.c:10
#define b2
#define b3
uint64_t ulong
Definition numth.h:36
#define b2n
#define b3n
#define b1
mp_size_t lmmp_pow_win2_(mp_ptr restrict dst, mp_size_t rn, mp_srcptr restrict base, mp_size_t n, ulong exp)
Definition pow_win2.c:30
#define b1n
#define new_b(_i_)
#define mul_b(_i_)
Definition pow_win2.c:11
#define TEMP_DECL
Definition tmp_alloc.h:72
#define TEMP_FREE
Definition tmp_alloc.h:93
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:89