LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
lmmpn.h 文件参考
#include <stdbool.h>
#include "lmmp.h"
+ lmmpn.h 的引用(Include)关系图:
+ 此图展示该文件直接或间接的被哪些文件引用了:

浏览源代码.

宏定义

#define INLINE_   static inline
 Copyright (C) 2026 HJimmyK(Jericho Knox)
 
#define LMMP_ADDCB_(r, x, y)   ((r) < (y))
 
#define LMMP_AORS_(FUNCTION, TEST)
 
#define LMMP_AORS_1_(OP, CB)
 
#define lmmp_dec(p)
 大数减1宏(预期无借位)
 
#define lmmp_dec_1(p, dec)
 大数减指定值宏(预期无借位)
 
#define lmmp_inc(p)
 大数加1宏(预期无进位)
 
#define lmmp_inc_1(p, inc)
 大数加指定值宏(预期无进位)
 
#define LMMP_SUBCB_(r, x, y)   ((x) < (y))
 

函数

static mp_limb_t lmmp_add_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 大数加法静态内联函数 [dst,na]=[numa,na]+[numb,nb]
 
static mp_limb_t lmmp_add_1_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
 大数加单精度数静态内联函数 [dst,na]=[numa,na]+x
 
mp_limb_t lmmp_add_n_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 无进位的n位加法 [dst,n] = [numa,n] + [numb,n]
 
mp_limb_t lmmp_add_n_sub_n_ (mp_ptr dsta, mp_ptr dstb, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 同时执行n位加法和减法 ([dsta,n],[dstb,n]) = ([numa,n]+[numb,n],[numa,n]-[numb,n])
 
mp_limb_t lmmp_add_nc_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
 带进位的n位加法 [dst,n] = [numa,n] + [numb,n] + c
 
mp_limb_t lmmp_addmul_1_ (mp_ptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t b)
 大数乘以单limb并累加操作 [numa,n] += [numb,n] * b
 
mp_limb_t lmmp_addshl1_n_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 加法结合左移1位操作 [dst,n] = [numa,n] + ([numb,n] << 1)
 
void lmmp_bninv_ (mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_size_t ni)
 精确逆元计算 [dstq,na+ni+2] = B^(2*(na+ni)) / ([numa,na] * B^ni)
 
static int lmmp_cmp_ (mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 大数比较函数(内联)
 
void lmmp_div_ (mp_ptr dstq, mp_ptr dstr, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 大数除法和取模操作
 
mp_limb_t lmmp_div_1_ (mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_limb_t x)
 单精度数除法
 
mp_limb_t lmmp_div_1_s_ (mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_limb_t x)
 单精度数除法(除数为1个limb)
 
void lmmp_div_2_ (mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_ptr numb)
 双精度数除法 (除数为2个limb)
 
mp_limb_t lmmp_div_2_s_ (mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb)
 双精度数除法(除数为2个limb)
 
mp_limb_t lmmp_div_3_2_ (mp_ptr numa, mp_srcptr numb, mp_limb_t inv21)
 3/2位除法运算 [numa,2]=[numa,3] mod [numb,2]
 
mp_limb_t lmmp_div_basecase_ (mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
 基础除法运算
 
mp_limb_t lmmp_div_divide_ (mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
 分治除法运算
 
static mp_size_t lmmp_div_inv_size_ (mp_size_t nq, mp_size_t nb)
 计算预计算逆元的尺寸
 
mp_limb_t lmmp_div_mulinv_ (mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_srcptr invappr, mp_size_t ni)
 乘法逆元除法
 
mp_limb_t lmmp_div_s_ (mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 除法运算
 
static bool lmmp_endian (void)
 运行时判断端序
 
mp_bitcnt_t lmmp_extract_bits_ (mp_srcptr num, mp_size_t n, mp_limb_t *ext, int bits)
 提取高位指定位数,并返回低位bits位数
 
mp_size_t lmmp_fft_next_size_ (mp_size_t n)
 计算满足 >=n 的最小费马/梅森乘法可行尺寸
 
mp_size_t lmmp_from_str_ (mp_ptr dst, const mp_byte_t *src, mp_size_t len, int base)
 字符串转大数操作 [src,len,base] to [dst,return value,B]
 
mp_size_t lmmp_from_str_len_ (const mp_byte_t *src, mp_size_t len, int base)
 计算字符串转大数所需的 limb 缓冲区长度
 
void lmmp_inv_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t nf)
 大数求逆操作 [dst,na+nf+1] = (B^(2*(na+nf)) - 1) / ([numa,na]*B^nf) + [0|-1]
 
mp_limb_t lmmp_inv_1_ (mp_limb_t x)
 1阶逆元计算 (inv1)
 
mp_limb_t lmmp_inv_2_1_ (mp_limb_t xh, mp_limb_t xl)
 2-1阶逆元计算 (inv21)
 
void lmmp_inv_basecase_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 近似逆元计算
 
void lmmp_inv_prediv_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t ni)
 除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B
 
void lmmp_invappr_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 近似逆元计算 (invappr)
 
void lmmp_invappr_newton_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 近似逆元计算(牛顿迭代法)
 
int lmmp_leading_zeros_ (mp_limb_t x)
 计算一个单精度数(limb)中前导零的个数
 
int lmmp_limb_bits_ (mp_limb_t x)
 计算满足 2^k > x 的最小自然数k
 
int lmmp_limb_popcnt_ (mp_limb_t x)
 计算一个64位无符号整数中1的个数
 
mp_limb_t lmmp_mod_1_ (mp_srcptr numa, mp_size_t na, mp_limb_t x)
 单精度数取余
 
void lmmp_mod_2_ (mp_srcptr numa, mp_size_t na, mp_ptr numb)
 双精度数取余 (除数为2个limb)
 
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
 
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]
 
void lmmp_mul_fermat_ (mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 费马数模乘法 [dst,rn+1]=[numa,na]*[numb,nb] mod B^rn+1
 
void lmmp_mul_fft_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 FFT乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_fft_unbalance_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 FFT不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_mersenne_ (mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 梅森数模乘法 [dst,rn] = [numa,na]*[numb,nb] mod B^rn-1
 
void lmmp_mul_n_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 等长大数乘法操作 [dst,2*n] = [numa,n] * [numb,n]
 
void lmmp_mul_toom22_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-22乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom32_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-32乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom33_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-33乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom42_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-42乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom42_unbalance_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-42不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom43_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-43乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom44_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-44乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom52_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-52乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom53_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-53乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom62_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-62乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
void lmmp_mul_toom62_unbalance_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 Toom-62不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]
 
mp_limb_t lmmp_mulh_ (mp_limb_t a, mp_limb_t b)
 计算两个64位无符号整数相乘的高位结果 (a*b)/B
 
void lmmp_mullh_ (mp_limb_t a, mp_limb_t b, mp_ptr dst)
 计算两个64位无符号整数相乘的128位结果 (a*b)
 
void lmmp_mullo_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
 
void lmmp_mullo_dc_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_ptr tp, mp_size_t n)
 低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
 
void lmmp_mullo_fft_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_ptr scratch)
 低位FFT乘法 [dst,n] = [numa,n] * [numb,n] mod B^n
 
void lmmp_not_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 大数按位取反操作 [dst,na] = ~[numa,na] (对每个limb执行按位非操作)
 
mp_limb_t lmmp_shl_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
 大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0
 
mp_limb_t lmmp_shl_c_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl, mp_limb_t c)
 带进位的大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充c的低shl位
 
mp_limb_t lmmp_shlnot_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
 左移后按位取反操作 [dst,na] = ~([numa,na] << shl),dst的低shl位填充1
 
mp_limb_t lmmp_shr1add_n_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 加法后右移1位 [dst,n] = ([numa,n] + [numb,n]) >> 1
 
mp_limb_t lmmp_shr1add_nc_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
 带进位加法后右移1位 [dst,n] = ([numa,n] + [numb,n] + c) >> 1
 
mp_limb_t lmmp_shr1sub_n_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 减法后右移1位 [dst,n] = ([numa,n] - [numb,n]) >> 1
 
mp_limb_t lmmp_shr1sub_nc_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
 带借位减法后右移1位 [dst,n] = ([numa,n] - [numb,n] - c) >> 1
 
mp_limb_t lmmp_shr_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr)
 大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0
 
mp_limb_t lmmp_shr_c_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr, mp_limb_t c)
 带进位的大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充c的高shr位
 
void lmmp_sqr_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 大数平方操作 [dst,2*na] = [numa,na]^2
 
void lmmp_sqr_basecase_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 基础平方运算 [dst,2*na] = [numa,na]^2
 
void lmmp_sqr_toom2_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 Toom-2平方运算 [dst,2*na] = [numa,na]^2
 
void lmmp_sqr_toom3_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 Toom-3平方运算 [dst,2*na] = [numa,na]^2
 
void lmmp_sqr_toom4_ (mp_ptr pp, mp_srcptr ap, mp_size_t an)
 Toom-4平方运算 [dst,2*na] = [numa,na]^2
 
void lmmp_sqrlo_dc_ (mp_ptr dst, mp_srcptr numa, mp_ptr tp, mp_size_t n)
 低位平方 [dst,n] = [numa,n]^2 mod B^n
 
void lmmp_sqrt_ (mp_ptr dsts, mp_ptr dstr, mp_srcptr numa, mp_size_t na, mp_size_t nf)
 大数平方根和取余操作
 
static mp_limb_t lmmp_sub_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
 大数减法静态内联函数 [dst,na]=[numa,na]-[numb,nb]
 
static mp_limb_t lmmp_sub_1_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
 大数减单精度数静态内联函数 [dst,na]=[numa,na]-x
 
mp_limb_t lmmp_sub_n_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 无借位的n位减法 [dst,n] = [numa,n] - [numb,n]
 
mp_limb_t lmmp_sub_nc_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
 带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c
 
mp_limb_t lmmp_submul_1_ (mp_ptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t b)
 大数乘以单limb并累减操作 [numa,n] -= [numb,n] * b
 
mp_limb_t lmmp_subshl1_n_ (mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
 减法结合左移1位操作 [dst,n] = [numa,n] - ([numb,n] << 1)
 
int lmmp_tailing_zeros_ (mp_limb_t x)
 计算一个单精度数(limb)中末尾零的个数
 
mp_size_t lmmp_to_str_ (mp_byte_t *dst, mp_srcptr numa, mp_size_t na, int base)
 大数转字符串操作 [numa,na,B] to [dst,return value,base]
 
mp_size_t lmmp_to_str_len_ (mp_srcptr numa, mp_size_t na, int base)
 计算大数转换为字符串,字符串需要的缓冲区长度
 
static int lmmp_zero_q_ (mp_srcptr p, mp_size_t n)
 大数判零函数(内联)
 

宏定义说明

◆ INLINE_

#define INLINE_   static inline

Copyright (C) 2026 HJimmyK(Jericho Knox)

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 lmmpn.h55 行定义.

◆ LMMP_ADDCB_

#define LMMP_ADDCB_ (   r,
  x,
  y 
)    ((r) < (y))

在文件 lmmpn.h1090 行定义.

◆ LMMP_AORS_

#define LMMP_AORS_ (   FUNCTION,
  TEST 
)
值:
do { \
if (nb >= na) \
return 1; \
_x_ = numa[nb]; \
} while (TEST); \
} \
if (dst != numa && na != nb) \
lmmp_copy(dst + nb, numa + nb, na - nb); \
return 0
uint64_t mp_limb_t
Definition lmmp.h:76
#define numb
#define n

在文件 lmmpn.h1027 行定义.

1029 { \
1030 do { \
1031 if (nb >= na) \
1032 return 1; \
1033 _x_ = numa[nb]; \
1034 } while (TEST); \
1035 } \
1036 if (dst != numa && na != nb) \
1037 lmmp_copy(dst + nb, numa + nb, na - nb); \
1038 return 0

◆ LMMP_AORS_1_

#define LMMP_AORS_1_ (   OP,
  CB 
)
值:
mp_size_t _i_ = 1; \
mp_limb_t _x_ = numa[0], _r_ = _x_ OP x; \
dst[0] = _r_; \
if (CB(_r_, _x_, x)) { \
do { \
if (_i_ >= na) \
return 1; \
_x_ = numa[_i_]; \
_r_ = _x_ OP 1; \
dst[_i_] = _r_; \
++_i_; \
} while (CB(_r_, _x_, 1)); \
} \
if (numa != dst && na != _i_) \
return 0
uint64_t mp_size_t
Definition lmmp.h:77

在文件 lmmpn.h1071 行定义.

1075 { \
1076 do { \
1077 if (_i_ >= na) \
1078 return 1; \
1079 _x_ = numa[_i_]; \
1080 _r_ = _x_ OP 1; \
1081 dst[_i_] = _r_; \
1082 ++_i_; \
1083 } while (CB(_r_, _x_, 1)); \
1084 } \
1085 if (numa != dst && na != _i_) \
1086 lmmp_copy(dst + _i_, numa + _i_, na - _i_); \
1087 return 0

◆ lmmp_dec

#define lmmp_dec (   p)
值:
do { \
mp_ptr _p_ = (p); \
while ((*(_p_++))-- == 0); \
} while (0)
mp_limb_t * mp_ptr
Definition lmmp.h:80

大数减1宏(预期无借位)

参数
p指向大数起始位置的指针
注解
从最低位开始减1,直到遇到非零值(预期无借位溢出)

在文件 lmmpn.h965 行定义.

966 { \
967 mp_ptr _p_ = (p); \
968 while ((*(_p_++))-- == 0); \
969 } while (0)

◆ lmmp_dec_1

#define lmmp_dec_1 (   p,
  dec 
)
值:
do { \
mp_ptr _p_ = (p); \
_x_ = *_p_; \
*_p_ = _x_ - _dec_; \
while ((*(++_p_))-- == 0); \
} while (0)

大数减指定值宏(预期无借位)

参数
p指向大数起始位置的指针
dec要减的单精度数值
注解
先减最低位,若产生借位则逐位减1,直到无借位(预期无溢出)

在文件 lmmpn.h977 行定义.

978 { \
979 mp_ptr _p_ = (p); \
980 mp_limb_t _dec_ = (dec), _x_; \
981 _x_ = *_p_; \
982 *_p_ = _x_ - _dec_; \
983 if (_x_ < _dec_) \
984 while ((*(++_p_))-- == 0); \
985 } while (0)

◆ lmmp_inc

#define lmmp_inc (   p)
值:
do { \
mp_ptr _p_ = (p); \
while (++(*(_p_++)) == 0); \
} while (0)

大数加1宏(预期无进位)

参数
p指向大数起始位置的指针
注解
从最低位开始加1,直到遇到非零值(预期无进位溢出)

在文件 lmmpn.h938 行定义.

939 { \
940 mp_ptr _p_ = (p); \
941 while (++(*(_p_++)) == 0); \
942 } while (0)

◆ lmmp_inc_1

#define lmmp_inc_1 (   p,
  inc 
)
值:
do { \
mp_ptr _p_ = (p); \
mp_limb_t _inc_ = (inc), _x_; \
_x_ = *_p_ + _inc_; \
*_p_ = _x_; \
while (++(*(++_p_)) == 0); \
} while (0)

大数加指定值宏(预期无进位)

参数
p指向大数起始位置的指针
inc要加的单精度数值
注解
先加最低位,若产生进位则逐位加1,直到无进位(预期无溢出)

在文件 lmmpn.h950 行定义.

951 { \
952 mp_ptr _p_ = (p); \
953 mp_limb_t _inc_ = (inc), _x_; \
954 _x_ = *_p_ + _inc_; \
955 *_p_ = _x_; \
956 if (_x_ < _inc_) \
957 while (++(*(++_p_)) == 0); \
958 } while (0)

◆ LMMP_SUBCB_

#define LMMP_SUBCB_ (   r,
  x,
  y 
)    ((x) < (y))

在文件 lmmpn.h1092 行定义.

函数说明

◆ lmmp_add_()

static mp_limb_t lmmp_add_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)
inlinestatic

大数加法静态内联函数 [dst,na]=[numa,na]+[numb,nb]

参数
dst输出结果缓冲区,存储numa + numb
numa第一个加数,长度为na
na第一个加数的 limb 长度
numb第二个加数,长度为nb
nb第二个加数的 limb 长度
返回
进位标志(1表示有进位,0表示无进位)
警告
0<nb<=na, eqsep(dst,[numa|numb])

在文件 lmmpn.h1050 行定义.

1050 {
1051 LMMP_AORS_(lmmp_add_n_, ((dst[nb++] = _x_ + 1) == 0));
1052}
#define LMMP_AORS_(FUNCTION, TEST)
Definition lmmpn.h:1027
mp_limb_t lmmp_add_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无进位的n位加法 [dst,n] = [numa,n] + [numb,n]
Definition add_n.c:81

引用了 lmmp_add_n_(), LMMP_AORS_ , 以及 n.

被这些函数引用 lmmp_add_signed_(), lmmp_invsqrt_newton_(), lmmp_mul_fermat_recombine_(), lmmp_mul_fft_(), lmmp_mul_fft_cache_(), lmmp_mul_mersenne_(), lmmp_mul_mersenne_single_(), lmmp_mul_toom22_(), lmmp_mul_toom32_(), lmmp_mul_toom33_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom43_(), lmmp_mul_toom52_(), lmmp_mul_toom53_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_init_(), lmmp_mullo_fft_(), lmmp_sqr_toom2_(), lmmp_sqr_toom3_(), lmmp_toom_eval_dgr3_pm1_(), lmmp_toom_eval_dgr3_pm2_() , 以及 lmmp_toom_eval_pm1_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_add_1_()

static mp_limb_t lmmp_add_1_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_limb_t  x 
)
inlinestatic

大数加单精度数静态内联函数 [dst,na]=[numa,na]+x

参数
dst输出结果缓冲区,存储numa + x
numa被加数,长度为na
na被加数的 limb 长度
x加数(单个 limb )
返回
进位标志(1表示有进位,0表示无进位)
警告
na>0, eqsep(dst,numa)

在文件 lmmpn.h1103 行定义.

#define LMMP_AORS_1_(OP, CB)
Definition lmmpn.h:1071
#define LMMP_ADDCB_(r, x, y)
Definition lmmpn.h:1090

引用了 LMMP_ADDCB_ , 以及 LMMP_AORS_1_.

被这些函数引用 lmmp_divexact_unbalanced_(), lmmp_from_str_basecase_(), lmmp_inv_prediv_(), lmmp_mul_fermat_recombine_(), lmmp_mul_mersenne_(), lmmp_mul_mersenne_single_(), lmmp_mul_toom32_(), lmmp_mul_toom33_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom43_(), lmmp_sqr_toom3_(), lmmp_sqrt_divide_() , 以及 lmmp_toom_eval_pm2_().

+ 这是这个函数的调用关系图:

◆ lmmp_add_n_()

mp_limb_t lmmp_add_n_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

无进位的n位加法 [dst,n] = [numa,n] + [numb,n]

参数
dst结果输出指针
numa第一个加数指针
numb第二个加数指针
nlimb长度
警告
n>0, eqsep(dst,[numa|numb])
返回
运算后的最终进位值 [0|1]

在文件 add_n.c81 行定义.

81 {
82 mp_size_t i = 0;
83 mp_limb_t cy = 0;
84
85 for (; i + 4 <= n; i += 4) {
86 mp_limb_t a0, b0, r0;
87 mp_limb_t a1, b1, r1;
88 mp_limb_t a2, b2, r2;
89 mp_limb_t a3, b3, r3;
90
91 a0 = numa[i + 0];
92 b0 = numb[i + 0];
93
94 a1 = numa[i + 1];
95 b1 = numb[i + 1];
96
97 a2 = numa[i + 2];
98 b2 = numb[i + 2];
99
100 a3 = numa[i + 3];
101 b3 = numb[i + 3];
102
103 r0 = a0 + cy;
104 cy = (r0 < cy);
105 r0 += b0;
106 cy += (r0 < b0);
107
108 r1 = a1 + cy;
109 cy = (r1 < cy);
110 r1 += b1;
111 cy += (r1 < b1);
112
113 r2 = a2 + cy;
114 cy = (r2 < cy);
115 r2 += b2;
116 cy += (r2 < b2);
117
118 r3 = a3 + cy;
119 cy = (r3 < cy);
120 r3 += b3;
121 cy += (r3 < b3);
122
123 dst[i + 0] = r0;
124 dst[i + 1] = r1;
125 dst[i + 2] = r2;
126 dst[i + 3] = r3;
127 }
128
129 for (; i < n; i++) {
130 mp_limb_t a, b, r;
131 a = numa[i];
132 b = numb[i];
133 r = a + cy;
134 cy = (r < cy);
135 r += b;
136 cy += (r < b);
137 dst[i] = r;
138 }
139
140 return cy;
141}
#define b0
#define b1
#define a0
#define a1
#define r2
#define r1
#define a2
#define r3
#define r0
#define b2
#define a3
#define b3

引用了 a0, a1, a2, a3, b0, b1, b2, b3, n, numb, r0, r1, r2 , 以及 r3.

被这些函数引用 lmmp_add_(), lmmp_binvert_n_dc_(), lmmp_binvert_unbalanced_(), lmmp_div_(), lmmp_div_basecase_(), lmmp_div_divide_n_(), lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_from_str_divide_(), lmmp_invappr_newton_(), lmmp_mul_(), lmmp_mul_fft_unbalance_(), lmmp_mul_toom22_(), lmmp_mul_toom32_(), lmmp_mul_toom33_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom42_unbalance_(), lmmp_mul_toom43_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_(), lmmp_mul_toom62_cache_init_(), lmmp_mul_toom62_unbalance_(), lmmp_mullo_dc_(), lmmp_sqr_toom2_(), lmmp_sqrlo_dc_(), lmmp_sqrt_divide_(), lmmp_toom_eval_dgr3_pm1_(), lmmp_toom_eval_dgr3_pm2_(), lmmp_toom_eval_pm1_(), lmmp_toom_interp5_(), lmmp_toom_interp6_() , 以及 lmmp_toom_interp7_().

+ 这是这个函数的调用关系图:

◆ lmmp_add_n_sub_n_()

mp_limb_t lmmp_add_n_sub_n_ ( mp_ptr  dsta,
mp_ptr  dstb,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

同时执行n位加法和减法 ([dsta,n],[dstb,n]) = ([numa,n]+[numb,n],[numa,n]-[numb,n])

参数
dsta加法结果输出指针
dstb减法结果输出指针
numa第一个操作数指针(被加数/被减数)
numb第二个操作数指针(加数/减数)
nlimb长度
警告
n>0, eqsep(dsta,[numa|numb]), eqsep(dstb,[numa|numb])
返回
组合返回值 cb = 2*c + b (c为加法进位, b为减法借位) 返回值范围: 0(无进位无借位),1(无进位有借位),2(有进位无借位),3(有进位有借位)

同时执行n位加法和减法 ([dsta,n],[dstb,n]) = ([numa,n]+[numb,n],[numa,n]-[numb,n])

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 add_n_sub_n.c20 行定义.

20 {
21 /*
22 这段代码看起来有点奇怪的原因是,对于使用x64汇编时,我们会使用带进位的加法和减法,而x64中
23 只能使用同一个进位寄存器,所以我们需要将两条指令分开执行。
24 而不使用汇编时,编译器通常不会使用进位寄存器。因此我们可以同时读取两路内存,以减少读写次数。
25 */
26#ifdef USE_ASM
27 mp_limb_t acyo = 0, scyo = 0;
29
30 if (dsta != numa && dsta != numb) {
31 for (off = 0; off < n; off += PART_SIZE) {
35 }
36 } else if (dstb != numa && dstb != numb) {
37 for (off = 0; off < n; off += PART_SIZE) {
41 }
42 } else {
44 for (off = 0; off < n; off += PART_SIZE) {
49 }
50 }
51 return 2 * acyo + scyo;
52#else
55
56 for (i = 0, acyo = 0, scyo = 0; i < n; i++) {
57 mp_limb_t a, b, r;
58 a = numa[i];
59 b = numb[i];
60 r = a + acyo;
61 acyo = (r < acyo);
62 r += b;
63 acyo += (r < b);
64 dsta[i] = r;
65
66 b += scyo;
67 scyo = (b < scyo);
68 scyo += (a < b);
69 dstb[i] = a - b;
70 }
71 return 2 * acyo + scyo;
72#endif
73}
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
#define LMMP_MIN(l, o)
Definition lmmp.h:351
mp_limb_t lmmp_add_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带进位的n位加法 [dst,n] = [numa,n] + [numb,n] + c
Definition add_n.c:19
mp_limb_t lmmp_sub_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c
Definition sub_n.c:19
#define PART_SIZE
Definition mparam.h:89
#define tp

引用了 lmmp_add_nc_(), lmmp_copy, LMMP_MIN, lmmp_sub_nc_(), n, numb, PART_SIZE , 以及 tp.

被这些函数引用 lmmp_mul_toom32_(), lmmp_mul_toom33_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom43_(), lmmp_mul_toom52_(), lmmp_mul_toom53_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_init_(), lmmp_sqr_toom3_(), lmmp_toom_eval_dgr3_pm1_(), lmmp_toom_eval_dgr3_pm2_(), lmmp_toom_eval_pm1_() , 以及 lmmp_toom_eval_pm2_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_add_nc_()

mp_limb_t lmmp_add_nc_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n,
mp_limb_t  c 
)

带进位的n位加法 [dst,n] = [numa,n] + [numb,n] + c

参数
dst结果输出指针
numa第一个加数指针
numb第二个加数指针
nlimb长度
c初始进位值 [0|1]
警告
c=[0|1], n>0, eqsep(dst,[numa|numb])
返回
运算后的最终进位值 [0|1]

带进位的n位加法 [dst,n] = [numa,n] + [numb,n] + c

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 add_n.c19 行定义.

19 {
20 mp_size_t i = 0;
21 mp_limb_t cy = c;
22
23 for (; i + 4 <= n; i += 4) {
24 mp_limb_t a0, b0, r0;
25 mp_limb_t a1, b1, r1;
26 mp_limb_t a2, b2, r2;
27 mp_limb_t a3, b3, r3;
28
29 a0 = numa[i + 0];
30 b0 = numb[i + 0];
31
32 a1 = numa[i + 1];
33 b1 = numb[i + 1];
34
35 a2 = numa[i + 2];
36 b2 = numb[i + 2];
37
38 a3 = numa[i + 3];
39 b3 = numb[i + 3];
40
41 r0 = a0 + cy;
42 cy = (r0 < cy);
43 r0 += b0;
44 cy += (r0 < b0);
45
46 r1 = a1 + cy;
47 cy = (r1 < cy);
48 r1 += b1;
49 cy += (r1 < b1);
50
51 r2 = a2 + cy;
52 cy = (r2 < cy);
53 r2 += b2;
54 cy += (r2 < b2);
55
56 r3 = a3 + cy;
57 cy = (r3 < cy);
58 r3 += b3;
59 cy += (r3 < b3);
60
61 dst[i + 0] = r0;
62 dst[i + 1] = r1;
63 dst[i + 2] = r2;
64 dst[i + 3] = r3;
65 }
66
67 for (; i < n; i++) {
68 mp_limb_t a, b, r;
69 a = numa[i];
70 b = numb[i];
71 r = a + cy;
72 cy = (r < cy);
73 r += b;
74 cy += (r < b);
75 dst[i] = r;
76 }
77
78 return cy;
79}
#define c

引用了 a0, a1, a2, a3, b0, b1, b2, b3, c, n, numb, r0, r1, r2 , 以及 r3.

被这些函数引用 lmmp_add_n_sub_n_(), lmmp_fft_bfy_(), lmmp_ifft_bfy_() , 以及 lmmp_invappr_newton_().

+ 这是这个函数的调用关系图:

◆ lmmp_addmul_1_()

mp_limb_t lmmp_addmul_1_ ( mp_ptr  numa,
mp_srcptr  numb,
mp_size_t  n,
mp_limb_t  b 
)

大数乘以单limb并累加操作 [numa,n] += [numb,n] * b

参数
numa被加数指针(结果也存储在此)
numb乘数指针
nlimb长度
b乘数
警告
n>0, eqsep(numa,numb))
返回
运算后的进位limb值

被这些函数引用 lmmp_mul_toom62_(), lmmp_mul_toom62_cache_(), lmmp_mul_toom62_cache_init_(), lmmp_sqrt_() , 以及 lmmp_toom_interp7_().

+ 这是这个函数的调用关系图:

◆ lmmp_addshl1_n_()

mp_limb_t lmmp_addshl1_n_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

加法结合左移1位操作 [dst,n] = [numa,n] + ([numb,n] << 1)

参数
dst结果输出指针
numa被加数指针
numb加数指针(先左移1位)
nlimb长度
警告
n>0, eqsep(dst,[numa|numb])
返回
运算后的进位值 [0|1|2]

在文件 shl.c66 行定义.

66 {
67 mp_size_t i, c = 0, mb = 0;
68
69 for (i = 0; i < n; i++) {
70 mp_limb_t a, b, r;
71 a = numa[i];
72 b = (numb[i] << 1) + mb;
73 mb = numb[i] >> (LIMB_BITS - 1);
74 r = a + c;
75 c = (r < c);
76 r += b;
77 c += (r < b);
78 dst[i] = r;
79 }
80 return c + mb;
81}
#define LIMB_BITS
Definition lmmp.h:86

引用了 c, LIMB_BITS, n , 以及 numb.

被这些函数引用 lmmp_mul_toom33_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom44_(), lmmp_mul_toom53_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_(), lmmp_mul_toom62_cache_init_(), lmmp_sqr_toom3_(), lmmp_sqr_toom4_(), lmmp_sqrlo_dc_() , 以及 lmmp_sqrt_divide_().

+ 这是这个函数的调用关系图:

◆ lmmp_bninv_()

void lmmp_bninv_ ( mp_ptr  dstq,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  ni 
)

精确逆元计算 [dstq,na+ni+2] = B^(2*(na+ni)) / ([numa,na] * B^ni)

参数
dstq输出商的缓冲区,长度至少为na+ni+2
numa输入被除数(长度na)
na被除数的 limb 长度
ni精度因子
警告
na>0, sep(dstq,numa), dstq!=NULL, numa[na-1]!=0
注解
也就是计算 B^(2*na+ni) div ([numa,na]

◆ lmmp_cmp_()

static int lmmp_cmp_ ( mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)
inlinestatic

大数比较函数(内联)

参数
numa第一个大数,长度为n
numb第二个大数,长度为n
n大数的单精度数(limb)长度
返回
1(numa>numb) / 0(numa==numb) / -1(numa<numb)
警告
n>0, numa!=NULL, numb!=NULL
注解
从最高位开始逐位比较,直到找到不同位

在文件 lmmpn.h996 行定义.

996 {
997 lmmp_param_assert(n > 0);
1000 mp_ssize_t i = n;
1001 mp_limb_t x, y;
1002 while (--i >= 0) {
1003 x = numa[i];
1004 y = numb[i];
1005 if (x != y)
1006 return (x > y ? 1 : -1);
1007 }
1008 return 0;
1009}
int64_t mp_ssize_t
Definition lmmp.h:79
#define lmmp_param_assert(x)
Definition lmmp.h:401

引用了 lmmp_param_assert, n , 以及 numb.

被这些函数引用 lmmp_add_signed_(), lmmp_cbrt_3_(), lmmp_cbrt_6_(), lmmp_div_(), lmmp_div_basecase_(), lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_divexact_unbalanced_(), lmmp_gcd_basecase_(), lmmp_gcd_lehmer_(), lmmp_invappr_newton_(), lmmp_lehmer_mul_(), lmmp_mul_toom22_(), lmmp_mul_toom32_(), lmmp_mul_toom33_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom43_(), lmmp_mul_toom52_(), lmmp_mul_toom53_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_init_(), lmmp_sqr_toom2_(), lmmp_sqr_toom3_(), lmmp_toom_eval_dgr3_pm1_(), lmmp_toom_eval_dgr3_pm2_(), lmmp_toom_eval_pm1_(), lmmp_toom_eval_pm2_() , 以及 try_div_().

+ 这是这个函数的调用关系图:

◆ lmmp_div_()

void lmmp_div_ ( mp_ptr  dstq,
mp_ptr  dstr,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

大数除法和取模操作

注解
如果dstq不为NULL: [dstq,na-nb+1] = [numa,na] / [numb,nb] (商) 如果dstr不为NULL: [dstr,nb] = [numa,na] mod [numb,nb] (余数)
警告
0<nb<=na, numb[nb-1]!=0, sep(dstq,[numa|numb]), eqsep(dstr,[numa|numb])) 特殊情况: nb==1时, dstq>=numa-1 是允许的 nb==2时, dstq>=numa 是允许的
参数
dstq商结果输出指针(NULL表示不计算商)
dstr余数结果输出指针(NULL表示不计算余数)
numa被除数指针
na被除数的 limb 长度
numb除数指针
nb除数的 limb 长度

在文件 div.c74 行定义.

74 {
75 if (nb == 1) {
77 if (dstr)
78 *dstr = rem;
79 } else if (nb == 2) {
80 mp_limb_t brem[2];
81 brem[0] = numb[0];
82 brem[1] = numb[1];
84 if (dstr) {
85 dstr[0] = brem[0];
86 dstr[1] = brem[1];
87 }
88 } else {
89 int adjust = numa[na - 1] >= numb[nb - 1];
90 int cnt = lmmp_leading_zeros_(numb[nb - 1]);
91 mp_size_t nq = na + adjust - nb;
92 if (nq == 0) {
93 if (dstr && dstr != numa)
95 if (dstq)
96 dstq[0] = 0;
97 return;
98 }
100
101 if (!dstq)
102 dstq = TALLOC_TYPE(na - nb + 1, mp_limb_t);
103 dstq[na - nb] = 0;
104
105 if (nq >= nb) {
108 if (cnt) {
112 } else {
113 numa2[na] = 0;
115 numb2 = (mp_ptr)numb;
116 }
117
119 na += adjust;
120
125 else {
130 }
131
132 if (dstr) {
133 if (cnt)
135 else
137 }
138 } else {
139 // nq=na-nb+adj<nb
140 //-> na+adj>=2nq+1
141 mp_size_t ni = nb - nq;
145
146 numa2 = TALLOC_TYPE(nq * 2 + 1, mp_limb_t);
147 if (cnt) {
149 lmmp_shl_(numb2, numb + ni, nq, cnt);
150 numb2[0] |= numb[ni - 1] >> (LIMB_BITS - cnt);
151 cy = lmmp_shl_(numa2, numa + na - 2 * nq, 2 * nq, cnt);
152 if (adjust) {
153 numa2[2 * nq] = cy;
154 ++numa2; // numa2[0] is as significant as numa[ni=na-2nq+adjust]
155 } else
156 numa2[0] |= numa[na - 2 * nq - 1] >> (LIMB_BITS - cnt);
157 } else {
158 numb2 = (mp_ptr)numb + ni;
159 lmmp_copy(numa2, numa + na - 2 * nq, 2 * nq);
160 if (adjust) {
161 numa2[2 * nq] = 0;
162 ++numa2;
163 }
164 }
165
166 // now: 0<=numa2<B^2nq, B^nq/2<=numb2<B^nq, and 0<=numa2/numb2<B^nq
167 // ignored bits could be seen as fraction part of numa and numb
168 // we can prove: Q<=Qh<=Q+2
169 // where Q=floor(numa/numb) is the real quotient
170 // Qh=floor(floor(numa)/floor(numb)) as below
171
172 if (nq == 1) {
174 } else if (nq == 2) {
176 } else {
178
181 else if (nq < DIV_MULINV_N_THRESHOLD)
183 else {
185 mp_ptr invappr = tp;
188 }
189 }
190 /*
191 true remainder = partial remainder - quotient * ignored divisor limbs
192
193 Multiply the first ignored divisor limb by the most significant
194 quotient limb. If that product is > the partial remainder's
195 most significant limb, we know the quotient is too large. This
196 test quickly catches most cases where the quotient is too large;
197 it catches all cases where the quotient is 2 too large.*/
198
199 mp_limb_t x;
200 if (cnt) {
202 if (ni < 2)
203 dl = 0;
204 else
205 dl = numb[ni - 2];
206 x = (numb[ni - 1] << cnt) | (dl >> (LIMB_BITS - cnt));
207 } else
208 x = numb[ni - 1];
209 mp_limb_t h = (x >> LIMB_BITS / 2) * (dstq[nq - 1] >> LIMB_BITS / 2);
210 mp_limb_t rnb = 0; // remainder[nb]
211 mp_size_t nr = nq; // remainder=rnb:[numa2,nr]:[...,ni]
212
213 if (h > numa2[nq - 1]) {
214 lmmp_dec(dstq);
216 }
217
218 // if cnt, recover the shift of partial remainder
219 // and remove the effect of the partial-ignored numa[ni-1] and numb[ni-1]
220 if (cnt) {
221 numa2[nq] = rnb;
222 ++nr;
223 --ni;
225 numa2[0] |= numa[ni] & (LIMB_MAX >> cnt);
226 cy = lmmp_submul_1_(numa2, dstq, nq, numb[ni] & (LIMB_MAX >> cnt));
227 rnb = -(numa2[nq] < cy);
228 numa2[nq] -= cy;
229 }
230
231 if (ni == 0) {
232 if (dstr) {
233 if (rnb)
235 else
237 }
238 } else {
239 tp[nb - 1] = 0;
240 if (ni < nq)
241 lmmp_mul_(tp, dstq, nq, numb, ni);
242 else
243 lmmp_mul_(tp, numb, ni, dstq, nq);
244
245 if (dstr) {
246 mp_ptr remptr = dstr == numb ? tp : dstr;
247 cy = lmmp_sub_n_(remptr, numa, tp, ni);
248 rnb -= lmmp_sub_nc_(remptr + ni, numa2, tp + ni, nr, cy);
249 if (rnb)
251 else if (dstr != remptr)
253 } else {
254 int hcmp = lmmp_cmp_(numa2, tp + ni, nr);
255 if (hcmp < 0)
256 --rnb;
257 else if (hcmp == 0)
258 rnb -= (lmmp_cmp_(numa, tp, ni) < 0);
259 }
260 }
261
262 if (rnb)
263 lmmp_dec(dstq);
264 }
265
266 TEMP_FREE;
267 }
268}
#define lmmp_leading_zeros_
Definition inlines.h:160
#define LIMB_MAX
Definition lmmp.h:89
static mp_size_t lmmp_div_inv_size_(mp_size_t nq, mp_size_t nb)
计算预计算逆元的尺寸
Definition lmmpn.h:804
mp_limb_t lmmp_div_1_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_limb_t x)
单精度数除法(除数为1个limb)
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_dec(p)
大数减1宏(预期无借位)
Definition lmmpn.h:965
void lmmp_inv_prediv_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t ni)
除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B
Definition div_mulinv.c:22
void lmmp_div_2_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_ptr numb)
双精度数除法 (除数为2个limb)
Definition div.c:234
mp_limb_t lmmp_shr_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr)
大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0
Definition shr.c:19
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_shl_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0
Definition shl.c:19
mp_limb_t lmmp_div_mulinv_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_srcptr invappr, mp_size_t ni)
乘法逆元除法
mp_limb_t lmmp_div_2_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb)
双精度数除法(除数为2个limb)
mp_limb_t lmmp_submul_1_(mp_ptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t b)
大数乘以单limb并累减操作 [numa,n] -= [numb,n] * b
mp_limb_t lmmp_sub_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无借位的n位减法 [dst,n] = [numa,n] - [numb,n]
Definition sub_n.c:80
mp_limb_t lmmp_inv_2_1_(mp_limb_t xh, mp_limb_t xl)
2-1阶逆元计算 (inv21)
Definition inv.c:20
mp_limb_t lmmp_div_basecase_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
基础除法运算
mp_limb_t lmmp_div_divide_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
分治除法运算
#define DIV_DIVIDE_THRESHOLD
Definition mparam.h:26
#define DIV_MULINV_N_THRESHOLD
Definition mparam.h:30
#define DIV_MULINV_L_THRESHOLD
Definition mparam.h:28
#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

引用了 DIV_DIVIDE_THRESHOLD, DIV_MULINV_L_THRESHOLD, DIV_MULINV_N_THRESHOLD, LIMB_BITS, LIMB_MAX, lmmp_add_n_(), lmmp_cmp_(), lmmp_copy, lmmp_dec, lmmp_div_1_(), lmmp_div_1_s_(), lmmp_div_2_(), lmmp_div_2_s_(), lmmp_div_basecase_(), lmmp_div_divide_(), lmmp_div_inv_size_(), lmmp_div_mulinv_(), lmmp_inv_2_1_(), lmmp_inv_prediv_(), lmmp_leading_zeros_, lmmp_mul_(), lmmp_shl_(), lmmp_shr_(), lmmp_sub_n_(), lmmp_sub_nc_(), lmmp_submul_1_(), n, numb, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_bninv_(), lmmp_gcd_basecase_(), lmmp_gcd_lehmer_(), lmmp_trialdiv_() , 以及 try_div_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_div_1_()

mp_limb_t lmmp_div_1_ ( mp_ptr  dstq,
mp_srcptr  numa,
mp_size_t  na,
mp_limb_t  x 
)

单精度数除法

参数
dstq输出商的缓冲区(可为NULL,此时仅计算余数)
numa输入被除数,长度为na
na被除数的 limb 长度
x除数(单个 limb )
返回
除法余数(单个 limb )
警告
na>0, x!=0, eqsep(dstq,numa), dstq>=numa-1 是可以接受的
注解
if (dstq!=NULL) [dstq,na] = [numa,na] div x

在文件 div.c77 行定义.

77 {
79 if (na == 1) {
80 ah = numa[0];
81 if (dstq)
82 dstq[0] = ah / x;
83 return ah % x;
84 }
85 if (dstq) {
86 mp_limb_t t = numa[na - 2], q = 0, r = 0;
87 const int shift = lmmp_leading_zeros_(x);
88 if (shift > 0) {
89 /*
90 ah al
91 X|XXXtttX|XXXmmmX|XXXnnnX|XXX----|
92 |000XXXX|tttXXXX|mmmXXXX|nnnXXXX|
93 t numa[na]
94
95 ah al
96 X|XXXtttX|XXXmmmX|XXXnnnX|XXX----|
97 |000XXXX|tttXXXX|mmmXXXX|nnnXXXX|
98 t
99 numa[na]
100 */
101 const int rshift = LIMB_BITS - shift;
102 ah = numa[na - 1] >> rshift;
103 t = numa[na - 2];
104 al = (numa[na - 1] << shift) | (t >> rshift);
105 x <<= shift;
106 const mp_limb_t inv = lmmp_inv_1_(x);
107 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
108 dstq[na - 1] = q;
109 na -= 2;
110 while (na-- > 0) {
111 ah = r;
112 al = t << shift;
113 t = numa[na];
114 al |= t >> rshift;
115 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
116 dstq[na + 1] = q;
117 }
118 ah = r;
119 al = t << shift;
120 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
121 dstq[0] = q;
122 return r >> shift;
123 } else {
124 /*
125 ah al
126 |000XXXX|tttXXXX|mmmXXXX|nnnXXXX|
127 t numa[na]
128 */
129 ah = 0;
130 t = numa[na - 2];
131 al = numa[na - 1];
132 const mp_limb_t inv = lmmp_inv_1_(x);
133 q = al / x;
134 r = al % x;
135 dstq[na - 1] = q;
136 na -= 2;
137 while (na-- > 0) {
138 ah = r;
139 al = t;
140 t = numa[na];
141 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
142 dstq[na + 1] = q;
143 }
144 ah = r;
145 al = t;
146 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
147 dstq[0] = q;
148 return r;
149 }
150 } else {
151 return lmmp_mod_1_(numa, na, x);
152 }
153}
mp_limb_t lmmp_mod_1_(mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数取余
Definition div.c:31
mp_limb_t lmmp_inv_1_(mp_limb_t x)
1阶逆元计算 (inv1)
Definition inv.c:117
#define _udiv_qrnnd_preinv(q, r, nh, nl, d, di)
Definition longlong.h:415
#define t

引用了 _udiv_qrnnd_preinv, LIMB_BITS, lmmp_inv_1_(), lmmp_leading_zeros_, lmmp_mod_1_(), n , 以及 t.

被这些函数引用 lmmp_bninv_(), lmmp_cbrtapprox_3_(), lmmp_cbrtapprox_6_(), lmmp_div_() , 以及 lmmp_to_str_basecase_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_div_1_s_()

mp_limb_t lmmp_div_1_s_ ( mp_ptr  dstq,
mp_ptr  numa,
mp_size_t  na,
mp_limb_t  x 
)

单精度数除法(除数为1个limb)

参数
dstq输出商的缓冲区,长度至少为na-1
numa输入被除数(长度na),运算后存储余数(长度1)
na被除数的 limb 长度
x除数(单个 limb )
返回
商的最高位(qh)
警告
na>1, MSB(x)=1, sep(dstq,numa)
注解
qh:[dstq,na-1]=[numa,na] div x, [numa,1]=[numa,na] mod x, return qh

被这些函数引用 lmmp_div_(), lmmp_div_s_(), mont63_R2() , 以及 mont64_R2().

+ 这是这个函数的调用关系图:

◆ lmmp_div_2_()

void lmmp_div_2_ ( mp_ptr  dstq,
mp_srcptr  numa,
mp_size_t  na,
mp_ptr  numb 
)

双精度数除法 (除数为2个limb)

参数
dstq输出商的缓冲区,长度至少为na-1
numa输入被除数(长度na)
na被除数的 limb 长度
numb输入除数(长度2)[numb,2]=[numa,na] mod [numb,2]
警告
na>=2, numb[1]!=0, eqsep(dstq,numa), dstq>=numa 是可以接受的
注解
if (dstq!=NULL) [dstq,na-1]=[numa,na] div [numb,2]

在文件 div.c234 行定义.

234 {
235 mp_limb_t q, r1, r0, a2, a1, a0, b1, b0;
236 b1 = numb[1];
237 b0 = numb[0];
238 if (na == 2) {
240 if (shift > 0) {
241 const int rshift = LIMB_BITS - shift;
242 b1 = (b1 << shift) | (b0 >> rshift);
243 b0 <<= shift;
244 a2 = numa[1] >> rshift;
245 a1 = (numa[1] << shift) | (numa[0] >> rshift);
246 a0 = (numa[0] << shift);
248 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
249 if (dstq)
250 dstq[0] = q;
251 numb[0] = (r0 >> shift) | (r1 << rshift);
252 numb[1] = r1 >> shift;
253 return;
254 } else {
255 if (_u128cmp(numa, numb)) {
256 numb[0] = numa[0];
257 numb[1] = numa[1];
258 if (dstq)
259 dstq[0] = 0;
260 return;
261 } else {
263 if (dstq)
264 dstq[0] = 1;
265 return;
266 }
267 }
268 }
269 if (dstq) {
271 if (shift > 0) {
272 /*
273 a2 a1 a0
274 X|XXXtttX|XXXmmmX|XXXnnnX|XXX----|
275 |000XXXX|tttXXXX|mmmXXXX|nnnXXXX|
276 numa[na]
277 */
278 const int rshift = LIMB_BITS - shift;
279 b1 = (b1 << shift) | (b0 >> rshift);
280 b0 <<= shift;
281 const mp_limb_t inv = lmmp_inv_2_1_(b1, b0);
282 a2 = numa[na - 1] >> rshift;
283 a1 = (numa[na - 1] << shift) | (numa[na - 2] >> rshift);
284 a0 = (numa[na - 2] << shift) | (numa[na - 3] >> rshift);
285 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
286 dstq[na - 2] = q;
287 na -= 2;
288 while (na-- > 1) {
289 a2 = r1;
290 a1 = r0;
291 a0 = (numa[na] << shift) | (numa[na - 1] >> rshift);
292 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
293 dstq[na] = q;
294 }
295
296 a2 = r1;
297 a1 = r0;
298 a0 = (numa[na] << shift);
299 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
300 dstq[0] = q;
301 numb[0] = (r0 >> shift) | (r1 << rshift);
302 numb[1] = r1 >> shift;
303 return;
304 } else {
305 /*
306 a2 a1 a0
307 |000XXXX|tttXXXX|mmmXXXX|nnnXXXX|
308 numa[na]
309 */
310 const mp_limb_t inv = lmmp_inv_2_1_(b1, b0);
311 a2 = 0;
312 a1 = numa[na - 1];
313 a0 = numa[na - 2];
314 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
315 dstq[na - 2] = q;
316 na -= 2;
317 while (na-- > 1) {
318 a2 = r1;
319 a1 = r0;
320 a0 = numa[na];
321 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
322 dstq[na] = q;
323 }
324 a2 = r1;
325 a1 = r0;
326 a0 = numa[na];
327 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
328 dstq[0] = q;
329 numb[0] = r0;
330 numb[1] = r1;
331 return;
332 }
333 } else {
335 if (shift > 0) {
336 const int rshift = LIMB_BITS - shift;
337 b1 = (b1 << shift) | (b0 >> rshift);
338 b0 <<= shift;
339 const mp_limb_t inv = lmmp_inv_2_1_(b1, b0);
340 a2 = numa[na - 1] >> rshift;
341 a1 = (numa[na - 1] << shift) | (numa[na - 2] >> rshift);
342 a0 = (numa[na - 2] << shift) | (numa[na - 3] >> rshift);
343 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
344 na -= 2;
345 while (na-- > 1) {
346 a2 = r1;
347 a1 = r0;
348 a0 = (numa[na] << shift) | (numa[na - 1] >> rshift);
349 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
350 }
351
352 a2 = r1;
353 a1 = r0;
354 a0 = (numa[na] << shift);
355 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
356 numb[0] = (r0 >> shift) | (r1 << rshift);
357 numb[1] = r1 >> shift;
358 return;
359 } else {
360 const mp_limb_t inv = lmmp_inv_2_1_(b1, b0);
361 a2 = 0;
362 a1 = numa[na - 1];
363 a0 = numa[na - 2];
364 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
365 na -= 2;
366 while (na-- > 1) {
367 a2 = r1;
368 a1 = r0;
369 a0 = numa[na];
370 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
371 }
372 a2 = r1;
373 a1 = r0;
374 a0 = numa[na];
375 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
376 numb[0] = r0;
377 numb[1] = r1;
378 return;
379 }
380 }
381}
#define _u128sub(r, x, y)
Definition longlong.h:368
#define _u128cmp(x, y)
Definition longlong.h:366
#define _udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv)
Definition longlong.h:432

引用了 _u128cmp, _u128sub, _udiv_qr_3by2, a0, a1, a2, b0, b1, LIMB_BITS, lmmp_inv_2_1_(), lmmp_leading_zeros_, n, numb, r0 , 以及 r1.

被这些函数引用 lmmp_bninv_() , 以及 lmmp_div_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_div_2_s_()

mp_limb_t lmmp_div_2_s_ ( mp_ptr  dstq,
mp_ptr  numa,
mp_size_t  na,
mp_srcptr  numb 
)

双精度数除法(除数为2个limb)

参数
dstq输出商的缓冲区,长度至少为na-2
numa输入被除数(长度na),运算后存储余数(长度2)
na被除数的 limb 长度
numb输入除数,长度为2
返回
商的最高位(qh)
警告
na>2, MSB(numb)=1, sep(dstq,numa,numb)
注解
qh:[dstq,na-2]=[numa,na] div [numb,2], [numa,2]=[numa,na] mod [numb,2], return qh

被这些函数引用 lmmp_div_(), lmmp_div_s_() , 以及 lmmp_inv_basecase_().

+ 这是这个函数的调用关系图:

◆ lmmp_div_3_2_()

mp_limb_t lmmp_div_3_2_ ( mp_ptr  numa,
mp_srcptr  numb,
mp_limb_t  inv21 
)

3/2位除法运算 [numa,2]=[numa,3] mod [numb,2]

参数
numa输入被除数(长度3),运算后存储余数(长度2)
numb输入除数(长度2)
inv21除数的2-1阶逆元(提前计算好的inv21([numb,2]))
返回
商值(单精度数)
警告
[numa,3]<[numb,2]*B, MSB(numb)=1, inv21=inv21([numb,2]), eqsep(numa,numb)

被这些函数引用 lmmp_div_basecase_().

+ 这是这个函数的调用关系图:

◆ lmmp_div_basecase_()

mp_limb_t lmmp_div_basecase_ ( mp_ptr  dstq,
mp_ptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb,
mp_limb_t  inv21 
)

基础除法运算

参数
dstq输出商的缓冲区,长度至少为na-nb
numa输入被除数(长度na),运算后存储余数(长度nb)
na被除数的单精度数(limb)长度
numb输入除数,长度为nb
nb除数的单精度数(limb)长度
inv21除数的2-1阶逆元(inv21([numb+nb-2,2]))
返回
商的最高位(qh)
警告
na>=nb>=3, MSB(numb)=1, inv21=inv21([numb+nb-2,2]), sep(dstq,numa,numb)
注解
qh:[dstq,na-nb]=[numa,na] div [numb,nb], [numa,na-nb]=[numa,na] mod [numb,nb], return qh

被这些函数引用 lmmp_bninv_appr_newton_(), lmmp_div_(), lmmp_div_divide_n_(), lmmp_div_s_() , 以及 lmmp_inv_basecase_().

+ 这是这个函数的调用关系图:

◆ lmmp_div_divide_()

mp_limb_t lmmp_div_divide_ ( mp_ptr  dstq,
mp_ptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb,
mp_limb_t  inv21 
)

分治除法运算

参数
dstq输出商的缓冲区,长度至少为na-nb
numa输入被除数(长度na),运算后存储余数(长度nb)
na被除数的单精度数(limb)长度
numb输入除数,长度为nb
nb除数的单精度数(limb)长度
inv21除数的2-1阶逆元(inv21([numb+nb-2,2]))
返回
商的最高位(qh)
警告
na>=2*nb, nb>=6, MSB(numb)=1, inv21=inv21([numb+nb-2,2]), sep(dstq,numa,numb)
注解
qh:[dstq,na-nb]=[numa,na] div [numb,nb], [numa,na-nb]=[numa,na] mod [numb,nb], return qh

被这些函数引用 lmmp_div_(), lmmp_div_s_() , 以及 lmmp_inv_basecase_().

+ 这是这个函数的调用关系图:

◆ lmmp_div_inv_size_()

static mp_size_t lmmp_div_inv_size_ ( mp_size_t  nq,
mp_size_t  nb 
)
inlinestatic

计算预计算逆元的尺寸

参数
nq商的 limb 长度
nb除数的 limb 长度
返回
计算需要预计算逆元尺寸ni(ni<=nb)
注解
用于已归一化除法([nq+nb]/[nb]=[nq])的逆元 ni 尺寸

在文件 lmmpn.h804 行定义.

804 {
805 mp_size_t ni, b;
806 if (nq > nb) {
807 b = (nq - 1) / nb + 1; // ceil(nq/nb), number of blocks
808 ni = (nq - 1) / b + 1; // ceil(nq/b)
809 } else if (3 * nq > nb) {
810 ni = (nq - 1) / 2 + 1; // b=2
811 } else {
812 ni = (nq - 1) / 1 + 1; // b=1
813 }
814 return ni;
815}

引用了 n.

被这些函数引用 lmmp_div_(), lmmp_div_s_() , 以及 lmmp_to_str_().

+ 这是这个函数的调用关系图:

◆ lmmp_div_mulinv_()

mp_limb_t lmmp_div_mulinv_ ( mp_ptr  dstq,
mp_ptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb,
mp_srcptr  invappr,
mp_size_t  ni 
)

乘法逆元除法

参数
dstq输出商的缓冲区,长度至少为na-nb
numa输入被除数(长度na),运算后存储余数(长度nb)
na被除数的 limb 长度
numb输入除数,长度为nb
nb除数的 limb 长度
invappr预计算的近似逆元,长度为ni
ni预计算逆元的 limb 长度
返回
商的最高位(qh)
警告
na>=nb>=ni>0, MSB(numb)=1, [invappr,ni]=inv_prediv([numb,nb]), sep(dstq,numa,numb,invappr))
注解
qh:[dstq,na-1]=[numa,na] div x, [numa,1]=[numa,na] mod x, return qh

被这些函数引用 lmmp_div_(), lmmp_div_s_() , 以及 lmmp_to_str_divide_().

+ 这是这个函数的调用关系图:

◆ lmmp_div_s_()

mp_limb_t lmmp_div_s_ ( mp_ptr  dstq,
mp_ptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

除法运算

参数
dstq输出商的缓冲区,长度至少为na-nb
numa输入被除数(长度na),运算后存储余数(长度nb)
na被除数的 limb 长度
numb输入除数,长度为nb
nb除数的 limb 长度
返回
商的最高位(qh)
警告
na>=nb>0, MSB(numb)=1, sep(dstq,numa,numb)
注解
qh:[dstq,na-nb]=[numa,na] div [numb,nb], [numa,nb]=[numa,na] mod [numb,nb], return qh

被这些函数引用 lmmp_div_divide_(), lmmp_invsqrt_newton_(), lmmp_sqrt_divide_() , 以及 lmmp_to_str_divide_().

+ 这是这个函数的调用关系图:

◆ lmmp_endian()

static bool lmmp_endian ( void  )
inlinestatic

运行时判断端序

返回
true 表示小端序,false 表示大端序

在文件 lmmpn.h65 行定义.

65 {
66 int num = 1;
67 return (*(char*)&num) == 0;
68}

引用了 n.

◆ lmmp_extract_bits_()

mp_bitcnt_t lmmp_extract_bits_ ( mp_srcptr  num,
mp_size_t  n,
mp_limb_t ext,
int  bits 
)

提取高位指定位数,并返回低位bits位数

参数
num待提取的大数指针
nnum的 limb 长度
bits待提取的位数(1-64)
ext提取结果输出指针
警告
n>0, 1<=bits<=64, ext!=NULL
注解
如果bits大于num的实际位数,则不会保证ext有效位数为bits位; 如果bits小于等于num的实际位数,则ext将会有bits位有效位数。
返回
剩余的低位bits数量

◆ lmmp_fft_next_size_()

mp_size_t lmmp_fft_next_size_ ( mp_size_t  n)

计算满足 >=n 的最小费马/梅森乘法可行尺寸

参数
n输入的目标尺寸
返回
满足条件的SSA乘法最小尺寸

计算满足 >=n 的最小费马/梅森乘法可行尺寸

参数
n- 原始长度
返回
规整后的长度(为2^k的倍数)

在文件 mul_fft.c95 行定义.

95 {
99 n = (((n - 1) >> k) + 1) << k;
100 return n;
101}
#define k
#define lmmp_debug_assert(x)
Definition lmmp.h:390
#define LOG2_LIMB_BITS
Definition lmmp.h:88
static mp_size_t lmmp_fft_best_k_(mp_size_t n)
查找对于 m>=n 的模 B^m+1 FFT运算的最优k值
Definition mul_fft.c:84

引用了 k, lmmp_debug_assert, lmmp_fft_best_k_(), LOG2_LIMB_BITS , 以及 n.

被这些函数引用 binvert_mulhi_(), lmmp_div_mulinv_(), lmmp_invappr_newton_(), lmmp_invsqrt_newton_(), lmmp_mul_fft_(), lmmp_mul_fft_unbalance_(), lmmp_mulhi_n_() , 以及 lmmp_mullo_fft_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_from_str_()

mp_size_t lmmp_from_str_ ( mp_ptr  dst,
const mp_byte_t src,
mp_size_t  len,
int  base 
)

字符串转大数操作 [src,len,base] to [dst,return value,B]

警告
len>=0, 2<=base<=256
参数
dst大数结果输出指针
src字符串源指针
len字符串长度
base字符串的进制基数
返回
转换后的大数 limb 长度

在文件 from_str.c154 行定义.

154 {
155 lmmp_param_assert(base >= 2 && base <= 256);
156 do {
157 if (len == 0)
158 return 0;
159 } while (src[--len] == 0);
160 ++len;
161
163 if (LMMP_POW2_Q(base)) {
164 mp_limb_t curlimb = 0;
165 const mp_byte_t* srcend = src + len;
166 int bitspd = lmmp_bases_table[base - 2].large_base;
167 int bitpos = 0;
168 limbs = 0;
169
170 do {
172 curlimb |= curdigit << bitpos;
173 bitpos += bitspd;
174 if (bitpos >= LIMB_BITS) {
175 dst[limbs] = curlimb;
176 ++limbs;
177 bitpos -= LIMB_BITS;
178 curlimb = curdigit >> (bitspd - bitpos);
179 }
180 } while (++src != srcend);
181 if (curlimb) {
182 dst[limbs] = curlimb;
183 ++limbs;
184 }
185 } else if (lmmp_from_str_len_(0, len, base) < FROM_STR_BASEPOW_THRESHOLD) {
187 } else {
188 TEMP_DECL;
192 mp_size_t bexp, lexp = (len - 1) / digitspl + 1;
194 // need 1 extra limb to store result
197 mp_ptr tp;
198
199 int cpow = lmmp_limb_bits_(lexp - 1);
200
201 for (int i = cpow; i > 0; --i) {
202 // we will calculate lbase^bexp
203 bexp = ((lexp - 1) >> i) + 1;
204 // we will calculate lbase^(bexp-1) first, and trim it s. t.
205 // it contains at most 2 tailing 0 limb, then multiply it by lbase,
206 // so we need npow limbs to store lbase^bexp
207 mp_size_t npow = lmmp_from_str_len_(0, (bexp - 1) * digitspl + 1, base) + 1;
208
209 if (tzbit) {
210 mp_size_t tzlimb = tzbit * (bexp - 1) / LIMB_BITS;
211 if (tzlimb >= 2)
212 npow -= tzlimb - 2;
213 }
214
215 // space needed for a trimmed npow-limb lbase^bexp
216 alloc_size += npow;
217 }
218
220
221 for (int i = 0; i < 2; ++i) {
222 tp[0] = lbase;
223 powers[i].p = tp;
224 powers[i].np = 1;
225 tp += i + 1;
226 powers[i].zeros = 0;
227 powers[i].digits = digitspl * (i + 1);
228 powers[i].base = base;
229 }
230
231 mp_ptr p = powers[1].p;
232 mp_size_t zeros = 0, np = 1;
233 for (int i = 2; i < cpow; ++i) {
234 lmmp_sqr_(tp, p, np);
235 np *= 2;
236 np -= tp[np - 1] == 0;
237 bexp = (lexp - 1) >> (cpow - i);
238 if (bexp & 1) {
239 cy = lmmp_mul_1_(tp, tp, np, lbase);
240 tp[np] = cy;
241 np += cy != 0;
242 }
243 zeros *= 2;
244 while (tp[0] == 0) {
245 // at most 2 tailing 0 limb here
246 ++zeros;
247 ++tp;
248 --np;
249 }
250 p = tp;
251 powers[i].p = p;
252 powers[i].np = np;
253 powers[i].zeros = zeros;
254 powers[i].digits = digitspl * (bexp + 1);
255 powers[i].base = base;
256 tp += np + 1;
257 }
258
259 for (int i = 1; i < cpow; ++i) {
260 p = powers[i].p;
261 np = powers[i].np;
262 cy = lmmp_mul_1_(p, p, np, lbase);
263 p[np] = cy;
264 np += cy != 0;
265 if (p[0] == 0) {
266 ++powers[i].zeros;
267 ++p;
268 --np;
269 }
270
271 powers[i].p = p;
272 powers[i].np = np;
273 }
274
277
278 TEMP_FREE;
279 }
280 return limbs;
281}
int digits_in_limb
Definition base_table.h:34
const mp_base_t lmmp_bases_table[255]
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition base_table.c:18
mp_limb_t large_base
Definition base_table.h:25
static mp_size_t lmmp_from_str_basecase_(mp_ptr dst, const mp_byte_t *src, mp_size_t len, int base)
将字符串转换为mp_limb_t数组
Definition from_str.c:44
static mp_size_t lmmp_from_str_divide_(mp_ptr restrict dst, const mp_byte_t *src, mp_size_t len, mp_basepow_t *pow, mp_ptr restrict tp)
将字符串转换为mp_limb_t数组
Definition from_str.c:95
mp_size_t lmmp_from_str_len_(const mp_byte_t *src, mp_size_t len, int base)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition from_str.c:23
#define lmmp_limb_bits_
Definition inlines.h:162
#define lmmp_sqr_
Definition inlines.h:166
#define lmmp_tailing_zeros_
Definition inlines.h:161
uint8_t mp_byte_t
Definition lmmp.h:75
#define LMMP_POW2_Q(n)
Definition lmmp.h:362
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 FROM_STR_BASEPOW_THRESHOLD
Definition mparam.h:74
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:146

引用了 BALLOC_TYPE, mp_base_t::digits_in_limb, FROM_STR_BASEPOW_THRESHOLD, mp_base_t::large_base, LIMB_BITS, lmmp_bases_table, lmmp_copy, lmmp_from_str_basecase_(), lmmp_from_str_divide_(), lmmp_from_str_len_(), lmmp_limb_bits_, lmmp_mul_1_(), lmmp_param_assert, LMMP_POW2_Q, lmmp_sqr_, lmmp_tailing_zeros_, n, TEMP_DECL, TEMP_FREE , 以及 tp.

+ 函数调用图:

◆ lmmp_from_str_len_()

mp_size_t lmmp_from_str_len_ ( const mp_byte_t src,
mp_size_t  len,
int  base 
)

计算字符串转大数所需的 limb 缓冲区长度

参数
src输入字符串指针
len字符串长度
base字符串的基数(2~256)
返回
存储该字符串数值所需的 limb 缓冲区长度
警告
len>=0, 2<=base<=256
注解
将会忽略前导零,
  1. if (src!=NULL) 返回的长度可能会多分配一个 limb 空间
  2. if (src==NULL) 返回len位base进制数的最大可能 limb 长度(最坏情况)

计算字符串转大数所需的 limb 缓冲区长度

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 from_str.c23 行定义.

23 {
24 lmmp_param_assert(base >= 2 && base <= 256);
25 if (src) {
26 do {
27 if (len == 0)
28 return 1;
29 } while (src[--len] == 0);
30 ++len;
31 }
32 return lmmp_mulh_(len, lmmp_bases_table[base - 2].lg_base) + 1;
33}
#define lmmp_mulh_
Definition inlines.h:165

引用了 lmmp_bases_table, lmmp_mulh_, lmmp_param_assert , 以及 n.

被这些函数引用 lmmp_from_str_(), lmmp_from_str_divide_() , 以及 lmmp_to_str_().

+ 这是这个函数的调用关系图:

◆ lmmp_inv_()

void lmmp_inv_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  nf 
)

大数求逆操作 [dst,na+nf+1] = (B^(2*(na+nf)) - 1) / ([numa,na]*B^nf) + [0|-1]

参数
dst逆元结果输出指针
numa源操作数指针
na操作数的 limb 长度
nf精度因子
警告
na>0, numa[na-1]!=0, eqsep(dst,numa)

在文件 inv.c163 行定义.

163 {
165 lmmp_param_assert(numa[na - 1] != 0);
166 mp_limb_t high = numa[na - 1];
168 TEMP_DECL;
169 if (dst == numa || nsh || nf) {
170 nf += nsh != 0;
173 if (nsh)
174 lmmp_shl_(numa2 + nf, numa, na, nsh);
175 else
176 lmmp_copy(numa2 + nf, numa, na);
177 numa = numa2;
178 }
180 if (nsh)
182 else
183 dst[na + nf] = 1;
184 TEMP_FREE;
185}
void lmmp_invappr_(mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na)
Definition inv.c:187
#define lmmp_zero(dst, n)
Definition lmmp.h:369
mp_limb_t lmmp_shr_c_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr, mp_limb_t c)
带进位的大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充c的高shr位
Definition shr.c:40

引用了 LIMB_BITS, lmmp_copy, lmmp_invappr_(), lmmp_leading_zeros_, lmmp_param_assert, lmmp_shl_(), lmmp_shr_c_(), lmmp_zero, n, TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

+ 函数调用图:

◆ lmmp_inv_1_()

mp_limb_t lmmp_inv_1_ ( mp_limb_t  x)

1阶逆元计算 (inv1)

参数
x输入的64位无符号整数,最高位为1(MSB(x)=1)
返回
计算结果:(B^2-1)/x - B
警告
MSB(x)=1, 即x>=2^63

在文件 inv.c117 行定义.

117 {
118 mp_limb_t r, m;
119 {
120 mp_limb_t p, ql;
121 unsigned ul, uh, qh;
122
123 ul = x & LLIMB_MASK;
124 uh = x >> (LIMB_BITS / 2);
125 qh = (x ^ LIMB_MAX) / uh;
126
127 r = ((~x - (mp_limb_t)qh * uh) << (LIMB_BITS / 2)) | LLIMB_MASK;
128 p = (mp_limb_t)qh * ul;
129 if (r < p) {
130 qh--;
131 r += x;
132 if (r >= x)
133 if (r < p) {
134 qh--;
135 r += x;
136 }
137 }
138 r -= p;
139 p = (r >> (LIMB_BITS / 2)) * qh + r;
140 ql = (p >> (LIMB_BITS / 2)) + 1;
141 r = (r << (LIMB_BITS / 2)) + LLIMB_MASK - ql * x;
142 if (r >= (LIMB_MAX & (p << (LIMB_BITS / 2)))) {
143 ql--;
144 r += x;
145 }
146 m = ((mp_limb_t)qh << (LIMB_BITS / 2)) + ql;
147 if (r >= x) {
148 m++;
149 r -= x;
150 }
151 }
152 return m;
153}
#define LLIMB_MASK
Definition lmmp.h:92

引用了 LIMB_BITS, LIMB_MAX, LLIMB_MASK , 以及 n.

被这些函数引用 lmmp_div_1_(), lmmp_div_1_s_(), lmmp_inv_basecase_(), lmmp_mod_1_() , 以及 lmmp_mulmod_ulong_().

+ 这是这个函数的调用关系图:

◆ lmmp_inv_2_1_()

mp_limb_t lmmp_inv_2_1_ ( mp_limb_t  xh,
mp_limb_t  xl 
)

2-1阶逆元计算 (inv21)

参数
xh输入数的高64位部分
xl输入数的低64位部分
返回
计算结果:(B^3-1)/(xh*B+xl) - B
警告
MSB(xh)=1, 即xh>=2^63

2-1阶逆元计算 (inv21)

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 inv.c20 行定义.

20 {
21 mp_limb_t r, m;
22 {
23 mp_limb_t p, ql;
24 unsigned ul, uh, qh;
25
26 /* For notation, let b denote the half-limb base, so that B = b^2.
27 Split u1 = b uh + ul. */
28 ul = xh & LLIMB_MASK;
29 uh = xh >> (LIMB_BITS / 2);
30
31 /* Approximation of the high half of quotient. Differs from the 2/1
32 inverse of the half limb uh, since we have already subtracted
33 u0. */
34 qh = (xh ^ LIMB_MAX) / uh;
35
36 /* Adjust to get a half-limb 3/2 inverse, i.e., we want
37
38 qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
39 = floor( (b (~u) + b-1) / u),
40
41 and the remainder
42
43 r = b (~u) + b-1 - qh (b uh + ul)
44 = b (~u - qh uh) + b-1 - qh ul
45
46 Subtraction of qh ul may underflow, which implies adjustments.
47 But by normalization, 2 u >= B > qh ul, so we need to adjust by
48 at most 2.
49 */
50
51 r = ((~xh - (mp_limb_t)qh * uh) << (LIMB_BITS / 2)) | LLIMB_MASK;
52
53 p = (mp_limb_t)qh * ul;
54 /* Adjustment steps taken from udiv_qrnnd_c */
55 if (r < p) {
56 qh--;
57 r += xh;
58 if (r >= xh) /* i.e. we didn't get carry when adding to r */
59 if (r < p) {
60 qh--;
61 r += xh;
62 }
63 }
64 r -= p;
65
66 /* Low half of the quotient is
67
68 ql = floor ( (b r + b-1) / u1).
69
70 This is a 3/2 division (on half-limbs), for which qh is a
71 suitable inverse. */
72
73 p = (r >> (LIMB_BITS / 2)) * qh + r;
74 /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
75 work, it is essential that ql is a full mp_limb_t. */
76 ql = (p >> (LIMB_BITS / 2)) + 1;
77
78 /* By the 3/2 trick, we don't need the high half limb. */
79 r = (r << (LIMB_BITS / 2)) + LLIMB_MASK - ql * xh;
80
81 if (r >= (LIMB_MAX & (p << (LIMB_BITS / 2)))) {
82 ql--;
83 r += xh;
84 }
85 m = ((mp_limb_t)qh << (LIMB_BITS / 2)) + ql;
86 if (r >= xh) {
87 m++;
88 r -= xh;
89 }
90 }
91
92 /* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a
93 3/2 inverse. */
94 if (xl > 0) {
96 r = ~r;
97 r += xl;
98 if (r < xl) {
99 m--;
100 if (r >= xh) {
101 m--;
102 r -= xh;
103 }
104 r -= xh;
105 }
106 _umul64to128_(xl, m, &tl, &th);
107 r += th;
108 if (r < th) {
109 m--;
110 m -= ((r > xh) | ((r == xh) & (tl > xl)));
111 }
112 }
113
114 return m;
115}
static void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high)
Definition longlong.h:174

引用了 _umul64to128_(), LIMB_BITS, LIMB_MAX, LLIMB_MASK , 以及 n.

被这些函数引用 lmmp_bninv_appr_newton_(), lmmp_div_(), lmmp_div_2_(), lmmp_div_2_s_(), lmmp_div_s_(), lmmp_inv_basecase_() , 以及 lmmp_mod_2_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_inv_basecase_()

void lmmp_inv_basecase_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

近似逆元计算

参数
dst输出结果缓冲区,长度为na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
na>0, MSB(numa)=1, sep(dst,numa)
返回
无返回值,结果存储在dst中,[dst,na]=(B^(2*na)-1)/[numa,na] - B^na

◆ lmmp_inv_prediv_()

void lmmp_inv_prediv_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  ni 
)

除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B

参数
dst输出预计算逆元的缓冲区,长度为ni
numa输入操作数,长度为na
na输入操作数的 limb 长度
ni预计算逆元的目标尺寸
警告
na>=ni>0, MSB(numa)=1, eqsep(dst,numa)
注解
if (ni=na) [dst,na] = (B^(2*na)-1) / [numa,na] - B^na

除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 div_mulinv.c22 行定义.

22 {
23 lmmp_param_assert(na >= ni);
24 lmmp_param_assert(ni > 0);
29
30 if (na == ni) {
31 lmmp_copy(tp + 1, numa, ni);
32 tp[0] = 1;
33 cy = 0;
34 } else {
35 cy = lmmp_add_1_(tp, numa + na - (ni + 1), ni + 1, 1);
36 }
37 if (cy)
38 lmmp_zero(dst, ni);
39 else {
41 lmmp_invappr_(invappr, tp, ni + 1);
42 lmmp_copy(dst, invappr + 1, ni);
43 }
45}
void lmmp_invappr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算 (invappr)
static mp_limb_t lmmp_add_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数加单精度数静态内联函数 [dst,na]=[numa,na]+x
Definition lmmpn.h:1103
#define LIMB_B_2
Definition mparam.h:157

引用了 LIMB_B_2, lmmp_add_1_(), lmmp_copy, lmmp_invappr_(), lmmp_param_assert, lmmp_zero, n, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_div_(), lmmp_div_s_() , 以及 lmmp_to_str_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_invappr_()

void lmmp_invappr_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

近似逆元计算 (invappr)

参数
dst输出结果缓冲区,长度为na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
na>0, MSB(numa)=1, sep(dst,numa)
返回
无返回值,结果存储在dst中,[dst,na] = (B^(2*na)-1)/[numa,na] - B^na + [0|-1]

被这些函数引用 lmmp_inv_prediv_().

+ 这是这个函数的调用关系图:

◆ lmmp_invappr_newton_()

void lmmp_invappr_newton_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

近似逆元计算(牛顿迭代法)

参数
dst输出结果缓冲区,长度为na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
na>4, MSB(numa)=1, sep(dst,numa)
返回
无返回值,结果存储在dst中,[dst,na]=(B^(2*na)-1)/[numa,na]-B^na+[0|-1]

◆ lmmp_leading_zeros_()

int lmmp_leading_zeros_ ( mp_limb_t  x)

计算一个单精度数(limb)中前导零的个数

参数
x输入的64位无符号整数
返回
前导零的位数(范围:0~64)

在文件 tiny.c51 行定义.

51 {
52 if (x == 0) return 64;
53#ifdef __GNUC__
54 return __builtin_clzll(x);
55#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
56 unsigned long index;
57 _BitScanReverse64(&index, x);
58 return 63 - (int)index;
59#else
60 int n = 0;
61 if (x <= 0x00000000FFFFFFFF) { n += 32; x <<= 32; }
62 if (x <= 0x0000FFFFFFFFFFFF) { n += 16; x <<= 16; }
63 if (x <= 0x00FFFFFFFFFFFFFF) { n += 8; x <<= 8; }
64 if (x <= 0x0FFFFFFFFFFFFFFF) { n += 4; x <<= 4; }
65 if (x <= 0x3FFFFFFFFFFFFFFF) { n += 2; x <<= 2; }
66 if (x <= 0x7FFFFFFFFFFFFFFF) { n += 1; x <<= 1; }
67 return n;
68#endif
69}

引用了 n.

◆ lmmp_limb_bits_()

int lmmp_limb_bits_ ( mp_limb_t  x)

计算满足 2^k > x 的最小自然数k

参数
x输入的64位无符号整数
返回
满足条件的最小自然数k

计算满足 2^k > x 的最小自然数k

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 tiny.c21 行定义.

21 {
22 int k = 0;
23 while (x) {
24 x >>= 1;
25 k++;
26 }
27 return k;
28}

引用了 k , 以及 n.

◆ lmmp_limb_popcnt_()

int lmmp_limb_popcnt_ ( mp_limb_t  x)

计算一个64位无符号整数中1的个数

参数
x输入的64位无符号整数
返回
1的个数

在文件 tiny.c30 行定义.

30 {
31#if defined(__GNUC__) || defined(__clang__)
33#if defined(__x86_64__) && defined(USE_ASM)
34 __asm__ volatile("popcnt %1, %0" : "=r"(count) : "r"(x) : "cc");
35#else
37#endif
38 return count;
39#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
40 return (int)__popcnt64(x);
41#else
42 int k = 0;
43 while (x) {
44 k += x & 1;
45 x >>= 1;
46 }
47 return k;
48#endif
49}

引用了 k , 以及 n.

◆ lmmp_mod_1_()

mp_limb_t lmmp_mod_1_ ( mp_srcptr  numa,
mp_size_t  na,
mp_limb_t  x 
)

单精度数取余

参数
numa输入被除数,长度为na
na被除数的 limb 长度
x除数(单个 limb )
返回
除法余数(单个 limb )
警告
na>0, x!=0, eqsep(dstq,numa), dstq>=numa-1 是可以接受的

在文件 div.c31 行定义.

31 {
33 // q: assigned for macro reuse, unused in this logic (known warning)
34 mp_limb_t t = numa[na - 2], q = 0, r = 0;
35 const int shift = lmmp_leading_zeros_(x);
36 if (shift > 0) {
37 const int rshift = LIMB_BITS - shift;
38 ah = numa[na - 1] >> rshift;
39 t = numa[na - 2];
40 al = (numa[na - 1] << shift) | (t >> rshift);
41 x <<= shift;
42 const mp_limb_t inv = lmmp_inv_1_(x);
43 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
44 na -= 2;
45 while (na-- > 0) {
46 ah = r;
47 al = t << shift;
48 t = numa[na];
49 al |= t >> rshift;
50 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
51 }
52 ah = r;
53 al = t << shift;
54 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
55 return r >> shift;
56 } else {
57 ah = 0;
58 t = numa[na - 2];
59 al = numa[na - 1];
60 const mp_limb_t inv = lmmp_inv_1_(x);
61 q = al / x;
62 r = al % x;
63 na -= 2;
64 while (na-- > 0) {
65 ah = r;
66 al = t;
67 t = numa[na];
68 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
69 }
70 ah = r;
71 al = t;
72 _udiv_qrnnd_preinv(q, r, ah, al, x, inv);
73 return r;
74 }
75}

引用了 _udiv_qrnnd_preinv, LIMB_BITS, lmmp_inv_1_(), lmmp_leading_zeros_, n , 以及 t.

被这些函数引用 lmmp_div_1_(), lmmp_gcd_1_() , 以及 lmmp_trialdiv_short_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_mod_2_()

void lmmp_mod_2_ ( mp_srcptr  numa,
mp_size_t  na,
mp_ptr  numb 
)

双精度数取余 (除数为2个limb)

参数
numa输入被除数(长度na)
na被除数的 limb 长度
numb输入除数(长度2)[numb,2]=[numa,na] mod [numb,2]
警告
na>=2, numb[1]!=0, eqsep(dstq,numa), dstq>=numa 是可以接受的

在文件 div.c155 行定义.

155 {
156 mp_limb_t q, r1, r0, a2, a1, a0, b1, b0;
157 b1 = numb[1];
158 b0 = numb[0];
159 if (na == 2) {
161 if (shift > 0) {
162 const int rshift = LIMB_BITS - shift;
163 b1 = (b1 << shift) | (b0 >> rshift);
164 b0 <<= shift;
165 a2 = numa[1] >> rshift;
166 a1 = (numa[1] << shift) | (numa[0] >> rshift);
167 a0 = (numa[0] << shift);
169 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
170 numb[0] = (r0 >> shift) | (r1 << rshift);
171 numb[1] = r1 >> shift;
172 return;
173 } else {
174 if (_u128cmp(numa, numb)) {
175 numb[0] = numa[0];
176 numb[1] = numa[1];
177 return;
178 } else {
180 return;
181 }
182 }
183 } else {
185 if (shift > 0) {
186 const int rshift = LIMB_BITS - shift;
187 b1 = (b1 << shift) | (b0 >> rshift);
188 b0 <<= shift;
189 const mp_limb_t inv = lmmp_inv_2_1_(b1, b0);
190 a2 = numa[na - 1] >> rshift;
191 a1 = (numa[na - 1] << shift) | (numa[na - 2] >> rshift);
192 a0 = (numa[na - 2] << shift) | (numa[na - 3] >> rshift);
193 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
194 na -= 2;
195 while (na-- > 1) {
196 a2 = r1;
197 a1 = r0;
198 a0 = (numa[na] << shift) | (numa[na - 1] >> rshift);
199 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
200 }
201
202 a2 = r1;
203 a1 = r0;
204 a0 = (numa[na] << shift);
205 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
206 numb[0] = (r0 >> shift) | (r1 << rshift);
207 numb[1] = r1 >> shift;
208 return;
209 } else {
210 const mp_limb_t inv = lmmp_inv_2_1_(b1, b0);
211 a2 = 0;
212 a1 = numa[na - 1];
213 a0 = numa[na - 2];
214 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
215 na -= 2;
216 while (na-- > 1) {
217 a2 = r1;
218 a1 = r0;
219 a0 = numa[na];
220 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
221 }
222 a2 = r1;
223 a1 = r0;
224 a0 = numa[na];
225 _udiv_qr_3by2(q, r1, r0, a2, a1, a0, b1, b0, inv);
226 numb[0] = r0;
227 numb[1] = r1;
228 return;
229 }
230 }
231}

引用了 _u128cmp, _u128sub, _udiv_qr_3by2, a0, a1, a2, b0, b1, LIMB_BITS, lmmp_inv_2_1_(), lmmp_leading_zeros_, n, numb, r0 , 以及 r1.

被这些函数引用 lmmp_gcd_2_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_mul_()

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]

警告
0<nb<=na, sep(dst,[numa|numb])
参数
dst乘积结果输出指针(需要 na+nb 的 limb 长度)
numa第一个乘数指针(较长的操作数)
na第一个操作数的 limb 长度
numb第二个乘数指针(较短的操作数)
nb第二个操作数的 limb 长度

被这些函数引用 lmmp_bninv_appr_newton_(), lmmp_cube_(), lmmp_div_(), lmmp_div_divide_n_(), lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_divexact_divide_(), lmmp_elem_mul_ulong_(), lmmp_from_str_divide_(), lmmp_huff_tree_mul_(), lmmp_invappr_newton_(), lmmp_invsqrt_newton_(), lmmp_mul_fft_unbalance_(), lmmp_mul_signed_(), lmmp_mul_toom22_(), lmmp_mul_toom32_(), lmmp_mul_toom33_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom42_unbalance_(), lmmp_mul_toom43_(), lmmp_mul_toom44_(), lmmp_mul_toom52_(), lmmp_mul_toom53_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_(), lmmp_mul_toom62_cache_init_(), lmmp_mul_toom62_unbalance_(), lmmp_pow_win2_(), lmmp_sqrt_newton_() , 以及 pow_nPr_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_1_()

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

参数
dst结果输出指针
numa被乘数指针
na操作数的位数(limb数量)
x单个limb乘数
警告
na>0, eqsep(dst,numa) 支持 dst<=numa+1 的内存布局
返回
运算后的进位limb值

被这些函数引用 lmmp_3pow_1_(), lmmp_elem_mul_ulong_(), lmmp_from_str_(), lmmp_from_str_basecase_(), lmmp_lehmer_mul_(), lmmp_mullo_dc_(), lmmp_pow_(), lmmp_sqrlo_dc_(), lmmp_to_str_(), lmmp_u32_pow_1_(), lmmp_u64_pow_1_() , 以及 lmmp_u8_pow_1_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_basecase_()

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]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
0<nb<=na, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_mul_n_(), lmmp_mul_(), lmmp_mul_n_() , 以及 lmmp_u16_pow_1_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_fermat_()

void lmmp_mul_fermat_ ( mp_ptr  dst,
mp_size_t  rn,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

费马数模乘法 [dst,rn+1]=[numa,na]*[numb,nb] mod B^rn+1

参数
dst输出结果缓冲区,长度至少为 rn+1
rn模运算的阶数参数,rn = lmmp_fft_next_size_((na + nb + 1) >> 1)
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
eqsep(dst,[numa|numb]), 0<=[numa,na]<2*B^rn, 0<=[numb,nb]<2*B^rn, rn = lmmp_fft_next_size_((na+nb+1)>>1)
返回
无返回值,结果存储在dst中

在文件 mul_fft.c687 行定义.

687 {
688 int nsqr = numa != numb || na != nb; // 判断是否为平方运算
689 mp_size_t N = rn * LIMB_BITS; // 结果总比特数
691 mp_size_t K = ((mp_size_t)1) << k; // FFT块数(2^k)
692 lmmp_debug_assert(!(N & (K - 1)));
693 mp_size_t M = N >> k; // 每个块的比特数
694 mp_size_t n = 2 * M + k + 2; // 扩展系数长度
695
696 n = (n + LIMB_BITS - 1) & (-LIMB_BITS);
697 n = (((n - 1) >> k) + 1) << k;
698
699 // 初始化内存栈
701 msr.maxdepth = -1;
702 msr.tempdepth = -1;
703 msr.lenw = n / LIMB_BITS;
704 mp_size_t nlen = msr.lenw + 1;
705
706 msr.temp_coef = (mp_ptr)lmmp_fft_memstack_(&msr, (((nlen + 1) << (k + nsqr)) + nlen) * LIMB_BYTES);
707
708 mp_ptr *pfca = (mp_ptr*)(msr.temp_coef + nlen), *pfcb = pfca;
710
711 for (mp_size_t i = 0; i < K; ++i) {
713 pfca[i] = (mp_ptr)(pfca + K) + i * nlen;
714 if (narest > 0) {
715 coeflen = M + (i == K - 1);
717 narest -= coeflen;
719 if (i > 0)
720 lmmp_fft_shl_coef_(&msr, pfca + i, i * n >> k);
721 } else {
722 lmmp_zero(pfca[i], nlen);
723 }
724 }
725 lmmp_fft_(&msr, pfca, k, n >> (k - 1));
726
727 if (nsqr) {
728 pfcb += (nlen + 1) << k;
729 for (mp_size_t i = 0; i < K; ++i) {
731 pfcb[i] = (mp_ptr)(pfcb + K) + i * nlen;
732 if (nbrest > 0) {
733 coeflen = M + (i == K - 1);
735 nbrest -= coeflen;
737 if (i > 0)
738 lmmp_fft_shl_coef_(&msr, pfcb + i, i * n >> k);
739 } else {
740 lmmp_zero(pfcb[i], nlen);
741 }
742 }
743 lmmp_fft_(&msr, pfcb, k, n >> (k - 1));
744 }
745
747
748 lmmp_ifft_(&msr, pfca, k, n >> (k - 1));
749
751
752 // 处理模 B^rn+1 的溢出
753 if (dst[rn] && !lmmp_zero_q_(dst, rn)) {
754 dst[rn] = 0;
755 lmmp_dec(dst);
756 }
757
759}
static int lmmp_zero_q_(mp_srcptr p, mp_size_t n)
大数判零函数(内联)
Definition lmmpn.h:1019
#define LIMB_BYTES
Definition mparam.h:85
mp_ssize_t maxdepth
Definition mul_fft.c:73
static void lmmp_mul_fermat_recurse_(fft_memstack *ms, mp_ptr *pc1, mp_ptr *pc2, mp_size_t K0)
费马变换乘法递归函数(核心乘法逻辑)
Definition mul_fft.c:611
static void lmmp_fft_(fft_memstack *ms, mp_ptr *coef, mp_size_t k, mp_size_t w)
Definition mul_fft.c:453
static void * lmmp_fft_memstack_(fft_memstack *ms, mp_size_t size)
FFT内存栈的分配/释放接口
Definition mul_fft.c:109
static void lmmp_fft_shl_coef_(fft_memstack *ms, mp_ptr *coef, mp_size_t shl)
对模 2^n+1 的系数执行左移操作
Definition mul_fft.c:161
static void lmmp_mul_fermat_recombine_(fft_memstack *ms, mp_ptr dst, mp_ptr *pfca, mp_size_t K, mp_size_t k, mp_size_t n, mp_size_t M, mp_size_t rn)
费马变换 模 B^n+1 乘法的结果合并
Definition mul_fft.c:528
static void lmmp_ifft_(fft_memstack *ms, mp_ptr *coef, mp_size_t k, mp_size_t w)
Definition mul_fft.c:506
static void lmmp_fft_extract_coef_(mp_ptr dst, mp_srcptr numa, mp_size_t bitoffset, mp_size_t bits, mp_size_t lenw)
[dst,lenw+1] = [(bit*)numa+bitoffset, bits]
Definition mul_fft.c:135

引用了 k, LIMB_BITS, LIMB_BYTES, lmmp_debug_assert, lmmp_dec, lmmp_fft_(), lmmp_fft_best_k_(), lmmp_fft_extract_coef_(), lmmp_fft_memstack_(), lmmp_fft_shl_coef_(), lmmp_ifft_(), LMMP_MIN, lmmp_mul_fermat_recombine_(), lmmp_mul_fermat_recurse_(), lmmp_zero, lmmp_zero_q_(), fft_memstack::maxdepth, n , 以及 numb.

被这些函数引用 lmmp_mul_fft_() , 以及 lmmp_mullo_fft_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_mul_fft_()

void lmmp_mul_fft_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

FFT乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
???<=nb<=na, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

在文件 mul_fft.c1095 行定义.

1095 {
1096 lmmp_param_assert(na > 0 && nb > 0);
1098 mp_size_t hn = lmmp_fft_next_size_((na + nb + 1) >> 1);
1099 lmmp_assert(na + nb > hn);
1101
1103 mp_size_t nam = na;
1104 if (na > hn) {
1105 /*
1106 Z = B^hb - 1
1107 amodm = a mod Z
1108 */
1109 if (lmmp_add_(dst, numa, hn, numa + hn, na - hn))
1110 lmmp_inc(dst);
1111 amodm = dst;
1112 nam = hn;
1113 }
1115
1117 mp_size_t nap = na;
1118 if (na > hn) {
1119 /*
1120 Z = B^hp - 1
1121 amodp = a mod Z
1122 */
1123 tp[hn] = 0;
1124 if (lmmp_sub_(tp, numa, hn, numa + hn, na - hn))
1125 lmmp_inc(tp);
1126 amodp = tp;
1127 nap = hn + 1;
1128 }
1130
1132 cy <<= LIMB_BITS - 1;
1133 dst[hn - 1] += cy;
1134 if (dst[hn - 1] < cy)
1135 lmmp_inc(dst);
1136
1137 if (na + nb == 2 * hn) {
1138 cy = tp[hn] + lmmp_sub_n_(dst + hn, dst, tp, hn);
1139 // cy==1 means [tp,hn+1]!=0, then [dst,hn]!=0
1140 // cy==2 is impossible since [tp,hn+1] is normalized.
1141 // so the following dec won't overflow.
1142 lmmp_dec_1(dst, cy);
1143 } else {
1144 cy = lmmp_sub_n_(dst + hn, dst, tp, na + nb - hn);
1145 cy = tp[hn] + lmmp_sub_nc_(tp + na + nb - hn, dst + na + nb - hn, tp + na + nb - hn, 2 * hn - (na + nb), cy);
1146 cy = lmmp_sub_1_(dst, dst, na + nb, cy);
1147 }
1148 lmmp_free(tp);
1149}
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
void lmmp_free(void *ptr)
内存释放函数(调用lmmp_heap_free_fn)
Definition memory.c:202
#define lmmp_assert(x)
Definition lmmp.h:373
static mp_limb_t lmmp_add_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数加法静态内联函数 [dst,na]=[numa,na]+[numb,nb]
Definition lmmpn.h:1050
mp_limb_t lmmp_shr1add_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带进位加法后右移1位 [dst,n] = ([numa,n] + [numb,n] + c) >> 1
Definition shr.c:89
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:938
static mp_limb_t lmmp_sub_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数减法静态内联函数 [dst,na]=[numa,na]-[numb,nb]
Definition lmmpn.h:1064
#define lmmp_dec_1(p, dec)
大数减指定值宏(预期无借位)
Definition lmmpn.h:977
static mp_limb_t lmmp_sub_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数减单精度数静态内联函数 [dst,na]=[numa,na]-x
Definition lmmpn.h:1114
void lmmp_mul_mersenne_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
梅森数模乘法 [dst,rn] = [numa,na]*[numb,nb] mod B^rn-1
Definition mul_fft.c:761
void lmmp_mul_fermat_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
费马数模乘法 [dst,rn+1]=[numa,na]*[numb,nb] mod B^rn+1
Definition mul_fft.c:687
mp_size_t lmmp_fft_next_size_(mp_size_t n)
计算FFT运算所需的最小规整化长度(向上取整到2^k的倍数)
Definition mul_fft.c:95
#define ALLOC_TYPE(n, type)
Definition tmp_alloc.h:173

引用了 ALLOC_TYPE, LIMB_BITS, lmmp_add_(), lmmp_assert, lmmp_dec_1, lmmp_fft_next_size_(), lmmp_free(), lmmp_inc, lmmp_mul_fermat_(), lmmp_mul_mersenne_(), lmmp_param_assert, lmmp_shr1add_nc_(), lmmp_sub_(), lmmp_sub_1_(), lmmp_sub_n_(), lmmp_sub_nc_(), n, numb , 以及 tp.

被这些函数引用 __lmmp_mul_n_(), __lmmp_sqr_(), lmmp_mul_(), lmmp_mul_n_() , 以及 lmmp_sqr_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_mul_fft_unbalance_()

void lmmp_mul_fft_unbalance_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

FFT不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
hnFFT模域参数
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
???<=nb<=na, na>=3*nb, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_mersenne_()

void lmmp_mul_mersenne_ ( mp_ptr  dst,
mp_size_t  rn,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

梅森数模乘法 [dst,rn] = [numa,na]*[numb,nb] mod B^rn-1

参数
dst输出结果缓冲区,长度至少为 rn
rn模运算的阶数参数,rn = lmmp_fft_next_size_((na + nb + 1) >> 1)
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
eqsep(dst,[numa|numb]), 0<=[numa,na]<B^rn, 0<=[numb,nb]<B^rn, rn = lmmp_fft_next_size_((na+nb+1)>>1)
返回
无返回值,结果存储在dst中,

在文件 mul_fft.c761 行定义.

761 {
762 int nsqr = numa != numb || na != nb; // 判断是否为平方运算
763 mp_size_t N = rn * LIMB_BITS; // 结果总比特数
764 mp_size_t k = lmmp_fft_best_k_(rn); // 最优FFT层数
765 mp_size_t K = ((mp_size_t)1) << k; // FFT块数(2^k)
766 // 断言:N必须是K的整数倍
767 lmmp_debug_assert(!(N & (K - 1)));
768 mp_size_t M = N >> k; // 每个块的比特数
769 mp_size_t n = 2 * M + k; // 扩展系数长度(梅森数比费马数少2)
770
771 // 规整n:必须是LIMB_BITS和K/2的整数倍
772 n = (n + LIMB_BITS - 1) & (-LIMB_BITS);
773 n = (((n - 1) >> (k - 1)) + 1) << (k - 1);
774
775 // 初始化内存栈
777 msr.maxdepth = -1;
778 msr.tempdepth = -1;
779 msr.lenw = n / LIMB_BITS;
780 mp_size_t nlen = msr.lenw + 1;
781
782 msr.temp_coef = (mp_ptr)lmmp_fft_memstack_(&msr, (((nlen + 1) << (k + nsqr)) + nlen) * LIMB_BYTES);
783
784 mp_ptr *pfca = (mp_ptr*)(msr.temp_coef + nlen), *pfcb = pfca;
786
787 for (mp_size_t i = 0; i < K; ++i) {
789 pfca[i] = (mp_ptr)(pfca + K) + i * nlen;
790 if (narest > 0) {
792 narest -= coeflen;
794 } else {
795 lmmp_zero(pfca[i], nlen);
796 }
797 }
798 lmmp_fft_(&msr, pfca, k, n >> (k - 1));
799
800 if (nsqr) {
801 pfcb += (nlen + 1) << k;
802 for (mp_size_t i = 0; i < K; ++i) {
804 pfcb[i] = (mp_ptr)(pfcb + K) + i * nlen;
805 if (nbrest > 0) {
807 nbrest -= coeflen;
809 } else {
810 lmmp_zero(pfcb[i], nlen);
811 }
812 }
813 lmmp_fft_(&msr, pfcb, k, n >> (k - 1));
814 }
815
817
818 lmmp_ifft_(&msr, pfca, k, n >> (k - 1));
819
820 mp_size_t rhead = 0, maxc = 0;
821 for (mp_size_t i = 0; i < K; ++i) {
823 mp_ptr nums = pfca[i];
824
825 if (nums[nlen - 1]) {
826 lmmp_dec(nums);
827 lmmp_debug_assert(nums[nlen - 1] == 1);
828 nums[nlen - 1] = 0;
829 }
830
831 mp_size_t roffset = i * M;
832 mp_size_t shl = roffset & (LIMB_BITS - 1);
834
835 if (shl)
837
838 if (i == 0) {
840 rhead = nlen;
841 } else if (roffset + nlen <= rn) {
843 rhead = roffset + nlen;
844 } else {
846 maxc += lmmp_add_(dst, dst, rn, nums + rn - roffset, nlen + roffset - rn);
847 rhead = rn;
848 }
849 }
850
851 if (!lmmp_add_1_(dst, dst, rn, 1 + maxc))
852 lmmp_dec(dst);
853
855}
static void lmmp_fft_shr_coef_(fft_memstack *ms, mp_ptr *coef, mp_size_t shr)
对模 2^n+1 的系数执行右移操作 右移shr位 = 左移(2n - shr)位(mod 2^n+1的循环特性)
Definition mul_fft.c:228

引用了 k, LIMB_BITS, LIMB_BYTES, lmmp_add_(), lmmp_add_1_(), lmmp_copy, lmmp_debug_assert, lmmp_dec, lmmp_fft_(), lmmp_fft_best_k_(), lmmp_fft_extract_coef_(), lmmp_fft_memstack_(), lmmp_fft_shr_coef_(), lmmp_ifft_(), LMMP_MIN, lmmp_mul_fermat_recurse_(), lmmp_shl_(), lmmp_zero, fft_memstack::maxdepth, n , 以及 numb.

被这些函数引用 binvert_mulhi_(), lmmp_div_mulinv_(), lmmp_invappr_newton_(), lmmp_invsqrt_newton_(), lmmp_mul_fft_(), lmmp_mulhi_n_() , 以及 lmmp_mullo_fft_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_mul_n_()

void lmmp_mul_n_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

等长大数乘法操作 [dst,2*n] = [numa,n] * [numb,n]

警告
n>0, sep(dst,[numa|numb])
参数
dst乘积结果输出指针(需要 2*n 的 limb 长度)
numa第一个乘数指针
numb第二个乘数指针
nlimb长度

◆ lmmp_mul_toom22_()

void lmmp_mul_toom22_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-22乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
4/5<=nb/na<=1, nb>=5, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_mul_n_(), lmmp_mul_() , 以及 lmmp_mul_n_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom32_()

void lmmp_mul_toom32_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-32乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
5/9<=nb/na<=4/5, nb>=12, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom33_()

void lmmp_mul_toom33_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-33乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
4/5<=nb/na<=1, nb>=26, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_mul_n_(), lmmp_mul_() , 以及 lmmp_mul_n_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom42_()

void lmmp_mul_toom42_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-42乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
1/3<=nb/na<=5/9, nb>=20, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom42_unbalance_()

void lmmp_mul_toom42_unbalance_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-42不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
na>=3*nb, nb>=20, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom43_()

void lmmp_mul_toom43_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-43乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
3/5<=nb/na<=4/5, nb>=??, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom44_()

void lmmp_mul_toom44_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-44乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
4/5<=nb/na<=1, nb>=??, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_mul_n_(), lmmp_mul_() , 以及 lmmp_mul_n_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom52_()

void lmmp_mul_toom52_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-52乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
1/3<=nb/na<=9/20, nb>=??, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom53_()

void lmmp_mul_toom53_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-53乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
9/20<=nb/na<=3/5, nb>=??, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom62_()

void lmmp_mul_toom62_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-62乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
1/5<=nb/na<=1/3, nb>=??, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mul_toom62_unbalance_()

void lmmp_mul_toom62_unbalance_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)

Toom-62不平衡乘法运算 [dst,na+nb] = [numa,na] * [numb,nb]

参数
dst输出结果缓冲区,长度至少为 na+nb
numa第一个输入操作数,长度为 na
na第一个操作数的 limb 长度
numb第二个输入操作数,长度为 nb
nb第二个操作数的 limb 长度
警告
na>=5*nb, nb>=??, sep(dst,[numa|numb])
返回
无返回值,结果存储在dst中

被这些函数引用 lmmp_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_mulh_()

mp_limb_t lmmp_mulh_ ( mp_limb_t  a,
mp_limb_t  b 
)

计算两个64位无符号整数相乘的高位结果 (a*b)/B

参数
a第一个64位无符号整数
b第二个64位无符号整数
返回
乘积的高64位结果

在文件 tiny.c91 行定义.

91 {
92#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__)
94 return (mp_limb_t)(t >> 64);
95#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
96 return __umulh(a, b);
97#else
98 uint64_t ah = a >> 32, bh = b >> 32;
99 a = (uint32_t)a, b = (uint32_t)b;
100 uint64_t r0 = a * b, r1 = a * bh, r2 = ah * b, r3 = ah * bh;
101 r3 += (r1 >> 32) + (r2 >> 32);
102 r1 = (uint32_t)r1, r2 = (uint32_t)r2;
103 r1 += r2;
104 r1 += (r0 >> 32);
105 return r3 + (r1 >> 32);
106#endif
107}

引用了 n, r0, r1, r2, r3 , 以及 t.

◆ lmmp_mullh_()

void lmmp_mullh_ ( mp_limb_t  a,
mp_limb_t  b,
mp_ptr  dst 
)

计算两个64位无符号整数相乘的128位结果 (a*b)

参数
dst输出结果缓冲区,存储乘积结果,长度为 2
a第一个64位无符号整数
b第二个64位无符号整数
警告
dst 必须指向一个长度为 2 的数组
返回
无返回值

◆ lmmp_mullo_()

void lmmp_mullo_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n

参数
dst输出结果缓冲区,长度至少为 n
numa第一个输入操作数,长度为 n
numb第二个输入操作数,长度为 n
nlimb长度
警告
n>0, sep(dst,[numa|numb]) 特殊情况:当 n >= MULLO_DC_THRESHOLD 时,eqsep(dst,[numa|numb])是允许的
返回
无返回值,结果存储在dst中,[dst,n]=[numa,n] * [numb,n] mod B^n

◆ lmmp_mullo_dc_()

void lmmp_mullo_dc_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_ptr  tp,
mp_size_t  n 
)

低位乘法 [dst,n] = [numa,n] * [numb,n] mod B^n

参数
dst输出结果缓冲区,长度至少为 n
numa第一个输入操作数,长度为 n
numb第二个输入操作数,长度为 n
tp临时缓冲区,长度至少为 2*n
nlimb长度
警告
n>0, sep(dst,[numa|numb],tp)
返回
无返回值,结果存储在dst中,[dst,n]=[numa,n] * [numb,n] mod B^n

被这些函数引用 lmmp_mullo_n_() , 以及 lmmp_mullo_n_().

+ 这是这个函数的调用关系图:

◆ lmmp_mullo_fft_()

void lmmp_mullo_fft_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n,
mp_ptr  scratch 
)

低位FFT乘法 [dst,n] = [numa,n] * [numb,n] mod B^n

参数
dst输出结果缓冲区,长度至少为 n
numa第一个输入操作数,长度为 n
numb第二个输入操作数,长度为 n
scratch临时缓冲区,长度至少为 2*n
n缓冲区 limb 长度
警告
???<n, sep(scratch,[numa|numb]), eqsep(dst,scratch)
返回
无返回值,结果存储在dst中,[dst,n]=[numa,n] * [numb,n] mod B^n

低位FFT乘法 [dst,n] = [numa,n] * [numb,n] mod B^n

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 mullo.c22 行定义.

22 {
24 mp_size_t hn = lmmp_fft_next_size_((n + n + 1) >> 1);
25 lmmp_assert(n + n > hn);
27
29 mp_size_t nam = n;
30 if (n > hn) {
31 /*
32 Z = B^hb - 1
33 amodm = a mod Z
34 */
35 if (lmmp_add_(scratch, numa, hn, numa + hn, n - hn))
37 amodm = scratch;
38 nam = hn;
39 }
41
43 mp_size_t nap = n;
44 if (n > hn) {
45 /*
46 Z = B^hp - 1
47 amodp = a mod Z
48 */
49 tp[hn] = 0;
50 if (lmmp_sub_(tp, numa, hn, numa + hn, n - hn))
51 lmmp_inc(tp);
52 amodp = tp;
53 nap = hn + 1;
54 }
56
58 cy <<= LIMB_BITS - 1;
59 scratch[hn - 1] += cy;
60 if (scratch[hn - 1] < cy)
62
63 if (n == hn) {
65 // cy==1 means [tp,hn+1]!=0, then [dst,hn]!=0
66 // cy==2 is impossible since [tp,hn+1] is normalized.
67 // so the following dec won't overflow.
69 } else {
70 mp_size_t n2 = 2 * n;
72 cy = tp[hn] + lmmp_sub_nc_(tp + n2 - hn, scratch + n2 - hn, tp + n2 - hn, 2 * hn - n2, cy);
74 }
77}
void lmmp_mul_mersenne_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
梅森数模乘法 [dst,rn] = [numa,na]*[numb,nb] mod B^rn-1
Definition mul_fft.c:761
void lmmp_mul_fermat_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
费马数模乘法 [dst,rn+1]=[numa,na]*[numb,nb] mod B^rn+1
Definition mul_fft.c:687
mp_size_t lmmp_fft_next_size_(mp_size_t n)
计算满足 >=n 的最小费马/梅森乘法可行尺寸
Definition mul_fft.c:95
#define scratch

引用了 ALLOC_TYPE, LIMB_BITS, lmmp_add_(), lmmp_assert, lmmp_copy, lmmp_dec_1, lmmp_fft_next_size_(), lmmp_free(), lmmp_inc, lmmp_mul_fermat_(), lmmp_mul_mersenne_(), lmmp_param_assert, lmmp_shr1add_nc_(), lmmp_sub_(), lmmp_sub_1_(), lmmp_sub_n_(), lmmp_sub_nc_(), n, numb, scratch , 以及 tp.

被这些函数引用 lmmp_mullo_(), lmmp_mullo_n_(), lmmp_mullo_n_() , 以及 lmmp_sqrlo_n_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_not_()

void lmmp_not_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

大数按位取反操作 [dst,na] = ~[numa,na] (对每个limb执行按位非操作)

参数
dst结果输出指针
numa源操作数指针
nalimb长度
警告
na>0, eqsep(dst,numa)

被这些函数引用 lmmp_binvert_n_dc_(), lmmp_binvert_unbalanced_(), lmmp_fft_shl_coef_(), lmmp_inv_basecase_(), lmmp_invappr_newton_() , 以及 lmmp_invsqrt_newton_().

+ 这是这个函数的调用关系图:

◆ lmmp_shl_()

mp_limb_t lmmp_shl_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  shr 
)

大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0

参数
dst结果输出指针
numa源操作数指针
nalimb长度
shl左移的位数 (0~63)
警告
na>0, 0<=shl<64, eqsep(dst,numa) 允许dst指针地址大于numa(即支持原地长移位操作)
返回
其最低shl个比特位填充[numa,na]被移出的shl个最高位,其余比特位为0

大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 shl.c19 行定义.

19 {
20 if (shr == 0) {
22 return 0;
23 } else {
24 const mp_limb_t rshr = LIMB_BITS - shr;
27 numa += na;
28 dst += na;
29 low_limb = *--numa;
30 retval = low_limb >> rshr;
31 high_limb = (low_limb << shr);
32 while (--na != 0) {
33 low_limb = *--numa;
34 *--dst = high_limb | (low_limb >> rshr);
35 high_limb = (low_limb << shr);
36 }
37 *--dst = high_limb;
38 return retval;
39 }
40}

引用了 LIMB_BITS, lmmp_copy , 以及 n.

被这些函数引用 lmmp_10pow_1_(), lmmp_12pow_1_(), lmmp_14pow_1_(), lmmp_2factorial_(), lmmp_6pow_1_(), lmmp_arith_seqprod_(), lmmp_bninv_(), lmmp_bninv_appr_newton_(), lmmp_div_(), lmmp_factorial_(), lmmp_fft_shl_coef_(), lmmp_hyperfac_(), lmmp_inv_(), lmmp_mul_fermat_recombine_(), lmmp_mul_mersenne_(), lmmp_mul_mersenne_single_(), lmmp_mul_toom43_(), lmmp_mul_toom44_(), lmmp_mul_toom53_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_(), lmmp_mul_toom62_cache_init_(), lmmp_multinomial_(), lmmp_nCr_(), lmmp_nPr_(), lmmp_pow_1_(), lmmp_sqr_toom4_(), lmmp_sqrt_(), lmmp_sqrt_newton_(), lmmp_superfac_(), lmmp_to_str_(), lmmp_to_str_divide_(), lmmp_toom_eval_dgr3_pm2_(), lmmp_toom_eval_pm2_(), lmmp_toom_interp5_(), lmmp_toom_interp6_(), lmmp_toom_interp7_() , 以及 pow_nPr_().

+ 这是这个函数的调用关系图:

◆ lmmp_shl_c_()

mp_limb_t lmmp_shl_c_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  shl,
mp_limb_t  c 
)

带进位的大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充c的低shl位

参数
dst结果输出指针
numa源操作数指针
nalimb长度
shl左移的位数 (0~63)
c进位值(其高(64-shl)位必须为0)
警告
na>0, 0<=shl<64, eqsep(dst,numa) c的高(64-shl)位必须为0 允许dst指针地址大于numa(即支持原地长移位操作)
返回
其最低shl个比特位填充[numa,na]被移出的shl个最高位,其余比特位为0

在文件 shl.c42 行定义.

42 {
43 if (shr == 0) {
45 return 0;
46 } else {
47 const mp_limb_t rshr = LIMB_BITS - shr;
50 numa += na;
51 dst += na;
52 low_limb = *--numa;
53 retval = low_limb >> rshr;
54 high_limb = (low_limb << shr);
55 while (--na != 0) {
56 low_limb = *--numa;
57 *--dst = high_limb | (low_limb >> rshr);
58 high_limb = (low_limb << shr);
59 }
60 c &= ((mp_limb_t)1 << shr) - 1;
61 *--dst = high_limb | c;
62 return retval;
63 }
64}

引用了 c, LIMB_BITS, lmmp_copy , 以及 n.

被这些函数引用 lmmp_fft_bfy_().

+ 这是这个函数的调用关系图:

◆ lmmp_shlnot_()

mp_limb_t lmmp_shlnot_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  shl 
)

左移后按位取反操作 [dst,na] = ~([numa,na] << shl),dst的低shl位填充1

参数
dst结果输出指针
numa源操作数指针
nalimb长度
shl左移的位数 (0~63)
警告
na>0, 0<=shl<64, eqsep(dst,numa)
返回
其最低shl个比特位填充[numa,na]被移出的shl个最高位,其余比特位为0

被这些函数引用 lmmp_fft_shl_coef_() , 以及 lmmp_invsqrt_newton_().

+ 这是这个函数的调用关系图:

◆ lmmp_shr1add_n_()

mp_limb_t lmmp_shr1add_n_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

加法后右移1位 [dst,n] = ([numa,n] + [numb,n]) >> 1

参数
dst结果输出指针
numa第一个加数指针
numb第二个加数指针
nlimb长度
警告
n>0, eqsep(dst,[numa|numb])
返回
右移操作产生的进位值 [0|1]

在文件 shr.c62 行定义.

62 {
63 mp_size_t i = 0, c = 0, l = 0;
64 mp_limb_t a, b, r;
65
66 a = numa[i];
67 b = numb[i];
68 r = a + c;
69 c = (r < c);
70 r += b;
71 c += (r < b);
72 dst[i] = r >> 1;
73 l = r & 1;
74
75 for (i = 1; i < n; i++) {
76 a = numa[i];
77 b = numb[i];
78 r = a + c;
79 c = (r < c);
80 r += b;
81 c += (r < b);
82 dst[i - 1] |= r << (LIMB_BITS - 1);
83 dst[i] = r >> 1;
84 }
85 dst[n - 1] |= c << (LIMB_BITS - 1);
86 return l;
87}
#define l

引用了 c, l, LIMB_BITS, n , 以及 numb.

被这些函数引用 lmmp_mul_toom32_(), lmmp_toom_interp5_(), lmmp_toom_interp6_() , 以及 lmmp_toom_interp7_().

+ 这是这个函数的调用关系图:

◆ lmmp_shr1add_nc_()

mp_limb_t lmmp_shr1add_nc_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n,
mp_limb_t  c 
)

带进位加法后右移1位 [dst,n] = ([numa,n] + [numb,n] + c) >> 1

参数
dst结果输出指针
numa第一个加数指针
numb第二个加数指针
nlimb长度
c初始进位值 [0|1]
警告
n>0, c=[0|1], eqsep(dst,[numa|numb])
返回
右移操作产生的进位值 [0|1]

在文件 shr.c89 行定义.

89 {
90 mp_size_t i = 0, l = 0;
91 mp_limb_t a, b, r;
92
93 a = numa[i];
94 b = numb[i];
95 r = a + c;
96 c = (r < c);
97 r += b;
98 c += (r < b);
99 dst[i] = r >> 1;
100 l = r & 1;
101
102 for (i = 1; i < n; i++) {
103 a = numa[i];
104 b = numb[i];
105 r = a + c;
106 c = (r < c);
107 r += b;
108 c += (r < b);
109 dst[i - 1] |= r << (LIMB_BITS - 1);
110 dst[i] = r >> 1;
111 }
112 dst[n - 1] |= c << (LIMB_BITS - 1);
113 return l;
114}

引用了 c, l, LIMB_BITS, n , 以及 numb.

被这些函数引用 lmmp_mul_fft_(), lmmp_mul_fft_cache_() , 以及 lmmp_mullo_fft_().

+ 这是这个函数的调用关系图:

◆ lmmp_shr1sub_n_()

mp_limb_t lmmp_shr1sub_n_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

减法后右移1位 [dst,n] = ([numa,n] - [numb,n]) >> 1

参数
dst结果输出指针
numa被减数指针
numb减数指针
n操作数的位数(limb数量)
警告
n>0, eqsep(dst,[numa|numb])
返回
右移操作产生的进位值 (0或1)

在文件 shr.c116 行定义.

116 {
117 mp_size_t i = 0, c = 0, l = 0;
118 mp_limb_t a, b, r;
119
120 a = numa[i];
121 b = numb[i];
122 b += c;
123 c = (b < c);
124 c += (a < b);
125 r = a - b;
126 dst[i] = r >> 1;
127 l = r & 1;
128
129 for (i = 1; i < n; i++) {
130 a = numa[i];
131 b = numb[i];
132 b += c;
133 c = (b < c);
134 c += (a < b);
135 r = a - b;
136 dst[i - 1] |= r << (LIMB_BITS - 1);
137 dst[i] = r >> 1;
138 }
139 dst[n - 1] |= c << (LIMB_BITS - 1);
140 return l;
141}

引用了 c, l, LIMB_BITS, n , 以及 numb.

被这些函数引用 lmmp_mul_toom32_(), lmmp_toom_interp5_(), lmmp_toom_interp6_() , 以及 lmmp_toom_interp7_().

+ 这是这个函数的调用关系图:

◆ lmmp_shr1sub_nc_()

mp_limb_t lmmp_shr1sub_nc_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n,
mp_limb_t  c 
)

带借位减法后右移1位 [dst,n] = ([numa,n] - [numb,n] - c) >> 1

参数
dst结果输出指针
numa被减数指针
numb减数指针
nlimb长度
c初始借位值 [0|1]
警告
n>0, c=[0|1], eqsep(dst,[numa|numb])
返回
右移操作产生的进位值 [0|1]

在文件 shr.c143 行定义.

143 {
144 mp_size_t i = 0, l = 0;
145 mp_limb_t a, b, r;
146
147 a = numa[i];
148 b = numb[i];
149 b += c;
150 c = (b < c);
151 c += (a < b);
152 r = a - b;
153 dst[i] = r >> 1;
154 l = r & 1;
155
156 for (i = 1; i < n; i++) {
157 a = numa[i];
158 b = numb[i];
159 b += c;
160 c = (b < c);
161 c += (a < b);
162 r = a - b;
163 dst[i - 1] |= r << (LIMB_BITS - 1);
164 dst[i] = r >> 1;
165 }
166 dst[n - 1] |= c << (LIMB_BITS - 1);
167 return l;
168}

引用了 c, l, LIMB_BITS, n , 以及 numb.

◆ lmmp_shr_()

mp_limb_t lmmp_shr_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  shr 
)

大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0

参数
dst结果输出指针
numa源操作数指针
nalimb长度
shr右移的位数 (0~63)
警告
na>0, 0<=shr<64, eqsep(dst,numa) 允许dst指针地址小于numa(即支持原地长移位操作)
返回
其最高shr个比特位填充[numa,na]被移出的shr个最低位,其余比特位为0

大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 shr.c19 行定义.

19 {
20 if (shr == 0) {
22 return 0;
23 } else {
25 const mp_size_t rshr = LIMB_BITS - shr;
27 high_limb = *numa++;
28 retval = (high_limb << rshr);
30 while (--na != 0) {
31 high_limb = *numa++;
32 *dst++ = low_limb | (high_limb << rshr);
34 }
35 *dst = low_limb;
36 return retval;
37 }
38}

引用了 LIMB_BITS, lmmp_copy , 以及 n.

被这些函数引用 lmmp_bninv_(), lmmp_div_(), lmmp_fft_extract_coef_(), lmmp_invsqrt_newton_(), lmmp_sqrt_(), lmmp_sqrt_newton_(), lmmp_to_str_divide_(), lmmp_toom_interp6_() , 以及 lmmp_toom_interp7_().

+ 这是这个函数的调用关系图:

◆ lmmp_shr_c_()

mp_limb_t lmmp_shr_c_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  shr,
mp_limb_t  c 
)

带进位的大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充c的高shr位

参数
dst结果输出指针
numa源操作数指针
nalimb长度
shr右移的位数 (0~63)
c进位值(其低(64-shr)位必须为0)
警告
na>0, 0<=shr<64, eqsep(dst,numa) c的低(64-shr)位必须为0 允许dst指针地址小于numa(即支持原地长移位操作)
返回
其最高shr个比特位填充[numa,na]被移出的shr个最低位,其余比特位为0

在文件 shr.c40 行定义.

40 {
41 if (shr == 0) {
43 return 0;
44 } else {
46 const mp_size_t rshr = LIMB_BITS - shr;
48 high_limb = *numa++;
49 retval = (high_limb << rshr);
51 while (--na != 0) {
52 high_limb = *numa++;
53 *dst++ = low_limb | (high_limb << rshr);
55 }
56 c &= ~(((mp_limb_t)1 << rshr) - 1);
57 *dst = low_limb | c;
58 return retval;
59 }
60}

引用了 c, LIMB_BITS, lmmp_copy , 以及 n.

被这些函数引用 lmmp_ifft_bfy_(), lmmp_inv_() , 以及 lmmp_sqrt_divide_().

+ 这是这个函数的调用关系图:

◆ lmmp_sqr_()

void lmmp_sqr_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

大数平方操作 [dst,2*na] = [numa,na]^2

警告
na>0, sep(dst,numa)
参数
dst平方结果输出指针(需要2*na的limb长度)
numa源操作数指针
nalimb长度

◆ lmmp_sqr_basecase_()

void lmmp_sqr_basecase_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

基础平方运算 [dst,2*na] = [numa,na]^2

参数
dst输出结果缓冲区,长度至少为2*na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
0<na, sep(dst,numa)
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_sqr_(), lmmp_sqr_(), lmmp_u32_pow_1_() , 以及 lmmp_u64_pow_1_().

+ 这是这个函数的调用关系图:

◆ lmmp_sqr_toom2_()

void lmmp_sqr_toom2_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

Toom-2平方运算 [dst,2*na] = [numa,na]^2

参数
dst输出结果缓冲区,长度至少为 2*na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
??<na, sep(dst,numa)
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_sqr_() , 以及 lmmp_sqr_().

+ 这是这个函数的调用关系图:

◆ lmmp_sqr_toom3_()

void lmmp_sqr_toom3_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na 
)

Toom-3平方运算 [dst,2*na] = [numa,na]^2

参数
dst输出结果缓冲区,长度至少为2*na
numa输入操作数,长度为na
na输入操作数的单精度数(limb)长度
警告
??<na, sep(dst,numa)
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_sqr_() , 以及 lmmp_sqr_().

+ 这是这个函数的调用关系图:

◆ lmmp_sqr_toom4_()

void lmmp_sqr_toom4_ ( mp_ptr  pp,
mp_srcptr  ap,
mp_size_t  an 
)

Toom-4平方运算 [dst,2*na] = [numa,na]^2

参数
dst输出结果缓冲区,长度至少为2*na
numa输入操作数,长度为na
na输入操作数的单精度数(limb)长度
警告
??<na, sep(dst,numa)
返回
无返回值,结果存储在dst中

被这些函数引用 __lmmp_sqr_() , 以及 lmmp_sqr_().

+ 这是这个函数的调用关系图:

◆ lmmp_sqrlo_dc_()

void lmmp_sqrlo_dc_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_ptr  tp,
mp_size_t  n 
)

低位平方 [dst,n] = [numa,n]^2 mod B^n

参数
dst输出结果缓冲区,长度至少为 n
numa第一个输入操作数,长度为 n
tp临时缓冲区,长度至少为 2*n
nlimb长度
警告
n>0, sep(dst,numa,tp)
返回
无返回值,结果存储在dst中,[dst,n]=[numa,n]^2 mod B^n

被这些函数引用 lmmp_sqrlo_n_().

+ 这是这个函数的调用关系图:

◆ lmmp_sqrt_()

void lmmp_sqrt_ ( mp_ptr  dsts,
mp_ptr  dstr,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  nf 
)

大数平方根和取余操作

注解
如果dstr不为NULL: [dsts,nf+na/2+1], [dstr,nf+na/2+1] = sqrtrem([numa,na]*B^(2*nf)) 也即 [numa,na] × B^(2×nf) = [dsts,nf+na/2+1]^2 + [dstr,nf+na/2+1] 且 0 <= [dstr,nf+na/2+1] < 2 * [dsts,nf+na/2+1] + 1 如果dstr为NULL: [dsts,nf+na/2+1] = [round|floor](sqrt([numa,na]*B^(2*nf)))
警告
na>0, numa[na-1]!=0, eqsep(dsts,numa), eqsep(dstr,numa)
参数
dsts平方根结果输出指针
dstr余数结果输出指针(NULL表示不计算余数)
numa源操作数指针
na操作数的 limb 长度
nf精度因子

在文件 sqrt.c333 行定义.

333 {
335 lmmp_debug_assert(numa[na - 1] > 0);
336 mp_limb_t high = numa[na - 1];
337 int nsh = lmmp_leading_zeros_(high) / 2;
338 mp_size_t nl = na + 2 * nf;
339 if (nl == 1) {
341 lmmp_sqrt_1_(&srt, high << nsh * 2);
342 srt >>= nsh;
343 dsts[0] = srt;
344 if (dstr)
345 dstr[0] = high - srt * srt;
346 } else if (!dstr && nf >= 10 * na + SQRT_NEWTON_THRESHOLD) {
348 } else {
349 TEMP_DECL;
350 mp_limb_t ns = (nl + 1) / 2;
352 if (nf)
353 lmmp_zero(numa2, 2 * nf);
354 if (nsh)
355 lmmp_shl_(numa2 + 2 * ns - na, numa, na, nsh * 2);
356 else
357 lmmp_copy(numa2 + 2 * ns - na, numa, na);
358 if (nl & 1) {
359 numa2[2 * nf] = 0;
360 nsh += LIMB_BITS / 2;
361 } else {
362 dsts[ns] = 0;
363 }
365 if (nsh) {
366 if (dstr) {
367 mp_limb_t ds = dsts[0] & (((mp_limb_t)1 << nsh) - 1);
368 rh += lmmp_addmul_1_(numa2, dsts, ns, 2 * ds);
370 if (ns == 1)
371 rh -= b;
372 else
373 rh -= lmmp_sub_1_(numa2 + 1, numa2 + 1, ns - 1, b);
374 }
376 }
377 if (dstr) {
378 numa2[ns] = rh;
379 nsh *= 2;
380 if (nsh >= LIMB_BITS) {
381 nsh -= LIMB_BITS;
382 ++numa2;
383 } else
384 ++ns;
385 if (nsh)
387 else
389 }
390
391 TEMP_FREE;
392 }
393}
mp_limb_t lmmp_addmul_1_(mp_ptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t b)
大数乘以单limb并累加操作 [numa,n] += [numb,n] * b
#define SQRT_NEWTON_THRESHOLD
Definition mparam.h:41
static mp_limb_t lmmp_sqrt_divide_(mp_ptr dsts, mp_ptr numa, mp_size_t ns, int nsh)
Definition sqrt.c:117
static mp_limb_t lmmp_sqrt_1_(mp_ptr dsts, mp_limb_t x)
Definition sqrt.c:48
static void lmmp_sqrt_newton_(mp_ptr dsts, mp_srcptr numa, mp_size_t na, mp_size_t nf)
Definition sqrt.c:285

引用了 LIMB_BITS, lmmp_addmul_1_(), lmmp_copy, lmmp_debug_assert, lmmp_leading_zeros_, lmmp_shl_(), lmmp_shr_(), lmmp_sqrt_1_(), lmmp_sqrt_divide_(), lmmp_sqrt_newton_(), lmmp_sub_1_(), lmmp_submul_1_(), lmmp_zero, n, SQRT_NEWTON_THRESHOLD, TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

+ 函数调用图:

◆ lmmp_sub_()

static mp_limb_t lmmp_sub_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb 
)
inlinestatic

大数减法静态内联函数 [dst,na]=[numa,na]-[numb,nb]

参数
dst输出结果缓冲区,存储numa - numb
numa被减数,长度为na
na被减数的 limb 长度
numb减数,长度为nb
nb减数的 limb 长度
返回
借位标志(1表示有借位,0表示无借位)
警告
0<nb<=na, eqsep(dst,[numa|numb])

在文件 lmmpn.h1064 行定义.

1064 {
1065 LMMP_AORS_(lmmp_sub_n_, ((dst[nb++] = _x_ - 1), _x_ == 0));
1066}

引用了 LMMP_AORS_, lmmp_sub_n_() , 以及 n.

被这些函数引用 lmmp_add_signed_(), lmmp_lehmer_mul_(), lmmp_mul_fermat_recombine_(), lmmp_mul_fft_(), lmmp_mul_fft_cache_(), lmmp_mul_toom22_(), lmmp_mul_toom32_(), lmmp_mul_toom52_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_init_(), lmmp_mulhi_n_(), lmmp_mullo_fft_() , 以及 lmmp_toom_interp7_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_sub_1_()

static mp_limb_t lmmp_sub_1_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_limb_t  x 
)
inlinestatic

大数减单精度数静态内联函数 [dst,na]=[numa,na]-x

参数
dst输出结果缓冲区,存储numa - x
numa被减数,长度为na
na被减数的 limb 长度
x减数(单个 limb )
返回
借位标志(1表示有借位,0表示无借位)
警告
na>0, eqsep(dst,numa)

在文件 lmmpn.h1114 行定义.

#define LMMP_SUBCB_(r, x, y)
Definition lmmpn.h:1092

引用了 LMMP_AORS_1_ , 以及 LMMP_SUBCB_.

被这些函数引用 lmmp_div_divide_n_(), lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_mul_fft_(), lmmp_mul_fft_cache_(), lmmp_mul_toom32_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_init_(), lmmp_mullo_fft_(), lmmp_sqrt_() , 以及 lmmp_sqrt_divide_().

+ 这是这个函数的调用关系图:

◆ lmmp_sub_n_()

mp_limb_t lmmp_sub_n_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

无借位的n位减法 [dst,n] = [numa,n] - [numb,n]

参数
dst结果输出指针
numa被减数指针
numb减数指针
nlimb长度
警告
n>0, eqsep(dst,[numa|numb])
返回
运算后的最终借位值 [0|1]

在文件 sub_n.c80 行定义.

80 {
81 mp_size_t i = 0;
82 mp_limb_t cy = 0;
83
84 for (; i + 4 <= n; i += 4) {
85 mp_limb_t a0, b0, r0;
86 mp_limb_t a1, b1, r1;
87 mp_limb_t a2, b2, r2;
88 mp_limb_t a3, b3, r3;
89
90 a0 = numa[i + 0];
91 b0 = numb[i + 0];
92
93 a1 = numa[i + 1];
94 b1 = numb[i + 1];
95
96 a2 = numa[i + 2];
97 b2 = numb[i + 2];
98
99 a3 = numa[i + 3];
100 b3 = numb[i + 3];
101
102 b0 += cy;
103 cy = (b0 < cy);
104 cy += (a0 < b0);
105 r0 = a0 - b0;
106
107 b1 += cy;
108 cy = (b1 < cy);
109 cy += (a1 < b1);
110 r1 = a1 - b1;
111
112 b2 += cy;
113 cy = (b2 < cy);
114 cy += (a2 < b2);
115 r2 = a2 - b2;
116
117 b3 += cy;
118 cy = (b3 < cy);
119 cy += (a3 < b3);
120 r3 = a3 - b3;
121
122 dst[i + 0] = r0;
123 dst[i + 1] = r1;
124 dst[i + 2] = r2;
125 dst[i + 3] = r3;
126 }
127
128 for (; i < n; i++) {
129 mp_limb_t a, b;
130 a = numa[i];
131 b = numb[i];
132 b += cy;
133 cy = (b < cy);
134 cy += (a < b);
135 dst[i] = a - b;
136 }
137
138 return cy;
139}

引用了 a0, a1, a2, a3, b0, b1, b2, b3, n, numb, r0, r1, r2 , 以及 r3.

被这些函数引用 lmmp_bninv_appr_newton_(), lmmp_div_(), lmmp_div_basecase_(), lmmp_div_divide_n_(), lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_divexact_divide_(), lmmp_divexact_unbalanced_(), lmmp_invappr_newton_(), lmmp_mul_fermat_recurse_(), lmmp_mul_fft_(), lmmp_mul_fft_cache_(), lmmp_mul_toom22_(), lmmp_mul_toom32_(), lmmp_mul_toom52_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_init_(), lmmp_mullo_fft_(), lmmp_sqr_toom2_(), lmmp_sqrt_divide_(), lmmp_sub_(), lmmp_toom_interp5_(), lmmp_toom_interp6_() , 以及 lmmp_toom_interp7_().

+ 这是这个函数的调用关系图:

◆ lmmp_sub_nc_()

mp_limb_t lmmp_sub_nc_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n,
mp_limb_t  c 
)

带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c

参数
dst结果输出指针
numa被减数指针
numb减数指针
nlimb长度
c初始借位值 [0|1]
警告
c=[0|1], n>0, eqsep(dst,[numa|numb])
返回
运算后的最终借位值 [0|1]

带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 sub_n.c19 行定义.

19 {
20 mp_size_t i = 0;
21 mp_limb_t cy = c;
22
23 for (; i + 4 <= n; i += 4) {
24 mp_limb_t a0, b0, r0;
25 mp_limb_t a1, b1, r1;
26 mp_limb_t a2, b2, r2;
27 mp_limb_t a3, b3, r3;
28
29 a0 = numa[i + 0];
30 b0 = numb[i + 0];
31
32 a1 = numa[i + 1];
33 b1 = numb[i + 1];
34
35 a2 = numa[i + 2];
36 b2 = numb[i + 2];
37
38 a3 = numa[i + 3];
39 b3 = numb[i + 3];
40
41 b0 += cy;
42 cy = (b0 < cy);
43 cy += (a0 < b0);
44 r0 = a0 - b0;
45
46 b1 += cy;
47 cy = (b1 < cy);
48 cy += (a1 < b1);
49 r1 = a1 - b1;
50
51 b2 += cy;
52 cy = (b2 < cy);
53 cy += (a2 < b2);
54 r2 = a2 - b2;
55
56 b3 += cy;
57 cy = (b3 < cy);
58 cy += (a3 < b3);
59 r3 = a3 - b3;
60
61 dst[i + 0] = r0;
62 dst[i + 1] = r1;
63 dst[i + 2] = r2;
64 dst[i + 3] = r3;
65 }
66
67 for (; i < n; i++) {
68 mp_limb_t a, b;
69 a = numa[i];
70 b = numb[i];
71 b += cy;
72 cy = (b < cy);
73 cy += (a < b);
74 dst[i] = a - b;
75 }
76
77 return cy;
78}

引用了 a0, a1, a2, a3, b0, b1, b2, b3, c, n, numb, r0, r1, r2 , 以及 r3.

被这些函数引用 lmmp_add_n_sub_n_(), lmmp_div_(), lmmp_div_mulinv_(), lmmp_fft_bfy_(), lmmp_ifft_bfy_(), lmmp_invappr_newton_(), lmmp_mul_fft_(), lmmp_mul_fft_cache_() , 以及 lmmp_mullo_fft_().

+ 这是这个函数的调用关系图:

◆ lmmp_submul_1_()

mp_limb_t lmmp_submul_1_ ( mp_ptr  numa,
mp_srcptr  numb,
mp_size_t  n,
mp_limb_t  b 
)

大数乘以单limb并累减操作 [numa,n] -= [numb,n] * b

参数
numa被减数指针(结果也存储在此)
numb乘数指针
nlimb长度
b乘数
警告
n>0, eqsep(numa,numb))
返回
运算后的借位limb值

被这些函数引用 lmmp_div_(), lmmp_div_basecase_(), lmmp_divexact_basecase_(), lmmp_sqrt_() , 以及 lmmp_toom_interp7_().

+ 这是这个函数的调用关系图:

◆ lmmp_subshl1_n_()

mp_limb_t lmmp_subshl1_n_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_srcptr  numb,
mp_size_t  n 
)

减法结合左移1位操作 [dst,n] = [numa,n] - ([numb,n] << 1)

参数
dst结果输出指针
numa被减数指针
numb减数指针(先左移1位)
nlimb长度
警告
n>0, eqsep(dst,[numa|numb])
返回
运算后的借位值 [0|1|2]

在文件 shl.c83 行定义.

83 {
84 mp_size_t i, c = 0, mb = 0;
85
86 for (i = 0; i < n; i++) {
87 mp_limb_t a, b;
88 a = numa[i];
89 b = (numb[i] << 1) + mb;
90 mb = numb[i] >> (LIMB_BITS - 1);
91 b += c;
92 c = (b < c);
93 c += (a < b);
94 dst[i] = a - b;
95 }
96 return c + mb;
97}

引用了 c, LIMB_BITS, n , 以及 numb.

◆ lmmp_tailing_zeros_()

int lmmp_tailing_zeros_ ( mp_limb_t  x)

计算一个单精度数(limb)中末尾零的个数

参数
x输入的64位无符号整数
返回
末尾零的位数(范围:0~64)

在文件 tiny.c71 行定义.

71 {
72 if (x == 0) return 64;
73#ifdef __GNUC__
74 return __builtin_ctzll(x);
75#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
76 unsigned long index;
77 _BitScanForward64(&index, x);
78 return (int)index;
79#else
80 int n = 0;
81 if ((x & 0x00000000FFFFFFFF) == 0) { n += 32; x >>= 32; }
82 if ((x & 0x000000000000FFFF) == 0) { n += 16; x >>= 16; }
83 if ((x & 0x00000000000000FF) == 0) { n += 8; x >>= 8; }
84 if ((x & 0x000000000000000F) == 0) { n += 4; x >>= 4; }
85 if ((x & 0x0000000000000003) == 0) { n += 2; x >>= 2; }
86 if ((x & 0x0000000000000001) == 0) { n += 1; x >>= 1; }
87 return n;
88#endif
89}

引用了 n.

◆ lmmp_to_str_()

mp_size_t lmmp_to_str_ ( mp_byte_t dst,
mp_srcptr  numa,
mp_size_t  na,
int  base 
)

大数转字符串操作 [numa,na,B] to [dst,return value,base]

警告
na>=0, 2<=base<=256
参数
dst字符串结果输出指针
numa大数源指针
na大数的 limb 长度
base目标字符串的进制基数
返回
转换后的字符串长度

在文件 to_str.c175 行定义.

175 {
176 lmmp_param_assert(base >= 2 && base <= 256);
177 do {
178 if (na == 0)
179 return 0;
180 } while (numa[--na] == 0);
181 ++na;
182
183 mp_size_t digits;
184 if (LMMP_POW2_Q(base)) {
185 mp_limb_t curlimb = numa[na - 1];
186 int cnt = lmmp_bases_table[base - 2].large_base;
188 int mask = (1 << cnt) - 1;
189 mp_size_t bits = bitsh + LIMB_BITS * (na - 1);
190 digits = (bits - 1) / cnt + 1;
191 dst += digits;
192 int bitpos = digits * cnt - LIMB_BITS * (na - 1);
193
194 do {
195 while ((bitpos -= cnt) >= 0) {
196 *--dst = curlimb >> bitpos & mask;
197 }
198 if (--na == 0)
199 break;
201 curlimb = numa[na - 1];
202 bitpos += LIMB_BITS;
203 *--dst = (prevlimb | curlimb >> bitpos) & mask;
204 } while (1);
205 } else if (na < TO_STR_BASEPOW_THRESHOLD) {
206 digits = lmmp_to_str_basecase_(dst, numa, na, base);
207 } else {
208 TEMP_DECL;
213 mp_size_t bexp = (lmmp_to_str_len_(numa, na, base) - 1) / digitspl + 1;
215 // numa 的拷贝空间,多一个 limb 预留规整化移位所需
216 mp_size_t alloc_size = na + 1;
218 mp_ptr tp;
219
220 int cpow = 0;
221
222 do {
223 bexp = (bexp + 1) >> 1;
224 exps[cpow] = bexp;
225 ++cpow;
226
227 // we will calculate lbase^(bexp-1) first, and trim it s. t.
228 // it contains at most 2 tailing 0 limb, then multiply it by lbase,
229 // so we need npow limbs to store lbase^bexp
230 mp_size_t npow = lmmp_from_str_len_(0, (bexp - 1) * digitspl + 1, base) + 1;
231
232 // space needed for quotients in recursive calls,
233 // quotients are smaller than lbase^bexp
234 alloc_size += npow + 1;
235
236 if (tzbit) {
237 mp_size_t tzlimb = tzbit * (bexp - 1) / LIMB_BITS;
238 if (tzlimb >= 2)
239 npow -= tzlimb - 2;
240 }
241
242 // space needed for a trimmed npow-limb lbase^bexp and its inverse
243 alloc_size += npow * 2;
244 } while (bexp > 1);
245
247
248 for (int i = 0; i < 2; ++i) {
249 tp[0] = lbase;
250 powers[i].p = tp;
251 powers[i].np = 1;
252 tp += i + 1;
253 powers[i].zeros = 0;
254 powers[i].digits = digitspl * (i + 1);
255 powers[i].base = base;
256 }
257
258 mp_ptr p = powers[1].p;
259 mp_size_t zeros = 0, np = 1;
260 bexp = 1;
261 for (int i = 2; i < cpow; ++i) {
262 lmmp_sqr_(tp, p, np);
263 bexp *= 2;
264 np *= 2;
265 np -= tp[np - 1] == 0;
266 if (bexp + 1 < exps[cpow - 1 - i]) {
267 cy = lmmp_mul_1_(tp, tp, np, lbase);
268 tp[np] = cy;
269 np += cy != 0;
270 ++bexp;
271 }
272 zeros *= 2;
273 while (tp[0] == 0) {
274 // at most 2 tailing 0 limb here
275 ++zeros;
276 ++tp;
277 --np;
278 }
279 p = tp;
280 powers[i].p = p;
281 powers[i].np = np;
282 powers[i].zeros = zeros;
283 powers[i].digits = digitspl * (bexp + 1);
284 powers[i].base = base;
285 tp += np + 1;
286 }
287
288 for (int i = 1; i < cpow; ++i) {
289 p = powers[i].p;
290 np = powers[i].np;
291 cy = lmmp_mul_1_(p, p, np, lbase);
292 p[np] = cy;
293 np += cy != 0;
294 if (p[0] == 0) {
295 ++powers[i].zeros;
296 ++p;
297 --np;
298 }
299
300 powers[i].p = p;
301 powers[i].np = np;
302
303 // Note: all powers except powers[0] are normalized
304 // ASSERT: powers[0] will be never used in lmmp_to_str_divide_
305 // i.e. TO_STR_DIVIDE_THRESHOLD >= 3
306 int cnt = lmmp_leading_zeros_(p[np - 1]);
307 if ((powers[i].norm_cnt = cnt))
308 lmmp_shl_(p, p, np, cnt);
309
310 if (np < DIV_MULINV_L_THRESHOLD) {
311 // use divs, no need to compute inv
312 powers[i].invp = 0;
313 powers[i].ni = 0;
314 } else {
315 // pre-compute inverse
316 mp_size_t ni = lmmp_div_inv_size_(np + powers[i].zeros, np);
317 lmmp_inv_prediv_(tp, p, np, ni);
318 powers[i].invp = tp;
319 powers[i].ni = ni;
320 tp += ni;
321 }
322 }
323
324 lmmp_copy(tp, numa, na);
325 digits = lmmp_to_str_divide_(dst, tp, na, powers + cpow - 1, tp + na + 1);
326
327 TEMP_FREE;
328 }
329
330 return digits;
331}
mp_size_t lmmp_from_str_len_(const mp_byte_t *src, mp_size_t len, int base)
计算字符串转大数所需的 limb 缓冲区长度
Definition from_str.c:23
#define TO_STR_BASEPOW_THRESHOLD
Definition mparam.h:70
static mp_size_t lmmp_to_str_divide_(mp_byte_t *dst, mp_ptr restrict numa, mp_size_t na, mp_basepow_t *pow, mp_ptr restrict tpq)
将mp_limb_t数组转换为字符串
Definition to_str.c:97
static mp_size_t lmmp_to_str_basecase_(mp_byte_t *dst, mp_srcptr numa, mp_size_t na, int base)
将mp_limb_t数组转换为字符串
Definition to_str.c:45
mp_size_t lmmp_to_str_len_(mp_srcptr numa, mp_size_t na, int base)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition to_str.c:23

引用了 BALLOC_TYPE, mp_base_t::digits_in_limb, DIV_MULINV_L_THRESHOLD, mp_base_t::large_base, LIMB_BITS, lmmp_bases_table, lmmp_copy, lmmp_div_inv_size_(), lmmp_from_str_len_(), lmmp_inv_prediv_(), lmmp_leading_zeros_, lmmp_limb_bits_, lmmp_mul_1_(), lmmp_param_assert, LMMP_POW2_Q, lmmp_shl_(), lmmp_sqr_, lmmp_tailing_zeros_, lmmp_to_str_basecase_(), lmmp_to_str_divide_(), lmmp_to_str_len_(), n, TEMP_DECL, TEMP_FREE, TO_STR_BASEPOW_THRESHOLD , 以及 tp.

+ 函数调用图:

◆ lmmp_to_str_len_()

mp_size_t lmmp_to_str_len_ ( mp_srcptr  numa,
mp_size_t  na,
int  base 
)

计算大数转换为字符串,字符串需要的缓冲区长度

参数
numa输入大数,长度为na
na大数的 limb 长度
base目标基数(2~256)
返回
大数在指定基数下的位数
警告
na>=0, 2<=base<=256
注解
将会忽略numa的前导零,
  1. if (numa!=NULL) 返回的长度可能会多分配一个字符空间
  2. if (numa==NULL) 返回na个limb长度的数的最大可能字符长度(最坏情况)

计算大数转换为字符串,字符串需要的缓冲区长度

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 to_str.c23 行定义.

23 {
24 lmmp_param_assert(base >= 2 && base <= 256);
25 int mslbits = 0;
26 if (numa) {
27 do {
28 if (na == 0)
29 return 1;
30 } while (numa[--na] == 0);
32 }
33 return lmmp_mulh_(na * LIMB_BITS + mslbits, lmmp_bases_table[base - 2].inv_lg_base) + 1;
34}

引用了 LIMB_BITS, lmmp_bases_table, lmmp_limb_bits_, lmmp_mulh_, lmmp_param_assert , 以及 n.

被这些函数引用 lmmp_to_str_().

+ 这是这个函数的调用关系图:

◆ lmmp_zero_q_()

static int lmmp_zero_q_ ( mp_srcptr  p,
mp_size_t  n 
)
inlinestatic

大数判零函数(内联)

参数
p指向大数起始位置的指针
n大数的单精度数(limb)长度
返回
1(全零) / 0(非零)
警告
n>0
注解
从最高位开始检查,只要有非零位则返回0

在文件 lmmpn.h1019 行定义.

1019 {
1020 do {
1021 if (p[--n] != 0)
1022 return 0;
1023 } while (n != 0);
1024 return 1;
1025}

引用了 n.

被这些函数引用 lmmp_invsqrt_newton_(), lmmp_mul_fermat_(), lmmp_mul_fermat_single_(), lmmp_mul_toom22_(), lmmp_mul_toom32_(), lmmp_mul_toom42_(), lmmp_mul_toom42_cache_init_(), lmmp_mul_toom52_(), lmmp_mul_toom62_(), lmmp_mul_toom62_cache_init_() , 以及 try_div_().

+ 这是这个函数的调用关系图: