促进 mpfr_float 的序列化
boost serialization of mpfr_float
我想序列化一个包含 boost::multiprecision::mpfr_float 作为成员的自定义 class。它在 Multiprecision 文档中说 here in the Boost.Serialization documentation that a type T
is serializable iff at least one of 5 properties is true, and here number
class 具有直通支持,这需要底层后端是可序列化的。
对于Boost.Multiprecision的mpfr_float
类型,我知道:
- 它不是原始类型。
- 它是 class 类型,但它没有定义
serialize
函数。
- 它不是指向可序列化类型的指针。
- 它不是对可序列化类型的引用。
- 它不是可序列化类型的本机 C++ 数组。
所以,看起来如果我想序列化 mpfr_float 类型,我必须为该类型提供 serialize
函数。
我的问题是:如何通过自己编写 serialize
函数将 mpfr_float
类型扩展为可序列化?我想我需要访问 mpfr 后端,并使用底层数据,但我不确定如何进行。来自具有 Boost 序列化先前未序列化 classes 经验的人的提示将不胜感激。
最终解决方案
根据 sehe 的回复,我得出了一个解决方案,它的往返精度为 100 和 1000:
namespace boost { namespace serialization { // insert this code to the appropriate namespaces
/**
Save a mpfr_float type to a boost archive.
*/
template <typename Archive>
void save(Archive& ar, ::boost::multiprecision::backends::mpfr_float_backend<0> const& r, unsigned /*version*/)
{
std::string tmp = r.str(0, std::ios::fixed);// 0 indicates use full precision
ar & tmp;
}
/**
Load a mpfr_float type from a boost archive.
*/
template <typename Archive>
void load(Archive& ar, ::boost::multiprecision::backends::mpfr_float_backend<0>& r, unsigned /*version*/)
{
std::string tmp;
ar & tmp;
r = tmp.c_str();
}
} } // re: namespaces
此解决方案解决了上面第 (2) 项的需求,这表明需要添加 serialize
功能。感谢您的帮助。
直通支持意味着您必须为 backend 类型添加序列化,确实如此。
您可以使用我在此答案中展示的相同方法:
- How to de/serialize a map with template class using boost::multiprecision::mpq_rational
我展示了如何(反)序列化 mpq_rational
如果您使用的是 4.0.0
或更高版本,您可以使用 mpfr_fpif_export
和 mpfr_fpif_import
到 serialize/deserialize 它。
using realtype = number<mpfr_float_backend<100, allocate_stack>>;
#define MPFR_BUFFER_SIZE 1000
namespace boost {
namespace serialization {
template<class Archive>
void save(Archive& ar, const realtype& x, const boost::serialization::version_type&) {
static char buffer[MPFR_BUFFER_SIZE];
FILE* fid = fmemopen(buffer, MPFR_BUFFER_SIZE, "wb+");
mpfr_fpif_export(fid, const_cast<mpfr_ptr>(x.backend().data()));
fseek(fid, 0L, SEEK_END);
long length = ftell(fid);
ar& length;
ar& boost::serialization::make_array(buffer, length);
fclose(fid);
}
template<class Archive>
void load(Archive& ar, realtype& x, const boost::serialization::version_type&) {
static char buffer[MPFR_BUFFER_SIZE];
long length = 0;
ar& length;
ar& boost::serialization::make_array(buffer, length);
FILE* fid = fmemopen(buffer, length, "r");
mpfr_fpif_import(x.backend().data(), fid);
fclose(fid);
}
template<class Archive>
inline void
serialize(Archive& ar, realtype& t, const unsigned int file_version) {
split_free(ar, t, file_version);
}
}
}
我想序列化一个包含 boost::multiprecision::mpfr_float 作为成员的自定义 class。它在 Multiprecision 文档中说 here in the Boost.Serialization documentation that a type T
is serializable iff at least one of 5 properties is true, and here number
class 具有直通支持,这需要底层后端是可序列化的。
对于Boost.Multiprecision的mpfr_float
类型,我知道:
- 它不是原始类型。
- 它是 class 类型,但它没有定义
serialize
函数。 - 它不是指向可序列化类型的指针。
- 它不是对可序列化类型的引用。
- 它不是可序列化类型的本机 C++ 数组。
所以,看起来如果我想序列化 mpfr_float 类型,我必须为该类型提供 serialize
函数。
我的问题是:如何通过自己编写 serialize
函数将 mpfr_float
类型扩展为可序列化?我想我需要访问 mpfr 后端,并使用底层数据,但我不确定如何进行。来自具有 Boost 序列化先前未序列化 classes 经验的人的提示将不胜感激。
最终解决方案
根据 sehe 的回复,我得出了一个解决方案,它的往返精度为 100 和 1000:
namespace boost { namespace serialization { // insert this code to the appropriate namespaces
/**
Save a mpfr_float type to a boost archive.
*/
template <typename Archive>
void save(Archive& ar, ::boost::multiprecision::backends::mpfr_float_backend<0> const& r, unsigned /*version*/)
{
std::string tmp = r.str(0, std::ios::fixed);// 0 indicates use full precision
ar & tmp;
}
/**
Load a mpfr_float type from a boost archive.
*/
template <typename Archive>
void load(Archive& ar, ::boost::multiprecision::backends::mpfr_float_backend<0>& r, unsigned /*version*/)
{
std::string tmp;
ar & tmp;
r = tmp.c_str();
}
} } // re: namespaces
此解决方案解决了上面第 (2) 项的需求,这表明需要添加 serialize
功能。感谢您的帮助。
直通支持意味着您必须为 backend 类型添加序列化,确实如此。
您可以使用我在此答案中展示的相同方法:
- How to de/serialize a map with template class using boost::multiprecision::mpq_rational
我展示了如何(反)序列化 mpq_rational
如果您使用的是 4.0.0
或更高版本,您可以使用 mpfr_fpif_export
和 mpfr_fpif_import
到 serialize/deserialize 它。
using realtype = number<mpfr_float_backend<100, allocate_stack>>;
#define MPFR_BUFFER_SIZE 1000
namespace boost {
namespace serialization {
template<class Archive>
void save(Archive& ar, const realtype& x, const boost::serialization::version_type&) {
static char buffer[MPFR_BUFFER_SIZE];
FILE* fid = fmemopen(buffer, MPFR_BUFFER_SIZE, "wb+");
mpfr_fpif_export(fid, const_cast<mpfr_ptr>(x.backend().data()));
fseek(fid, 0L, SEEK_END);
long length = ftell(fid);
ar& length;
ar& boost::serialization::make_array(buffer, length);
fclose(fid);
}
template<class Archive>
void load(Archive& ar, realtype& x, const boost::serialization::version_type&) {
static char buffer[MPFR_BUFFER_SIZE];
long length = 0;
ar& length;
ar& boost::serialization::make_array(buffer, length);
FILE* fid = fmemopen(buffer, length, "r");
mpfr_fpif_import(x.backend().data(), fid);
fclose(fid);
}
template<class Archive>
inline void
serialize(Archive& ar, realtype& t, const unsigned int file_version) {
split_free(ar, t, file_version);
}
}
}