LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
cbrt.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/inlines.h"
17#include "../../../include/lammp/impl/longlong.h"
18#include "../../../include/lammp/impl/log2_exp2.h"
19#include "../../../include/lammp/numth.h"
20#include "../../../include/lammp/lmmpn.h"
21
22
23static inline void lmmp_cube_3_(mp_ptr restrict dst, mp_limb_t a) {
24 mp_limb_t t[2];
25 lmmp_mullh_(a, a, t);
26 lmmp_mullh_(t[0], a, dst);
27 lmmp_mullh_(t[1], a, t);
28 dst[1] += t[0];
29 dst[2] = t[1] + (dst[1] < t[0] ? 1 : 0);
30}
31
34 mp_limb_t x[2];
35 /* exact high 65 bits */
38 if (a2 == 0) {
41 a1_bits--;
42 if (a1_bits == 0)
43 a_hi = a0;
44 else
45 a_hi = (a1 << (LIMB_BITS - a1_bits)) | (a0 >> a1_bits);
46 } else {
48 bits = LIMB_BITS * 2 + a2_bits;
49 a2_bits--;
50 if (a2_bits == 0)
51 a_hi = a1;
52 else
53 a_hi = (a2 << (LIMB_BITS - a2_bits)) | (a1 >> a2_bits);
54 }
56
57 x[1] = bits - 1;
58 x[0] = log2_fixed_64(a_hi);
59
60 mp_limb_t r = lmmp_div_1_(x, x, 2, 3);
61 if (2 * r >= 3) // round
62 lmmp_inc(x);
63
64 mp_bitcnt_t shift = x[1];
65 x[0] = exp2_fixed_64(x[0]);
66
68 if (shift == 64)
69 return LIMB_MAX;
70 else
71 return (x[0] >> (64 - shift)) | (1ULL << shift);
72}
73
76
78 if (r == LIMB_MAX)
79 return LIMB_MAX;
80 mp_limb_t t[3], a[3] = {a0, a1, a2};
81 lmmp_cube_3_(t, r + 1);
82 int cmp = lmmp_cmp_(t, a, 3);
83 // approx的结果至多只会低估1
84 if (cmp <= 0)
85 return r + 1;
86 else
87 return r;
88}
89
90/**
91 * @brief 计算 [numa, na] 的立方
92 * @param dst 目标数组(3*na个limb)
93 * @param numa 源数组
94 * @param na 源数组的长度
95 * @param tp 临时数组(2*na个limb)
96 * @return 返回结果的数组长度
97 */
100 lmmp_mul_(dst, tp, 2 * na, numa, na);
101 na *= 3;
102 while (na > 1 && dst[na - 1] == 0) --na;
103 return na;
104}
105
107 lmmp_param_assert(na > 3 && na <= 6);
109 lmmp_param_assert(numa[na - 1] != 0);
110 /* extract the first 129 bits */
111 int bits = lmmp_limb_bits_(numa[na - 1]);
112 mp_bitcnt_t n = bits - 1;
114 if (bits == 1) {
115 high = numa[na - 2];
116 low = numa[na - 3];
117 } else {
118 bits--;
119 high = (numa[na - 1] << (64 - bits)) | (numa[na - 2] >> bits);
120 low = (numa[na - 2] << (64 - bits)) | (numa[na - 3] >> bits);
121 }
122
123 n += LIMB_BITS * (na - 1);
124 mp_limb_t x[3] = {0, 0, n};
125
127 mp_limb_t r = lmmp_div_1_(x, x, 3, 3);
128 if (2 * r >= 3) // round
129 lmmp_inc(x);
130
131 n = x[2];
132 high = x[1];
133 low = x[0];
134
136
137 lmmp_debug_assert(n >= 64 && n <= 128);
138 if (n == 64) {
139 dst[0] = x[1];
140 dst[1] = 1;
141 } else if (n < 128) {
142 n -= 64;
143 mp_limb_t t = 1ULL << n;
144 dst[1] = (x[1] >> (64 - n)) | t;
145 dst[0] = (x[1] << n) | (x[0] >> (64 - n));
146 } else {
147 dst[1] = LIMB_MAX;
148 dst[0] = LIMB_MAX;
149 }
150}
151
153 mp_limb_t ret[2];
155
156 if (ret[1] == LIMB_MAX && ret[0] == LIMB_MAX) {
157 dst[0] = LIMB_MAX;
158 dst[1] = LIMB_MAX;
159 } else {
160 mp_limb_t r[2];
161 r[0] = ret[0] + 1;
162 r[1] = ret[1] + (r[0] == 0 ? 1 : 0);
163 mp_limb_t t[10];
164 mp_size_t tn = lmmp_cube_(t, r, 2, t + 6);
165 if (tn < na) {
166 dst[0] = r[0];
167 dst[1] = r[1];
168 } else if (tn > na) {
169 dst[0] = ret[0];
170 dst[1] = ret[1];
171 } else if (tn == na) {
172 int cmp = lmmp_cmp_(t, numa, tn);
173 // approx的结果至多只会低估1
174 if (cmp <= 0) {
175 dst[0] = r[0];
176 dst[1] = r[1];
177 } else {
178 dst[0] = ret[0];
179 dst[1] = ret[1];
180 }
181 }
182 }
183}
mp_limb_t lmmp_cbrt_3_(mp_limb_t a0, mp_limb_t a1, mp_limb_t a2)
计算算数立方根 floor(cbrt(a0+a1*B+a2*B^2))
Definition cbrt.c:74
static mp_size_t lmmp_cube_(mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na, mp_ptr restrict tp)
计算 [numa, na] 的立方
Definition cbrt.c:98
void lmmp_cbrtapprox_6_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
计算近似立方根 floor(cbrt([numa,na]))-[0|1]
Definition cbrt.c:106
void lmmp_cbrt_6_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
计算算数立方根 floor(cbrt([numa,na]))
Definition cbrt.c:152
mp_limb_t lmmp_cbrtapprox_3_(mp_limb_t a0, mp_limb_t a1, mp_limb_t a2)
计算近似立方根 floor(cbrt(a0+a1*B+a2*B^2))-[0|1]
Definition cbrt.c:32
static void lmmp_cube_3_(mp_ptr restrict dst, mp_limb_t a)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition cbrt.c:23
#define lmmp_limb_bits_
Definition inlines.h:162
#define lmmp_mullh_
Definition inlines.h:164
#define lmmp_sqr_
Definition inlines.h:166
mp_limb_t * mp_ptr
Definition lmmp.h:80
size_t mp_bitcnt_t
Definition lmmp.h:82
uint64_t mp_size_t
Definition lmmp.h:77
#define lmmp_debug_assert(x)
Definition lmmp.h:390
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
#define LIMB_MAX
Definition lmmp.h:89
uint64_t mp_limb_t
Definition lmmp.h:76
#define LIMB_BITS
Definition lmmp.h:86
#define lmmp_param_assert(x)
Definition lmmp.h:401
mp_limb_t lmmp_div_1_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数除法
Definition div.c:77
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:996
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:938
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 exp2_fixed_128(uint64_t *dst, uint64_t high, uint64_t low)
floor(exp2(x/B)*B-B), B=2^128
Definition log2_exp2.c:409
void log2_fixed_128(uint64_t *dst, uint64_t high, uint64_t low)
floor(log2(1+x/B)*B), B=2^128
Definition log2_exp2.c:292
uint64_t exp2_fixed_64(uint64_t x)
floor(exp2(x/B)*B-B), B=2^64
Definition log2_exp2.c:485
uint64_t log2_fixed_64(uint64_t x)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition log2_exp2.c:458
#define a0
#define a1
#define a2
#define t
#define tp
#define n