мин. и макс. значения:
C#
static int GetMin(int a, int b) {
int delta = a - b;
return b + (delta & (delta >> 31));
}
static int GetMax(int a, int b) {
int delta = a - b;
return a - (delta & (delta >> 31));
}
интересно - это что реально быстрее сравнения будет?
Сделай сравнение? Интересно на паскале что получится??
https://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax Нашёл на счет сравнения.... надо подумать
program project1; {$WRITEABLECONST OFF} {$IFDEF FPC} {$ASMMODE intel} {$ENDIF} uses SysUtils, Math; function max_cmov(x, y: Integer): Integer; assembler; asm cmp y, x mov ecx, x cmovge ecx, y mov eax, ecx end; const k = 200; var a: array of Integer = nil; max, x, y: Integer; i, n, c: Cardinal; t1, t2: TDateTime; s: String; begin Randomize; SetLength(a, 10*1000*1000); for i:=Low(a) to High(a) do a[i]:=Random(MaxInt); for c:=0 to 2 do begin t1:=Now; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do max := max + Math.Max(a[i], a[i+1]); t2:=Now; DateTimeToString(s, '.ss.zzz', t2-t1); WriteLn('Math.Max: ', max, ', t:', s, 's'); t1:=Now; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do max := max + max_cmov(a[i], a[i+1]); t2:=Now; DateTimeToString(s, '.ss.zzz', t2-t1); WriteLn('max_cmov1: ', max, ', t:', s, 's'); t1:=Now; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do begin x:=a[i]; y:=a[i+1]; asm mov eax, x cmp y, eax cmovge eax, y add max, eax end{$IFDEF FPC}['eax']{$ENDIF}; end; t2:=Now; DateTimeToString(s, '.ss.zzz', t2-t1); WriteLn('max_cmov2: ', max, ', t:', s, 's'); t1:=Now; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do if a[i]>a[i+1] then max:=max+a[i] else max:=max+a[i+1]; t2:=Now; DateTimeToString(s, '.ss.zzz', t2-t1); WriteLn('if then1: ', max, ', t:', s, 's'); t1:=Now; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do if a[i]<a[i+1] then max:=max+a[i+1] else max:=max+a[i]; t2:=Now; DateTimeToString(s, '.ss.zzz', t2-t1); WriteLn('if then2: ', max, ', t:', s, 's'); t1:=Now; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do max:= max + (a[i] xor ((a[i] xor a[i+1]) and -Integer(a[i] < a[i+1]))); t2:=Now; DateTimeToString(s, '.ss.zzz', t2-t1); WriteLn('bithack: ', max, ', t:', s, 's'); end; WriteLn('Done... press key...'); ReadLn; end. Полная фигня Работает хак-то!
обновил код, совместимость с Delphi @zamtmn ☝️бинарник Delphi
с gettickcount ... если нужно program project1; {$WRITEABLECONST OFF} uses SysUtils, Math; function max_cmov(x, y: Integer): Integer; assembler; inline; asm cmpl %ecx, %edx movl %ecx, %eax cmovge %edx, %eax end; const k = 200; var a: array of Integer = nil; max: Integer; i, n, c: Cardinal; s: String; t1:cardinal; begin Randomize; SetLength(a, 10*1000*1000); for i:=Low(a) to High(a) do a[i]:=Random(MaxInt); for c:=0 to 2 do begin t1:=GetTickCount; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do max += Math.Max(a[i], a[i+1]); WriteLn('Math.Max: ', max, ', t:', IntToStr(GetTickCount - t1), 'ms'); t1:=GetTickCount; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do max += max_cmov(a[i], a[i+1]); WriteLn('max_cmov: ', max, ', t:', IntToStr(GetTickCount - t1), 'ms'); t1:=GetTickCount; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do if a[i]>a[i+1] then max+=a[i] else max+=a[i+1]; WriteLn('if then1: ', max, ', t:', IntToStr(GetTickCount - t1), 'ms'); t1:=GetTickCount; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do if a[i]<a[i+1] then max+=a[i+1] else max+=a[i]; WriteLn('if then2: ', max, ', t:', IntToStr(GetTickCount - t1), 'ms'); t1:=GetTickCount; max := 0; for n:=0 to k do for i:=Low(a) to Pred(High(a)) do max+=a[i] xor ((a[i] xor a[i+1]) and -Integer(a[i] < a[i+1])); WriteLn('bithack: ', max, ', t:', IntToStr(GetTickCount - t1), 'ms'); end; WriteLn('Done... press key...'); ReadLn; end.
не портабельно, хочу потом на других архитектурах потестить
Обновил код оказывается у Delphi была фора в тесте max_cmov - она не создает фреймы отключил у FPC тоже
Обсуждают сегодня