Skip to content

Instantly share code, notes, and snippets.

@matthewcrews
Created August 9, 2021 17:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewcrews/1908afd52573819dd24c797227bcf3b8 to your computer and use it in GitHub Desktop.
Save matthewcrews/1908afd52573819dd24c797227bcf3b8 to your computer and use it in GitHub Desktop.
Compiler throws error saying it doesn't have a `Item` method for `ReadOnlySpan<'T>`
open System
open System.Collections.Generic
module rec SliceMap =
[<Struct>]
type IndexRange = {
Start : int
Length : int
}
let inline private hadamardProduct (l: SliceMap<_,_>, r: SliceMap<_,_>) =
let lKeys = l.Keys.Span
let lValues = l.Values.Span
let rKeys = r.Keys.Span
let rValues = r.Values.Span
let outKeys = Array.zeroCreate l.Keys.Length
let outValues = Array.zeroCreate r.Keys.Length
let mutable outIdx = 0
let mutable thisIdx = 0
let mutable thatIdx = 0
while thisIdx < l.Keys.Length && thatIdx < r.Keys.Length do
let c = l.Comparer.Compare (lKeys.[thisIdx], rKeys.[thatIdx])
if c = 0 then
outKeys.[outIdx] <- lKeys.[thisIdx]
outValues.[outIdx] <- lValues.[thisIdx] * rValues.[thatIdx]
outIdx <- outIdx + 1
thisIdx <- thisIdx + 1
thatIdx <- thatIdx + 1
elif c < 0 then
thisIdx <- thisIdx + 1
else
thatIdx <- thatIdx + 1
// Only want the data we actually computed
SliceMap (ReadOnlyMemory (outKeys, 0, outIdx - 1), ReadOnlyMemory (outValues, 0, outIdx - 1))
let inline sum (x : SliceMap<_,_>) =
let values = x.Values.Span
let mutable acc = LanguagePrimitives.GenericZero
for idx = 0 to x.Values.Length - 1 do
acc <- acc + values.[idx]
acc
type SliceMap<'k, 'v when 'k : comparison> internal (keys: ReadOnlyMemory<'k>, values: ReadOnlyMemory<'v>) =
let comparer = LanguagePrimitives.FastGenericComparer<'k>
let keys = keys
let values = values
new (keyValuePairs: seq<'k * 'v>) =
let data =
let x = Array.ofSeq keyValuePairs
Array.sortInPlaceBy fst x
x
let keys = data |> Array.map fst
let values = data |> Array.map snd
SliceMap (ReadOnlyMemory keys, ReadOnlyMemory values)
member internal _.Keys : ReadOnlyMemory<'k> = keys
member internal _.Values : ReadOnlyMemory<'v> = values
member internal _.Comparer : IComparer<'k> = comparer
static member inline ( .* ) (l: SliceMap<_,_>, r: SliceMap<_,_>) =
if l.Keys.Length > r.Keys.Length then
hadamardProduct (l, r)
else
hadamardProduct (r, l)
open SliceMap
let x =
[for i in 0..5 -> i, float i]
|> SliceMap
let r = sum x
@matthewcrews
Copy link
Author

When I run this in fsi I get the following error:

System.MissingMethodException: Method not found: '!0 ByRef System.ReadOnlySpan`1.get_Item(Int32)'.
   at <StartupCode$FSI_0010>.$FSI_0010.main@()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment