Узнайте самый большой собственный целочисленный тип на текущей платформе - PullRequest
11 голосов
/ 29 декабря 2010

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

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

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

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

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

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

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

Ответы [ 4 ]

6 голосов
/ 29 декабря 2010

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

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

4 голосов
/ 29 декабря 2010

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

0 голосов
/ 29 декабря 2010

Использование int_fast32_t из stdint.h может показаться приемлемым вариантом, хотя вы зависите от тех, кто решает, что означает «быстрый».

0 голосов
/ 29 декабря 2010

Вот как мы это сделали в 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

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

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

#define GMP_LIMB_BITS                      @GMP_LIMB_BITS@

Короче говоря, длина устанавливается как часть процесса сборки, который обрабатывает ее с помощью config.guess (то есть автоинструмент).

...