我最近在Ubuntu 16.04上安装了GMP库。我试图编译一些程序,比如C ++中的这个阶乘计算器,以确保一切正常。
#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
void fact(int n)
{
int i;
mpz_t p;
mpz_init_set_ui(p,1); /* p = 1 */
for (i=1; i <= n ; ++i)
{
mpz_mul_ui(p,p,i); /* p = p * i */
}
printf ("%d! = ", n);
mpz_out_str(stdout,10,p);
std::cout<<"\n";
mpz_clear(p);
}
int main(int argc, char * argv[])
{
int n;
if (argc <= 1)
{
printf ("Usage: %s <number> \n", argv[0]);
return 2;
}
n = atoi(argv[1]);
assert( n >= 0);
fact(n);
return 1;
}
我使用此命令成功编译了此程序 - g++ foo.cpp -o bar -lgmp
我也可以使用./bar INT
成功运行该程序。
当我尝试使用此命令(gcc gmp-chudnovsky.c -o pi -lgmp -lm -std=gnu11
)从gmplib.org编译gmp-chudnovsky.c时,每次调用内联函数时都会抛出这些错误:
$ sudo gcc gmp-chudnovsky.c -o pi -lgmp -lm -std=gnu11
/tmp/ccwzMQ8N.o: In function `fac_remove_gcd':
gmp-chudnovsky.c:(.text+0x798): undefined reference to `fac_resize'
gmp-chudnovsky.c:(.text+0x9da): undefined reference to `fac_compact'
gmp-chudnovsky.c:(.text+0x9e6): undefined reference to `fac_compact'
/tmp/ccwzMQ8N.o: In function `bs':
gmp-chudnovsky.c:(.text+0xd48): undefined reference to `fac_set_bp'
gmp-chudnovsky.c:(.text+0xd6f): undefined reference to `fac_mul_bp'
gmp-chudnovsky.c:(.text+0xdc2): undefined reference to `fac_set_bp'
gmp-chudnovsky.c:(.text+0xdfb): undefined reference to `fac_mul_bp'
gmp-chudnovsky.c:(.text+0xe34): undefined reference to `fac_mul_bp'
gmp-chudnovsky.c:(.text+0x1197): undefined reference to `fac_mul'
gmp-chudnovsky.c:(.text+0x1228): undefined reference to `fac_mul'
/tmp/ccwzMQ8N.o: In function `main':
gmp-chudnovsky.c:(.text+0x18e4): undefined reference to `fac_init'
gmp-chudnovsky.c:(.text+0x1901): undefined reference to `fac_init'
gmp-chudnovsky.c:(.text+0x1931): undefined reference to `fac_init'
gmp-chudnovsky.c:(.text+0x193b): undefined reference to `fac_init'
gmp-chudnovsky.c:(.text+0x1a61): undefined reference to `fac_clear'
gmp-chudnovsky.c:(.text+0x1a6b): undefined reference to `fac_clear'
gmp-chudnovsky.c:(.text+0x1aef): undefined reference to `fac_clear'
gmp-chudnovsky.c:(.text+0x1b0c): undefined reference to `fac_clear'
gmp-chudnovsky.c:(.text+0x1b46): undefined reference to `fac_clear'
/tmp/ccwzMQ8N.o:gmp-chudnovsky.c:(.text+0x1b55): more undefined references to `fac_clear' follow
collect2: error: ld returned 1 exit status
inline void
fac_resize(fac_t f, long int s)
{
if (f[0].max_facs < s) {
fac_clear(f);
fac_init_size(f, s);
}
}
/* remove factors of power 0 */
inline void
fac_compact(fac_t f)
{
long int i, j;
for (i=0, j=0; i<f[0].num_facs; i++) {
if (f[0].pow[i]>0) {
if (j<i) {
f[0].fac[j] = f[0].fac[i];
f[0].pow[j] = f[0].pow[i];
}
j++;
}
}
f[0].num_facs = j;
}
/* f = base^pow */
inline void
fac_set_bp(fac_t f, unsigned long base, long int pow)
{
long int i;
assert(base<sieve_size);
for (i=0, base/=2; base>0; i++, base = sieve[base].nxt) {
f[0].fac[i] = sieve[base].fac;
f[0].pow[i] = sieve[base].pow*pow;
}
f[0].num_facs = i;
assert(i<=f[0].max_facs);
}
/* f *= base^pow */
inline void
fac_mul_bp(fac_t f, unsigned long base, unsigned long pow)
{
fac_set_bp(ftmp, base, pow);
fac_mul(f, ftmp);
}
/* f *= g */
inline void
fac_mul(fac_t f, fac_t g)
{
fac_t tmp;
fac_resize(fmul, f[0].num_facs + g[0].num_facs);
fac_mul2(fmul, f, g);
tmp[0] = f[0];
f[0] = fmul[0];
fmul[0] = tmp[0];
}
inline void
fac_init(fac_t f)
{
fac_init_size(f, INIT_FACS);
}
inline void
fac_clear(fac_t f)
{
free(f[0].fac);
}
fac_remove_gcd
中:/* f /= gcd(f,g), g /= gcd(f,g) */
void
fac_remove_gcd(mpz_t p, fac_t fp, mpz_t g, fac_t fg)
{
long int i, j, k, c;
/* VV undefined reference VV */
fac_resize(fmul, min(fp->num_facs, fg->num_facs));
for (i=j=k=0; i<fp->num_facs && j<fg->num_facs; ) {
if (fp->fac[i] == fg->fac[j]) {
c = min(fp->pow[i], fg->pow[j]);
fp->pow[i] -= c;
fg->pow[j] -= c;
fmul->fac[k] = fp->fac[i];
fmul->pow[k] = c;
i++; j++; k++;
} else if (fp->fac[i] < fg->fac[j]) {
i++;
} else {
j++;
}
}
fmul->num_facs = k;
assert(k <= fmul->max_facs);
if (fmul->num_facs) {
bs_mul(gcd, 0, fmul->num_facs);
#if HAVE_DIVEXACT_PREINV
mpz_invert_mod_2exp (mgcd, gcd);
mpz_divexact_pre (p, p, gcd, mgcd);
mpz_divexact_pre (g, g, gcd, mgcd);
#else
#define SIZ(x) x->_mp_size
mpz_divexact(p, p, gcd);
mpz_divexact(g, g, gcd);
#endif
/* VV undefined reference VV */
fac_compact(fp);
fac_compact(fg);
}
}
bs
中:/* binary splitting */
void
bs(unsigned long a, unsigned long b, unsigned gflag, long int level)
{
unsigned long i, mid;
int ccc;
if (b-a==1) {
/*
g(b-1,b) = (6b-5)(2b-1)(6b-1)
p(b-1,b) = b^3 * C^3 / 24
q(b-1,b) = (-1)^b*g(b-1,b)*(A+Bb).
*/
mpz_set_ui(p1, b);
mpz_mul_ui(p1, p1, b);
mpz_mul_ui(p1, p1, b);
mpz_mul_ui(p1, p1, (C/24)*(C/24));
mpz_mul_ui(p1, p1, C*24);
mpz_set_ui(g1, 2*b-1);
mpz_mul_ui(g1, g1, 6*b-1);
mpz_mul_ui(g1, g1, 6*b-5);
mpz_set_ui(q1, b);
mpz_mul_ui(q1, q1, B);
mpz_add_ui(q1, q1, A);
mpz_mul (q1, q1, g1);
if (b%2)
mpz_neg(q1, q1);
i=b;
while ((i&1)==0) i>>=1;
fac_set_bp(fp1, i, 3); /* b^3 */
fac_mul_bp(fp1, 3*5*23*29, 3);
fp1[0].pow[0]--;
fac_set_bp(fg1, 2*b-1, 1); /* 2b-1 */
fac_mul_bp(fg1, 6*b-1, 1); /* 6b-1 */
fac_mul_bp(fg1, 6*b-5, 1); /* 6b-5 */
if (b>(int)(progress)) {
printf("."); fflush(stdout);
progress += percent*2;
}
} else {
/*
p(a,b) = p(a,m) * p(m,b)
g(a,b) = g(a,m) * g(m,b)
q(a,b) = q(a,m) * p(m,b) + q(m,b) * g(a,m)
*/
mid = a+(b-a)*0.5224; /* tuning parameter */
bs(a, mid, 1, level+1);
top++;
bs(mid, b, gflag, level+1);
top--;
if (level == 0)
puts ("");
ccc = level == 0;
if (ccc) CHECK_MEMUSAGE;
if (level>=4) { /* tuning parameter */
#if 0
long t = cputime();
#endif
fac_remove_gcd(p2, fp2, g1, fg1);
#if 0
gcd_time += cputime()-t;
#endif
}
if (ccc) CHECK_MEMUSAGE;
mpz_mul(p1, p1, p2);
if (ccc) CHECK_MEMUSAGE;
mpz_mul(q1, q1, p2);
if (ccc) CHECK_MEMUSAGE;
mpz_mul(q2, q2, g1);
if (ccc) CHECK_MEMUSAGE;
mpz_add(q1, q1, q2);
if (ccc) CHECK_MEMUSAGE;
fac_mul(fp1, fp2);
if (gflag) {
mpz_mul(g1, g1, g2);
fac_mul(fg1, fg2);
}
}
if (out&2) {
printf("p(%ld,%ld)=",a,b); fac_show(fp1);
if (gflag)
printf("g(%ld,%ld)=",a,b); fac_show(fg1);
}
}
main
中:int
main(int argc, char *argv[])
{
mpf_t pi, qi;
long int d=100, i, depth=1, terms;
unsigned long psize, qsize;
long begin, mid0, mid1, mid2, mid3, mid4, end;
prog_name = argv[0];
if (argc>1)
d = strtoul(argv[1], 0, 0);
if (argc>2)
out = atoi(argv[2]);
terms = d/DIGITS_PER_ITER;
while ((1L<<depth)<terms)
depth++;
depth++;
percent = terms/100.0;
printf("#terms=%ld, depth=%ld\n", terms, depth);
begin = cputime();
printf("sieve "); fflush(stdout);
sieve_size = max(3*5*23*29+1, terms*6);
sieve = (sieve_t *)malloc(sizeof(sieve_t)*sieve_size/2);
build_sieve(sieve_size, sieve);
mid0 = cputime();
printf("time = %6.3f\n", (double)(mid0-begin)/1000);
/* allocate stacks */
pstack = malloc(sizeof(mpz_t)*depth);
qstack = malloc(sizeof(mpz_t)*depth);
gstack = malloc(sizeof(mpz_t)*depth);
fpstack = malloc(sizeof(fac_t)*depth);
fgstack = malloc(sizeof(fac_t)*depth);
for (i=0; i<depth; i++) {
mpz_init(pstack[i]);
mpz_init(qstack[i]);
mpz_init(gstack[i]);
/* VV undefined reference VV */
fac_init(fpstack[i]);
fac_init(fgstack[i]);
}
mpz_init(gcd);
#if HAVE_DIVEXACT_PREINV
mpz_init(mgcd);
#endif
/* VV undefined reference VV */
fac_init(ftmp);
fac_init(fmul);
/* begin binary splitting process */
if (terms<=0) {
mpz_set_ui(p2,1);
mpz_set_ui(q2,0);
mpz_set_ui(g2,1);
} else {
bs(0,terms,0,0);
}
mid1 = cputime();
printf("\nbs time = %6.3f\n", (double)(mid1-mid0)/1000);
printf(" gcd time = %6.3f\n", (double)(gcd_time)/1000);
/* printf("misc "); fflush(stdout); */
/* free some resources */
free(sieve);
#if HAVE_DIVEXACT_PREINV
mpz_clear(mgcd);
#endif
mpz_clear(gcd);
/* VV undefined reference VV */
fac_clear(ftmp);
fac_clear(fmul);
for (i=1; i<depth; i++) {
mpz_clear(pstack[i]);
mpz_clear(qstack[i]);
mpz_clear(gstack[i]);
/* VV undefined reference VV */
fac_clear(fpstack[i]);
fac_clear(fgstack[i]);
}
mpz_clear(gstack[0]);
/* VV undefined reference VV */
fac_clear(fpstack[0]);
fac_clear(fgstack[0]);
free(gstack);
free(fpstack);
free(fgstack);
/* prepare to convert integers to floats */
mpf_set_default_prec((long int)(d*BITS_PER_DIGIT+16));
/*
p*(C/D)*sqrt(C)
pi = -----------------
(q+A*p)
*/
psize = mpz_sizeinbase(p1,10);
qsize = mpz_sizeinbase(q1,10);
mpz_addmul_ui(q1, p1, A);
mpz_mul_ui(p1, p1, C/D);
mpf_init(pi);
mpf_set_z(pi, p1);
mpz_clear(p1);
mpf_init(qi);
mpf_set_z(qi, q1);
mpz_clear(q1);
free(pstack);
free(qstack);
mid2 = cputime();
/* printf("time = %6.3f\n", (double)(mid2-mid1)/1000); */
/* initialize temp float variables for sqrt & div */
mpf_init(t1);
mpf_init(t2);
/* mpf_set_prec_raw(t1, mpf_get_prec(pi)); */
/* final step */
printf("div "); fflush(stdout);
my_div(qi, pi, qi);
mid3 = cputime();
printf("time = %6.3f\n", (double)(mid3-mid2)/1000);
printf("sqrt "); fflush(stdout);
my_sqrt_ui(pi, C);
mid4 = cputime();
printf("time = %6.3f\n", (double)(mid4-mid3)/1000);
printf("mul "); fflush(stdout);
mpf_mul(qi, qi, pi);
end = cputime();
printf("time = %6.3f\n", (double)(end-mid4)/1000);
printf("total time = %6.3f\n", (double)(end-begin)/1000);
fflush(stdout);
printf(" P size=%ld digits (%f)\n"
" Q size=%ld digits (%f)\n",
psize, (double)psize/d, qsize, (double)qsize/d);
/* output Pi and timing statistics */
if (out&1) {
printf("pi(0,%ld)=\n", terms);
mpf_out_str(stdout, 10, d+2, qi);
printf("\n");
}
/* free float resources */
mpf_clear(pi);
mpf_clear(qi);
mpf_clear(t1);
mpf_clear(t2);
exit (0);
}
我在这个帖子https://ubuntuforums.org/showthread.php?t=2209074中发现了类似的问题,但是根据解决方案,我给出了与以前相同的错误。
此外,程序中的其他内联函数在调用时不会出现undefined reference
错误,例如fac_reset
,fac_init_size
和fac_mul2
;我相信这是因为它们只是从问题函数中调用过来。
我是否对与使用内联函数编译代码相关的一些信息一无所知,或者这是我遇到的一个独特问题?
希望我提供了所需的任何信息和背景信息,但如果需要,我很乐意提供任何内容。
编辑:我刚刚为所有内联函数添加了静态,程序现在编译,但我不知道为什么会有效。