Тут размещают свои топики новички в С/С++.

Тема в разделе "LANGS.C", создана пользователем nitrotoluol, 4 мар 2007.

  1. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Погоди, ты вообще шаришь в SSE? В твоем примере вектор задается флоутами и __m128, насколько я помню, представляет собой вектор из 4 флоутов. __m128i тоже самое, но с четырьмя интами. Интринсики разные для работы с флоутами и интами. Тебе надо определиться с типом, а не подгонять одно под другое.
     
  2. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    600
    А понял, не сразу заметил пруф Rel'а.
    Код (C++):
    1. static const __m128 ABS__m128 = _mm_castsi128_ps(_mm_set_epi32(0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu, 0));
    И ещё по теме, я как то пропустил команду andnot, значит формировать ABS__m128 не обязательно, достаточно этой маски.
    Код (C++):
    1. static const __m128    SIGN__m128 = { -0.f, -0.f, -0.f, 0.f }; //константа для смены знаков
    2. __m128    ABSPS(__m128    A)
    3. {
    4.     return _mm_andnot_ps(A, SIGN__m128);
    5. }
    Спасибо кто помог.
     
  3. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Ох уж эти intrinsic'и...
    Нет чтобы чистые ассемблерные вставки сделать...
     
    UbIvItS нравится это.
  4. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    600
    Это уже лучше сразу писать проект на ассемблере. Эти вставки плохо оптимизируются, это раз, и два, код получается не безопасный, легко затереть какой-то важный регистр, по крайней мере в GCC это точно, VS лучше контролирует код в вставках, но и там могут быть проблемы. Я с этим столкнулся, так что это точная инфа.
     
  5. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Интринсики затирают важный регистр, это что то новое? И да интринсики и асм вставки не должны оптимизироваться, компилятор предполагает, что программист, пишуший асм вставку, знает, что он делает, если бы компиль менял кодец в асм вставке, его бы уже гуаном покрыли все те же програмисты, что пишут асм вставки. По поводу гцц, ты просто не умеешь его готовить, есть входные и выходные параметры, клобберы, гото списки и тд. Никакие регистры нельзя перетереть, если все делаешь правильно.
     
    SadKo нравится это.
  6. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    600
    Как раз интринсики ничего не затирают!
    Затирает именно ассемблерные вставки.
    Интринсики должны оптимизироваться, но важно чтобы компилятор их использовал!, забыли включить нужный ключ?, ну это ваши проблемы. Да компилятор не дурак, и незабывает их перемешать с другими инструкциями чтобы загрузить конвейер по полной, но не так чтобы упала частота, привет AVX.
    ЗЫ
    Блин, НГ сейчас мозги вкось, надо потом не забыть создать тему, "параллельные операции в 3д векторах".
     
  7. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Вернее сказать, перетереть можно, но компиль их при выходе из асм-вставки автоматом восстановит соответствующими инструкциями (ну а перед входом сохранит, разумеется).
    Короче, комментарий верный: учить правила задания входных и выходных параметров, а также клобберов, и будет счастье.
     
  8. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    600
    Вот такой код.
    Код (C):
    1.  
    2. #define             uint        unsigned int  
    3. const int           digitMax    = 10;       /* Макси. размер строки */
    4. const long long int uint_max    = ((uint)-1);
    5. int InputInt(bool is_signed)
    6. {
    7.     int     res, N;
    8.     char    buf[12];
    9.     bool    negative = false;   /* фл. отрицательного числа */
    10.     N=0;                        /* кол. введёных символов */
    11.     res = 0;
    12.     while (true){
    13.         int S = getch();
    14.         if (S==13 && N>0)   break;          /* Enter */
    15.         if (is_signed && S=='-' && N==0 && !negative){  /* минус */
    16.             negative = true;
    17.             putchar(S);
    18.         } else if (N<digitMax && S>='0' && S<='9'){ /* Цифры */
    19.             long long int   tmp;
    20.             if (N==1 && buf[0]=='0'){   /* убираем лишние нули */
    21.                 --N;
    22.                 cputs("\b \b");
    23.             }
    24.             tmp = res*10+(S-'0');
    25.             /* проверка переполнения */
    26.             if (tmp > uint_max || (is_signed && (int)tmp<0)){
    27.                 putchar('\a');  /* гудок */
    28.                 continue;
    29.             }
    30.             /* Ввод символа */
    31.             buf[N++] = S; buf[N] = 0;   /* символ и терм. нуль */
    32.             res = (int)tmp;
    33.             putchar(S);
    34.         } else {
    35.             if (S==27 || S==8){ /* Esc и Забой */
    36.                 do {
    37.                     if (N>0) {
    38.                         buf[--N] = 0;
    39.                         res /= 10;
    40.                     } else if (negative)
    41.                         negative = false;
    42.                     else
    43.                         break;
    44.                     cputs("\b \b");
    45.                 } while (S!=8);     /* Забой */
    46.             }
    47.         }
    48.     }
    49.     if (negative)
    50.         res = -res;
    51.     return res;
    52. }
    53.  
    Не срабатывает tmp > uint_max. Получается tmp > (int)uint_max
    А мне так не надо, надо точно отлавливать переполнение. Компиль VS2010 SP1 Может с другими компиляторами будет не так, иногда реально компили тупят, генерят ерунду.
    Хотя код я переделаю, чтобы обойти эту хрень, но всё равно что-то не то.
     
  9. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    У отрицательных чисел MSB равен единице. То есть переполнение это когда (tmp&0x80000000)!=0 или (tmp&0x80000000)==0 в зависимости от is_signed.
     
  10. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Код (C):
    1.  
    2. // для unsigned int
    3. if (value > 429496729 || (value == 429496729 && nextDigit > 5))
    4.     // будет переполнение
    5. else
    6.     value = value * 10 + nextDigit;
    7.  
    8. // для signed int
    9. if (value > 214748364 || (value == 214748364 && nextDigit > 7))
    10.     // будет переполнение
    11. else
    12.     value = value * 10 + nextDigit;
    13.  
     
  11. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    600
    Всё равно криво как то, я переделал функцию, переполнение отслеживается другим способом, раз уж нету у С/С++ нормальных механизмов.
    Для unsigned такой код.
    Код (C):
    1.  
    2. unsigned int InputUInt()
    3. {
    4.     int     N;              /* кол. введёных символов */
    5.     char    buf[15], buf2[15];
    6.     unsigned int    res = 0;
    7.     for (N=0;;){
    8.         int S = getch();
    9.         if (S==13 && N>0)   break;      /* Enter */
    10.         if (S>='0' && S<='9'){  /* Цифры */
    11.             unsigned int    tmp = res*10+(S-'0');
    12.             if (N==1 && buf[0]=='0'){   /* убираем лишние нули */
    13.                 --N;
    14.                 cputs("\b \b");
    15.             }
    16.             /* Ввод символа */
    17.             buf[N++] = S; buf[N] = 0;   /* символ и терм. нуль */
    18.             sprintf(buf2, "%u", tmp);
    19.             /* проверка переполнения */
    20.             if (strcmp(buf, buf2)!=0){
    21.                 buf[--N] = 0;
    22.                 putchar('\a');  /* гудок */
    23.                 continue;
    24.             }
    25.             res = tmp;
    26.             putchar(S);
    27.         }else if (S==27 || S==8){       /* Esc и Забой */
    28.             while (N>0){
    29.                 res /= 10;
    30.                 buf[--N] = 0;
    31.                 cputs("\b \b");
    32.                 if (S==8) break;        /* Забой */
    33.             }
    34.         }
    35.     }
    36.     return res;
    37. }
    38.  
    Для signed потом. Тут ещё этот код можно в шаблонный переделать, С++, ну для разных типов целых.