самый быстрый способ конвертировать int8 в int7 - PullRequest
0 голосов
/ 30 января 2019

У меня есть функция, которая принимает int8_t val и преобразует ее в int7_t.

//Bit [7] reserved
//Bits [6:0] = signed -64 to +63 offset value
// user who calls this function will use it correctly (-64 to +63)
uint8_t func_int7_t(int8_t val){
    uint8_t val_6 = val & 0b01111111;
    if (val & 0x80)
        val_6 |= 0x40;
    //...
    //do stuff...
    return val_6;
}

Каков лучший и самый быстрый способ манипулирования int8 в int7?Я сделал это эффективно и быстро?или есть лучший способ?

Цель - ARM Cortex M0 +, если это имеет значение

ОБНОВЛЕНИЕ:

После прочтения разных ответов я могу сказать вопросспросили неправильно?(или мой код в вопросе - это то, что давало неверные предположения другим) У меня было намерение сделать int8-int7

Так что это будет сделано бездействием, потому что

8bit:

 63 = 0011 1111
 62 = 0011 1110
  0 = 0000 0000
 -1 = 1111 1111
 -2 = 1111 1110
-63 = 1100 0001
-64 = 1100 0000

7bit:

 63 = 011 1111
 62 = 011 1110
  0 = 000 0000
 -1 = 111 1111
 -2 = 111 1110
-63 = 100 0001
-64 = 100 0000

Ответы [ 5 ]

0 голосов
/ 30 января 2019

пользователь, который вызывает эту функцию, знает, что он должен поместить данные -64 в + 63

Так что, не считая других значений, действительно самая быстрая вещь, которую выможно сделать вообще ничего не делать !

7-битное значение хранится в восьми битах.Любое значение в указанном диапазоне будет иметь как бит 7, так и бит 6 одинаковое значение, и при обработке 7-битного значения вы просто игнорируете MSB (8-битного значения), независимо от того, установлено ли оноили нет, например:

for(unsigned int bit = 0x40; bit; bit >>= 1)
//                NOT: 0x80!
    std::cout << (value & bit);

И наоборот, более критично: всякий раз, когда вы получаете эти семь битов по какому-либо каналу связи, вам необходимо выполнить ручное расширение знака для восьми (или более) битов, чтобывозможность правильно использовать это значение.

0 голосов
/ 30 января 2019

Чтобы очистить зарезервированный бит, просто

return val & 0x7f;

Чтобы оставить зарезервированный бит точно таким же, как он был на входе, ничего не нужно делать

return val;

и низкий 7биты будут содержать значения в [-64, 63].Потому что в двух дополнениях приведение вниз выполняется простым усечением.Значение остается прежним.Вот что происходит для задания типа (int8_t)some_int_value

Нет такой вещи как 0bX1100001.Там нет неопределенного бита в машинном языке.Это состояние существует только в оборудовании, например, состояние с высоким Z или неопределенное состояние в Verilog или других языках описания оборудования

0 голосов
/ 30 января 2019

Если вас не интересует, что происходит со значениями, выходящими за пределы допустимого, тогда достаточно

return val & 0x7f;

.Это правильно обрабатывает значения в диапазоне -64 <= val <= 63.Вы не сказали, как хотите обрабатывать значения, выходящие за пределы диапазона, поэтому мне нечего сказать по этому поводу.

Обновлено, чтобы добавить: Вопрос был обновлен, поэтому укажите, чтофункция никогда не будет вызываться со значениями вне диапазона.Таким образом, этот метод однозначно квалифицируется как «лучший и самый быстрый».

0 голосов
/ 30 января 2019

Используйте битовое поле, чтобы сузить значение и позволить компилятору выбрать, какая последовательность сдвигов и / или масок наиболее эффективна для вашей платформы.

inline uint8_t to7bit(int8_t x) 
{ 
    struct {uint8_t x:7;} s; 
    return s.x = x; 
} 
0 голосов
/ 30 января 2019

вероятно, более быстрый путь:

uint8_t val_7 = (val & 0x3f) | ((val >> 1) & 0x40);

val & 0x3f получить 6 младших битов (усеченное) и ((val >> 1) & 0x40) переместить бит для знака из позиции 8 в 7

Преимущество не использовать , если , состоит в том, чтобы иметь более короткий код (даже если вы можете использовать арифметику , если ) и иметь код без разрыва последовательности

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...