CD
это только для целых чисел или для всего?
g-cont
Почти, это только для Ordinal Types (целые (кроме UInt64, он глючит), перечисления (куда входит Boolean), строковые символы)
const WA = WideChar('A'); WZ = WideChar( 'Z'); AA = AnsiChar( 'A'); AZ = AnsiChar( 'Z'); type tx = ( x0, x1, x2); var x: x0..x1; y: -1..1; z: false..false; a: WA..WZ; //2 байта b: AA..AZ; //1 байт с: '0'..'9'; //зависит от версии делфи gg: array[x0..x2] of Integer; //можно еще так применять
Тут такой вопрос(причем очень нужный) возник(касается LCL Лазаруса скорее). В каком модуле есть что-то наподобие IndexOfByte, но с проверкой не на первую попавшуюся ячейку памяти из определенного интервала с соотвествующим значением, а именно чтоб вместо равенства было наоборот отличие от заданного значения? Или может у кого есть ассемблерная функция? Уж больно шустрая данная функция(как минимум в 7 раз быстрее простого сдвига и проверки разыменованного указателя).
ArtProg
> простого сдвига и проверки
Умножай байт на $01010101 и проверяй сразу 4 байта, или если 64-битный код, то на $0101010101010101 и сразу 8 байт
Интересная идея, надо будет проверить позже. Спасибо!
Увы, но не работает как надо. Точнее обнаруживается только первый, отличный од заданного значения байт(а надо произвольный) в цепочке из восьми байтов. Вот наглядные примеры:
var arr : array of byte; arr_ptr: PByte; i : integer; begin SetLength(arr,8); arr_ptr:=@arr[0]; arr[0]:=1; if (((arr_ptr+0)^ and $0101010101010101)<>0) then Writeln('arr[0] is not 0;') else Writeln('arr[0] is 0;'); arr[0]:=0; arr[1]:=1; if (((arr_ptr+0)^ and $0101010101010101)<>0) then Writeln('arr[1] is not 0;') else Writeln('arr[1] is 0;'); Readln; end. Output: arr[0] is not 0; arr[1] is 0; // хотя выше мы установили 1;
var arr : array of byte; arr_ptr: PByte; i : integer; begin SetLength(arr,8); arr_ptr:=@arr[0]; arr[1]:=1; if (((arr_ptr+0)^ and $0101010101010101)<>0) then Writeln('arr[1] is not 0;') else Writeln('arr[1] is 0;'); Readln; end. Output: arr[1] is 0; // хотя выше мы установили 1;
Еще будут идеи?
P.S. винда 64-битная.
проверь что вообще в массиве лежит.
Пока что такое придумалось:
var arr : array of byte; arr_ptr : PByte; i : integer; non_zero_item_pos: integer; begin SetLength(arr,8); arr_ptr :=@arr[0]; arr[1] :=1; if (PQWord(arr_ptr)^<>0) then begin for i:=0 to 7 do if ((arr_ptr+i)^<>0) then begin non_zero_item_pos:=i; Break; end; Writeln('arr[0] is not 0; non_zero_item_pos=',i,';'); end else Writeln('arr[0] is 0;'); Readln; end.
То есть те же проверки блоков по 8 байт, но если нашлась цепочка, содержащая хоть один ненулевой байт, то дальше идет уточняющий поиск. Ну и конечно же надо отслеживать, чтоб проверка не вышла за границы массива(где будут возможно "мусорные" байты). Не знаю как оно будет по скорости, предполагаемо, что быстрее байтовых сдвигов с последующими проверками, но возможно несколько медленнее, чем IndexOfByte. Тут надо еще отдельный тест сделать.
Также в процессе поиска решения наткнулся на весьма интересный хак .
Mirrel, в массиве нули, как и ожидается.
function OnlyFans(const bt: array of byte; v: byte {the fan}): Boolean; const m = ( $FFFFFFFF div 255); // $01010101 var p : PDWORD; trg : longword; cnt : integer; i : integer; begin trg := m * v; {$push POINTERMATH} {$POINTERMATH ON} p := @bt[0]; cnt := length( bt) div 4; i := cnt * 4; while cnt>0 do begin Result := p^ = trg; // Result := (p^ xor trg) = 0; if not Result then Exit; inc( p); dec( cnt); end; Result := ( ( i>=length( bt)) or ( bt[i]=v)) and ( ( i+1>=length( bt)) or ( bt[i+1]=v)) and ( ( i+2>=length( bt)) or ( bt[i+2]=v)); {$pop pointermath} end;
ArtProg
PQWord или PLongWord поставь. Это твоё решение.
if (((PQWord(arr_ptr+0)^) and $0101010101010101)<>0) then
В противном случае он сравнивает байты, а ты не смещал байт для проверки.
И как я и думал, в массиве как раз единица лежит, там, куда ты её положил. )))
Mirrel
> ArtProg, PQWord поставь. Это твоё решение.
а если в arr_ptr будут $22448824 записаны? :)
то это тоже норм? нулями считается?
Ага, спасибо! Сейчас проверю на работоспособность ;).
skalogryz
> а если в arr_ptr будут $22448824 записаны?
он хочет единицы проверить )))
По сути проверку двойную делать надо.
в твоём варианте вообще все нули выпадут )))
Mirrel, да, мой огрех, все верно. Впрочем это уже исправлено в следующем примере.