# Board index » delphi » FastCode CharPos

## FastCode CharPos

2005-03-14 09:08:58 PM
delphi159
Revisiting an older one.
Below is a slightly faster version of my function
NB The benchmark always only test string where the last character is the once
be a searching for. As a result the function below has 15 paths that are
never exercised!!!!! Although are required in everyday use. As such I would
have to question the accuracy of the benchmark.
Thanks
Chris
function CharPosCJGPas8_d(Ch : Char; const Str : AnsiString) : Integer;
var
L0, L1 : Integer;
PC, PD : PChar;
label NoAlignment, Ender;
label F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,F16;
label P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16;
begin
if Str <>'' then
begin
L0 := PInteger(Integer(Str)-4)^; {Get The Length of the String}
PC := Pointer(Str); {Point to start of string}
PD := PC + L0;
L1 := L0 and 15;
Inc(PC,L1);
case L1 of
0: goto NoAlignment;
1: goto P1;
2: goto P2;
3: goto P3;
4: goto P4;
5: goto P5;
6: goto P6;
7: goto P7;
8: goto P8;
9: goto P9;
10: goto P10;
11: goto P11;
12: goto P12;
13: goto P13;
14: goto P14;
15: goto P15;
end;
NoAlignment:
if L0 = 0 then goto Ender;
Inc(PC,16);
P16: if Ch = PC[-16] then goto F16;
P15: if Ch = PC[-15] then goto F15;
P14: if Ch = PC[-14] then goto F14;
P13: if Ch = PC[-13] then goto F13;
P12: if Ch = PC[-12] then goto F12;
P11: if Ch = PC[-11] then goto F11;
P10: if Ch = PC[-10] then goto F10;
P9: if Ch = PC[-9] then goto F9;
P8: if Ch = PC[-8] then goto F8;
P7: if Ch = PC[-7] then goto F7;
P6: if Ch = PC[-6] then goto F6;
P5: if Ch = PC[-5] then goto F5;
P4: if Ch = PC[-4] then goto F4;
P3: if Ch = PC[-3] then goto F3;
P2: if Ch = PC[-2] then goto F2;
P1: if Ch = PC[-1] then goto F1;
Inc(PC,16);
if PC <= PD then goto P16;
Ender:Result := 0; exit;
F16: Result := PC - 15 - Pointer(Str); exit;
F15: Result := PC - 14 - Pointer(Str); exit;
F14: Result := PC - 13 - Pointer(Str); exit;
F13: Result := PC - 12 - Pointer(Str); exit;
F12: Result := PC - 11 - Pointer(Str); exit;
F11: Result := PC - 10 - Pointer(Str); exit;
F10: Result := PC - 9 - Pointer(Str); exit;
F9: Result := PC - 8 - Pointer(Str); exit;
F8: Result := PC - 7 - Pointer(Str); exit;
F7: Result := PC - 6 - Pointer(Str); exit;
F6: Result := PC - 5 - Pointer(Str); exit;
F5: Result := PC - 4 - Pointer(Str); exit;
F4: Result := PC - 3 - Pointer(Str); exit;
F3: Result := PC - 2 - Pointer(Str); exit;
F2: Result := PC - 1 - Pointer(Str); exit;
F1: Result := PC - Pointer(Str);
end
else
begin
Result := 0;
exit;
end;
end;

## Re:FastCode CharPos

Hi Chris
Fine. I will look into it as soon as possible. Expect that it will be
necessary to remind now and then.
Regards
Dennis

## Re:FastCode CharPos

And a quicker one.
function CharPosCJGPas9_d(Ch : Char; const Str : AnsiString) : Integer;
var
L0 : Integer;
label NoAlignment, Ender;
label F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,F16;
label P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16;
begin
If Str<>'' then
begin
L0 := PInteger(Integer(Str)-4)^; {Get The Length of the String}
Result := L0 and 15;
case Result of
0: goto NoAlignment;
1: goto P1;
2: goto P2;
3: goto P3;
4: goto P4;
5: goto P5;
6: goto P6;
7: goto P7;
8: goto P8;
9: goto P9;
10: goto P10;
11: goto P11;
12: goto P12;
13: goto P13;
14: goto P14;
15: goto P15;
end;
NoAlignment:
If L0 = 0 then goto Ender;
Inc(Result,16);
P16: if Ch = PChar(Pointer(Str))[Result - 16] then goto F16;
P15: if Ch = PChar(Pointer(Str))[Result - 15] then goto F15;
P14: if Ch = PChar(Pointer(Str))[Result - 14] then goto F14;
P13: if Ch = PChar(Pointer(Str))[Result - 13] then goto F13;
P12: if Ch = PChar(Pointer(Str))[Result - 12] then goto F12;
P11: if Ch = PChar(Pointer(Str))[Result - 11] then goto F11;
P10: if Ch = PChar(Pointer(Str))[Result - 10] then goto F10;
P9: if Ch = PChar(Pointer(Str))[Result - 9] then goto F9;
P8: if Ch = PChar(Pointer(Str))[Result - 8] then goto F8;
P7: if Ch = PChar(Pointer(Str))[Result - 7] then goto F7;
P6: if Ch = PChar(Pointer(Str))[Result - 6] then goto F6;
P5: if Ch = PChar(Pointer(Str))[Result - 5] then goto F5;
P4: if Ch = PChar(Pointer(Str))[Result - 4] then goto F4;
P3: if Ch = PChar(Pointer(Str))[Result - 3] then goto F3;
P2: if Ch = PChar(Pointer(Str))[Result - 2] then goto F2;
P1: if Ch = PChar(Pointer(Str))[Result - 1] then exit;
Inc(Result,16);
if Result <= L0 then goto P16;
Result := 0; exit;
F16: Dec(Result,15); exit;
F15: Dec(Result,14); exit;
F14: Dec(Result,13); exit;
F13: Dec(Result,12); exit;
F12: Dec(Result,11); exit;
F11: Dec(Result,10); exit;
F10: Dec(Result,9 ); exit;
F9: Dec(Result,8 ); exit;
F8: Dec(Result,7 ); exit;
F7: Dec(Result,6 ); exit;
F6: Dec(Result,5 ); exit;
F5: Dec(Result,4 ); exit;
F4: Dec(Result,3 ); exit;
F3: Dec(Result,2 ); exit;
F2: Dec(Result,1 ); exit;
end
else
Ender:Result := 0;
end;

## Re:FastCode CharPos

Hi
I reused one of my CharPos functions when creating a CharPosIEx function. I
did not investigate it fully but it looks like there was a bug in the
function and this means that there is a hole in the CharPos validation.
It is important that we fix the validation before Borland hopefully
integrate CharPos into the Highlander RTL.
I also believe that the CharPos benchmark puts to little pressure on the
branch predictor.
This is the validation function that triggered the bug
function TMainForm.Validate9 : Boolean;
var
I, Iref, J, OffSet : Integer;
Str : String;
SearchChar : Char;
const
STRLENMAX : Integer = 33000;
VALIDATENO : Cardinal = 9;
MINOFFSET : Integer = 0;
MAXOFFSET : Integer = 2;
begin
StatusBar1.SimpleText := 'Running Validate9';
Update;
Result := True;
Str := '';
SearchChar := #0;
Iref := 0;
for J := 1 to STRLENMAX do
begin
for OffSet := MINOFFSET to MAXOFFSET do
begin
try
I := CharPosIExFunction(SearchChar, Str, OffSet);
if I <>Iref then
begin
ErrorTrap(VALIDATENO, SearchChar, Str, OffSet);
Result := False;
Exit;
end;
except
ErrorTrap(VALIDATENO, SearchChar, Str, OffSet);
Result := False;
end;
end;
Str := Str + Char(Random(255)+1); //Never generate a #0
end;
end;
Best regards
Dennis Kjaer Christensen