Skip to content

Commit

Permalink
Adding unsafe FastByteArrayEqual function for more speed.
Browse files Browse the repository at this point in the history
  • Loading branch information
MainMemory committed May 11, 2015
1 parent 55a3fc6 commit 31ddc70
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 31 deletions.
2 changes: 1 addition & 1 deletion LevelConverter/MainForm.cs
Expand Up @@ -492,7 +492,7 @@ private void ConvertLevel()
byte[] b = newchnk[i].GetBytes();
int match = -1;
for (int c = 0; c < tmpchnk.Count; c++)
if (b.ArrayEqual(tmpchnk[c].GetBytes()))
if (b.FastByteArrayEqual(tmpchnk[c].GetBytes()))
{
match = c;
break;
Expand Down
2 changes: 1 addition & 1 deletion ObjectLayoutDiff/Program.cs
Expand Up @@ -37,7 +37,7 @@ static void Main(string[] args)
List<ObjectEntry> newobjs = LoadObjects(File.ReadAllBytes(args[3]), format);
for (int i = 0; i < origobjs.Count; i++)
for (int j = 0; j < newobjs.Count; j++)
if (origobjs[i].GetBytes().ArrayEqual(newobjs[j].GetBytes()))
if (origobjs[i].GetBytes().FastByteArrayEqual(newobjs[j].GetBytes()))
{
origobjs.RemoveAt(i--);
newobjs.RemoveAt(j);
Expand Down
52 changes: 26 additions & 26 deletions SonLVL/MainForm.cs
Expand Up @@ -4301,7 +4301,7 @@ private void pasteBeforeToolStripMenuItem_Click(object sender, EventArgs e)
{
ushort ti = (ushort)LevelData.Tiles.Count;
for (ushort j = 0; j < LevelData.Tiles.Count; j++)
if (tile.ArrayEqual(LevelData.Tiles[j]))
if (tile.FastByteArrayEqual(LevelData.Tiles[j]))
{
ti = j;
break;
Expand Down Expand Up @@ -4367,7 +4367,7 @@ private void pasteBeforeToolStripMenuItem_Click(object sender, EventArgs e)
{
ushort ti = (ushort)LevelData.Tiles.Count;
for (ushort j = 0; j < LevelData.Tiles.Count; j++)
if (tile.ArrayEqual(LevelData.Tiles[j]))
if (tile.FastByteArrayEqual(LevelData.Tiles[j]))
{
ti = j;
break;
Expand Down Expand Up @@ -4436,7 +4436,7 @@ private void pasteAfterToolStripMenuItem_Click(object sender, EventArgs e)
{
ushort ti = (ushort)LevelData.Tiles.Count;
for (ushort j = 0; j < LevelData.Tiles.Count; j++)
if (tile.ArrayEqual(LevelData.Tiles[j]))
if (tile.FastByteArrayEqual(LevelData.Tiles[j]))
{
ti = j;
break;
Expand Down Expand Up @@ -4503,7 +4503,7 @@ private void pasteAfterToolStripMenuItem_Click(object sender, EventArgs e)
{
ushort ti = (ushort)LevelData.Tiles.Count;
for (ushort j = 0; j < LevelData.Tiles.Count; j++)
if (tile.ArrayEqual(LevelData.Tiles[j]))
if (tile.FastByteArrayEqual(LevelData.Tiles[j]))
{
ti = j;
break;
Expand Down Expand Up @@ -4750,27 +4750,27 @@ private void ImportImage(Bitmap bmp, Bitmap colbmp1, Bitmap colbmp2, Bitmap prib
if (!Object.ReferenceEquals(LevelData.ColInds1, LevelData.ColInds2) && LevelData.ColInds2[i] != col.ColInd2)
continue;
}
if (blkb.ArrayEqual(blocks[i]))
if (blkb.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
break;
}
if (blkh.ArrayEqual(blocks[i]))
if (blkh.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
cnk.Blocks[bx, by].XFlip = true;
break;
}
if (blkv.ArrayEqual(blocks[i]))
if (blkv.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
cnk.Blocks[bx, by].YFlip = true;
break;
}
if (blkhv.ArrayEqual(blocks[i]))
if (blkhv.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
Expand All @@ -4789,7 +4789,7 @@ private void ImportImage(Bitmap bmp, Bitmap colbmp1, Bitmap colbmp2, Bitmap prib
match = false;
byte[] cnkb = cnk.GetBytes();
for (int i = 0; i < chunks.Count; i++)
if (cnkb.ArrayEqual(chunks[i]))
if (cnkb.FastByteArrayEqual(chunks[i]))
{
match = true;
break;
Expand Down Expand Up @@ -4941,8 +4941,8 @@ private void ImportImage(Bitmap bmp, Bitmap colbmp1, Bitmap colbmp2, Bitmap prib
if (!Object.ReferenceEquals(LevelData.ColInds1, LevelData.ColInds2) && LevelData.ColInds2[i] != col.ColInd2)
continue;
}
if (blkb.ArrayEqual(blocks[i]) || blkh.ArrayEqual(blocks[i])
|| blkv.ArrayEqual(blocks[i]) || blkhv.ArrayEqual(blocks[i]))
if (blkb.FastByteArrayEqual(blocks[i]) || blkh.FastByteArrayEqual(blocks[i])
|| blkv.FastByteArrayEqual(blocks[i]) || blkhv.FastByteArrayEqual(blocks[i]))
{
match = true;
break;
Expand Down Expand Up @@ -7619,7 +7619,7 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)
{
ushort ti = (ushort)LevelData.Tiles.Count;
for (ushort j = 0; j < LevelData.Tiles.Count; j++)
if (tile.ArrayEqual(LevelData.Tiles[j]))
if (tile.FastByteArrayEqual(LevelData.Tiles[j]))
{
ti = j;
break;
Expand Down Expand Up @@ -7683,7 +7683,7 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)
{
ushort ti = (ushort)LevelData.Tiles.Count;
for (ushort j = 0; j < LevelData.Tiles.Count; j++)
if (tile.ArrayEqual(LevelData.Tiles[j]))
if (tile.FastByteArrayEqual(LevelData.Tiles[j]))
{
ti = j;
break;
Expand Down Expand Up @@ -7852,27 +7852,27 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)
if (!Object.ReferenceEquals(LevelData.ColInds1, LevelData.ColInds2) && LevelData.ColInds2[i] != col.ColInd2)
continue;
}
if (blkb.ArrayEqual(blocks[i]))
if (blkb.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
break;
}
if (blkh.ArrayEqual(blocks[i]))
if (blkh.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
cnk.Blocks[bx, by].XFlip = true;
break;
}
if (blkv.ArrayEqual(blocks[i]))
if (blkv.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
cnk.Blocks[bx, by].YFlip = true;
break;
}
if (blkhv.ArrayEqual(blocks[i]))
if (blkhv.FastByteArrayEqual(blocks[i]))
{
match = true;
cnk.Blocks[bx, by].Block = (ushort)i;
Expand All @@ -7891,7 +7891,7 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)
match = false;
byte[] cnkb = cnk.GetBytes();
for (int i = 0; i < chunks.Count; i++)
if (cnkb.ArrayEqual(chunks[i]))
if (cnkb.FastByteArrayEqual(chunks[i]))
{
result[cx, cy] = (byte)i;
match = true;
Expand Down Expand Up @@ -7993,7 +7993,7 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)
blk2 = coldata2[x, y];
byte ind1 = 0, ind2 = 0;
bool xflip = false, yflip = false;
if ((blk1.HeightMap.ArrayEqual(LevelData.ColArr1[0xFF]) || blk1.Solidity == Solidity.NotSolid) && coldata2 != null)
if ((blk1.HeightMap.FastSByteArrayEqual(LevelData.ColArr1[0xFF]) || blk1.Solidity == Solidity.NotSolid) && coldata2 != null)
{
ind1 = (byte)(blk1.Solidity == Solidity.NotSolid ? 0 : 0xFF);
if (blk2.Solidity != Solidity.NotSolid)
Expand All @@ -8005,7 +8005,7 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)
MatchCol(blk1, out ind1, out xflip, out yflip);
if (blk2.Solidity != Solidity.NotSolid)
{
if (blk2.HeightMap.ArrayEqual(LevelData.ColArr1[0xFF]))
if (blk2.HeightMap.FastSByteArrayEqual(LevelData.ColArr1[0xFF]))
{
ind2 = 0xFF;
}
Expand All @@ -8030,7 +8030,7 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)
bool found = false;
for (int i = 0; i < LevelData.ColArr1.Length; i++)
{
if (map.ArrayEqual(LevelData.ColArr1[i]))
if (map.FastSByteArrayEqual(LevelData.ColArr1[i]))
{
ind2 = (byte)i;
found = true;
Expand All @@ -8057,7 +8057,7 @@ private void pasteOverToolStripMenuItem_Click(object sender, EventArgs e)

private void MatchCol(ColInfo blk, out byte ind, out bool xflip, out bool yflip)
{
if (blk.HeightMap.ArrayEqual(LevelData.ColArr1[0xFF]))
if (blk.HeightMap.FastSByteArrayEqual(LevelData.ColArr1[0xFF]))
{
xflip = false;
yflip = false;
Expand All @@ -8074,28 +8074,28 @@ private void MatchCol(ColInfo blk, out byte ind, out bool xflip, out bool yflip)
byte? emptymap = null;
for (int i = 0; i < LevelData.ColArr1.Length; i++)
{
if (blk.HeightMap.ArrayEqual(LevelData.ColArr1[i]))
if (blk.HeightMap.FastSByteArrayEqual(LevelData.ColArr1[i]))
{
xflip = false;
yflip = false;
ind = (byte)i;
return;
}
if (maph.ArrayEqual(LevelData.ColArr1[i]))
if (maph.FastSByteArrayEqual(LevelData.ColArr1[i]))
{
xflip = true;
yflip = false;
ind = (byte)i;
return;
}
if (mapv.ArrayEqual(LevelData.ColArr1[i]))
if (mapv.FastSByteArrayEqual(LevelData.ColArr1[i]))
{
xflip = false;
yflip = true;
ind = (byte)i;
return;
}
if (maphv.ArrayEqual(LevelData.ColArr1[i]))
if (maphv.FastSByteArrayEqual(LevelData.ColArr1[i]))
{
xflip = true;
yflip = true;
Expand Down
2 changes: 1 addition & 1 deletion SonLVLAPI/BitmapBits.cs
Expand Up @@ -558,7 +558,7 @@ public override bool Equals(object obj)
BitmapBits other = obj as BitmapBits;
if (other == null) return false;
if (Width != other.Width | Height != other.Height) return false;
return Bits.ArrayEqual(other.Bits);
return Bits.FastByteArrayEqual(other.Bits);
}

public override int GetHashCode()
Expand Down
84 changes: 82 additions & 2 deletions SonLVLAPI/Extensions.cs
Expand Up @@ -211,18 +211,98 @@ public static string ToHex68k(this short number)

public static bool ArrayEqual<T>(this T[] arr1, T[] arr2)
{
if (arr1 == arr2) return true;
if (arr1.Length != arr2.Length) return false;
for (int i = 0; i < arr1.Length; i++)
if (!arr1[i].Equals(arr2[1]))
if (!arr1[i].Equals(arr2[i]))
return false;
return true;
}

public static unsafe bool FastByteArrayEqual(this byte[] arr1, byte[] arr2)
{
if (arr1 == arr2) return true;
if (arr1.Length != arr2.Length) return false;
fixed (byte* fp1 = arr1, fp2 = arr2)
{
ulong* lp1 = (ulong*)fp1;
ulong* lp2 = (ulong*)fp2;
int length = arr1.Length;
int longlen = length / 8;
for (int i = 0; i < longlen; i++)
if (*lp1++ != *lp2++) return false;
if ((length & 7) != 0)
{
byte* bp1 = (byte*)lp1;
byte* bp2 = (byte*)lp2;
if ((length & 4) == 4)
if (*(uint*)bp1 != *(uint*)bp2)
return false;
else
{
bp1 += 4;
bp2 += 4;
}
if ((length & 2) == 2)
if (*(ushort*)bp1 != *(ushort*)bp2)
return false;
else
{
bp1 += 2;
bp2 += 2;
}
if ((length & 1) == 1)
return *bp1 != *bp2;
}
}
return true;
}

public static unsafe bool FastSByteArrayEqual(this sbyte[] arr1, sbyte[] arr2)
{
if (arr1 == arr2) return true;
if (arr1.Length != arr2.Length) return false;
fixed (sbyte* fp1 = arr1, fp2 = arr2)
{
ulong* lp1 = (ulong*)fp1;
ulong* lp2 = (ulong*)fp2;
int length = arr1.Length;
int longlen = length / 8;
for (int i = 0; i < longlen; i++)
if (*lp1++ != *lp2++) return false;
if ((length & 7) != 0)
{
byte* bp1 = (byte*)lp1;
byte* bp2 = (byte*)lp2;
if ((length & 4) == 4)
if (*(uint*)bp1 != *(uint*)bp2)
return false;
else
{
bp1 += 4;
bp2 += 4;
}
if ((length & 2) == 2)
if (*(ushort*)bp1 != *(ushort*)bp2)
return false;
else
{
bp1 += 2;
bp2 += 2;
}
if ((length & 1) == 1)
return *bp1 != *bp2;
}
}
return true;
}

public static bool ListEqual<T>(this IList<T> lst1, IList<T> lst2)
{
if (lst1 == lst2) return true;
if (lst1.Count != lst2.Count) return false;
for (int i = 0; i < lst1.Count; i++)
if (!lst1[i].Equals(lst2[1]))
if (!lst1[i].Equals(lst2[i]))
return false;
return true;
}
Expand Down
2 changes: 2 additions & 0 deletions SonLVLAPI/SonLVL.API.csproj
Expand Up @@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -30,6 +31,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="SonicRetro.KensSharp.Common">
Expand Down

0 comments on commit 31ddc70

Please sign in to comment.