Конференция "Начинающим" » ЧИсла меньше машинного эпсилон
 
  • dmk © (03.05.18 13:42) [20]
    Delphi в отладчике CPU пишет -9.30880643132136E18
    В переменной -9.30880643132136e+18

    В любом случае переполнение разрядной сетки.
  • dmk © (03.05.18 13:43) [21]
    У меня это происходит при округлении:

    function Round(F: double): int64;
    asm
     .NOFRAME

     cvtsd2si rax, F
    end;
  • KSergey © (03.05.18 13:52) [22]
    > dmk ©   (03.05.18 13:42) [20]
    > Delphi в отладчике CPU пишет -9.30880643132136E18
    > В переменной -9.30880643132136e+18

    Славно.
    А нули-то при этом куда надо рисовать? куда я написал, ведь правда?

    > В любом случае переполнение разрядной сетки.

    Разрядной сетки чего? какой "разрядной сетки"?
    Я же уже приводил диапазон для Double, вы почему невнимательно читаете?
    впрочем, я почитал про "основание" в [14]
    уу.....

    Это называется мантисса, а не основание, и это важно.
  • KSergey © (03.05.18 13:53) [23]
    нда..
    вот бы еще понять как приведённый код на asm связан с исходным вопросом...
  • KSergey © (03.05.18 13:54) [24]
    кстати, возвращаемое значение из функции объявлено как int64
    это вас не удивляет? 1E+18 не лезет в int64
  • KilkennyCat © (03.05.18 13:58) [25]

    > z := 1.0 + X;
    >
    >   writeln(z);
    >
    > end.
    >
    > Выдаёт:
    >
    > 1.00000000000000E+0000


    совпадает с описанием машинного эпсилона в вики. значит, гуд.
  • KSergey © (03.05.18 14:04) [26]
    телепатирую:

    вы вызвали стандартную функцию Round() для числа  -9.30880643132136E18
    И она рванула "переполнение".
    Ну так это понятно: ибо диапазон для int64  
    От -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
    т.е. грубо говоря -9.2E+18 до +9.2Е+18

    А вы в него пытаетесь запихать -9.3E+18

    Оно выходит за границы int64, отсюда и взрыв

    Ведь так?
  • Dimka Maslov © (03.05.18 14:31) [27]

    > -9.30880643132136e+18 = 0.00000000000000000930880643132136.


    Да ну? С какой радости?
  • KSergey © (03.05.18 14:56) [28]
    Автору стоит рекомендовать почитать статью
    http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374
  • dmk © (03.05.18 15:35) [29]
    Ну да, неправильно понял из-за разницы в отладочном окне.
    Там просто E18 написано, а не +. В переменной +18.
    Учитывая, что тангенс у меня в диапазоне -2Pi..2PI - не ожидал, что число вылезет в обратную сторону после умножения на K.

    Это просто масштабирование.
    K := (gFactor * Aspect); //Масштаб(%) * соотношение сторон

    Это просто графики функций:
     //Графики
     repeat
       DX := (X * gFactor) + cX;
       NA := NormalizeAngle(A) * DegToRadD;

       sinY := Sin(@NA) * K;
       cosY := Cos(@NA) * K;
       tanY := Tan(@NA) * K;
       cotY := Cot(@NA) * K;

       with RT^ do
       begin
         FloatPixel(DX, cY + sinY, crLtYellow, 255, Alpha);
         FloatPixel(DX, cY + cosY, crLtGreen, 255, Alpha);
         FloatPixel(DX, cY + tanY, crLtBlue, 255, Alpha);
         FloatPixel(DX, cY + cotY, crLtRed, 255, Alpha);
       end;

       X := (X + StepX); //Шаги в радианах
       A := (X * RadToDegD); //Угол для вычисления функции
     until (X > R);


    И вот где cY + tanY вылезает Exception.
  • dmk © (03.05.18 15:43) [30]
    Это просто графики функций:
    https://yadi.sk/i/Y_w_IWJg3VF9fL

    Проверял как считаются. Если gFactor > 500% - происходит Exception.
    А мне надо до 100000%, чтобы отклонения посмотреть.
    Это свой расчет SinCosTanCot.
  • dmk © (03.05.18 16:03) [31]
    Извиняшки. Это я дурак. Tan(90°) не определен. Cosec(0°) тоже не определен.
    Потому и ошибка. Я не обрабатываю эту ситуацию в своей функции ;)
  • KSergey © (03.05.18 16:05) [32]
    Как это всё связано с изначальным вопросом - вот бы понять.
    Впрочем, не важно.

    Что же до приведённого куска кода - очевидно, что ошибок в нём нет, ошибки (если они вообще есть) - где-то в других частях кода.
    К тому же мы не знаем что за секретная функция FloatPixel и какие значения принимают переменные cY и  tanY в момент возникновения проблемы. От нас это зачем-то скрывают, но посочувствовать я готов.
  • KSergey © (03.05.18 16:06) [33]
    Ура, вот всё и разрешилось.
    А то "не понимаете, не понимаете" :)
  • dmk © (03.05.18 17:04) [34]
    >что за секретная функция FloatPixel
    Она не секретная. Просто пиксел распределяется на 4 пиксела
    и получается сглаженная линия. Удобно функции рисовать.
    Типа AntiAliasing'а.

    procedure FloatPixel(X, Y: double; dColor: TColorRef; dAlpha, dOpacity: byte);
    var
     fX, fY, sX, sY: double;
     x0, y0, x1, y1: integer;

    begin
     //Координата отсчетного пиксела
     if (X < 0.0) then
     begin
       x0 := Trunc(X - 1.0);
       x1 := (x0 + 1); //Пиксел справа
       fX := Abs(Frac(X)); //Дробная часть сдвигается в пиксел справа
       sX := (1.0 - fX); //Остаток в стартовом пикселе
     end
     else
     begin
       x0 := Trunc(X);
       x1 := (x0 + 1); //Пиксел справа
       sX := Frac(X); //Дробная часть сдвигается в пиксел справа
       fX := (1.0 - sX); //Остаток в стартовом пикселе
     end;

     if (Y < 0.0) then
     begin
       y0 := Trunc(Y - 1.0);
       y1 := (y0 + 1); //Пиксел снизу
       fY := Abs(Frac(Y)); //Дробная часть сдвигается в пиксел снизу
       sY := (1.0 - fY); //Остаток в стартовом пикселе
     end
     else
     begin
       y0 := Trunc(Y);
       y1 := (y0 + 1); //Пиксел снизу
       sY := Frac(Y); //Дробная часть сдвигается в пиксел снизу
       fY := (1.0 - sY); //Остаток в стартовом пикселе
     end;

     //Отсчетный пиксел
     if FClipRegion.PtInRegion(x0, y0) then
       FBlendPixel(PAddress32(x0, y0), dColor, dAlpha, Round((fX * fY) * dOpacity));
     //Пиксел справа
     if FClipRegion.PtInRegion(x1, y0) then
       FBlendPixel(PAddress32(x1, y0), dColor, dAlpha, Round((sX * fY) * dOpacity));
     //Пиксел снизу
     if FClipRegion.PtInRegion(x0, y1) then
       FBlendPixel(PAddress32(x0, y1), dColor, dAlpha, Round((fX * sY) * dOpacity));
     //Пиксел по диагонали справа внизу
     if FClipRegion.PtInRegion(x1, y1) then
       FBlendPixel(PAddress32(x1, y1), dColor, dAlpha, Round((sX * sY) * dOpacity));
    end;


    БлендПиксел тоже не секретный. Смешивает содержимое буфера с цветом.
    Получается смешанный пиксел.
    procedure BlendPixel(dA: QWord; AColor: TColorRef; Alpha, Opacity: byte);
    var
     A: word;
     ADif: word;
     WR, WG, WB: word;

    begin
     //Прозрачность канала
     A := (((Alpha + 1) * Opacity) shr 8);
     //Для исходного пиксела нужно обратное насыщение
     ADif := (A xor $FF) + 1;
     //Коррекция на единицу для корректного деления на 256
     A := (A + 1);

     //Расчет компонентов пиксела наложения
     WR := TBgrPixel(AColor).r * A;
     WG := TBgrPixel(AColor).g * A;
     WB := TBgrPixel(AColor).b * A;

     //Смешиваем цвета
     TBgrPixel(PDWord(dA)^).r := ((TBgrPixel(PDWord(dA)^).r * ADif + WR) shr 8);
     TBgrPixel(PDWord(dA)^).g := ((TBgrPixel(PDWord(dA)^).g * ADif + WG) shr 8);
     TBgrPixel(PDWord(dA)^).b := ((TBgrPixel(PDWord(dA)^).b * ADif + WB) shr 8);
    end;


    Есть версия на асме:
    procedure BlendPixel(dA: QWord; AColor: TColorRef; Alpha, Opacity: byte);
    const
     ShufMask: uint64 = $0100010001000100;

    asm
     .NOFRAME

     pxor mm0, mm0 //<- APixel
     pxor mm1, mm1 //<- AColor
     movq mm2, ShufMask //Формирование маски умножения

     punpcklbw mm0, [dA] //Преобразуем байты в слова
     psrld mm0, 8 //Преобразование старших бит в младшие

     movd mm5, AColor
     punpcklbw mm1, mm5 //Преобразуем байты в слова
     psrld mm1, 8 //Преобразование старших бит в младшие

     movzx eax, Alpha //Вычислим прозрачность альфа-канала
     inc eax //Прибавим единицу, чтобы корректно разделить на 256
     movzx r8d, Opacity //Компонента прозрачности
     mul eax, r8d //Умножаем
     shr ax, 8 //Делим на 256
     mov dx, ax
     xor dx, $FF //<- ADif - величина цвета обратная альфе

     inc edx //Прибавим единицу, чтобы корректно разделить на 256
     movd mm3, edx
     pshufb mm3, mm2 //<- mm3: формируем маску разницы ADif

     inc eax //Прибавим единицу, чтобы корректно разделить на 256
     movd mm4, eax
     pshufb mm4, mm2 //<- mm2: формируем 64-битную альфа-маску

     pmullw mm1, mm4 // AColor * Alpha = lpBR, lpBG, lpBB
     pmullw mm0, mm3 // APixel * ADif
     paddusw mm0, mm1 //APixel + AColor
     psrlw mm0, 8 //(APixel + AColor) div 256

     packuswb mm0, mm0 //Транслируем слова в байты
     movd [dA], mm0
    end;


    У меня еще куча версий такой фукнции, в том числе и через вектора,
    но думаю сможете и сами реализовать.
  • dmk © (03.05.18 17:07) [35]
    ФлоатПикселом удобно Безьешку рисовать. Она же дробная получается.
  • dmk © (03.05.18 17:08) [36]
    Вот вам сразу бленд-сканлайн:
    procedure BlendColorScLineMMX(dA: QWord; dLen: dword; AColor: TColorRef; Alpha, Opacity: byte);
    const
     ShufMask: uint64 = $0100010001000100;

    asm
     .NOFRAME

     xor r10, r10
     mov r10d, dLen

     movq mm2, ShufMask //Формирование маски умножения

     pxor mm1, mm1 //Очистка старших битов
     movd mm5, AColor //Цвет наложения
     punpcklbw mm1, mm5 //Разложим байты в слова 32 -> 64 бита
     psrld mm1, 8 //Сдвиг вправо для очистки старших бит

     movzx eax, Alpha //Вычислим прозрачность альфа-канала
     inc eax //Прибавим единицу, чтобы корректно разделить на 256
     movzx r11d, Opacity //Компонента прозрачности
     mul eax, r11d //Умножаем
     shr ax, 8 //Делим на 256
     mov dx, ax
     xor dx, $FF //<- ADif - величина цвета обратная альфе

     inc edx //Прибавим единицу, чтобы корректно разделить на 256
     movd mm3, edx
     pshufb mm3, mm2 //<- mm3: формируем маску разницы ADif

     inc eax //Прибавим единицу, чтобы корректно разделить на 256
     movd mm4, eax
     pshufb mm4, mm2 //<- mm2: формируем 64-битную альфа-маску

     pmullw mm1, mm4 //AColor * Alpha = lpBR, lpBG, lpBB
     movq mm5, mm1 //Сохраним для повторения

    @NextPixel:
     pxor mm0, mm0 //Очистим для формирования маски следующего пиксела
     punpcklbw mm0, [dA] //Читаем 32 бита //Транслируем байты в слова
     psrld mm0, 8 //Сдвиг вправо для очистки старших бит

     movq mm1, mm5 //В mm5 сохраненный цвет наложения
     pmullw mm0, mm3 // APixel * ADif
     paddusw mm0, mm1 //APixel + AColor
     psrlw mm0, 8 //mm0 div 256

     packuswb mm0, mm0 //Транслируем слова в байты
     movd [dA], mm0  //Пишем обратно

     add dA, 4
     dec r10
     jnz @NextPixel
    end;
  • dmk © (03.05.18 17:12) [37]
    А это супер-секретный PtInRegion:

    type
     PRegion = ^TRegion;
     TRegion = record
       private
         rX: integer; //Позиция слева
         rY: integer; //Позиция сверху
         rEX: integer; //Позиция справа
         rEY: integer; //Позиция снизу
         rW: integer; //Ширина включая первую точку
         rH: integer; //Высота включая первую точку
     end;

    function TRegion.PtInRegion(x, y: integer): boolean;
    begin
     if (x >= rX) and (x <= rEX) then Result := (y >= rY) and (y <= rEY) else Result := false;
    end;
  • kilkennycat © (03.05.18 20:33) [38]

    > dmk ©  

    а готового всего этого нет? или это практики ради?
  • dmk © (03.05.18 21:17) [39]
    >а готового всего этого нет? или это практики ради?
    Готового чего?

    Если про пиксели, то это я из своего класса подергал.
    Есть. Много. Почти все на асме. Работает шустро.
    Тут видео: https://yadi.sk/i/I_NwsFF-3UcVzK
    Это 3D-шечка. Движок делаю небольшой.
 
Конференция "Начинающим" » ЧИсла меньше машинного эпсилон
Есть новые Нет новых   [118456   +59][b:0][p:0.001]