Узнайте самый большой собственный целочисленный тип на текущей платформе

Проблема заключается в создании своего рода большой целочисленной библиотеки. Я хочу сделать это как кросс-платформу, так и как можно быстрее. Это означает, что я должен попытаться выполнить математику с такими же большими типами данных, которые поддерживаются в системе.

Я действительно не хочу знать, компилирую ли я для 32-битной или 64-битной системы; все, что мне нужно - это способ создания 64-битного или 32-битного или любого другого целого числа на основе того, что является самым большим доступным. Я буду использовать sizeof для того, чтобы вести себя по-разному в зависимости от того, что это такое.

Вот некоторые возможные решения и их проблемы:

Используйте sizeof (void *): Это дает размер указателя на память. Возможно (хотя и маловероятно), что система может иметь более крупные указатели на память, чем способна выполнять математику с или наоборот.

Всегда используйте long: Хотя верно, что на нескольких платформах длинные целые числа составляют 4 байта или 8 байтов в зависимости от архитектуры (моя система является одним из таких примеров), некоторые компиляторы реализуют длинные целые числа как 4 байта даже в 64-битных системах.

Всегда использовать длинный длинный: На многих 32-разрядных системах это 64-битное целое число, которое может быть не таким эффективным (хотя, вероятно, более эффективным, чем любой код, который я могу писать). Настоящая проблема заключается в том, что она может вообще не поддерживаться на некоторых архитектурах (например, в том, что один из них поддерживает мой mp3-плеер).

Чтобы подчеркнуть, мой код не заботится о том, какой фактический размер целого числа когда-либо был выбран (он полагается на sizeof() для чего-либо, где имеет значение размер). Я просто хочу, чтобы он выбрал тип целого числа, что приведет к тому, что мой код будет наиболее эффективным.

Ответ 1

Если вам действительно нужен тип нативного размера, я бы использовал size_t, ptrdiff_t или intptr_t и uintptr_t. В любой непатологической системе все это будет родной размер слова.

С другой стороны, есть преимущества в простоте, чтобы всегда работать с фиксированным размером, и в этом случае я бы просто использовал int32_t или uint32_t. Причина, по которой я говорю проще, состоит в том, что вам часто приходится знать такие вещи, как "наибольшая степень 10, которая подходит для типа" (для десятичного преобразования) и другие константы, которые не могут быть легко выражены как постоянные выражения в терминах типа вы использовали. Если вы просто выбираете фиксированное количество бит, вы также можете исправить удобные константы (например, 1000000000 в моем примере). Конечно, делая это таким образом, вы жертвуете некоторой производительностью в более высоких системах. Вы можете использовать противоположный подход и использовать больший фиксированный размер (64 бита), который был бы оптимальным для более высокопроизводительных систем, и предположим, что код компилятора для 64-разрядной арифметики на 32-битных машинах будет по меньшей мере так же быстро, как ваш код bignum обрабатывает 2 32-битных слова, и в этом случае он по-прежнему оптимален.

Ответ 2

Лучший способ - не полагаться на автоматическое обнаружение, а на целевые компиляторы с набором операторов #if/#else выбрать тип, который вы протестировали, и знать, что он оптимален.

Ответ 3

Здесь как мы это сделали в bsdnt

#if ULONG_MAX == 4294967295U

typedef uint32_t word_t;
typedef unsigned int dword_t __attribute__((mode(DI)));
#define WORD_BITS 32

#else

typedef uint64_t word_t;
typedef unsigned int dword_t __attribute__((mode(TI)));
#define WORD_BITS 64

#endif

Если это интересно, парень, который инициировал проект, написал blog при написании библиотек bignum.

GMP/MPIR значительно сложнее; gmp-h.in становится gmp.h post-configure, который определяет это:

#define GMP_LIMB_BITS                      @[email protected]

Короче говоря, длина задается как часть процесса сборки, которая работает через config.guess (т.е. autotools).

Ответ 4

Использование int_fast32_t из stdint.h представляется вариантом, хотя вы на милость тех, кто решает, что касается того, что "быстрая".