Skip to content

Instantly share code, notes, and snippets.

@manofstick
Created August 24, 2016 04:59
Show Gist options
  • Save manofstick/c9181594a9dbac170b01ce9ae14f3b2d to your computer and use it in GitHub Desktop.
Save manofstick/c9181594a9dbac170b01ce9ae14f3b2d to your computer and use it in GitHub Desktop.
Fast filtering
let boolToUInt32 (b:bool) = (# "conv.u4" (# "cgt.un" b 0 : int32 #) : uint32 #)
module internal Filter =
[<Struct; NoComparison; NoEquality>]
type MaskStruct =
val mutable _0x00 : bool
val mutable _0x01 : bool
val mutable _0x02 : bool
val mutable _0x03 : bool
val mutable _0x04 : bool
val mutable _0x05 : bool
val mutable _0x06 : bool
val mutable _0x07 : bool
val mutable _0x08 : bool
val mutable _0x09 : bool
val mutable _0x0A : bool
val mutable _0x0B : bool
val mutable _0x0C : bool
val mutable _0x0D : bool
val mutable _0x0E : bool
val mutable _0x0F : bool
val mutable _0x10 : bool
val mutable _0x11 : bool
val mutable _0x12 : bool
val mutable _0x13 : bool
val mutable _0x14 : bool
val mutable _0x15 : bool
val mutable _0x16 : bool
val mutable _0x17 : bool
val mutable _0x18 : bool
val mutable _0x19 : bool
val mutable _0x1A : bool
val mutable _0x1B : bool
val mutable _0x1C : bool
val mutable _0x1D : bool
val mutable _0x1E : bool
val mutable _0x1F : bool
let populateMaskStruct f (array:array<_>) arrayBaseIdx (fd:byref<MaskStruct>) =
fd._0x00 <- f array.[arrayBaseIdx+0x00]
fd._0x01 <- f array.[arrayBaseIdx+0x01]
fd._0x02 <- f array.[arrayBaseIdx+0x02]
fd._0x03 <- f array.[arrayBaseIdx+0x03]
fd._0x04 <- f array.[arrayBaseIdx+0x04]
fd._0x05 <- f array.[arrayBaseIdx+0x05]
fd._0x06 <- f array.[arrayBaseIdx+0x06]
fd._0x07 <- f array.[arrayBaseIdx+0x07]
fd._0x08 <- f array.[arrayBaseIdx+0x08]
fd._0x09 <- f array.[arrayBaseIdx+0x09]
fd._0x0A <- f array.[arrayBaseIdx+0x0A]
fd._0x0B <- f array.[arrayBaseIdx+0x0B]
fd._0x0C <- f array.[arrayBaseIdx+0x0C]
fd._0x0D <- f array.[arrayBaseIdx+0x0D]
fd._0x0E <- f array.[arrayBaseIdx+0x0E]
fd._0x0F <- f array.[arrayBaseIdx+0x0F]
fd._0x10 <- f array.[arrayBaseIdx+0x10]
fd._0x11 <- f array.[arrayBaseIdx+0x11]
fd._0x12 <- f array.[arrayBaseIdx+0x12]
fd._0x13 <- f array.[arrayBaseIdx+0x13]
fd._0x14 <- f array.[arrayBaseIdx+0x14]
fd._0x15 <- f array.[arrayBaseIdx+0x15]
fd._0x16 <- f array.[arrayBaseIdx+0x16]
fd._0x17 <- f array.[arrayBaseIdx+0x17]
fd._0x18 <- f array.[arrayBaseIdx+0x18]
fd._0x19 <- f array.[arrayBaseIdx+0x19]
fd._0x1A <- f array.[arrayBaseIdx+0x1A]
fd._0x1B <- f array.[arrayBaseIdx+0x1B]
fd._0x1C <- f array.[arrayBaseIdx+0x1C]
fd._0x1D <- f array.[arrayBaseIdx+0x1D]
fd._0x1E <- f array.[arrayBaseIdx+0x1E]
fd._0x1F <- f array.[arrayBaseIdx+0x1F]
let calculateMask (fd:byref<MaskStruct>) =
let mutable mask =
((LanguagePrimitives.boolToUInt32 fd._0x00) <<< 0x00)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x01) <<< 0x01)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x02) <<< 0x02)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x03) <<< 0x03)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x04) <<< 0x04)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x05) <<< 0x05)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x06) <<< 0x06)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x07) <<< 0x07)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x08) <<< 0x08)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x09) <<< 0x09)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x0A) <<< 0x0A)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x0B) <<< 0x0B)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x0C) <<< 0x0C)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x0D) <<< 0x0D)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x0E) <<< 0x0E)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x0F) <<< 0x0F)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x10) <<< 0x10)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x11) <<< 0x11)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x12) <<< 0x12)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x13) <<< 0x13)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x14) <<< 0x14)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x15) <<< 0x15)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x16) <<< 0x16)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x17) <<< 0x17)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x18) <<< 0x18)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x19) <<< 0x19)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x1A) <<< 0x1A)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x1B) <<< 0x1B)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x1C) <<< 0x1C)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x1D) <<< 0x1D)
mask <- mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x1E) <<< 0x1E)
mask ||| ((LanguagePrimitives.boolToUInt32 fd._0x1F) <<< 0x1F)
let createMask f (array:array<_>) =
let thirtytooth = array.Length/32
let filterMaskMap = Array.zeroCreateUnchecked<uint32> (thirtytooth+1)
let mutable filteredCount = 0
let mutable filterMaskMapIdx = 0
let mutable fd = Unchecked.defaultof<MaskStruct>
while filterMaskMapIdx < thirtytooth do
populateMaskStruct f array (filterMaskMapIdx*32) &fd
let mask = calculateMask &fd
if mask <> 0u then
filteredCount <- filteredCount + int (fastGetBitsCount mask)
filterMaskMap.[filterMaskMapIdx] <- mask
filterMaskMapIdx <- filterMaskMapIdx + 1
let arrayIdx = filterMaskMapIdx*32
if arrayIdx < array.Length then
let mutable filterMask = 0u
let mutable offset = 0
for arrayIdx = arrayIdx to array.Length-1 do
filterMask <- filterMask ||| (LanguagePrimitives.boolToUInt32 (f array.[arrayIdx]) <<< offset)
offset <- offset + 1
filteredCount <- filteredCount + int (fastGetBitsCount filterMask)
filterMaskMap.[filterMaskMap.Length-1] <- filterMask
filterMaskMap, filteredCount
let createAndPopulate (filterMaskMap:array<uint32>,filteredCount) (src:array<_>) =
let dst = Array.zeroCreateUnchecked filteredCount
let mutable dstIdx = 0
let mutable srcIdx = 0
for mask in filterMaskMap do
if mask <> 0u then
if (mask &&& (1u<<<0x00)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x00]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x01)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x01]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x02)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x02]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x03)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x03]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x04)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x04]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x05)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x05]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x06)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x06]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x07)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x07]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x08)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x08]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x09)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x09]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x0A)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x0A]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x0B)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x0B]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x0C)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x0C]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x0D)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x0D]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x0E)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x0E]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x0F)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x0F]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x10)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x10]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x11)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x11]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x12)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x12]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x13)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x13]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x14)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x14]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x15)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x15]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x16)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x16]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x17)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x17]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x18)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x18]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x19)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x19]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x1A)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x1A]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x1B)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x1B]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x1C)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x1C]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x1D)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x1D]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x1E)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x1E]; dstIdx <- dstIdx + 1
if (mask &&& (1u<<<0x1F)) <> 0u then dst.[dstIdx] <- src.[srcIdx+0x1F]; dstIdx <- dstIdx + 1
srcIdx <- srcIdx + 32
dst
[<CompiledName("Filter")>]
let filter f (array: _[]) =
checkNonNull "array" array
match array |> Filter.createMask f with
| _, 0 -> empty
| _, count when count = array.Length -> array.Clone () :?> _
| mask -> array |> Filter.createAndPopulate mask
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment