namespaceboost{namespacemultiprecision{typedefunspecified-typelimb_type;enumcpp_integer_type{signed_magnitude,unsigned_magnitude};enumcpp_int_check_type{checked,unchecked};template<unsignedMinBits=0,unsignedMaxBits=0,cpp_integer_typeSignType=signed_magnitude,cpp_int_check_typeChecked=unchecked,classAllocator=std::allocator<limb_type>>classcpp_int_backend;//// Expression templates default to et_off if there is no allocator://template<unsignedMinBits,unsignedMaxBits,cpp_integer_typeSignType,cpp_int_check_typeChecked>structexpression_template_default<cpp_int_backend<MinBits,MaxBits,SignType,Checked,void>>{staticconstexpression_template_optionvalue=et_off;};typedefnumber<cpp_int_backend<>>cpp_int;// arbitrary precision integertypedefrational_adaptor<cpp_int_backend<>>cpp_rational_backend;typedefnumber<cpp_rational_backend>cpp_rational;// arbitrary precision rational number// Fixed precision unsigned types:typedefnumber<cpp_int_backend<128,128,unsigned_magnitude,unchecked,void>>uint128_t;typedefnumber<cpp_int_backend<256,256,unsigned_magnitude,unchecked,void>>uint256_t;typedefnumber<cpp_int_backend<512,512,unsigned_magnitude,unchecked,void>>uint512_t;typedefnumber<cpp_int_backend<1024,1024,unsigned_magnitude,unchecked,void>>uint1024_t;// Fixed precision signed types:typedefnumber<cpp_int_backend<128,128,signed_magnitude,unchecked,void>>int128_t;typedefnumber<cpp_int_backend<256,256,signed_magnitude,unchecked,void>>int256_t;typedefnumber<cpp_int_backend<512,512,signed_magnitude,unchecked,void>>int512_t;typedefnumber<cpp_int_backend<1024,1024,signed_magnitude,unchecked,void>>int1024_t;// Over again, but with checking enabled this time:typedefnumber<cpp_int_backend<0,0,signed_magnitude,checked>>checked_cpp_int;typedefrational_adaptor<cpp_int_backend<0,0,signed_magnitude,checked>>checked_cpp_rational_backend;typedefnumber<cpp_rational_backend>checked_cpp_rational;// Checked fixed precision unsigned types:typedefnumber<cpp_int_backend<128,128,unsigned_magnitude,checked,void>>checked_uint128_t;typedefnumber<cpp_int_backend<256,256,unsigned_magnitude,checked,void>>checked_uint256_t;typedefnumber<cpp_int_backend<512,512,unsigned_magnitude,checked,void>>checked_uint512_t;typedefnumber<cpp_int_backend<1024,1024,unsigned_magnitude,checked,void>>checked_uint1024_t;// Fixed precision signed types:typedefnumber<cpp_int_backend<128,128,signed_magnitude,checked,void>>checked_int128_t;typedefnumber<cpp_int_backend<256,256,signed_magnitude,checked,void>>checked_int256_t;typedefnumber<cpp_int_backend<512,512,signed_magnitude,checked,void>>checked_int512_t;typedefnumber<cpp_int_backend<1024,1024,signed_magnitude,checked,void>>checked_int1024_t;}}// namespaces
Тип cpp_int_backend обычно используется с помощью одного из приведенных выше наборов удобств.
Этот бэкэнд представляет собой «швейцарский армейский нож» целых типов, поскольку он может представлять как фиксированные, так и произвольную точность целых типов, а также как подписанные, так и неподписанные типы. Существует пять шаблонных аргументов:
MinBits
Определяет количество битов для хранения непосредственно внутри объекта, прежде чем прибегнуть к динамическому выделению памяти. При нуле это поле определяется автоматически на основе того, сколько битов может храниться в союзе с динамическим заголовком хранилища: установка большего значения может улучшить производительность, поскольку большие целые значения будут храниться внутри до того, как потребуется выделение памяти.
MaxBits
Определяет максимальное количество битов, подлежащих хранению в типе: в результате получается фиксированный тип точности. Когда это значение такое же, как у MinBits, то параметр Allocator игнорируется, так как динамическое распределение памяти никогда не будет выполнено: в этой ситуации параметр Allocator должен быть настроен на тип void. Обратите внимание, что этот параметр не должен использоваться просто для предотвращения больших выделений памяти, не только потому, что роль лучше выполняется распределителем, но и фиксированные целые числа имеют тенденцию выделять все MaxBits памяти чаще, чем можно было бы ожидать.
SignType
Определяет, подписан ли полученный тип или нет. Обратите внимание, что для типов произвольной точности этот параметр должен быть signed_magnitude. Для типов с фиксированной точностью этот тип может быть либо signed_magnitude, либо unsigned_magnitude.
Checked
Этот параметр имеет два значения: проверено или непроверено. Смотрите ниже.
Allocator
Распределитель для динамического распределения памяти, или тип void, если MaxBits == MinBits.
Когда параметр шаблона Checked установлен на checked, то результатом является checked-integer, проверенные и непроверенные целые числа имеют следующие свойства:
Состояние
Проверенное целое число
Неконтролируемое целое число
Численный перелив в фиксированной точной арифметике
Бросает std::overflow_error.
Выполняет арифметический модуль 2MaxBits
Построение целого числа из значения, которое не может быть представлено в целевом типе
Бросает std::range_error.
Преобразует значение modulo 2MaxBits, подписанное на неподписанные преобразования, извлекает последние биты MaxBits из представления дополнения 2 входного значения.
Неподписанное вычитание дает отрицательное значение.
Бросает std::range_error.
Дает значение, которое будет получено в результате обработки неподписанного типа как типа, подписанного дополнением 2.
Попытка операции на отрицательном значении.
Выбрасывает std::range_error
Дает значение, но не битовый шаблон, который будет результатом выполнения операции на целочисленном типе комплемента 2.
Что вы должны знать при использовании этого типа:
По умолчанию построенные cpp_int_backends имеют значение ноль.
Разделение на ноль приводит к выпадению std::overflow_error.
Конструкция из строки, которая содержит недействительные не числовые символы, приводит к тому, что бросается std::runtime_error.
Поскольку точность cpp_int_backend обязательно ограничена, когда параметр распределителя недействителен, следует соблюдать осторожность, чтобы избежать численного переполнения при использовании этого типа.
Тип использует представление величины знака внутри, поэтому тип int128_t имеет 128 бит точности плюс дополнительный бит знака. В этом отношении поведение этих типов отличается от встроенных типов комплемента 2. Вместо этого может возникнуть соблазн использовать 127-битный тип, и это действительно работает, но поведение по-прежнему немного отличается от встроенного типа комплемента 2, поскольку значения мин и макс идентичны (кроме знака), где они отличаются друг от друга для типа комплемента истинного 2. Тем не менее, следует отметить, что нет необходимости в том, чтобы встроенные типы были дополнением 2 - это просто самый распространенный формат на сегодняшний день.
Попытка напечатать отрицательные значения в виде октальной или шестидесятичной строки приводит к бросанию std::runtime_error, что является прямым следствием представления величины знака.
Фиксированные типы прецизионности [checked_][u]intXXX_t имеют выключенную поддержку шаблона экспрессии - кажется, что это мало влияет на производительность этих типов в любом случае - поэтому мы можем также иметь более быстрое время компиляции, выключив функцию.
Неподписанные типы поддерживают вычитание — результат «как если бы» операция комплемента 2 выполнялась до тех пор, пока они не являются проверенными интеграторами (см. выше). Другими словами, они ведут себя в значительной степени как встроенный в целое число тип в этой ситуации. Так, например, если бы мы использовали uint128_t, то uint128_t(1)-4 привело бы к значению 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF Однако если бы эта операция была выполнена на checked_uint128_t, то была бы брошена std::range_error.
Унарное отрицание неподписанных типов приводит к ошибке компилятора (статическое утверждение).
Этот бэкэнд поддерживает rvalue-ссылки и является Move-Aware, делая инстанциации номер на этом бэкэнд-движении осведомленными.
При использовании с фиксированной точностью размер этого типа всегда является одним машинным словом, большим, чем вы ожидаете для целого числа N-бит: дополнительное слово хранит как знак, так и количество машинных слов в целом. Последнее является оптимизацией для более крупных фиксированных целых чисел с фиксированной точностью, так что 1024-битное целое число имеет почти те же характеристики производительности, что и 128-битное целое число, а не в 4 раза медленнее для сложения и в 16 раз медленнее для умножения (при условии, что соответствующие значения всегда будут соответствовать 128 битам). Как правило, это означает, что вы можете использовать целочисленный тип, достаточно широкий для «наихудшего сценария» с незначительным ухудшением производительности, даже если большую часть времени арифметика фактически может быть выполнена с более узким типом.
При использовании при фиксированной точности и MaxBits меньше, чем количество битов в самом большом нативном целочисленном типе, тогда внутренне cpp_int_backend переключается на «тривиальную» реализацию, где это просто тонкая обертка вокруг одного целого числа. Обратите внимание, что он по-прежнему будет немного медленнее, чем простое целое число, поскольку он эмулирует представление с подписанной величиной, а не просто использует представление родного знака на платформах: это гарантирует, что нет никаких изменений в поведении по мере роста размера cpp_int.
Фиксированная точность cpp_int имеет некоторую поддержку значений constexpr и определяемых пользователем букв, см. здесь для полного описания. Например, 0xfffff_cppi1024 указывает 1024-битовое целое число со значением 0xffff. Это может быть использовано для генерации констант времени, которые слишком велики, чтобы вписаться в любой тип числа.
Вы можете импортировать / экспортировать необработанные биты cpp_int в и из внешнего хранилища через функции import_bits и export_bits. Более подробная информация содержится в разделе по импорту/экспорту .
#include<boost/multiprecision/cpp_int.hpp>#include<iostream>intmain(){usingnamespaceboost::multiprecision;int128_tv=1;// Do some fixed precision arithmetic:for(unsignedi=1;i<=20;++i)v*=i;std::cout<<v<<std::endl;// prints 20!// Repeat at arbitrary precision:cpp_intu=1;for(unsignedi=1;i<=100;++i)u*=i;std::cout<<u<<std::endl;// prints 100!return0;}
Статья cpp_int раздела Chapter 1. Boost.Multiprecision Integer Types может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.