10

GMP 提供了初始化和分配 mpz_t 的方法。

调用 mpz_init_set(a, b) 会将 b 的内容分配给 a。但是,我认为这会对 b 执行深层复制。

在我的项目中,我需要使用长达 5,000,000 的 mpz_t 数组(我们谈论的是 640MB 内存),并且我正在使用的框架对此类类型执行各种分配操作(我没有开发框架并重写它不是一个选项)。最近,我意识到在大多数赋值之后,b 的值都被清除了,所以深度复制一个已经可以使用的值似乎是不自然的。但是,框架的接口不允许这样做(使用 mpz_t 的包装器),并且需要付出很多努力才能改变它(我仍然可以改变一些基本的东西)。

我已经尝试过基于指向 mpz_class 的指针的解决方案,但令人惊讶的是,它根本没有提高性能。事实上,它减慢了执行速度(虽然没有在巨大的数组上测试)。

我的问题是:我可以浅拷贝一个 mpz_t 吗?下面给出的例子

class somewrapper
{
    mpz_t v;
    somewrapper(mpz_t x)    //constructor: probably performing deep copy here as well
    {
        // the following line performs a deep copy(?) on x
        // but x is not used. why not shallow copy it?
        mpz_init_set(v, x);
    }
    somefunction() { }
}
4

1 回答 1

1

Consider that mpz_t is a struct defined in gmp.h:

typedef struct
{
  int _mp_alloc;        /* Number of *limbs* allocated and pointed to by the _mp_d field.  */
  int _mp_size;         /* abs(_mp_size) is the number of limbs the last field points to.  If _mp_size is negative this is a negative number.  */
  mp_limb_t *_mp_d;     /* Pointer to the limbs.  */
} __mpz_struct;

// ... 

typedef __mpz_struct mpz_t[1];

where the GMP developers cast the type as an array of size one because this simplifies passing the type to functions just as if it was a pointer (see here for a fine explanation)

So you can make a shallow copy of an mpz_t like this:

class somewrapper
{
    mpz_t v;
    somewrapper(mpz_t x)    //constructor: for sure passing the reference
    {
        // the following line performs a shallow copy
        v->_mp_alloc = x->_mp_alloc;
        v->_mp_size = x->_mp_size;
        v->_mp_d = x->_mp_d;
    }
    somefunction() { }
}

but note that if you delete the original mpz before deleting the shallow copy, say using mpz_clear, then the juice in mp_limb_t *_mp_d will be gone, and the pointer in the shallow copy will no longer be valid so accessing it may cause trouble.

于 2021-12-19T01:35:47.113 回答