Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/release-notes/.FSharp.Core/10.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
### Changed

* Random functions support for zero element chosen/sampled ([PR #18568](https://github.com/dotnet/fsharp/pull/18568))
* Optimize array slicing performance. ([PR #18778](https://github.com/dotnet/fsharp/pull/18778))

### Breaking Changes

* 1D array slicing now returns an empty array singleton instead of allocating a new array when the result is empty. ([PR #18778](https://github.com/dotnet/fsharp/pull/18778))
20 changes: 10 additions & 10 deletions src/FSharp.Core/prim-types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -779,17 +779,17 @@ namespace Microsoft.FSharp.Core

let inline SetArray (target: 'T array) (index:int) (value:'T) = (# "stelem.any !0" type ('T) target index value #)

let inline GetArraySub arr (start:int) (len:int) =
let len = if len < 0 then 0 else len
let dst = zeroCreate len
for i = 0 to len - 1 do
SetArray dst i (GetArray arr (start + i))
dst

let inline SetArraySub arr (start:int) (len:int) (src:_ array) =
for i = 0 to len - 1 do
SetArray arr (start+i) (GetArray src i)
let inline GetArraySub (arr: 'a array) (start:int) (len:int) : 'a array =
if len <= 0 then
[||]
else
let dst = zeroCreate len
Array.Copy(arr, start, dst, 0, len)
dst

let inline SetArraySub (arr: 'T array) (start:int) (len:int) (src: 'T array) =
if len > 0 then
Array.Copy(src, 0, arr, start, len)

let inline GetArray2D (source: 'T[,]) (index1: int) (index2: int) = (# "ldelem.multi 2 !0" type ('T) source index1 index2 : 'T #)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1962,6 +1962,24 @@ type ArrayModule() =
Assert.AreEqual(arr.[-4..(-3)], ([||]: int array))


[<Fact>]
member _.``Slicing creates new non-empty arrays`` () =
let arr = [|1;2;3;4;5;6|]

Assert.False(Object.ReferenceEquals(arr[1..3], arr[1..3]))
Assert.False(Object.ReferenceEquals(arr[0..], arr[0..]))
Assert.False(Object.ReferenceEquals(arr[..^1], arr[..^1]))

[<Fact>]
member _.``Empty slices are referentially equivalent`` () =
let arr = [|1;2;3;4;5;6|]

Assert.AreEqual(arr[1..-1].Length, 0)
Assert.True(Object.ReferenceEquals(arr[1..-1], arr[1..-1]))

Assert.True(Object.ReferenceEquals(arr[1..-1], ([||]: int array)))


[<Fact>]
member _.RandomShuffle() =
let arr = [| 1..20 |]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module ArraySlicing

open BenchmarkDotNet.Attributes
open System

[<SimpleJob(launchCount = 2, warmupCount = 1, iterationCount = 2)>]
[<GcServer(true)>]
[<MemoryDiagnoser>]
[<MarkdownExporterAttribute.GitHub>]
type ArraySlicingBenchmark() =
let b = [| for _ in 1 .. 100_000 -> byte DateTime.Now.Ticks |]

[<Benchmark>]
member _.x () =
b[ 20 .. 4999 ]
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<Compile Include="Equality\OptionsAndCo.fs" />
<Compile Include="Equality\ExactEquals.fs" />
<Compile Include="Async.fs" />
<Compile Include="ArraySlicing.fs" />
<Compile Include="Conditions.fs" />
<Compile Include="Collections.fs" />
<Compile Include="Program.fs" />
Expand Down
Loading