diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 4c4490073..673835b8d 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"paket": {
- "version": "7.2.1",
+ "version": "8.0.3",
"commands": [
"paket"
]
diff --git a/README.md b/README.md
index 23df751e2..b332a31ba 100644
--- a/README.md
+++ b/README.md
@@ -2,35 +2,13 @@
![MacOS](https://github.com/aardvark-platform/aardvark.base/workflows/MacOS/badge.svg)
![Linux](https://github.com/aardvark-platform/aardvark.base/workflows/Linux/badge.svg)
-
[![Discord](https://badgen.net/discord/online-members/UyecnhM)](https://discord.gg/UyecnhM)
[![license](https://img.shields.io/github/license/aardvark-platform/aardvark.base.svg)](https://github.com/aardvark-platform/aardvark.base/blob/master/LICENSE)
[The Aardvark Platform](https://aardvarkians.com/) |
-[Platform Wiki](https://github.com/aardvarkplatform/aardvark.docs/wiki) |
-[The Platform Walkthrough Repository](https://github.com/aardvark-platform/walkthrough) |
-[Gallery](https://github.com/aardvarkplatform/aardvark.docs/wiki/Gallery) |
-[Quickstart](https://github.com/aardvarkplatform/aardvark.docs/wiki/Quickstart-Windows) |
-[Status](https://github.com/aardvarkplatform/aardvark.docs/wiki/Status)
-
-
-Aardvark.Base consists of multiple platform-independent packages (netstandard2.0) delivering essential tools for visual computing, such as vectors and matrices, as well as many algorithms and data structures.
-It is the lowest-level foundation of the open-source [Aardvark Platform](https://github.com/aardvark-platform/aardvark.docs/wiki) for visual computing, real-time graphics and visualization:
-
-repository | description
-:-- | --- |
-`aardvark.media` | a unified ELM-style UI framework for both 2D and 3D |
-`aardvark.rendering` | powerful incremental rendering engine |
-`aardvark.base` | math, geometry, algorithms, data structures |
-
-The repository `aardvark.base` includes many packages, e.g.
- - [Aardvark.Base](https://www.nuget.org/packages/Aardvark.Base/): matrices, vectors, geometry, basic algorithms and data structures.
- - [Aardvark.Base.FSharp](https://www.nuget.org/packages/Aardvark.Base.FSharp/): stuff you always need, optimized persistent (e.g. hash maps), ephemeral data structures (e.g. SkipList) as well as spatial data structures (e.g. bounding volume hierarchies). The package also contains an attribute grammar system exposed as an embedded domain specific language. We use it in [aardvark.rendering](https://github.com/aardvark-platform/aardvark.base) for our scene graph system, as described in [Attribute Grammars for Incremental Scene Graph Rendering](https://www.vrvis.at/publications/pdfs/PB-VRVis-2019-004.pdf).
- - [Aardvark.Base.Incremental](https://www.nuget.org/packages/Aardvark.Base.Incremental/): incremental data structures similarly but extended to Hammer et al.'s paper [Adapton: Composable, Demand-Driven Incremental Computation](https://www.cs.umd.edu/~hammer/adapton/). Additionally to modifiable cells, we have more sophisticated optimized incremental data structures such as adaptive sets, maps etc. and computation expression builders to conveniently work with.
- - [Aardvark.Base.Runtime](https://www.nuget.org/packages/Aardvark.Base.Runtime/): Crazy tools such as an AMD64 assembler used for incremental Just In Time Compilation as used in [aardvark.rendering](https://github.com/aardvark-platform/aardvark.base)
- - [Aardvark.Data.Vrml97](https://www.nuget.org/packages/Aardvark.Data.Vrml97/): legacy Vrml97 parser
- - [Aardvark.Geometry](https://www.nuget.org/packages/Aardvark.Geometry/): currently a rather small set of F# geometry tools. Most functionality regarding geometry lives in base and [algodat](https://github.com/aardvark-platform/aardvark.algodat)
+[Gallery](https://github.com/aardvark-platform/aardvark.docs/wiki/Gallery) |
+[Packages&Repositories](https://github.com/aardvark-platform/aardvark.docs/wiki/Packages-and-Repositories)
-All packages are distributed under the [Apache 2.0 license](https://github.com/aardvark-platform/aardvark.base/blob/master/LICENSE).
+Aardvark.Base is the foundation of the open-source [Aardvark Platform](https://github.com/aardvark-platform) for visual computing, real-time graphics, and visualization. It consists of multiple platform-independent packages (netstandard2.0) that deliver essential tools for visual computing, including vectors, matrices, algorithms, data structures, or image loaders. Supported platforms are windows, linux, macOS.
-For support please have a look at [Aardvarkians](https://aardvarkians.com).
+You can find demos and code in the Gallery and Packages&Repositories links above. [This repository's wiki](https://github.com/aardvark-platform/aardvark.base/wiki) hosts technical documentation. For more information, please refer to the [aardvark.docs wiki](https://github.com/aardvark-platform/aardvark.docs/wiki).
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 2cb2c6926..06a1104f1 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,29 @@
+### 5.2.29
+* Fixed color parsing to be independent of the current culture (regression in 5.2.27)
+* Added more value variants for Dictionary, Dict, and SymbolDict functions
+
+### 5.2.28
+* Added Brewer color schemes
+* Added String.replace
+* Added IDictionary.TryPop overload with output argument
+
+### 5.2.27
+* Improved and fixed RangeSet implementation
+* Added utilities for ValueOption
+* Added more ArraySegment utilities
+* [Text] Fixed NestedBracketSplitCount
+* [Color] Fixed overflow issue in C4ui constructors
+* [Color] Improved color parsing, now supports hexadecimal color strings
+* [PixImage] Fixed file handle leak in Windows Media loader
+* [MapExt] Added value variants of some operations
+
### 5.2.26
* LinearRegression3d: made fields public
+* Added getLines, normalizeLineEndings, withLineNumbers in String module
+* Fixed FGetValueOrDefault dictionary extension
+* Added value variants for Dict functions
+* Added F# ArraySegment utilities
+* [Introspection] Tidied up exception reporting
### 5.2.25
* Fixed issue with PixImageMipMap loading
diff --git a/paket.dependencies b/paket.dependencies
index 0d8b738c0..639c21276 100644
--- a/paket.dependencies
+++ b/paket.dependencies
@@ -33,13 +33,13 @@ group Test
source https://api.nuget.org/v3/index.json
nuget NUnit ~> 3.13.3
- nuget FsUnit ~> 5.2.0
+ nuget FsUnit ~> 5.4.0
nuget FsCheck ~> 2.16.4
nuget FsCheck.NUnit ~> 2.16.4
- nuget NUnit3TestAdapter ~> 4.4.2
- nuget Microsoft.NET.Test.Sdk ~> 17.5.0
- nuget Expecto ~> 9.0.4
- nuget Expecto.FsCheck ~> 9.0.4
- nuget YoloDev.Expecto.TestSdk ~> 0.13.3
+ nuget NUnit3TestAdapter ~> 4.5.0
+ nuget Microsoft.NET.Test.Sdk ~> 17.7.2
+ nuget Expecto ~> 10.1.0
+ nuget Expecto.FsCheck ~> 10.1.0
+ nuget YoloDev.Expecto.TestSdk ~> 0.14.2
- nuget BenchmarkDotNet ~> 0.13.1
\ No newline at end of file
+ nuget BenchmarkDotNet ~> 0.13.9
\ No newline at end of file
diff --git a/paket.lock b/paket.lock
index f5969f495..834221633 100644
--- a/paket.lock
+++ b/paket.lock
@@ -201,33 +201,33 @@ GROUP Test
RESTRICTION: || (== net6.0) (== net6.0-windows7.0)
NUGET
remote: https://api.nuget.org/v3/index.json
- BenchmarkDotNet (0.13.5)
- BenchmarkDotNet.Annotations (>= 0.13.5)
- CommandLineParser (>= 2.4.3)
+ BenchmarkDotNet (0.13.9)
+ BenchmarkDotNet.Annotations (>= 0.13.9)
+ CommandLineParser (>= 2.9.1)
Gee.External.Capstone (>= 2.3)
Iced (>= 1.17)
- Microsoft.CodeAnalysis.CSharp (>= 3.0)
+ Microsoft.CodeAnalysis.CSharp (>= 4.1)
Microsoft.Diagnostics.Runtime (>= 2.2.332302)
Microsoft.Diagnostics.Tracing.TraceEvent (>= 3.0.2)
Microsoft.DotNet.PlatformAbstractions (>= 3.1.6)
- Perfolizer (>= 0.2.1)
- System.Management (>= 6.0)
- BenchmarkDotNet.Annotations (0.13.5)
+ Perfolizer (0.2.1)
+ System.Management (>= 5.0)
+ BenchmarkDotNet.Annotations (0.13.9)
CommandLineParser (2.9.1)
- Expecto (9.0.4)
- FSharp.Core (>= 4.6)
- Mono.Cecil (>= 0.11.3)
- Expecto.FsCheck (9.0.4)
- Expecto (>= 9.0.4)
- FsCheck (>= 2.14.3)
- FsCheck (2.16.5)
+ Expecto (10.1)
+ FSharp.Core (>= 7.0.200)
+ Mono.Cecil (>= 0.11.4 < 1.0)
+ Expecto.FsCheck (10.1)
+ Expecto (>= 10.1)
+ FsCheck (>= 2.16.5 < 3.0)
+ FsCheck (2.16.6)
FSharp.Core (>= 4.2.3)
- FsCheck.NUnit (2.16.5)
- FsCheck (2.16.5)
+ FsCheck.NUnit (2.16.6)
+ FsCheck (2.16.6)
NUnit (>= 3.13.1 < 4.0)
FSharp.Core (7.0.200)
- FsUnit (5.2)
- FSharp.Core (>= 6.0.7)
+ FsUnit (5.4)
+ FSharp.Core (>= 5.0.2)
NUnit (>= 3.13.3 < 3.14)
Gee.External.Capstone (2.3)
Iced (1.17)
@@ -243,7 +243,7 @@ NUGET
System.Threading.Tasks.Extensions (>= 4.5.4)
Microsoft.CodeAnalysis.CSharp (4.2)
Microsoft.CodeAnalysis.Common (4.2)
- Microsoft.CodeCoverage (17.5)
+ Microsoft.CodeCoverage (17.7.2)
Microsoft.Diagnostics.NETCore.Client (0.2.327302)
Microsoft.Bcl.AsyncInterfaces (>= 1.1)
Microsoft.Extensions.Logging (>= 2.1.1)
@@ -270,24 +270,24 @@ NUGET
Microsoft.Extensions.Primitives (>= 6.0)
Microsoft.Extensions.Primitives (6.0)
System.Runtime.CompilerServices.Unsafe (>= 6.0)
- Microsoft.NET.Test.Sdk (17.5)
- Microsoft.CodeCoverage (>= 17.5)
- Microsoft.TestPlatform.TestHost (>= 17.5)
+ Microsoft.NET.Test.Sdk (17.7.2)
+ Microsoft.CodeCoverage (>= 17.7.2)
+ Microsoft.TestPlatform.TestHost (>= 17.7.2)
Microsoft.NETCore.Platforms (6.0.3)
- Microsoft.TestPlatform.ObjectModel (17.5)
- NuGet.Frameworks (>= 5.11)
+ Microsoft.TestPlatform.ObjectModel (17.7.2)
+ NuGet.Frameworks (>= 6.5)
System.Reflection.Metadata (>= 1.6)
- Microsoft.TestPlatform.TestHost (17.5)
- Microsoft.TestPlatform.ObjectModel (>= 17.5)
+ Microsoft.TestPlatform.TestHost (17.7.2)
+ Microsoft.TestPlatform.ObjectModel (>= 17.7.2)
Newtonsoft.Json (>= 13.0.1)
Mono.Cecil (0.11.4)
NETStandard.Library (2.0.3)
Microsoft.NETCore.Platforms (>= 1.1)
Newtonsoft.Json (13.0.1)
- NuGet.Frameworks (6.2)
+ NuGet.Frameworks (6.7)
NUnit (3.13.3)
NETStandard.Library (>= 2.0)
- NUnit3TestAdapter (4.4.2)
+ NUnit3TestAdapter (4.5)
Perfolizer (0.2.1)
System.Memory (>= 4.5.3)
System.CodeDom (6.0)
@@ -304,7 +304,7 @@ NUGET
System.Text.Encoding.CodePages (6.0)
System.Runtime.CompilerServices.Unsafe (>= 6.0)
System.Threading.Tasks.Extensions (4.5.4)
- YoloDev.Expecto.TestSdk (0.13.3)
- Expecto (>= 9.0 < 10.0)
- FSharp.Core (>= 4.6.2)
+ YoloDev.Expecto.TestSdk (0.14.2)
+ Expecto (>= 10.0 < 11.0)
+ FSharp.Core (>= 7.0.200)
System.Collections.Immutable (>= 6.0)
diff --git a/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj b/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj
index 24d5d2544..3daf34648 100644
--- a/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj
+++ b/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj
@@ -15,23 +15,31 @@
..\..\bin\Release
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -43,6 +51,8 @@
+
+
@@ -50,6 +60,9 @@
+
+
+
@@ -67,20 +80,14 @@
-
-
-
-
-
-
-
-
+
+
diff --git a/src/Aardvark.Base.FSharp/Color/ColorBrewer.fs b/src/Aardvark.Base.FSharp/Color/ColorBrewer.fs
new file mode 100644
index 000000000..d0abca79e
--- /dev/null
+++ b/src/Aardvark.Base.FSharp/Color/ColorBrewer.fs
@@ -0,0 +1,135 @@
+namespace Aardvark.Base
+
+open System
+open System.Collections
+open System.Collections.Generic
+
+/// Brewer color schemes designed for choropleth map visualizations.
+module ColorBrewer =
+
+ []
+ type PaletteUsage =
+ | None = 0
+
+ /// Does not confuse people with red-green color blindness.
+ | ColorBlind = 1
+
+ /// Suitable for desktop color printing.
+ | Print = 2
+
+ /// Suitable for viewing on a laptop LCD display.
+ /// Small, portable LCD monitors tend to wash-out colors which results in noticeable differences from computer-to-computer.
+ | LCD = 4
+
+ /// Withstands black and white photocopying.
+ /// Diverging schemes can not be photocopied successfully.
+ /// Differences in lightness should be preserved with sequential schemes.
+ | PhotoCopy = 8
+
+ []
+ type Palette =
+ {
+ /// The color values of the palette.
+ Colors : C3b[]
+
+ /// Usage properties of the palette.
+ Usage : PaletteUsage
+ }
+
+ member inline x.Length =
+ x.Colors.Length
+
+ member inline x.Item (index : int) =
+ x.Colors.[index]
+
+ interface IEnumerable with
+ member x.GetEnumerator() = x.Colors.GetEnumerator()
+
+ interface IEnumerable with
+ member x.GetEnumerator() = (x.Colors :> IEnumerable).GetEnumerator()
+
+
+ type SchemeType =
+
+ /// Diverging schemes put equal emphasis on mid-range critical values and extremes at both ends of the data range.
+ /// The critical class or break in the middle of the legend is emphasized with light colors and low and high extremes are
+ /// emphasized with dark colors that have contrasting hues.
+ | Diverging = 0
+
+ /// Qualitative schemes do not imply magnitude differences between legend classes, and hues are used to
+ /// create the primary visual differences between classes. Qualitative schemes are best suited to representing nominal or categorical data.
+ | Qualitative = 1
+
+ /// Sequential schemes are suited to ordered data that progress from low to high.
+ /// Lightness steps dominate the look of these schemes, with light colors for low data values to dark colors for high data values.
+ | Sequential = 2
+
+ /// A color scheme containing palettes of various size.
+ []
+ type Scheme =
+ {
+ /// Name of the scheme.
+ Name : Symbol
+
+ /// Type of the scheme.
+ Type : SchemeType
+
+ /// The palettes of the scheme according to their size.
+ Palettes : MapExt
+ }
+
+ /// Returns whether the scheme is empty (i.e. has no palettes).
+ member inline x.IsEmpty =
+ x.Palettes.IsEmpty
+
+ /// Size of the smallest palette.
+ member inline x.MinSize =
+ x.Palettes.TryMinKeyV |> ValueOption.defaultValue 0
+
+ /// Size of the largest palette.
+ member inline x.MaxSize =
+ x.Palettes.TryMaxKeyV |> ValueOption.defaultValue 0
+
+ /// Gets the palette with the given size.
+ /// If the scheme is not defined for the requested size, gets the next larger palette.
+ /// Throws an exception if the requested size is greater than the maximum size.
+ member inline x.Item (requestedSize : int) =
+ match x.Palettes |> MapExt.neighboursV requestedSize with
+ | struct (_, ValueSome (struct (_, palette)), _)
+ | struct (_, _, ValueSome (struct (_, palette))) ->
+ palette
+
+ | struct (ValueSome (struct (max, _)), _, _) ->
+ raise <| ArgumentOutOfRangeException("requestedSize", $"Scheme {x.Name} has a maximum palette size of {max} (requested {requestedSize}).")
+
+ | struct (ValueNone, ValueNone, ValueNone) ->
+ raise <| ArgumentException($"Scheme {x.Name} is empty.")
+
+ []
+ module Scheme =
+
+ /// Returns whether the scheme is empty (i.e. has no palettes).
+ let inline isEmpty (scheme : Scheme) =
+ scheme.IsEmpty
+
+ /// Return the size of the smallest palette for the given scheme.
+ let inline minSize (scheme : Scheme) =
+ scheme.MinSize
+
+ /// Return the size of the largest palette for the given scheme.
+ let inline maxSize (scheme : Scheme) =
+ scheme.MaxSize
+
+ /// Gets the palette with the given size.
+ /// If the scheme is not defined for the requested size, gets the next larger palette.
+ /// Throws an exception if the requested size is greater than the maximum size.
+ let inline getPalette (requestedSize : int) (scheme : Scheme) =
+ scheme.[requestedSize]
+
+ /// Returns a new scheme containing only the palettes for which the predicate returns true.
+ let inline filter (predicate : Palette -> bool) (scheme : Scheme) =
+ { scheme with Palettes = scheme.Palettes |> MapExt.filter (fun _ -> predicate) }
+
+ /// Returns a new scheme containing only the palettes with the given usage flags.
+ let inline filterUsage (usage : PaletteUsage) (scheme : Scheme) =
+ scheme |> filter (fun p -> p.Usage &&& usage = usage)
\ No newline at end of file
diff --git a/src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fs b/src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fs
new file mode 100644
index 000000000..2a22cc682
--- /dev/null
+++ b/src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fs
@@ -0,0 +1,1924 @@
+namespace Aardvark.Base
+
+[]
+module ColorBrewerSchemes =
+ open ColorBrewer
+
+ /// Brewer color schemes designed for choropleth map visualizations.
+ module ColorBrewer =
+
+ module Scheme =
+
+ /// Diverging schemes put equal emphasis on mid-range critical values and extremes at both ends of the data range.
+ /// The critical class or break in the middle of the legend is emphasized with light colors and low and high extremes are
+ /// emphasized with dark colors that have contrasting hues.
+ module Diverging =
+
+ let Spectral =
+ {
+ Name = Sym.ofString "Spectral"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(252uy,141uy,89uy); C3b(255uy,255uy,191uy); C3b(153uy,213uy,148uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(171uy,221uy,164uy); C3b(43uy,131uy,186uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(255uy,255uy,191uy); C3b(171uy,221uy,164uy)
+ C3b(43uy,131uy,186uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(213uy,62uy,79uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(230uy,245uy,152uy)
+ C3b(153uy,213uy,148uy); C3b(50uy,136uy,189uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(213uy,62uy,79uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy)
+ C3b(230uy,245uy,152uy); C3b(153uy,213uy,148uy); C3b(50uy,136uy,189uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)
+ C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy); C3b(102uy,194uy,165uy); C3b(50uy,136uy,189uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)
+ C3b(255uy,255uy,191uy); C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy); C3b(102uy,194uy,165uy)
+ C3b(50uy,136uy,189uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(158uy,1uy,66uy); C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)
+ C3b(254uy,224uy,139uy); C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy); C3b(102uy,194uy,165uy)
+ C3b(50uy,136uy,189uy); C3b(94uy,79uy,162uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(158uy,1uy,66uy); C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)
+ C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy); C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy)
+ C3b(102uy,194uy,165uy); C3b(50uy,136uy,189uy); C3b(94uy,79uy,162uy) |]
+ }
+
+ ]
+ }
+
+ let RdYlGn =
+ {
+ Name = Sym.ofString "RdYlGn"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(252uy,141uy,89uy); C3b(255uy,255uy,191uy); C3b(145uy,207uy,96uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(166uy,217uy,106uy); C3b(26uy,150uy,65uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(255uy,255uy,191uy); C3b(166uy,217uy,106uy)
+ C3b(26uy,150uy,65uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(217uy,239uy,139uy)
+ C3b(145uy,207uy,96uy); C3b(26uy,152uy,80uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy)
+ C3b(217uy,239uy,139uy); C3b(145uy,207uy,96uy); C3b(26uy,152uy,80uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)
+ C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy); C3b(102uy,189uy,99uy); C3b(26uy,152uy,80uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)
+ C3b(255uy,255uy,191uy); C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy); C3b(102uy,189uy,99uy)
+ C3b(26uy,152uy,80uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)
+ C3b(254uy,224uy,139uy); C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy); C3b(102uy,189uy,99uy)
+ C3b(26uy,152uy,80uy); C3b(0uy,104uy,55uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)
+ C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy); C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy)
+ C3b(102uy,189uy,99uy); C3b(26uy,152uy,80uy); C3b(0uy,104uy,55uy) |]
+ }
+
+ ]
+ }
+
+ let RdBu =
+ {
+ Name = Sym.ofString "RdBu"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(239uy,138uy,98uy); C3b(247uy,247uy,247uy); C3b(103uy,169uy,207uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(146uy,197uy,222uy); C3b(5uy,113uy,176uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(247uy,247uy,247uy); C3b(146uy,197uy,222uy)
+ C3b(5uy,113uy,176uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(209uy,229uy,240uy)
+ C3b(103uy,169uy,207uy); C3b(33uy,102uy,172uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(247uy,247uy,247uy)
+ C3b(209uy,229uy,240uy); C3b(103uy,169uy,207uy); C3b(33uy,102uy,172uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)
+ C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy); C3b(67uy,147uy,195uy); C3b(33uy,102uy,172uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)
+ C3b(247uy,247uy,247uy); C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy); C3b(67uy,147uy,195uy)
+ C3b(33uy,102uy,172uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)
+ C3b(253uy,219uy,199uy); C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy); C3b(67uy,147uy,195uy)
+ C3b(33uy,102uy,172uy); C3b(5uy,48uy,97uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)
+ C3b(253uy,219uy,199uy); C3b(247uy,247uy,247uy); C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy)
+ C3b(67uy,147uy,195uy); C3b(33uy,102uy,172uy); C3b(5uy,48uy,97uy) |]
+ }
+
+ ]
+ }
+
+ let PiYG =
+ {
+ Name = Sym.ofString "PiYG"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(233uy,163uy,201uy); C3b(247uy,247uy,247uy); C3b(161uy,215uy,106uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(208uy,28uy,139uy); C3b(241uy,182uy,218uy); C3b(184uy,225uy,134uy); C3b(77uy,172uy,38uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(208uy,28uy,139uy); C3b(241uy,182uy,218uy); C3b(247uy,247uy,247uy); C3b(184uy,225uy,134uy)
+ C3b(77uy,172uy,38uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(197uy,27uy,125uy); C3b(233uy,163uy,201uy); C3b(253uy,224uy,239uy); C3b(230uy,245uy,208uy)
+ C3b(161uy,215uy,106uy); C3b(77uy,146uy,33uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(197uy,27uy,125uy); C3b(233uy,163uy,201uy); C3b(253uy,224uy,239uy); C3b(247uy,247uy,247uy)
+ C3b(230uy,245uy,208uy); C3b(161uy,215uy,106uy); C3b(77uy,146uy,33uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy); C3b(253uy,224uy,239uy)
+ C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy); C3b(127uy,188uy,65uy); C3b(77uy,146uy,33uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy); C3b(253uy,224uy,239uy)
+ C3b(247uy,247uy,247uy); C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy); C3b(127uy,188uy,65uy)
+ C3b(77uy,146uy,33uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(142uy,1uy,82uy); C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy)
+ C3b(253uy,224uy,239uy); C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy); C3b(127uy,188uy,65uy)
+ C3b(77uy,146uy,33uy); C3b(39uy,100uy,25uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(142uy,1uy,82uy); C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy)
+ C3b(253uy,224uy,239uy); C3b(247uy,247uy,247uy); C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy)
+ C3b(127uy,188uy,65uy); C3b(77uy,146uy,33uy); C3b(39uy,100uy,25uy) |]
+ }
+
+ ]
+ }
+
+ let PRGn =
+ {
+ Name = Sym.ofString "PRGn"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(175uy,141uy,195uy); C3b(247uy,247uy,247uy); C3b(127uy,191uy,123uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(123uy,50uy,148uy); C3b(194uy,165uy,207uy); C3b(166uy,219uy,160uy); C3b(0uy,136uy,55uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(123uy,50uy,148uy); C3b(194uy,165uy,207uy); C3b(247uy,247uy,247uy); C3b(166uy,219uy,160uy)
+ C3b(0uy,136uy,55uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(118uy,42uy,131uy); C3b(175uy,141uy,195uy); C3b(231uy,212uy,232uy); C3b(217uy,240uy,211uy)
+ C3b(127uy,191uy,123uy); C3b(27uy,120uy,55uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(118uy,42uy,131uy); C3b(175uy,141uy,195uy); C3b(231uy,212uy,232uy); C3b(247uy,247uy,247uy)
+ C3b(217uy,240uy,211uy); C3b(127uy,191uy,123uy); C3b(27uy,120uy,55uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy); C3b(231uy,212uy,232uy)
+ C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy); C3b(90uy,174uy,97uy); C3b(27uy,120uy,55uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy); C3b(231uy,212uy,232uy)
+ C3b(247uy,247uy,247uy); C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy); C3b(90uy,174uy,97uy)
+ C3b(27uy,120uy,55uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(64uy,0uy,75uy); C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy)
+ C3b(231uy,212uy,232uy); C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy); C3b(90uy,174uy,97uy)
+ C3b(27uy,120uy,55uy); C3b(0uy,68uy,27uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(64uy,0uy,75uy); C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy)
+ C3b(231uy,212uy,232uy); C3b(247uy,247uy,247uy); C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy)
+ C3b(90uy,174uy,97uy); C3b(27uy,120uy,55uy); C3b(0uy,68uy,27uy) |]
+ }
+
+ ]
+ }
+
+ let RdYlBu =
+ {
+ Name = Sym.ofString "RdYlBu"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(252uy,141uy,89uy); C3b(255uy,255uy,191uy); C3b(145uy,191uy,219uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(171uy,217uy,233uy); C3b(44uy,123uy,182uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(255uy,255uy,191uy); C3b(171uy,217uy,233uy)
+ C3b(44uy,123uy,182uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,144uy); C3b(224uy,243uy,248uy)
+ C3b(145uy,191uy,219uy); C3b(69uy,117uy,180uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,144uy); C3b(255uy,255uy,191uy)
+ C3b(224uy,243uy,248uy); C3b(145uy,191uy,219uy); C3b(69uy,117uy,180uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,144uy)
+ C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy); C3b(116uy,173uy,209uy); C3b(69uy,117uy,180uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,144uy)
+ C3b(255uy,255uy,191uy); C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy); C3b(116uy,173uy,209uy)
+ C3b(69uy,117uy,180uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)
+ C3b(254uy,224uy,144uy); C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy); C3b(116uy,173uy,209uy)
+ C3b(69uy,117uy,180uy); C3b(49uy,54uy,149uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)
+ C3b(254uy,224uy,144uy); C3b(255uy,255uy,191uy); C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy)
+ C3b(116uy,173uy,209uy); C3b(69uy,117uy,180uy); C3b(49uy,54uy,149uy) |]
+ }
+
+ ]
+ }
+
+ let BrBG =
+ {
+ Name = Sym.ofString "BrBG"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(216uy,179uy,101uy); C3b(245uy,245uy,245uy); C3b(90uy,180uy,172uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(166uy,97uy,26uy); C3b(223uy,194uy,125uy); C3b(128uy,205uy,193uy); C3b(1uy,133uy,113uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(166uy,97uy,26uy); C3b(223uy,194uy,125uy); C3b(245uy,245uy,245uy); C3b(128uy,205uy,193uy)
+ C3b(1uy,133uy,113uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(140uy,81uy,10uy); C3b(216uy,179uy,101uy); C3b(246uy,232uy,195uy); C3b(199uy,234uy,229uy)
+ C3b(90uy,180uy,172uy); C3b(1uy,102uy,94uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(140uy,81uy,10uy); C3b(216uy,179uy,101uy); C3b(246uy,232uy,195uy); C3b(245uy,245uy,245uy)
+ C3b(199uy,234uy,229uy); C3b(90uy,180uy,172uy); C3b(1uy,102uy,94uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy); C3b(246uy,232uy,195uy)
+ C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy); C3b(53uy,151uy,143uy); C3b(1uy,102uy,94uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy); C3b(246uy,232uy,195uy)
+ C3b(245uy,245uy,245uy); C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy); C3b(53uy,151uy,143uy)
+ C3b(1uy,102uy,94uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(84uy,48uy,5uy); C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy)
+ C3b(246uy,232uy,195uy); C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy); C3b(53uy,151uy,143uy)
+ C3b(1uy,102uy,94uy); C3b(0uy,60uy,48uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(84uy,48uy,5uy); C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy)
+ C3b(246uy,232uy,195uy); C3b(245uy,245uy,245uy); C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy)
+ C3b(53uy,151uy,143uy); C3b(1uy,102uy,94uy); C3b(0uy,60uy,48uy) |]
+ }
+
+ ]
+ }
+
+ let RdGy =
+ {
+ Name = Sym.ofString "RdGy"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(239uy,138uy,98uy); C3b(255uy,255uy,255uy); C3b(153uy,153uy,153uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(186uy,186uy,186uy); C3b(64uy,64uy,64uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print
+ Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(255uy,255uy,255uy); C3b(186uy,186uy,186uy)
+ C3b(64uy,64uy,64uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(224uy,224uy,224uy)
+ C3b(153uy,153uy,153uy); C3b(77uy,77uy,77uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(255uy,255uy,255uy)
+ C3b(224uy,224uy,224uy); C3b(153uy,153uy,153uy); C3b(77uy,77uy,77uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)
+ C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy); C3b(135uy,135uy,135uy); C3b(77uy,77uy,77uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)
+ C3b(255uy,255uy,255uy); C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy); C3b(135uy,135uy,135uy)
+ C3b(77uy,77uy,77uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)
+ C3b(253uy,219uy,199uy); C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy); C3b(135uy,135uy,135uy)
+ C3b(77uy,77uy,77uy); C3b(26uy,26uy,26uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)
+ C3b(253uy,219uy,199uy); C3b(255uy,255uy,255uy); C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy)
+ C3b(135uy,135uy,135uy); C3b(77uy,77uy,77uy); C3b(26uy,26uy,26uy) |]
+ }
+
+ ]
+ }
+
+ let PuOr =
+ {
+ Name = Sym.ofString "PuOr"
+ Type = SchemeType.Diverging
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(241uy,163uy,64uy); C3b(247uy,247uy,247uy); C3b(153uy,142uy,195uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(230uy,97uy,1uy); C3b(253uy,184uy,99uy); C3b(178uy,171uy,210uy); C3b(94uy,60uy,153uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(230uy,97uy,1uy); C3b(253uy,184uy,99uy); C3b(247uy,247uy,247uy); C3b(178uy,171uy,210uy)
+ C3b(94uy,60uy,153uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(179uy,88uy,6uy); C3b(241uy,163uy,64uy); C3b(254uy,224uy,182uy); C3b(216uy,218uy,235uy)
+ C3b(153uy,142uy,195uy); C3b(84uy,39uy,136uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(179uy,88uy,6uy); C3b(241uy,163uy,64uy); C3b(254uy,224uy,182uy); C3b(247uy,247uy,247uy)
+ C3b(216uy,218uy,235uy); C3b(153uy,142uy,195uy); C3b(84uy,39uy,136uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy); C3b(254uy,224uy,182uy)
+ C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy); C3b(128uy,115uy,172uy); C3b(84uy,39uy,136uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy); C3b(254uy,224uy,182uy)
+ C3b(247uy,247uy,247uy); C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy); C3b(128uy,115uy,172uy)
+ C3b(84uy,39uy,136uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(127uy,59uy,8uy); C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy)
+ C3b(254uy,224uy,182uy); C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy); C3b(128uy,115uy,172uy)
+ C3b(84uy,39uy,136uy); C3b(45uy,0uy,75uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(127uy,59uy,8uy); C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy)
+ C3b(254uy,224uy,182uy); C3b(247uy,247uy,247uy); C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy)
+ C3b(128uy,115uy,172uy); C3b(84uy,39uy,136uy); C3b(45uy,0uy,75uy) |]
+ }
+
+ ]
+ }
+
+ /// Qualitative schemes do not imply magnitude differences between legend classes, and hues are used to
+ /// create the primary visual differences between classes. Qualitative schemes are best suited to representing nominal or categorical data.
+ module Qualitative =
+
+ let Set2 =
+ {
+ Name = Sym.ofString "Set2"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print
+ Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)
+ C3b(166uy,216uy,84uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)
+ C3b(166uy,216uy,84uy); C3b(255uy,217uy,47uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)
+ C3b(166uy,216uy,84uy); C3b(255uy,217uy,47uy); C3b(229uy,196uy,148uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)
+ C3b(166uy,216uy,84uy); C3b(255uy,217uy,47uy); C3b(229uy,196uy,148uy); C3b(179uy,179uy,179uy) |]
+ }
+
+ ]
+ }
+
+ let Accent =
+ {
+ Name = Sym.ofString "Accent"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.LCD
+ Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)
+ C3b(56uy,108uy,176uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)
+ C3b(56uy,108uy,176uy); C3b(240uy,2uy,127uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)
+ C3b(56uy,108uy,176uy); C3b(240uy,2uy,127uy); C3b(191uy,91uy,23uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)
+ C3b(56uy,108uy,176uy); C3b(240uy,2uy,127uy); C3b(191uy,91uy,23uy); C3b(102uy,102uy,102uy) |]
+ }
+
+ ]
+ }
+
+ let Set1 =
+ {
+ Name = Sym.ofString "Set1"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)
+ C3b(255uy,127uy,0uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)
+ C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)
+ C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy); C3b(166uy,86uy,40uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)
+ C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy); C3b(166uy,86uy,40uy); C3b(247uy,129uy,191uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)
+ C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy); C3b(166uy,86uy,40uy); C3b(247uy,129uy,191uy)
+ C3b(153uy,153uy,153uy) |]
+ }
+
+ ]
+ }
+
+ let Set3 =
+ {
+ Name = Sym.ofString "Set3"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.Print
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.Print
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.Print
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)
+ C3b(217uy,217uy,217uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)
+ C3b(217uy,217uy,217uy); C3b(188uy,128uy,189uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)
+ C3b(217uy,217uy,217uy); C3b(188uy,128uy,189uy); C3b(204uy,235uy,197uy) |]
+ }
+
+ 12, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)
+ C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)
+ C3b(217uy,217uy,217uy); C3b(188uy,128uy,189uy); C3b(204uy,235uy,197uy); C3b(255uy,237uy,111uy) |]
+ }
+
+ ]
+ }
+
+ let Dark2 =
+ {
+ Name = Sym.ofString "Dark2"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)
+ C3b(102uy,166uy,30uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)
+ C3b(102uy,166uy,30uy); C3b(230uy,171uy,2uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)
+ C3b(102uy,166uy,30uy); C3b(230uy,171uy,2uy); C3b(166uy,118uy,29uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)
+ C3b(102uy,166uy,30uy); C3b(230uy,171uy,2uy); C3b(166uy,118uy,29uy); C3b(102uy,102uy,102uy) |]
+ }
+
+ ]
+ }
+
+ let Paired =
+ {
+ Name = Sym.ofString "Paired"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)
+ C3b(202uy,178uy,214uy) |]
+ }
+
+ 10, {
+ Usage = PaletteUsage.LCD
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)
+ C3b(202uy,178uy,214uy); C3b(106uy,61uy,154uy) |]
+ }
+
+ 11, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)
+ C3b(202uy,178uy,214uy); C3b(106uy,61uy,154uy); C3b(255uy,255uy,153uy) |]
+ }
+
+ 12, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)
+ C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)
+ C3b(202uy,178uy,214uy); C3b(106uy,61uy,154uy); C3b(255uy,255uy,153uy); C3b(177uy,89uy,40uy) |]
+ }
+
+ ]
+ }
+
+ let Pastel2 =
+ {
+ Name = Sym.ofString "Pastel2"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)
+ C3b(230uy,245uy,201uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)
+ C3b(230uy,245uy,201uy); C3b(255uy,242uy,174uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)
+ C3b(230uy,245uy,201uy); C3b(255uy,242uy,174uy); C3b(241uy,226uy,204uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)
+ C3b(230uy,245uy,201uy); C3b(255uy,242uy,174uy); C3b(241uy,226uy,204uy); C3b(204uy,204uy,204uy) |]
+ }
+
+ ]
+ }
+
+ let Pastel1 =
+ {
+ Name = Sym.ofString "Pastel1"
+ Type = SchemeType.Qualitative
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)
+ C3b(254uy,217uy,166uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)
+ C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)
+ C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy); C3b(229uy,216uy,189uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)
+ C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy); C3b(229uy,216uy,189uy); C3b(253uy,218uy,236uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.None
+ Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)
+ C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy); C3b(229uy,216uy,189uy); C3b(253uy,218uy,236uy)
+ C3b(242uy,242uy,242uy) |]
+ }
+
+ ]
+ }
+
+ /// Sequential schemes are suited to ordered data that progress from low to high.
+ /// Lightness steps dominate the look of these schemes, with light colors for low data values to dark colors for high data values.
+ module Sequential =
+
+ let OrRd =
+ {
+ Name = Sym.ofString "OrRd"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(254uy,232uy,200uy); C3b(253uy,187uy,132uy); C3b(227uy,74uy,51uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,204uy,138uy); C3b(252uy,141uy,89uy); C3b(215uy,48uy,31uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,204uy,138uy); C3b(252uy,141uy,89uy); C3b(227uy,74uy,51uy)
+ C3b(179uy,0uy,0uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy); C3b(252uy,141uy,89uy)
+ C3b(227uy,74uy,51uy); C3b(179uy,0uy,0uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy); C3b(252uy,141uy,89uy)
+ C3b(239uy,101uy,72uy); C3b(215uy,48uy,31uy); C3b(153uy,0uy,0uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,236uy); C3b(254uy,232uy,200uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy)
+ C3b(252uy,141uy,89uy); C3b(239uy,101uy,72uy); C3b(215uy,48uy,31uy); C3b(153uy,0uy,0uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,236uy); C3b(254uy,232uy,200uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy)
+ C3b(252uy,141uy,89uy); C3b(239uy,101uy,72uy); C3b(215uy,48uy,31uy); C3b(179uy,0uy,0uy)
+ C3b(127uy,0uy,0uy) |]
+ }
+
+ ]
+ }
+
+ let PuBu =
+ {
+ Name = Sym.ofString "PuBu"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(236uy,231uy,242uy); C3b(166uy,189uy,219uy); C3b(43uy,140uy,190uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(241uy,238uy,246uy); C3b(189uy,201uy,225uy); C3b(116uy,169uy,207uy); C3b(5uy,112uy,176uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(241uy,238uy,246uy); C3b(189uy,201uy,225uy); C3b(116uy,169uy,207uy); C3b(43uy,140uy,190uy)
+ C3b(4uy,90uy,141uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(241uy,238uy,246uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(116uy,169uy,207uy)
+ C3b(43uy,140uy,190uy); C3b(4uy,90uy,141uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(241uy,238uy,246uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(116uy,169uy,207uy)
+ C3b(54uy,144uy,192uy); C3b(5uy,112uy,176uy); C3b(3uy,78uy,123uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,231uy,242uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)
+ C3b(116uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(5uy,112uy,176uy); C3b(3uy,78uy,123uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,231uy,242uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)
+ C3b(116uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(5uy,112uy,176uy); C3b(4uy,90uy,141uy)
+ C3b(2uy,56uy,88uy) |]
+ }
+
+ ]
+ }
+
+ let BuPu =
+ {
+ Name = Sym.ofString "BuPu"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(224uy,236uy,244uy); C3b(158uy,188uy,218uy); C3b(136uy,86uy,167uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(237uy,248uy,251uy); C3b(179uy,205uy,227uy); C3b(140uy,150uy,198uy); C3b(136uy,65uy,157uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(237uy,248uy,251uy); C3b(179uy,205uy,227uy); C3b(140uy,150uy,198uy); C3b(136uy,86uy,167uy)
+ C3b(129uy,15uy,124uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,251uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy); C3b(140uy,150uy,198uy)
+ C3b(136uy,86uy,167uy); C3b(129uy,15uy,124uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,251uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy); C3b(140uy,150uy,198uy)
+ C3b(140uy,107uy,177uy); C3b(136uy,65uy,157uy); C3b(110uy,1uy,107uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,253uy); C3b(224uy,236uy,244uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy)
+ C3b(140uy,150uy,198uy); C3b(140uy,107uy,177uy); C3b(136uy,65uy,157uy); C3b(110uy,1uy,107uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,253uy); C3b(224uy,236uy,244uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy)
+ C3b(140uy,150uy,198uy); C3b(140uy,107uy,177uy); C3b(136uy,65uy,157uy); C3b(129uy,15uy,124uy)
+ C3b(77uy,0uy,75uy) |]
+ }
+
+ ]
+ }
+
+ let Oranges =
+ {
+ Name = Sym.ofString "Oranges"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(254uy,230uy,206uy); C3b(253uy,174uy,107uy); C3b(230uy,85uy,13uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,190uy,133uy); C3b(253uy,141uy,60uy); C3b(217uy,71uy,1uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,190uy,133uy); C3b(253uy,141uy,60uy); C3b(230uy,85uy,13uy)
+ C3b(166uy,54uy,3uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy); C3b(253uy,141uy,60uy)
+ C3b(230uy,85uy,13uy); C3b(166uy,54uy,3uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy); C3b(253uy,141uy,60uy)
+ C3b(241uy,105uy,19uy); C3b(217uy,72uy,1uy); C3b(140uy,45uy,4uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,245uy,235uy); C3b(254uy,230uy,206uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy)
+ C3b(253uy,141uy,60uy); C3b(241uy,105uy,19uy); C3b(217uy,72uy,1uy); C3b(140uy,45uy,4uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,245uy,235uy); C3b(254uy,230uy,206uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy)
+ C3b(253uy,141uy,60uy); C3b(241uy,105uy,19uy); C3b(217uy,72uy,1uy); C3b(166uy,54uy,3uy)
+ C3b(127uy,39uy,4uy) |]
+ }
+
+ ]
+ }
+
+ let BuGn =
+ {
+ Name = Sym.ofString "BuGn"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(229uy,245uy,249uy); C3b(153uy,216uy,201uy); C3b(44uy,162uy,95uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(237uy,248uy,251uy); C3b(178uy,226uy,226uy); C3b(102uy,194uy,164uy); C3b(35uy,139uy,69uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,251uy); C3b(178uy,226uy,226uy); C3b(102uy,194uy,164uy); C3b(44uy,162uy,95uy)
+ C3b(0uy,109uy,44uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,251uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy); C3b(102uy,194uy,164uy)
+ C3b(44uy,162uy,95uy); C3b(0uy,109uy,44uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,251uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy); C3b(102uy,194uy,164uy)
+ C3b(65uy,174uy,118uy); C3b(35uy,139uy,69uy); C3b(0uy,88uy,36uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,253uy); C3b(229uy,245uy,249uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy)
+ C3b(102uy,194uy,164uy); C3b(65uy,174uy,118uy); C3b(35uy,139uy,69uy); C3b(0uy,88uy,36uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,253uy); C3b(229uy,245uy,249uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy)
+ C3b(102uy,194uy,164uy); C3b(65uy,174uy,118uy); C3b(35uy,139uy,69uy); C3b(0uy,109uy,44uy)
+ C3b(0uy,68uy,27uy) |]
+ }
+
+ ]
+ }
+
+ let YlOrBr =
+ {
+ Name = Sym.ofString "YlOrBr"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(255uy,247uy,188uy); C3b(254uy,196uy,79uy); C3b(217uy,95uy,14uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,217uy,142uy); C3b(254uy,153uy,41uy); C3b(204uy,76uy,2uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,217uy,142uy); C3b(254uy,153uy,41uy); C3b(217uy,95uy,14uy)
+ C3b(153uy,52uy,4uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy); C3b(254uy,153uy,41uy)
+ C3b(217uy,95uy,14uy); C3b(153uy,52uy,4uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy); C3b(254uy,153uy,41uy)
+ C3b(236uy,112uy,20uy); C3b(204uy,76uy,2uy); C3b(140uy,45uy,4uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,229uy); C3b(255uy,247uy,188uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy)
+ C3b(254uy,153uy,41uy); C3b(236uy,112uy,20uy); C3b(204uy,76uy,2uy); C3b(140uy,45uy,4uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,229uy); C3b(255uy,247uy,188uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy)
+ C3b(254uy,153uy,41uy); C3b(236uy,112uy,20uy); C3b(204uy,76uy,2uy); C3b(153uy,52uy,4uy)
+ C3b(102uy,37uy,6uy) |]
+ }
+
+ ]
+ }
+
+ let YlGn =
+ {
+ Name = Sym.ofString "YlGn"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(247uy,252uy,185uy); C3b(173uy,221uy,142uy); C3b(49uy,163uy,84uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(255uy,255uy,204uy); C3b(194uy,230uy,153uy); C3b(120uy,198uy,121uy); C3b(35uy,132uy,67uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(255uy,255uy,204uy); C3b(194uy,230uy,153uy); C3b(120uy,198uy,121uy); C3b(49uy,163uy,84uy)
+ C3b(0uy,104uy,55uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,204uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy); C3b(120uy,198uy,121uy)
+ C3b(49uy,163uy,84uy); C3b(0uy,104uy,55uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,204uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy); C3b(120uy,198uy,121uy)
+ C3b(65uy,171uy,93uy); C3b(35uy,132uy,67uy); C3b(0uy,90uy,50uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,229uy); C3b(247uy,252uy,185uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy)
+ C3b(120uy,198uy,121uy); C3b(65uy,171uy,93uy); C3b(35uy,132uy,67uy); C3b(0uy,90uy,50uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,229uy); C3b(247uy,252uy,185uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy)
+ C3b(120uy,198uy,121uy); C3b(65uy,171uy,93uy); C3b(35uy,132uy,67uy); C3b(0uy,104uy,55uy)
+ C3b(0uy,69uy,41uy) |]
+ }
+
+ ]
+ }
+
+ let Reds =
+ {
+ Name = Sym.ofString "Reds"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(254uy,224uy,210uy); C3b(252uy,146uy,114uy); C3b(222uy,45uy,38uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,174uy,145uy); C3b(251uy,106uy,74uy); C3b(203uy,24uy,29uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,174uy,145uy); C3b(251uy,106uy,74uy); C3b(222uy,45uy,38uy)
+ C3b(165uy,15uy,21uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy); C3b(251uy,106uy,74uy)
+ C3b(222uy,45uy,38uy); C3b(165uy,15uy,21uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy); C3b(251uy,106uy,74uy)
+ C3b(239uy,59uy,44uy); C3b(203uy,24uy,29uy); C3b(153uy,0uy,13uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,245uy,240uy); C3b(254uy,224uy,210uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy)
+ C3b(251uy,106uy,74uy); C3b(239uy,59uy,44uy); C3b(203uy,24uy,29uy); C3b(153uy,0uy,13uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,245uy,240uy); C3b(254uy,224uy,210uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy)
+ C3b(251uy,106uy,74uy); C3b(239uy,59uy,44uy); C3b(203uy,24uy,29uy); C3b(165uy,15uy,21uy)
+ C3b(103uy,0uy,13uy) |]
+ }
+
+ ]
+ }
+
+ let RdPu =
+ {
+ Name = Sym.ofString "RdPu"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(253uy,224uy,221uy); C3b(250uy,159uy,181uy); C3b(197uy,27uy,138uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(254uy,235uy,226uy); C3b(251uy,180uy,185uy); C3b(247uy,104uy,161uy); C3b(174uy,1uy,126uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(254uy,235uy,226uy); C3b(251uy,180uy,185uy); C3b(247uy,104uy,161uy); C3b(197uy,27uy,138uy)
+ C3b(122uy,1uy,119uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,235uy,226uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy); C3b(247uy,104uy,161uy)
+ C3b(197uy,27uy,138uy); C3b(122uy,1uy,119uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(254uy,235uy,226uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy); C3b(247uy,104uy,161uy)
+ C3b(221uy,52uy,151uy); C3b(174uy,1uy,126uy); C3b(122uy,1uy,119uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,243uy); C3b(253uy,224uy,221uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy)
+ C3b(247uy,104uy,161uy); C3b(221uy,52uy,151uy); C3b(174uy,1uy,126uy); C3b(122uy,1uy,119uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,243uy); C3b(253uy,224uy,221uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy)
+ C3b(247uy,104uy,161uy); C3b(221uy,52uy,151uy); C3b(174uy,1uy,126uy); C3b(122uy,1uy,119uy)
+ C3b(73uy,0uy,106uy) |]
+ }
+
+ ]
+ }
+
+ let Greens =
+ {
+ Name = Sym.ofString "Greens"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(229uy,245uy,224uy); C3b(161uy,217uy,155uy); C3b(49uy,163uy,84uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,233uy); C3b(186uy,228uy,179uy); C3b(116uy,196uy,118uy); C3b(35uy,139uy,69uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,233uy); C3b(186uy,228uy,179uy); C3b(116uy,196uy,118uy); C3b(49uy,163uy,84uy)
+ C3b(0uy,109uy,44uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,233uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy); C3b(116uy,196uy,118uy)
+ C3b(49uy,163uy,84uy); C3b(0uy,109uy,44uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(237uy,248uy,233uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy); C3b(116uy,196uy,118uy)
+ C3b(65uy,171uy,93uy); C3b(35uy,139uy,69uy); C3b(0uy,90uy,50uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,245uy); C3b(229uy,245uy,224uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy)
+ C3b(116uy,196uy,118uy); C3b(65uy,171uy,93uy); C3b(35uy,139uy,69uy); C3b(0uy,90uy,50uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,245uy); C3b(229uy,245uy,224uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy)
+ C3b(116uy,196uy,118uy); C3b(65uy,171uy,93uy); C3b(35uy,139uy,69uy); C3b(0uy,109uy,44uy)
+ C3b(0uy,68uy,27uy) |]
+ }
+
+ ]
+ }
+
+ let YlGnBu =
+ {
+ Name = Sym.ofString "YlGnBu"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(237uy,248uy,177uy); C3b(127uy,205uy,187uy); C3b(44uy,127uy,184uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(255uy,255uy,204uy); C3b(161uy,218uy,180uy); C3b(65uy,182uy,196uy); C3b(34uy,94uy,168uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(255uy,255uy,204uy); C3b(161uy,218uy,180uy); C3b(65uy,182uy,196uy); C3b(44uy,127uy,184uy)
+ C3b(37uy,52uy,148uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,204uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy); C3b(65uy,182uy,196uy)
+ C3b(44uy,127uy,184uy); C3b(37uy,52uy,148uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,204uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy); C3b(65uy,182uy,196uy)
+ C3b(29uy,145uy,192uy); C3b(34uy,94uy,168uy); C3b(12uy,44uy,132uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,217uy); C3b(237uy,248uy,177uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy)
+ C3b(65uy,182uy,196uy); C3b(29uy,145uy,192uy); C3b(34uy,94uy,168uy); C3b(12uy,44uy,132uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,217uy); C3b(237uy,248uy,177uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy)
+ C3b(65uy,182uy,196uy); C3b(29uy,145uy,192uy); C3b(34uy,94uy,168uy); C3b(37uy,52uy,148uy)
+ C3b(8uy,29uy,88uy) |]
+ }
+
+ ]
+ }
+
+ let Purples =
+ {
+ Name = Sym.ofString "Purples"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(239uy,237uy,245uy); C3b(188uy,189uy,220uy); C3b(117uy,107uy,177uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(242uy,240uy,247uy); C3b(203uy,201uy,226uy); C3b(158uy,154uy,200uy); C3b(106uy,81uy,163uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(242uy,240uy,247uy); C3b(203uy,201uy,226uy); C3b(158uy,154uy,200uy); C3b(117uy,107uy,177uy)
+ C3b(84uy,39uy,143uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(242uy,240uy,247uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy); C3b(158uy,154uy,200uy)
+ C3b(117uy,107uy,177uy); C3b(84uy,39uy,143uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(242uy,240uy,247uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy); C3b(158uy,154uy,200uy)
+ C3b(128uy,125uy,186uy); C3b(106uy,81uy,163uy); C3b(74uy,20uy,134uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(252uy,251uy,253uy); C3b(239uy,237uy,245uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy)
+ C3b(158uy,154uy,200uy); C3b(128uy,125uy,186uy); C3b(106uy,81uy,163uy); C3b(74uy,20uy,134uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(252uy,251uy,253uy); C3b(239uy,237uy,245uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy)
+ C3b(158uy,154uy,200uy); C3b(128uy,125uy,186uy); C3b(106uy,81uy,163uy); C3b(84uy,39uy,143uy)
+ C3b(63uy,0uy,125uy) |]
+ }
+
+ ]
+ }
+
+ let GnBu =
+ {
+ Name = Sym.ofString "GnBu"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(224uy,243uy,219uy); C3b(168uy,221uy,181uy); C3b(67uy,162uy,202uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(240uy,249uy,232uy); C3b(186uy,228uy,188uy); C3b(123uy,204uy,196uy); C3b(43uy,140uy,190uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(240uy,249uy,232uy); C3b(186uy,228uy,188uy); C3b(123uy,204uy,196uy); C3b(67uy,162uy,202uy)
+ C3b(8uy,104uy,172uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(240uy,249uy,232uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy); C3b(123uy,204uy,196uy)
+ C3b(67uy,162uy,202uy); C3b(8uy,104uy,172uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(240uy,249uy,232uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy); C3b(123uy,204uy,196uy)
+ C3b(78uy,179uy,211uy); C3b(43uy,140uy,190uy); C3b(8uy,88uy,158uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,240uy); C3b(224uy,243uy,219uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy)
+ C3b(123uy,204uy,196uy); C3b(78uy,179uy,211uy); C3b(43uy,140uy,190uy); C3b(8uy,88uy,158uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,252uy,240uy); C3b(224uy,243uy,219uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy)
+ C3b(123uy,204uy,196uy); C3b(78uy,179uy,211uy); C3b(43uy,140uy,190uy); C3b(8uy,104uy,172uy)
+ C3b(8uy,64uy,129uy) |]
+ }
+
+ ]
+ }
+
+ let Greys =
+ {
+ Name = Sym.ofString "Greys"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(240uy,240uy,240uy); C3b(189uy,189uy,189uy); C3b(99uy,99uy,99uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(247uy,247uy,247uy); C3b(204uy,204uy,204uy); C3b(150uy,150uy,150uy); C3b(82uy,82uy,82uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,247uy,247uy); C3b(204uy,204uy,204uy); C3b(150uy,150uy,150uy); C3b(99uy,99uy,99uy)
+ C3b(37uy,37uy,37uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,247uy,247uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy); C3b(150uy,150uy,150uy)
+ C3b(99uy,99uy,99uy); C3b(37uy,37uy,37uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,247uy,247uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy); C3b(150uy,150uy,150uy)
+ C3b(115uy,115uy,115uy); C3b(82uy,82uy,82uy); C3b(37uy,37uy,37uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,255uy); C3b(240uy,240uy,240uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy)
+ C3b(150uy,150uy,150uy); C3b(115uy,115uy,115uy); C3b(82uy,82uy,82uy); C3b(37uy,37uy,37uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,255uy); C3b(240uy,240uy,240uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy)
+ C3b(150uy,150uy,150uy); C3b(115uy,115uy,115uy); C3b(82uy,82uy,82uy); C3b(37uy,37uy,37uy)
+ C3b(0uy,0uy,0uy) |]
+ }
+
+ ]
+ }
+
+ let YlOrRd =
+ {
+ Name = Sym.ofString "YlOrRd"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(255uy,237uy,160uy); C3b(254uy,178uy,76uy); C3b(240uy,59uy,32uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print
+ Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,204uy,92uy); C3b(253uy,141uy,60uy); C3b(227uy,26uy,28uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,204uy,92uy); C3b(253uy,141uy,60uy); C3b(240uy,59uy,32uy)
+ C3b(189uy,0uy,38uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy); C3b(253uy,141uy,60uy)
+ C3b(240uy,59uy,32uy); C3b(189uy,0uy,38uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy); C3b(253uy,141uy,60uy)
+ C3b(252uy,78uy,42uy); C3b(227uy,26uy,28uy); C3b(177uy,0uy,38uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,204uy); C3b(255uy,237uy,160uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy)
+ C3b(253uy,141uy,60uy); C3b(252uy,78uy,42uy); C3b(227uy,26uy,28uy); C3b(177uy,0uy,38uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,255uy,204uy); C3b(255uy,237uy,160uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy)
+ C3b(253uy,141uy,60uy); C3b(252uy,78uy,42uy); C3b(227uy,26uy,28uy); C3b(189uy,0uy,38uy)
+ C3b(128uy,0uy,38uy) |]
+ }
+
+ ]
+ }
+
+ let PuRd =
+ {
+ Name = Sym.ofString "PuRd"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(231uy,225uy,239uy); C3b(201uy,148uy,199uy); C3b(221uy,28uy,119uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(241uy,238uy,246uy); C3b(215uy,181uy,216uy); C3b(223uy,101uy,176uy); C3b(206uy,18uy,86uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD
+ Colors = [| C3b(241uy,238uy,246uy); C3b(215uy,181uy,216uy); C3b(223uy,101uy,176uy); C3b(221uy,28uy,119uy)
+ C3b(152uy,0uy,67uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(241uy,238uy,246uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy); C3b(223uy,101uy,176uy)
+ C3b(221uy,28uy,119uy); C3b(152uy,0uy,67uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(241uy,238uy,246uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy); C3b(223uy,101uy,176uy)
+ C3b(231uy,41uy,138uy); C3b(206uy,18uy,86uy); C3b(145uy,0uy,63uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,244uy,249uy); C3b(231uy,225uy,239uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy)
+ C3b(223uy,101uy,176uy); C3b(231uy,41uy,138uy); C3b(206uy,18uy,86uy); C3b(145uy,0uy,63uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,244uy,249uy); C3b(231uy,225uy,239uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy)
+ C3b(223uy,101uy,176uy); C3b(231uy,41uy,138uy); C3b(206uy,18uy,86uy); C3b(152uy,0uy,67uy)
+ C3b(103uy,0uy,31uy) |]
+ }
+
+ ]
+ }
+
+ let Blues =
+ {
+ Name = Sym.ofString "Blues"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(222uy,235uy,247uy); C3b(158uy,202uy,225uy); C3b(49uy,130uy,189uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(239uy,243uy,255uy); C3b(189uy,215uy,231uy); C3b(107uy,174uy,214uy); C3b(33uy,113uy,181uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(239uy,243uy,255uy); C3b(189uy,215uy,231uy); C3b(107uy,174uy,214uy); C3b(49uy,130uy,189uy)
+ C3b(8uy,81uy,156uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(239uy,243uy,255uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy); C3b(107uy,174uy,214uy)
+ C3b(49uy,130uy,189uy); C3b(8uy,81uy,156uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(239uy,243uy,255uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy); C3b(107uy,174uy,214uy)
+ C3b(66uy,146uy,198uy); C3b(33uy,113uy,181uy); C3b(8uy,69uy,148uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,251uy,255uy); C3b(222uy,235uy,247uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy)
+ C3b(107uy,174uy,214uy); C3b(66uy,146uy,198uy); C3b(33uy,113uy,181uy); C3b(8uy,69uy,148uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(247uy,251uy,255uy); C3b(222uy,235uy,247uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy)
+ C3b(107uy,174uy,214uy); C3b(66uy,146uy,198uy); C3b(33uy,113uy,181uy); C3b(8uy,81uy,156uy)
+ C3b(8uy,48uy,107uy) |]
+ }
+
+ ]
+ }
+
+ let PuBuGn =
+ {
+ Name = Sym.ofString "PuBuGn"
+ Type = SchemeType.Sequential
+ Palettes =
+ MapExt.ofList [
+ 3, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy
+ Colors = [| C3b(236uy,226uy,240uy); C3b(166uy,189uy,219uy); C3b(28uy,144uy,153uy) |]
+ }
+
+ 4, {
+ Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD
+ Colors = [| C3b(246uy,239uy,247uy); C3b(189uy,201uy,225uy); C3b(103uy,169uy,207uy); C3b(2uy,129uy,138uy) |]
+ }
+
+ 5, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(246uy,239uy,247uy); C3b(189uy,201uy,225uy); C3b(103uy,169uy,207uy); C3b(28uy,144uy,153uy)
+ C3b(1uy,108uy,89uy) |]
+ }
+
+ 6, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(246uy,239uy,247uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(103uy,169uy,207uy)
+ C3b(28uy,144uy,153uy); C3b(1uy,108uy,89uy) |]
+ }
+
+ 7, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(246uy,239uy,247uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(103uy,169uy,207uy)
+ C3b(54uy,144uy,192uy); C3b(2uy,129uy,138uy); C3b(1uy,100uy,80uy) |]
+ }
+
+ 8, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,226uy,240uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)
+ C3b(103uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(2uy,129uy,138uy); C3b(1uy,100uy,80uy) |]
+ }
+
+ 9, {
+ Usage = PaletteUsage.ColorBlind
+ Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,226uy,240uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)
+ C3b(103uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(2uy,129uy,138uy); C3b(1uy,108uy,89uy)
+ C3b(1uy,70uy,54uy) |]
+ }
+
+ ]
+ }
+
+ /// Array of all available color schemes.
+ let All =
+ [|
+ Diverging.Spectral; Diverging.RdYlGn; Diverging.RdBu; Diverging.PiYG; Diverging.PRGn; Diverging.RdYlBu
+ Diverging.BrBG; Diverging.RdGy; Diverging.PuOr; Qualitative.Set2; Qualitative.Accent; Qualitative.Set1
+ Qualitative.Set3; Qualitative.Dark2; Qualitative.Paired; Qualitative.Pastel2; Qualitative.Pastel1; Sequential.OrRd
+ Sequential.PuBu; Sequential.BuPu; Sequential.Oranges; Sequential.BuGn; Sequential.YlOrBr; Sequential.YlGn
+ Sequential.Reds; Sequential.RdPu; Sequential.Greens; Sequential.YlGnBu; Sequential.Purples; Sequential.GnBu
+ Sequential.Greys; Sequential.YlOrRd; Sequential.PuRd; Sequential.Blues; Sequential.PuBuGn
+ |]
diff --git a/src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fsx b/src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fsx
new file mode 100644
index 000000000..85fbbe0a2
--- /dev/null
+++ b/src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fsx
@@ -0,0 +1,247 @@
+#r "../../../bin/Debug/netstandard2.0/Aardvark.Base.dll"
+#r "../../../bin/Debug/netstandard2.0/Aardvark.Base.FSharp.dll"
+#r "../../../bin/Debug/net6.0/FSharp.Data.Adaptive.dll"
+#r "System.Net.Http.dll"
+
+open Aardvark.Base
+open System
+open System.IO
+open System.Text
+open System.Text.RegularExpressions
+open System.Net.Http
+
+fsi.ShowDeclarationValues <- false
+
+let source =
+ let ws = Regex(@"\s+", RegexOptions.Compiled)
+
+ use client = new HttpClient()
+ use task = client.GetStringAsync "https://raw.githubusercontent.com/axismaps/colorbrewer/master/colorbrewer_schemes.js"
+ task.Wait()
+
+ task.Result
+ |> String.getLines
+ |> Array.map (fun str -> ws.Replace(str, ""))
+
+module Regex =
+
+ let Scheme =
+ Regex(
+ @"^(?[A-Za-z0-9]+):\{" +
+ @"(?(?:[0-9]:\[.+?\],?)+)" +
+ @"'properties':\{(?.+)\}\},?$",
+ RegexOptions.Multiline
+ );
+
+ let Palette =
+ Regex(@"(?[0-9]+):\[(?[0-9'rgb\(\),]+)\]", RegexOptions.Compiled);
+
+ let Color =
+ Regex(@"'(?rgb\([0-9]{1,3},[0-9]{1,3},[0-9]{1,3}\))'", RegexOptions.Compiled)
+
+ let RGB =
+ Regex(@"^rgb\((?[0-9]{1,3}),(?[0-9]{1,3}),(?[0-9]{1,3})\)$", RegexOptions.Compiled)
+
+ let Property =
+ Regex(@"'(?[a-zA-Z]+)':(?:'(?[a-zA-Z]+)'|\[(?[0-9,]+)\])", RegexOptions.Compiled);
+
+
+type Severity =
+ | Warning = 0
+ | Error = 1
+
+let messages = ResizeArray()
+
+let log severity fmt =
+ Printf.kprintf (fun str -> messages.Add (severity, str)) fmt
+
+let schemes =
+ source |> Array.choose (fun str ->
+ let m = Regex.Scheme.Match str
+
+ if m.Success then
+ let schemeName = m.Groups.["Name"].Value
+
+ try
+ let properties =
+ Regex.Property.Matches m.Groups.["Properties"].Value
+ |> Seq.map (fun p ->
+ let value =
+ if p.Groups.["Value"].Success then p.Groups.["Value"].Value
+ else p.Groups.["PerPaletteValue"].Value
+
+ p.Groups.["Key"].Value, value
+ )
+ |> Map.ofSeq
+
+ let typ =
+ match properties.["type"] with
+ | "div" -> ColorBrewer.SchemeType.Diverging
+ | "qual" -> ColorBrewer.SchemeType.Qualitative
+ | "seq" -> ColorBrewer.SchemeType.Sequential
+ | t -> failwithf "Unknown scheme type '%s'" t
+
+ let colors =
+ Regex.Palette.Matches m.Groups.["Palettes"].Value
+ |> Seq.map (fun p ->
+ let size = Int32.Parse p.Groups.["Size"].Value
+
+ let colors =
+ Regex.Color.Matches p.Groups.["Colors"].Value
+ |> Seq.map (fun m ->
+ let m = Regex.RGB.Match m.Groups.["Color"].Value
+ let r = m.Groups.["R"].Value
+ let g = m.Groups.["G"].Value
+ let b = m.Groups.["B"].Value
+ $"C3b({r}uy,{g}uy,{b}uy)"
+ )
+ |> Array.ofSeq
+
+ if colors.Length <> size then
+ failwithf "Size mismatch (expected %d but got %d)" size colors.Length
+
+ colors
+ )
+ |> Array.ofSeq
+
+ let getFlags (propertyName : string) =
+ let values =
+ properties.[propertyName] |> String.split "," |> Array.map (fun str ->
+ Int32.Parse str = 1
+ )
+
+ if values.Length >= colors.Length then values
+ elif values.Length = 1 then Array.replicate colors.Length values.[0]
+ else
+ let missing = Array.replicate (colors.Length - values.Length) false
+ log Severity.Warning "Property '%s' in scheme '%s' has %d entries but expected %d." propertyName schemeName values.Length colors.Length
+ Array.concat [values; missing]
+
+ let blind = getFlags "blind"
+ let print = getFlags "print"
+ let copy = getFlags "copy"
+ let screen = getFlags "screen"
+
+ let palettes =
+ colors |> Array.mapi (fun i c ->
+ let mutable usage = Set.empty
+ if blind.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.ColorBlind
+ if print.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.Print
+ if copy.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.PhotoCopy
+ if screen.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.LCD
+
+ c.Length, {| Colors = c; Usage = usage |}
+ )
+ |> Map.ofArray
+
+ Some {| Name = schemeName; Type = typ; Palettes = palettes |}
+
+ with e ->
+ log Severity.Error "Failed to parse scheme %s: %s" schemeName e.Message
+ None
+ else
+ None
+ )
+
+printfn "Found %d schemes" schemes.Length
+
+let writeToFile() =
+ let builder = StringBuilder()
+
+ let writeln indent fmt =
+ Printf.kprintf (fun str -> builder.AppendLine(str |> String.indent indent) |> ignore) fmt
+
+ let schemeTypeComments =
+ Map.ofList [
+ ColorBrewer.SchemeType.Diverging, "/// Diverging schemes put equal emphasis on mid-range critical values and extremes at both ends of the data range.\n/// The critical class or break in the middle of the legend is emphasized with light colors and low and high extremes are\n/// emphasized with dark colors that have contrasting hues."
+
+ ColorBrewer.SchemeType.Qualitative, "/// Qualitative schemes do not imply magnitude differences between legend classes, and hues are used to\n/// create the primary visual differences between classes. Qualitative schemes are best suited to representing nominal or categorical data."
+
+ ColorBrewer.SchemeType.Sequential, "/// Sequential schemes are suited to ordered data that progress from low to high.\n/// Lightness steps dominate the look of these schemes, with light colors for low data values to dark colors for high data values."
+ ]
+
+ writeln 0 "namespace Aardvark.Base"
+ writeln 0 ""
+ writeln 0 "[]"
+ writeln 0 "module ColorBrewerSchemes ="
+ writeln 1 "open ColorBrewer"
+ writeln 0 ""
+ writeln 1 "/// Brewer color schemes designed for choropleth map visualizations."
+ writeln 1 "module ColorBrewer ="
+ writeln 0 ""
+ writeln 2 "module Scheme ="
+ writeln 0 ""
+
+ let grouped =
+ schemes |> Array.groupBy (fun s -> s.Type)
+
+ for (typ, schemes) in grouped do
+
+ for c in schemeTypeComments.[typ] |> String.getLines do
+ writeln 3 "%s" c
+
+ writeln 3 "module %A =" typ
+ writeln 0 ""
+
+ for s in schemes do
+ writeln 4 "let %s =" s.Name
+ writeln 5 "{"
+ writeln 6 "Name = Sym.ofString \"%s\"" s.Name
+ writeln 6 "Type = SchemeType.%A" s.Type
+ writeln 6 "Palettes ="
+ writeln 7 "MapExt.ofList ["
+
+ for (KeyValue(n, p)) in s.Palettes do
+ let usage =
+ if Set.isEmpty p.Usage then "PaletteUsage.None"
+ else p.Usage |> Seq.map (fun u -> $"PaletteUsage.{u}") |> String.concat " ||| "
+
+ let colors =
+ Array.chunkBySize 4 p.Colors
+ |> Array.map (String.concat "; ")
+
+ colors.[0] <- $"Colors = [| {colors.[0]}"
+ colors.[colors.Length - 1] <- $"{colors.[colors.Length - 1]} |]"
+
+ writeln 8 "%d, {" n
+ writeln 9 "Usage = %s" usage
+
+ writeln 9 "%s" colors.[0]
+ for i = 1 to colors.Length - 1 do
+ writeln 12 "%s" colors.[i]
+
+ writeln 8 "}"
+ writeln 0 ""
+
+ writeln 7 "]"
+ writeln 5 "}"
+ writeln 0 ""
+
+ writeln 3 "/// Array of all available color schemes."
+ writeln 3 "let All ="
+ writeln 4 "[|"
+
+ let all =
+ grouped |> Array.collect (fun (typ, schemes) ->
+ schemes |> Array.map (fun s -> $"{typ}.{s.Name}")
+ )
+ |> Array.chunkBySize 6
+ |> Array.map (String.concat "; ")
+
+ for schemes in all do
+ writeln 5 "%s" schemes
+
+ writeln 4 "|]"
+
+
+ let file = Path.Combine(__SOURCE_DIRECTORY__, "ColorBrewerSchemes.fs")
+ File.writeAllText file (builder.ToString())
+
+ for s in schemes do
+ printfn "%s" s.Name
+ printfn "%A" s.Palettes
+
+ for (s, e) in messages do
+ printfn "[%A] %s" s e
+
+writeToFile()
\ No newline at end of file
diff --git a/src/Aardvark.Base.FSharp/Datastructures/Immutable/MapExt.fs b/src/Aardvark.Base.FSharp/Datastructures/Immutable/MapExt.fs
index be9a614a6..f8eea6f1c 100644
--- a/src/Aardvark.Base.FSharp/Datastructures/Immutable/MapExt.fs
+++ b/src/Aardvark.Base.FSharp/Datastructures/Immutable/MapExt.fs
@@ -455,6 +455,40 @@ module internal MapExtImplementation =
| ValueSome v -> join left k v right
| ValueNone -> merge left right
+ let rec range (comparer : IComparer<'Value>) lk rk m =
+ match m with
+ | _ when comparer.Compare(lk, rk) > 0 ->
+ MapEmpty
+
+ | MapEmpty ->
+ MapEmpty
+
+ | MapOne(k, _) as n ->
+ if comparer.Compare(lk, k) <= 0 && comparer.Compare(k, rk) <= 0 then n
+ else MapEmpty
+
+ | MapNode(k, v, l, r, _, _) ->
+ let cl = comparer.Compare(lk, k)
+
+ if cl = 0 then
+ if comparer.Compare(k, rk) = 0 then
+ MapOne(k, v)
+ else
+ join MapEmpty k v (range comparer lk rk r)
+
+ elif cl < 0 then
+ let cr = comparer.Compare(k, rk)
+
+ if cr = 0 then
+ join (range comparer lk rk l) k v MapEmpty
+ elif cr < 0 then
+ join (range comparer lk rk l) k v (range comparer lk rk r)
+ else
+ range comparer lk rk l
+
+ else
+ range comparer lk rk r
+
let rec split (comparer: IComparer<'Value>) k m =
match m with
| MapEmpty ->
@@ -1681,12 +1715,19 @@ module internal MapExtImplementation =
let ofList comparer l = List.fold (fun acc (k,v) -> add comparer k v acc) empty l
+ let ofListV comparer l = List.fold (fun acc (struct (k,v)) -> add comparer k v acc) empty l
let rec mkFromEnumerator comparer acc (e : IEnumerator<_>) =
if e.MoveNext() then
let (x,y) = e.Current
mkFromEnumerator comparer (add comparer x y acc) e
else acc
+
+ let rec mkFromEnumeratorV comparer acc (e : IEnumerator<_>) =
+ if e.MoveNext() then
+ let struct (x,y) = e.Current
+ mkFromEnumeratorV comparer (add comparer x y acc) e
+ else acc
let ofArray comparer (arr : array<_>) =
let mutable res = empty
@@ -1694,13 +1735,27 @@ module internal MapExtImplementation =
res <- add comparer x y res
res
+ let ofArrayV comparer (arr : array<_>) =
+ let mutable res = empty
+ for struct (x,y) in arr do
+ res <- add comparer x y res
+ res
+
let ofSeq comparer (c : seq<'Key * 'T>) =
match c with
| :? array<'Key * 'T> as xs -> ofArray comparer xs
| :? list<'Key * 'T> as xs -> ofList comparer xs
| _ ->
use ie = c.GetEnumerator()
- mkFromEnumerator comparer empty ie
+ mkFromEnumerator comparer empty ie
+
+ let ofSeqV comparer (c : seq) =
+ match c with
+ | :? array as xs -> ofArrayV comparer xs
+ | :? list as xs -> ofListV comparer xs
+ | _ ->
+ use ie = c.GetEnumerator()
+ mkFromEnumeratorV comparer empty ie
let copyToArray s (arr: _[]) i =
@@ -1948,6 +2003,10 @@ type MapExt<[]'Key,[) : MapExt<'Key,'Value> =
let comparer = LanguagePrimitives.FastGenericComparer<'Key>
new MapExt<_,_>(comparer,MapTree.ofSeq comparer ie)
+
+ static member CreateV(ie : IEnumerable<_>) : MapExt<'Key,'Value> =
+ let comparer = LanguagePrimitives.FastGenericComparer<'Key>
+ new MapExt<_,_>(comparer,MapTree.ofSeqV comparer ie)
static member Create() : MapExt<'Key,'Value> = empty
@@ -2085,6 +2144,9 @@ type MapExt<[]'Key,[ ValueOption.map (fun struct(_,v) -> v)
member x.TryMaxValueV = MapTree.tryMaxV tree |> ValueOption.map (fun struct(_,v) -> v)
+ member x.Range(min, max) =
+ MapExt<'Key, 'Value>(comparer, MapTree.range comparer min max tree)
+
member x.Split (k) =
let l, self, r = MapTree.split comparer k tree
MapExt<'Key, 'Value>(comparer, l), self, MapExt<'Key, 'Value>(comparer, r)
@@ -2153,6 +2215,10 @@ type MapExt<[]'Key,[ =
let comparer = LanguagePrimitives.FastGenericComparer<'Key>
new MapExt<_,_>(comparer,MapTree.ofList comparer l)
+
+ static member ofListV(l) : MapExt<'Key,'Value> =
+ let comparer = LanguagePrimitives.FastGenericComparer<'Key>
+ new MapExt<_,_>(comparer,MapTree.ofListV comparer l)
member this.ComputeHashCode() =
let combineHash x y = (x <<< 1) + y + 631
@@ -2351,9 +2417,15 @@ module MapExt =
[]
let ofList (l: ('Key * 'Value) list) = MapExt<_,_>.ofList(l)
+ []
+ let ofListV (l: (struct ('Key * 'Value)) list) = MapExt<_,_>.ofListV(l)
+
[]
let ofSeq l = MapExt<_,_>.Create(l)
-
+
+ []
+ let ofSeqV l = MapExt<_,_>.CreateV(l)
+
[]
let singleton k v = MapExt<_,_>(LanguagePrimitives.FastGenericComparer<_>,MapOne(k,v))
@@ -2362,6 +2434,11 @@ module MapExt =
let comparer = LanguagePrimitives.FastGenericComparer<'Key>
new MapExt<_,_>(comparer,MapTree.ofArray comparer array)
+ []
+ let ofArrayV (array: (struct ('Key * 'Value)) array) =
+ let comparer = LanguagePrimitives.FastGenericComparer<'Key>
+ new MapExt<_,_>(comparer,MapTree.ofArrayV comparer array)
+
[]
let toList (m:MapExt<_,_>) = m.ToList()
@@ -2388,6 +2465,9 @@ module MapExt =
[]
let tryMin (m:MapExt<_,_>) = m.TryMinKey
+
+ []
+ let tryMinV (m:MapExt<_,_>) = m.TryMinKeyV
[]
let min (m:MapExt<_,_>) =
@@ -2398,6 +2478,9 @@ module MapExt =
[]
let tryMax (m:MapExt<_,_>) = m.TryMaxKey
+ []
+ let tryMaxV (m:MapExt<_,_>) = m.TryMaxKeyV
+
[]
let max (m:MapExt<_,_>) =
match m.TryMaxKey with
@@ -2426,9 +2509,15 @@ module MapExt =
[]
let chooseMonotonic f (m:MapExt<_,_>) = m.ChooseMonotonic(f)
+ []
+ let range min max (m:MapExt<_,_>) = m.Range(min, max)
+
[]
let split k (m:MapExt<_,_>) = m.Split k
+ []
+ let splitV k (m:MapExt<_,_>) = m.SplitV k
+
[]
let tryIndexOf i (m:MapExt<_,_>) = m.TryIndexOf i
diff --git a/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSetOld_auto.fs b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSetOld_auto.fs
new file mode 100644
index 000000000..2d1137f3d
--- /dev/null
+++ b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSetOld_auto.fs
@@ -0,0 +1,455 @@
+namespace Aardvark.Base
+
+open System
+open System.Collections
+open System.Collections.Generic
+open FingerTreeImplementation
+
+#nowarn "44"
+
+[]
+type private HalfRange =
+ struct
+ val mutable public IsMax : bool
+ val mutable public Value : int32
+
+ new(m,v) = { IsMax = m; Value = v }
+
+ override x.GetHashCode() =
+ if x.IsMax then 0
+ else x.Value.GetHashCode()
+
+ override x.Equals o =
+ match o with
+ | :? HalfRange as o ->
+ x.IsMax = o.IsMax && x.Value = o.Value
+ | _ ->
+ false
+
+ member x.CompareTo (o : HalfRange) =
+ let c = x.Value.CompareTo o.Value
+ if c = 0 then
+ if x.IsMax = o.IsMax then 0
+ else (if x.IsMax then 1 else -1)
+ else
+ c
+
+ interface IComparable with
+ member x.CompareTo o =
+ match o with
+ | :? HalfRange as o -> x.CompareTo(o)
+ | _ -> failwith "uncomparable"
+ end
+
+
+[]
+[]
+type RangeSet = private { root : FingerTreeNode } with
+
+ member private x.AsString =
+ x |> Seq.map (sprintf "%A")
+ |> String.concat "; "
+ |> sprintf "set [%s]"
+
+ member x.Min =
+ match x.root |> FingerTreeNode.firstOpt with
+ | Some f -> f.Value
+ | _ -> Int32.MaxValue
+
+ member x.Max =
+ match x.root |> FingerTreeNode.lastOpt with
+ | Some f -> f.Value
+ | _ -> Int32.MinValue
+
+ member x.Range =
+ match FingerTreeNode.firstOpt x.root, FingerTreeNode.lastOpt x.root with
+ | Some min, Some max -> Range1i(min.Value, max.Value)
+ | _ -> Range1i.Invalid
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSetEnumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> IEnumerator
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSetEnumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> _
+
+
+and private RangeSetEnumerator(i : IEnumerator) =
+
+ let mutable last = HalfRange()
+ let mutable current = HalfRange()
+
+ member x.Current = Range1i(last.Value, current.Value - 1)
+
+ interface IEnumerator with
+ member x.MoveNext() =
+ if i.MoveNext() then
+ last <- i.Current
+ if i.MoveNext() then
+ current <- i.Current
+ true
+ else
+ false
+ else
+ false
+
+ member x.Current = x.Current :> obj
+
+ member x.Reset() =
+ i.Reset()
+
+ interface IEnumerator with
+ member x.Current = x.Current
+ member x.Dispose() = i.Dispose()
+
+[]
+[]
+module RangeSet =
+ let private mm =
+ {
+ quantify = fun (r : HalfRange) -> r
+ mempty = HalfRange(false, Int32.MinValue)
+ mappend = fun l r -> if l.CompareTo r > 0 then l else r
+ }
+
+ let private minRange = HalfRange(false, Int32.MinValue)
+
+ let inline private leq v = HalfRange(true, v)
+ let inline private geq v = HalfRange(false, v)
+
+ let inline private (|Leq|Geq|) (r : HalfRange) =
+ if r.IsMax then Leq r.Value
+ else Geq r.Value
+
+ let empty = { root = Empty }
+
+ let insert (range : Range1i) (t : RangeSet) =
+ let rangeMax = range.Max + 1
+
+ let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
+ let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+
+ let max = leq rangeMax
+ let min = geq range.Min
+
+ match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
+ | None, None ->
+ { root = Deep(max, One(min), Empty, One(max)) }
+
+ | Some lmax, None ->
+ match lmax with
+ | Leq _ -> { root = l |> FingerTreeNode.append mm min |> FingerTreeNode.append mm max }
+ | Geq _ -> { root = l |> FingerTreeNode.append mm max }
+
+ | None, Some rmin ->
+ match rmin with
+ | Leq _ -> { root = r |> FingerTreeNode.prepend mm min }
+ | Geq _ -> { root = r |> FingerTreeNode.prepend mm max |> FingerTreeNode.prepend mm min }
+
+ | Some lmax, Some rmin ->
+ match lmax, rmin with
+ | Leq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min;max] r }
+
+ | Geq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [] r }
+
+ | Leq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+
+ | Geq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+
+ let remove (range : Range1i) (t : RangeSet) =
+ let rangeMax = range.Max + 1
+
+ let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
+ let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+
+ let max = geq rangeMax
+ let min = leq range.Min
+
+ match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
+ | None, None ->
+ { root = Empty }
+
+ | Some lmax, None ->
+ match lmax with
+ | Leq _ -> { root = l }
+ | Geq _ -> { root = l |> FingerTreeNode.append mm min }
+
+ | None, Some rmin ->
+ match rmin with
+ | Leq _ -> { root = r |> FingerTreeNode.prepend mm max }
+ | Geq _ -> { root = r }
+
+ | Some lmax, Some rmin ->
+ match lmax, rmin with
+ | Leq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [] r }
+
+ | Geq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min; max] r }
+
+ | Leq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+
+ | Geq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+
+ let ofSeq (s : seq) =
+ let mutable res = empty
+ for e in s do res <- insert e res
+ res
+
+ let inline ofList (l : list) = ofSeq l
+ let inline ofArray (l : Range1i[]) = ofSeq l
+
+ let toSeq (r : RangeSet) = r :> seq<_>
+ let toList (r : RangeSet) = r |> Seq.toList
+ let toArray (r : RangeSet) = r |> Seq.toArray
+
+ let inline min (t : RangeSet) = t.Min
+ let inline max (t : RangeSet) = t.Max
+ let inline range (t : RangeSet) = t.Range
+
+ let window (window : Range1i) (set : RangeSet) =
+ let rangeMax = window.Max + 1
+
+ let (l,rest) = set.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo window.Min > 0) minRange
+ let (inner,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax >= 0) minRange
+
+ let inner =
+ match FingerTreeNode.lastOpt l with
+ | Some (Geq _) -> FingerTreeNode.prepend mm (geq window.Min) inner
+ | _ -> inner
+
+ let inner =
+ match FingerTreeNode.firstOpt r with
+ | Some (Leq _) -> FingerTreeNode.append mm (leq rangeMax) inner
+ | _ -> inner
+
+ { root = inner }
+
+[]
+type private HalfRange64 =
+ struct
+ val mutable public IsMax : bool
+ val mutable public Value : int64
+
+ new(m,v) = { IsMax = m; Value = v }
+
+ override x.GetHashCode() =
+ if x.IsMax then 0
+ else x.Value.GetHashCode()
+
+ override x.Equals o =
+ match o with
+ | :? HalfRange64 as o ->
+ x.IsMax = o.IsMax && x.Value = o.Value
+ | _ ->
+ false
+
+ member x.CompareTo (o : HalfRange64) =
+ let c = x.Value.CompareTo o.Value
+ if c = 0 then
+ if x.IsMax = o.IsMax then 0
+ else (if x.IsMax then 1 else -1)
+ else
+ c
+
+ interface IComparable with
+ member x.CompareTo o =
+ match o with
+ | :? HalfRange64 as o -> x.CompareTo(o)
+ | _ -> failwith "uncomparable"
+ end
+
+
+[]
+[]
+type RangeSet64 = private { root : FingerTreeNode } with
+
+ member private x.AsString =
+ x |> Seq.map (sprintf "%A")
+ |> String.concat "; "
+ |> sprintf "set [%s]"
+
+ member x.Min =
+ match x.root |> FingerTreeNode.firstOpt with
+ | Some f -> f.Value
+ | _ -> Int64.MaxValue
+
+ member x.Max =
+ match x.root |> FingerTreeNode.lastOpt with
+ | Some f -> f.Value
+ | _ -> Int64.MinValue
+
+ member x.Range =
+ match FingerTreeNode.firstOpt x.root, FingerTreeNode.lastOpt x.root with
+ | Some min, Some max -> Range1l(min.Value, max.Value)
+ | _ -> Range1l.Invalid
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSet64Enumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> IEnumerator
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSet64Enumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> _
+
+
+and private RangeSet64Enumerator(i : IEnumerator) =
+
+ let mutable last = HalfRange64()
+ let mutable current = HalfRange64()
+
+ member x.Current = Range1l(last.Value, current.Value - 1L)
+
+ interface IEnumerator with
+ member x.MoveNext() =
+ if i.MoveNext() then
+ last <- i.Current
+ if i.MoveNext() then
+ current <- i.Current
+ true
+ else
+ false
+ else
+ false
+
+ member x.Current = x.Current :> obj
+
+ member x.Reset() =
+ i.Reset()
+
+ interface IEnumerator with
+ member x.Current = x.Current
+ member x.Dispose() = i.Dispose()
+
+[]
+[]
+module RangeSet64 =
+ let private mm =
+ {
+ quantify = fun (r : HalfRange64) -> r
+ mempty = HalfRange64(false, Int64.MinValue)
+ mappend = fun l r -> if l.CompareTo r > 0 then l else r
+ }
+
+ let private minRange = HalfRange64(false, Int64.MinValue)
+
+ let inline private leq v = HalfRange64(true, v)
+ let inline private geq v = HalfRange64(false, v)
+
+ let inline private (|Leq|Geq|) (r : HalfRange64) =
+ if r.IsMax then Leq r.Value
+ else Geq r.Value
+
+ let empty = { root = Empty }
+
+ let insert (range : Range1l) (t : RangeSet64) =
+ let rangeMax = range.Max + 1L
+
+ let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
+ let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+
+ let max = leq rangeMax
+ let min = geq range.Min
+
+ match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
+ | None, None ->
+ { root = Deep(max, One(min), Empty, One(max)) }
+
+ | Some lmax, None ->
+ match lmax with
+ | Leq _ -> { root = l |> FingerTreeNode.append mm min |> FingerTreeNode.append mm max }
+ | Geq _ -> { root = l |> FingerTreeNode.append mm max }
+
+ | None, Some rmin ->
+ match rmin with
+ | Leq _ -> { root = r |> FingerTreeNode.prepend mm min }
+ | Geq _ -> { root = r |> FingerTreeNode.prepend mm max |> FingerTreeNode.prepend mm min }
+
+ | Some lmax, Some rmin ->
+ match lmax, rmin with
+ | Leq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min;max] r }
+
+ | Geq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [] r }
+
+ | Leq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+
+ | Geq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+
+ let remove (range : Range1l) (t : RangeSet64) =
+ let rangeMax = range.Max + 1L
+
+ let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
+ let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+
+ let max = geq rangeMax
+ let min = leq range.Min
+
+ match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
+ | None, None ->
+ { root = Empty }
+
+ | Some lmax, None ->
+ match lmax with
+ | Leq _ -> { root = l }
+ | Geq _ -> { root = l |> FingerTreeNode.append mm min }
+
+ | None, Some rmin ->
+ match rmin with
+ | Leq _ -> { root = r |> FingerTreeNode.prepend mm max }
+ | Geq _ -> { root = r }
+
+ | Some lmax, Some rmin ->
+ match lmax, rmin with
+ | Leq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [] r }
+
+ | Geq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min; max] r }
+
+ | Leq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+
+ | Geq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+
+ let ofSeq (s : seq) =
+ let mutable res = empty
+ for e in s do res <- insert e res
+ res
+
+ let inline ofList (l : list) = ofSeq l
+ let inline ofArray (l : Range1l[]) = ofSeq l
+
+ let toSeq (r : RangeSet64) = r :> seq<_>
+ let toList (r : RangeSet64) = r |> Seq.toList
+ let toArray (r : RangeSet64) = r |> Seq.toArray
+
+ let inline min (t : RangeSet64) = t.Min
+ let inline max (t : RangeSet64) = t.Max
+ let inline range (t : RangeSet64) = t.Range
+
+ let window (window : Range1l) (set : RangeSet64) =
+ let rangeMax = window.Max + 1L
+
+ let (l,rest) = set.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo window.Min > 0) minRange
+ let (inner,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax >= 0) minRange
+
+ let inner =
+ match FingerTreeNode.lastOpt l with
+ | Some (Geq _) -> FingerTreeNode.prepend mm (geq window.Min) inner
+ | _ -> inner
+
+ let inner =
+ match FingerTreeNode.firstOpt r with
+ | Some (Leq _) -> FingerTreeNode.append mm (leq rangeMax) inner
+ | _ -> inner
+
+ { root = inner }
+
diff --git a/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSetOld_template.fs b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSetOld_template.fs
new file mode 100644
index 000000000..759b6e7f8
--- /dev/null
+++ b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSetOld_template.fs
@@ -0,0 +1,242 @@
+namespace Aardvark.Base
+
+open System
+open System.Collections
+open System.Collections.Generic
+open FingerTreeImplementation
+
+#nowarn "44"
+
+//# foreach (var isLong in new[] { false, true }) {
+//# var halfrange = isLong ? "HalfRange64" : "HalfRange";
+//# var rangeset = isLong ? "RangeSet64" : "RangeSet";
+//# var rangesetenumerator = isLong ? "RangeSet64Enumerator" : "RangeSetEnumerator";
+//# var range = isLong ? "Range1l" : "Range1i";
+//# var systype = isLong ? "Int64" : "Int32";
+//# var ft = isLong ? "int64" : "int32";
+//# var one = isLong ? "1L" : "1";
+//# var replacement = isLong ? "RangeSet1l" : "RangeSet1i";
+[]
+type private __halfrange__ =
+ struct
+ val mutable public IsMax : bool
+ val mutable public Value : __ft__
+
+ new(m,v) = { IsMax = m; Value = v }
+
+ override x.GetHashCode() =
+ if x.IsMax then 0
+ else x.Value.GetHashCode()
+
+ override x.Equals o =
+ match o with
+ | :? __halfrange__ as o ->
+ x.IsMax = o.IsMax && x.Value = o.Value
+ | _ ->
+ false
+
+ member x.CompareTo (o : __halfrange__) =
+ let c = x.Value.CompareTo o.Value
+ if c = 0 then
+ if x.IsMax = o.IsMax then 0
+ else (if x.IsMax then 1 else -1)
+ else
+ c
+
+ interface IComparable with
+ member x.CompareTo o =
+ match o with
+ | :? __halfrange__ as o -> x.CompareTo(o)
+ | _ -> failwith "uncomparable"
+ end
+
+
+[]
+[]
+type __rangeset__ = private { root : FingerTreeNode<__halfrange__, __halfrange__> } with
+
+ member private x.AsString =
+ x |> Seq.map (sprintf "%A")
+ |> String.concat "; "
+ |> sprintf "set [%s]"
+
+ member x.Min =
+ match x.root |> FingerTreeNode.firstOpt with
+ | Some f -> f.Value
+ | _ -> __systype__.MaxValue
+
+ member x.Max =
+ match x.root |> FingerTreeNode.lastOpt with
+ | Some f -> f.Value
+ | _ -> __systype__.MinValue
+
+ member x.Range =
+ match FingerTreeNode.firstOpt x.root, FingerTreeNode.lastOpt x.root with
+ | Some min, Some max -> __range__(min.Value, max.Value)
+ | _ -> __range__.Invalid
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new __rangesetenumerator__(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> IEnumerator
+
+ interface IEnumerable<__range__> with
+ member x.GetEnumerator() = new __rangesetenumerator__(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> _
+
+
+and private __rangesetenumerator__(i : IEnumerator<__halfrange__>) =
+
+ let mutable last = __halfrange__()
+ let mutable current = __halfrange__()
+
+ member x.Current = __range__(last.Value, current.Value - __one__)
+
+ interface IEnumerator with
+ member x.MoveNext() =
+ if i.MoveNext() then
+ last <- i.Current
+ if i.MoveNext() then
+ current <- i.Current
+ true
+ else
+ false
+ else
+ false
+
+ member x.Current = x.Current :> obj
+
+ member x.Reset() =
+ i.Reset()
+
+ interface IEnumerator<__range__> with
+ member x.Current = x.Current
+ member x.Dispose() = i.Dispose()
+
+[]
+[]
+module __rangeset__ =
+ let private mm =
+ {
+ quantify = fun (r : __halfrange__) -> r
+ mempty = __halfrange__(false, __systype__.MinValue)
+ mappend = fun l r -> if l.CompareTo r > 0 then l else r
+ }
+
+ let private minRange = __halfrange__(false, __systype__.MinValue)
+
+ let inline private leq v = __halfrange__(true, v)
+ let inline private geq v = __halfrange__(false, v)
+
+ let inline private (|Leq|Geq|) (r : __halfrange__) =
+ if r.IsMax then Leq r.Value
+ else Geq r.Value
+
+ let empty = { root = Empty }
+
+ let insert (range : __range__) (t : __rangeset__) =
+ let rangeMax = range.Max + __one__
+
+ let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
+ let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+
+ let max = leq rangeMax
+ let min = geq range.Min
+
+ match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
+ | None, None ->
+ { root = Deep(max, One(min), Empty, One(max)) }
+
+ | Some lmax, None ->
+ match lmax with
+ | Leq _ -> { root = l |> FingerTreeNode.append mm min |> FingerTreeNode.append mm max }
+ | Geq _ -> { root = l |> FingerTreeNode.append mm max }
+
+ | None, Some rmin ->
+ match rmin with
+ | Leq _ -> { root = r |> FingerTreeNode.prepend mm min }
+ | Geq _ -> { root = r |> FingerTreeNode.prepend mm max |> FingerTreeNode.prepend mm min }
+
+ | Some lmax, Some rmin ->
+ match lmax, rmin with
+ | Leq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min;max] r }
+
+ | Geq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [] r }
+
+ | Leq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+
+ | Geq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+
+ let remove (range : __range__) (t : __rangeset__) =
+ let rangeMax = range.Max + __one__
+
+ let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
+ let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+
+ let max = geq rangeMax
+ let min = leq range.Min
+
+ match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
+ | None, None ->
+ { root = Empty }
+
+ | Some lmax, None ->
+ match lmax with
+ | Leq _ -> { root = l }
+ | Geq _ -> { root = l |> FingerTreeNode.append mm min }
+
+ | None, Some rmin ->
+ match rmin with
+ | Leq _ -> { root = r |> FingerTreeNode.prepend mm max }
+ | Geq _ -> { root = r }
+
+ | Some lmax, Some rmin ->
+ match lmax, rmin with
+ | Leq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [] r }
+
+ | Geq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min; max] r }
+
+ | Leq _, Leq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+
+ | Geq _, Geq _ ->
+ { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+
+ let ofSeq (s : seq<__range__>) =
+ let mutable res = empty
+ for e in s do res <- insert e res
+ res
+
+ let inline ofList (l : list<__range__>) = ofSeq l
+ let inline ofArray (l : __range__[]) = ofSeq l
+
+ let toSeq (r : __rangeset__) = r :> seq<_>
+ let toList (r : __rangeset__) = r |> Seq.toList
+ let toArray (r : __rangeset__) = r |> Seq.toArray
+
+ let inline min (t : __rangeset__) = t.Min
+ let inline max (t : __rangeset__) = t.Max
+ let inline range (t : __rangeset__) = t.Range
+
+ let window (window : __range__) (set : __rangeset__) =
+ let rangeMax = window.Max + __one__
+
+ let (l,rest) = set.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo window.Min > 0) minRange
+ let (inner,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax >= 0) minRange
+
+ let inner =
+ match FingerTreeNode.lastOpt l with
+ | Some (Geq _) -> FingerTreeNode.prepend mm (geq window.Min) inner
+ | _ -> inner
+
+ let inner =
+ match FingerTreeNode.firstOpt r with
+ | Some (Leq _) -> FingerTreeNode.append mm (leq rangeMax) inner
+ | _ -> inner
+
+ { root = inner }
+
+//# }
\ No newline at end of file
diff --git a/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_auto.fs b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_auto.fs
index 0eff6f368..20320d66b 100644
--- a/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_auto.fs
+++ b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_auto.fs
@@ -3,447 +3,1844 @@ namespace Aardvark.Base
open System
open System.Collections
open System.Collections.Generic
-open FingerTreeImplementation
+open Aardvark.Base
-[]
-type private HalfRange =
- struct
- val mutable public IsMax : bool
- val mutable public Value : int32
+type internal HalfRangeKind =
+ | Left = 0
+ | Right = 1
- new(m,v) = { IsMax = m; Value = v }
+module private RangeSetUtils =
- override x.GetHashCode() =
- if x.IsMax then 0
- else x.Value.GetHashCode()
+ let inline inc (value : 'T) =
+ let res = value + LanguagePrimitives.GenericOne<'T>
+ if res = Constant<'T>.ParseableMinValue then struct (Constant<'T>.ParseableMaxValue, true)
+ else struct (res, false)
- override x.Equals o =
- match o with
- | :? HalfRange as o ->
- x.IsMax = o.IsMax && x.Value = o.Value
- | _ ->
- false
+ module MapExt =
+ let inline splitAt (key : 'K) (map : MapExt<'K, 'V>) =
+ let struct (l, _, _, _, r) = MapExt.splitV key map
+ struct (l, r)
- member x.CompareTo (o : HalfRange) =
- let c = x.Value.CompareTo o.Value
- if c = 0 then
- if x.IsMax = o.IsMax then 0
- else (if x.IsMax then 1 else -1)
- else
- c
+ let inline tryMinValue (map : MapExt<'K, 'V>) =
+ MapExt.tryMinV map |> ValueOption.map (fun mk -> map.[mk])
- interface IComparable with
- member x.CompareTo o =
- match o with
- | :? HalfRange as o -> x.CompareTo(o)
- | _ -> failwith "uncomparable"
- end
+ let inline tryMaxValue (map : MapExt<'K, 'V>) =
+ MapExt.tryMaxV map |> ValueOption.map (fun mk -> map.[mk])
+
+ let inline maxValue (map : MapExt<'K, 'V>) =
+ map.[MapExt.max map]
+open RangeSetUtils
+/// Set of ranges where overlapping and neighboring ranges are coalesced.
+/// Note that ranges describe closed intervals.
[]
-type RangeSet = private { root : FingerTreeNode } with
-
- member private x.AsString =
- x |> Seq.map (sprintf "%A")
- |> String.concat "; "
- |> sprintf "set [%s]"
+type RangeSet1i internal (store : MapExt) =
+ static let empty = RangeSet1i(MapExt.empty)
+ /// Empty range set.
+ static member Empty = empty
+
+ member inline private x.Store = store
+
+ // We cannot directly describe a range that ends at Int32.MaxValue since the right half-range is inserted
+ // at max + 1. In that case the right-half range will be missing and the total count is odd.
+ member inline private x.HasMaxValue = store.Count % 2 = 1
+
+ /// Returns the minimum value in the range set or Int32.MaxValue if the range is empty.
member x.Min =
- match x.root |> FingerTreeNode.firstOpt with
- | Some f -> f.Value
+ match store.TryMinKeyV with
+ | ValueSome min -> min
| _ -> Int32.MaxValue
+ /// Returns the maximum value in the range set or Int32.MinValue if the range is empty.
member x.Max =
- match x.root |> FingerTreeNode.lastOpt with
- | Some f -> f.Value
- | _ -> Int32.MinValue
+ if x.HasMaxValue then Int32.MaxValue
+ else
+ match store.TryMaxKeyV with
+ | ValueSome max -> max - 1
+ | _ -> Int32.MinValue
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ member inline x.Range =
+ Range1i(x.Min, x.Max)
+
+ /// Adds the given range to the set.
+ member x.Add(r : Range1i) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained Int32.MaxValue or we have overflown, we must not add an explicit right half-range.
+ // Int32.MaxValue is stored implicitly.
+ let fixRightBoundary =
+ if x.HasMaxValue || overflow then
+ id
+ else
+ MapExt.add max HalfRangeKind.Right
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.ofListV [
+ struct (min, HalfRangeKind.Left)
+ ]
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Left
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> fixRightBoundary
+
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+ |> MapExt.add max HalfRangeKind.Right
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ MapExt.union lm rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1i(newStore)
+
+ /// Removes the given range from the set.
+ member x.Remove(r : Range1i) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained Int32.MaxValue and we have not overflown, there is still a range [max, Int32.MaxValue]
+ let fixRightBoundary =
+ if x.HasMaxValue && not overflow then
+ MapExt.add max HalfRangeKind.Left
+ else
+ id
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.empty
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Right
+ |> fixRightBoundary
+
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add max HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ MapExt.union lm rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1i(newStore)
+
+ /// Returns the union of the set with the given set.
+ member inline x.Union(other : RangeSet1i) =
+ let mutable res = x
+ for r in other do
+ res <- res.Add r
+ res
+
+ /// Returns the intersection of the set with the given range.
+ member x.Intersect(r : Range1i) =
+ if r.Max < r.Min then
+ empty
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let inner =
+ store
+ |> MapExt.splitAt min |> sndv
+ |> if not overflow then MapExt.splitAt max >> fstv else id
+
+ let newStore =
+ inner
+ |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id
+ |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1i(newStore)
+
+ member private x.TryFindLeftBoundary(v : int32) =
+ let struct (l, s, _) = MapExt.neighboursV v store
+ match s with
+ | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone
+ | _ ->
+ match l with
+ | ValueSome (i, HalfRangeKind.Left) -> ValueSome i
+ | _ -> ValueNone
+
+ /// Returns whether the given value is contained in the range set.
+ member x.Contains(v : int32) =
+ x.TryFindLeftBoundary v |> ValueOption.isSome
+
+ /// Returns whether the given range is contained in the set.
+ member x.Contains(r : Range1i) =
+ if r.Max < r.Min then false
+ elif r.Min = r.Max then x.Contains r.Min
+ else
+ match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with
+ | ValueSome l, ValueSome r -> l = r
+ | _ -> false
+
+ /// Returns the number of disjoint ranges in the set.
+ member x.Count =
+ (store.Count + 1) / 2
+
+ /// Returns whether the set is empty.
+ member inline x.IsEmpty =
+ x.Count = 0
+
+ /// Builds an array from the range set.
+ member x.ToArray() =
+ let arr = Array.zeroCreate x.Count
+
+ let rec write (i : int) (l : struct (int32 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ arr.[i] <- Range1i(l, r - 1)
+ write (i + 1) rest
+
+ | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->
+ arr.[i] <- Range1i(l, Int32.MaxValue)
+
+ | [_] -> failwith "bad RangeSet"
- member x.Range =
- match FingerTreeNode.firstOpt x.root, FingerTreeNode.lastOpt x.root with
- | Some min, Some max -> Range1i(min.Value, max.Value)
- | _ -> Range1i.Invalid
+ | [] -> ()
+
+ store |> MapExt.toListV |> write 0
+ arr
+
+ /// Builds a list from the range set.
+ member x.ToList() =
+ let rec build (accum : Range1i list) (l : struct (int32 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ build (Range1i(l, r - 1) :: accum) rest
+
+ | [struct (l, HalfRangeKind.Left)] ->
+ build (Range1i(l, Int32.MaxValue) :: accum) []
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> List.rev accum
+
+ store |> MapExt.toListV |> build []
+
+ /// Views the range set as a sequence.
+ member x.ToSeq() =
+ x :> seq<_>
+
+ member inline private x.Equals(other : RangeSet1i) =
+ store = other.Store
+
+ override x.Equals(other : obj) =
+ match other with
+ | :? RangeSet1i as o -> x.Equals o
+ | _ -> false
+
+ override x.GetHashCode() =
+ store.GetHashCode()
+
+ member private x.AsString = x.ToString()
+
+ override x.ToString() =
+ let content =
+ x |> Seq.map (fun r ->
+ $"[{r.Min}, {r.Max}]"
+ )
+ |> String.concat "; "
+
+ $"ranges [{content}]"
+
+ member x.GetEnumerator() =
+ new RangeSetEnumerator1i((store :> seq<_>).GetEnumerator())
+
+ interface IEquatable with
+ member x.Equals(other) = x.Equals(other)
interface IEnumerable with
- member x.GetEnumerator() = new RangeSetEnumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> IEnumerator
+ member x.GetEnumerator() = new RangeSetEnumerator1i((store :> seq<_>).GetEnumerator()) :> _
interface IEnumerable with
- member x.GetEnumerator() = new RangeSetEnumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> _
-
+ member x.GetEnumerator() = new RangeSetEnumerator1i((store :> seq<_>).GetEnumerator()) :> _
-and private RangeSetEnumerator(i : IEnumerator) =
-
- let mutable last = HalfRange()
- let mutable current = HalfRange()
+// TODO: MapExt should use a struct enumerator and return it directly.
+// That way we could get rid of allocations.
+and RangeSetEnumerator1i =
+ struct
+ val private Inner : IEnumerator>
+ val mutable private Left : KeyValuePair
+ val mutable private Right : KeyValuePair
- member x.Current = Range1i(last.Value, current.Value - 1)
+ internal new (inner : IEnumerator>) =
+ { Inner = inner
+ Left = Unchecked.defaultof<_>
+ Right = Unchecked.defaultof<_> }
- interface IEnumerator with
member x.MoveNext() =
- if i.MoveNext() then
- last <- i.Current
- if i.MoveNext() then
- current <- i.Current
+ if x.Inner.MoveNext() then
+ x.Left <- x.Inner.Current
+ if x.Inner.MoveNext() then
+ x.Right <- x.Inner.Current
true
else
- false
+ if x.Left.Value = HalfRangeKind.Left then
+ x.Right <- KeyValuePair(Int32.MinValue, HalfRangeKind.Right) // MaxValue + 1
+ true
+ else
+ failwithf "bad RangeSet"
else
false
- member x.Current = x.Current :> obj
-
member x.Reset() =
- i.Reset()
-
- interface IEnumerator with
- member x.Current = x.Current
- member x.Dispose() = i.Dispose()
+ x.Inner.Reset()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ member x.Current =
+ assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)
+ Range1i(x.Left.Key, x.Right.Key - 1)
+
+ member x.Dispose() =
+ x.Inner.Dispose()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member x.MoveNext() = x.MoveNext()
+ member x.Current = x.Current :> obj
+ member x.Reset() = x.Reset()
+
+ interface IEnumerator with
+ member x.Dispose() = x.Dispose()
+ member x.Current = x.Current
+ end
[]
-module RangeSet =
- let private mm =
- {
- quantify = fun (r : HalfRange) -> r
- mempty = HalfRange(false, Int32.MinValue)
- mappend = fun l r -> if l.CompareTo r > 0 then l else r
- }
+module RangeSet1i =
+
+ /// Empty range set.
+ let empty = RangeSet1i.Empty
+
+ /// Returns the minimum value in the range set or Int32.MaxValue if the range is empty.
+ let inline min (set : RangeSet1i) = set.Min
+
+ /// Returns the maximum value in the range set or Int32.MinValue if the range is empty.
+ let inline max (set : RangeSet1i) = set.Max
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ let inline range (set : RangeSet1i) = set.Range
+
+ let inline private getHalfRanges (r : Range1i) =
+ [ struct (r.Min, HalfRangeKind.Left)
+ if r.Max < Int32.MaxValue then struct (r.Max + 1, HalfRangeKind.Right) ]
+
+ let inline private ofRange (r : Range1i) =
+ RangeSet1i(MapExt.ofListV <| getHalfRanges r)
+
+ let private ofRanges (ranges : seq) =
+ let halves =
+ ranges
+ |> Seq.toList
+ |> List.collect getHalfRanges
+ |> List.sortBy fstv
+
+ let mutable level = 0
+ let result = ResizeArray()
+
+ for (struct (i, k) as h) in halves do
+ if k = HalfRangeKind.Left then
+ if level = 0 then result.Add h
+ level <- level + 1
+ else
+ level <- level - 1
+ if level = 0 then result.Add h
+
+ RangeSet1i(MapExt.ofSeqV result)
+
+ /// Builds a range set of the given list of ranges.
+ let ofList (ranges : Range1i list) =
+ match ranges with
+ | [] -> empty
+ | [r] -> ofRange r
+ | _ -> ofRanges ranges
+
+ /// Builds a range set of the given array of ranges.
+ let ofArray (ranges : Range1i[]) =
+ if ranges.Length = 0 then empty
+ elif ranges.Length = 1 then ofRange ranges.[0]
+ else ofRanges ranges
+
+ /// Builds a range set of the given sequence of ranges.
+ let inline ofSeq (ranges : seq) =
+ ofList <| Seq.toList ranges
+
+ /// Adds the given range to the set.
+ let inline add (range : Range1i) (set : RangeSet1i) = set.Add range
- let private minRange = HalfRange(false, Int32.MinValue)
+ []
+ let inline insert (range : Range1i) (set : RangeSet1i) = set.Add range
- let inline private leq v = HalfRange(true, v)
- let inline private geq v = HalfRange(false, v)
+ /// Removes the given range from the set.
+ let inline remove (range : Range1i) (set : RangeSet1i) = set.Remove range
- let inline private (|Leq|Geq|) (r : HalfRange) =
- if r.IsMax then Leq r.Value
- else Geq r.Value
+ /// Returns the union of two sets.
+ let inline union (l : RangeSet1i) (r : RangeSet1i) = l.Union r
- let empty = { root = Empty }
+ /// Returns the intersection of the set with the given range.
+ let inline intersect (range : Range1i) (set : RangeSet1i) = set.Intersect range
- let insert (range : Range1i) (t : RangeSet) =
- let rangeMax = range.Max + 1
+ []
+ let inline window (range : Range1i) (set : RangeSet1i) = intersect range set
- let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
- let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+ /// Returns whether the given value is contained in the range set.
+ let inline contains (value : int32) (set : RangeSet1i) = set.Contains value
- let max = leq rangeMax
- let min = geq range.Min
+ /// Returns whether the given range is contained in the set.
+ let inline containsRange (range : Range1i) (set : RangeSet1i) = set.Contains range
- match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
- | None, None ->
- { root = Deep(max, One(min), Empty, One(max)) }
+ /// Returns the number of disjoint ranges in the set.
+ let inline count (set : RangeSet1i) = set.Count
- | Some lmax, None ->
- match lmax with
- | Leq _ -> { root = l |> FingerTreeNode.append mm min |> FingerTreeNode.append mm max }
- | Geq _ -> { root = l |> FingerTreeNode.append mm max }
+ /// Returns whether the set is empty.
+ let inline isEmpty (set : RangeSet1i) = set.IsEmpty
- | None, Some rmin ->
- match rmin with
- | Leq _ -> { root = r |> FingerTreeNode.prepend mm min }
- | Geq _ -> { root = r |> FingerTreeNode.prepend mm max |> FingerTreeNode.prepend mm min }
+ /// Views the range set as a sequence.
+ let inline toSeq (set : RangeSet1i) = set :> seq<_>
- | Some lmax, Some rmin ->
- match lmax, rmin with
- | Leq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min;max] r }
+ /// Builds a list from the range set.
+ let inline toList (set : RangeSet1i) = set.ToList()
- | Geq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [] r }
+ /// Builds an array from the range set.
+ let inline toArray (set : RangeSet1i) = set.ToArray()
- | Leq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min] r }
- | Geq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+/// Set of ranges where overlapping and neighboring ranges are coalesced.
+/// Note that ranges describe closed intervals.
+[]
+type RangeSet1ui internal (store : MapExt) =
+ static let empty = RangeSet1ui(MapExt.empty)
+
+ /// Empty range set.
+ static member Empty = empty
+
+ member inline private x.Store = store
+
+ // We cannot directly describe a range that ends at UInt32.MaxValue since the right half-range is inserted
+ // at max + 1. In that case the right-half range will be missing and the total count is odd.
+ member inline private x.HasMaxValue = store.Count % 2 = 1
+
+ /// Returns the minimum value in the range set or UInt32.MaxValue if the range is empty.
+ member x.Min =
+ match store.TryMinKeyV with
+ | ValueSome min -> min
+ | _ -> UInt32.MaxValue
+
+ /// Returns the maximum value in the range set or UInt32.MinValue if the range is empty.
+ member x.Max =
+ if x.HasMaxValue then UInt32.MaxValue
+ else
+ match store.TryMaxKeyV with
+ | ValueSome max -> max - 1u
+ | _ -> UInt32.MinValue
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ member inline x.Range =
+ Range1ui(x.Min, x.Max)
+
+ /// Adds the given range to the set.
+ member x.Add(r : Range1ui) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained UInt32.MaxValue or we have overflown, we must not add an explicit right half-range.
+ // UInt32.MaxValue is stored implicitly.
+ let fixRightBoundary =
+ if x.HasMaxValue || overflow then
+ id
+ else
+ MapExt.add max HalfRangeKind.Right
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.ofListV [
+ struct (min, HalfRangeKind.Left)
+ ]
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Left
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> fixRightBoundary
+
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+ |> MapExt.add max HalfRangeKind.Right
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ MapExt.union lm rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1ui(newStore)
+
+ /// Removes the given range from the set.
+ member x.Remove(r : Range1ui) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained UInt32.MaxValue and we have not overflown, there is still a range [max, UInt32.MaxValue]
+ let fixRightBoundary =
+ if x.HasMaxValue && not overflow then
+ MapExt.add max HalfRangeKind.Left
+ else
+ id
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.empty
+ |> fixRightBoundary
- let remove (range : Range1i) (t : RangeSet) =
- let rangeMax = range.Max + 1
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> fixRightBoundary
- let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
- let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Right
+ |> fixRightBoundary
- let max = geq rangeMax
- let min = leq range.Min
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
- match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
- | None, None ->
- { root = Empty }
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add max HalfRangeKind.Left
- | Some lmax, None ->
- match lmax with
- | Leq _ -> { root = l }
- | Geq _ -> { root = l |> FingerTreeNode.append mm min }
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ MapExt.union lm rm
- | None, Some rmin ->
- match rmin with
- | Leq _ -> { root = r |> FingerTreeNode.prepend mm max }
- | Geq _ -> { root = r }
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
- | Some lmax, Some rmin ->
- match lmax, rmin with
- | Leq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [] r }
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
- | Geq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min; max] r }
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
- | Leq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+ | _ ->
+ failwithf "impossible"
- | Geq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1ui(newStore)
- let ofSeq (s : seq) =
- let mutable res = empty
- for e in s do res <- insert e res
+ /// Returns the union of the set with the given set.
+ member inline x.Union(other : RangeSet1ui) =
+ let mutable res = x
+ for r in other do
+ res <- res.Add r
res
- let inline ofList (l : list) = ofSeq l
- let inline ofArray (l : Range1i[]) = ofSeq l
+ /// Returns the intersection of the set with the given range.
+ member x.Intersect(r : Range1ui) =
+ if r.Max < r.Min then
+ empty
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let inner =
+ store
+ |> MapExt.splitAt min |> sndv
+ |> if not overflow then MapExt.splitAt max >> fstv else id
- let toSeq (r : RangeSet) = r :> seq<_>
- let toList (r : RangeSet) = r |> Seq.toList
- let toArray (r : RangeSet) = r |> Seq.toArray
+ let newStore =
+ inner
+ |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id
+ |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id
- let inline min (t : RangeSet) = t.Min
- let inline max (t : RangeSet) = t.Max
- let inline range (t : RangeSet) = t.Range
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1ui(newStore)
- let window (window : Range1i) (set : RangeSet) =
- let rangeMax = window.Max + 1
+ member private x.TryFindLeftBoundary(v : uint32) =
+ let struct (l, s, _) = MapExt.neighboursV v store
+ match s with
+ | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone
+ | _ ->
+ match l with
+ | ValueSome (i, HalfRangeKind.Left) -> ValueSome i
+ | _ -> ValueNone
- let (l,rest) = set.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo window.Min > 0) minRange
- let (inner,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax >= 0) minRange
+ /// Returns whether the given value is contained in the range set.
+ member x.Contains(v : uint32) =
+ x.TryFindLeftBoundary v |> ValueOption.isSome
- let inner =
- match FingerTreeNode.lastOpt l with
- | Some (Geq _) -> FingerTreeNode.prepend mm (geq window.Min) inner
- | _ -> inner
+ /// Returns whether the given range is contained in the set.
+ member x.Contains(r : Range1ui) =
+ if r.Max < r.Min then false
+ elif r.Min = r.Max then x.Contains r.Min
+ else
+ match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with
+ | ValueSome l, ValueSome r -> l = r
+ | _ -> false
- let inner =
- match FingerTreeNode.firstOpt r with
- | Some (Leq _) -> FingerTreeNode.append mm (leq rangeMax) inner
- | _ -> inner
+ /// Returns the number of disjoint ranges in the set.
+ member x.Count =
+ (store.Count + 1) / 2
- { root = inner }
+ /// Returns whether the set is empty.
+ member inline x.IsEmpty =
+ x.Count = 0
-[]
-type private HalfRange64 =
- struct
- val mutable public IsMax : bool
- val mutable public Value : int64
+ /// Builds an array from the range set.
+ member x.ToArray() =
+ let arr = Array.zeroCreate x.Count
- new(m,v) = { IsMax = m; Value = v }
+ let rec write (i : int) (l : struct (uint32 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ arr.[i] <- Range1ui(l, r - 1u)
+ write (i + 1) rest
- override x.GetHashCode() =
- if x.IsMax then 0
- else x.Value.GetHashCode()
+ | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->
+ arr.[i] <- Range1ui(l, UInt32.MaxValue)
- override x.Equals o =
- match o with
- | :? HalfRange64 as o ->
- x.IsMax = o.IsMax && x.Value = o.Value
- | _ ->
- false
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> ()
+
+ store |> MapExt.toListV |> write 0
+ arr
+
+ /// Builds a list from the range set.
+ member x.ToList() =
+ let rec build (accum : Range1ui list) (l : struct (uint32 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ build (Range1ui(l, r - 1u) :: accum) rest
+
+ | [struct (l, HalfRangeKind.Left)] ->
+ build (Range1ui(l, UInt32.MaxValue) :: accum) []
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> List.rev accum
+
+ store |> MapExt.toListV |> build []
+
+ /// Views the range set as a sequence.
+ member x.ToSeq() =
+ x :> seq<_>
+
+ member inline private x.Equals(other : RangeSet1ui) =
+ store = other.Store
+
+ override x.Equals(other : obj) =
+ match other with
+ | :? RangeSet1ui as o -> x.Equals o
+ | _ -> false
+
+ override x.GetHashCode() =
+ store.GetHashCode()
+
+ member private x.AsString = x.ToString()
+
+ override x.ToString() =
+ let content =
+ x |> Seq.map (fun r ->
+ $"[{r.Min}, {r.Max}]"
+ )
+ |> String.concat "; "
+
+ $"ranges [{content}]"
+
+ member x.GetEnumerator() =
+ new RangeSetEnumerator1ui((store :> seq<_>).GetEnumerator())
+
+ interface IEquatable with
+ member x.Equals(other) = x.Equals(other)
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSetEnumerator1ui((store :> seq<_>).GetEnumerator()) :> _
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSetEnumerator1ui((store :> seq<_>).GetEnumerator()) :> _
+
+// TODO: MapExt should use a struct enumerator and return it directly.
+// That way we could get rid of allocations.
+and RangeSetEnumerator1ui =
+ struct
+ val private Inner : IEnumerator>
+ val mutable private Left : KeyValuePair
+ val mutable private Right : KeyValuePair
+
+ internal new (inner : IEnumerator>) =
+ { Inner = inner
+ Left = Unchecked.defaultof<_>
+ Right = Unchecked.defaultof<_> }
- member x.CompareTo (o : HalfRange64) =
- let c = x.Value.CompareTo o.Value
- if c = 0 then
- if x.IsMax = o.IsMax then 0
- else (if x.IsMax then 1 else -1)
+ member x.MoveNext() =
+ if x.Inner.MoveNext() then
+ x.Left <- x.Inner.Current
+ if x.Inner.MoveNext() then
+ x.Right <- x.Inner.Current
+ true
+ else
+ if x.Left.Value = HalfRangeKind.Left then
+ x.Right <- KeyValuePair(UInt32.MinValue, HalfRangeKind.Right) // MaxValue + 1
+ true
+ else
+ failwithf "bad RangeSet"
else
- c
+ false
- interface IComparable with
- member x.CompareTo o =
- match o with
- | :? HalfRange64 as o -> x.CompareTo(o)
- | _ -> failwith "uncomparable"
+ member x.Reset() =
+ x.Inner.Reset()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ member x.Current =
+ assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)
+ Range1ui(x.Left.Key, x.Right.Key - 1u)
+
+ member x.Dispose() =
+ x.Inner.Dispose()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member x.MoveNext() = x.MoveNext()
+ member x.Current = x.Current :> obj
+ member x.Reset() = x.Reset()
+
+ interface IEnumerator with
+ member x.Dispose() = x.Dispose()
+ member x.Current = x.Current
end
+[]
+module RangeSet1ui =
+
+ /// Empty range set.
+ let empty = RangeSet1ui.Empty
+
+ /// Returns the minimum value in the range set or UInt32.MaxValue if the range is empty.
+ let inline min (set : RangeSet1ui) = set.Min
+
+ /// Returns the maximum value in the range set or UInt32.MinValue if the range is empty.
+ let inline max (set : RangeSet1ui) = set.Max
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ let inline range (set : RangeSet1ui) = set.Range
+
+ let inline private getHalfRanges (r : Range1ui) =
+ [ struct (r.Min, HalfRangeKind.Left)
+ if r.Max < UInt32.MaxValue then struct (r.Max + 1u, HalfRangeKind.Right) ]
+
+ let inline private ofRange (r : Range1ui) =
+ RangeSet1ui(MapExt.ofListV <| getHalfRanges r)
+
+ let private ofRanges (ranges : seq) =
+ let halves =
+ ranges
+ |> Seq.toList
+ |> List.collect getHalfRanges
+ |> List.sortBy fstv
+
+ let mutable level = 0
+ let result = ResizeArray()
+
+ for (struct (i, k) as h) in halves do
+ if k = HalfRangeKind.Left then
+ if level = 0 then result.Add h
+ level <- level + 1
+ else
+ level <- level - 1
+ if level = 0 then result.Add h
+
+ RangeSet1ui(MapExt.ofSeqV result)
+
+ /// Builds a range set of the given list of ranges.
+ let ofList (ranges : Range1ui list) =
+ match ranges with
+ | [] -> empty
+ | [r] -> ofRange r
+ | _ -> ofRanges ranges
+ /// Builds a range set of the given array of ranges.
+ let ofArray (ranges : Range1ui[]) =
+ if ranges.Length = 0 then empty
+ elif ranges.Length = 1 then ofRange ranges.[0]
+ else ofRanges ranges
+
+ /// Builds a range set of the given sequence of ranges.
+ let inline ofSeq (ranges : seq) =
+ ofList <| Seq.toList ranges
+
+ /// Adds the given range to the set.
+ let inline add (range : Range1ui) (set : RangeSet1ui) = set.Add range
+
+ []
+ let inline insert (range : Range1ui) (set : RangeSet1ui) = set.Add range
+
+ /// Removes the given range from the set.
+ let inline remove (range : Range1ui) (set : RangeSet1ui) = set.Remove range
+
+ /// Returns the union of two sets.
+ let inline union (l : RangeSet1ui) (r : RangeSet1ui) = l.Union r
+
+ /// Returns the intersection of the set with the given range.
+ let inline intersect (range : Range1ui) (set : RangeSet1ui) = set.Intersect range
+
+ []
+ let inline window (range : Range1ui) (set : RangeSet1ui) = intersect range set
+
+ /// Returns whether the given value is contained in the range set.
+ let inline contains (value : uint32) (set : RangeSet1ui) = set.Contains value
+
+ /// Returns whether the given range is contained in the set.
+ let inline containsRange (range : Range1ui) (set : RangeSet1ui) = set.Contains range
+
+ /// Returns the number of disjoint ranges in the set.
+ let inline count (set : RangeSet1ui) = set.Count
+
+ /// Returns whether the set is empty.
+ let inline isEmpty (set : RangeSet1ui) = set.IsEmpty
+
+ /// Views the range set as a sequence.
+ let inline toSeq (set : RangeSet1ui) = set :> seq<_>
+
+ /// Builds a list from the range set.
+ let inline toList (set : RangeSet1ui) = set.ToList()
+
+ /// Builds an array from the range set.
+ let inline toArray (set : RangeSet1ui) = set.ToArray()
+
+
+/// Set of ranges where overlapping and neighboring ranges are coalesced.
+/// Note that ranges describe closed intervals.
[]
-type RangeSet64 = private { root : FingerTreeNode } with
-
- member private x.AsString =
- x |> Seq.map (sprintf "%A")
- |> String.concat "; "
- |> sprintf "set [%s]"
+type RangeSet1l internal (store : MapExt) =
+ static let empty = RangeSet1l(MapExt.empty)
+
+ /// Empty range set.
+ static member Empty = empty
+ member inline private x.Store = store
+
+ // We cannot directly describe a range that ends at Int64.MaxValue since the right half-range is inserted
+ // at max + 1. In that case the right-half range will be missing and the total count is odd.
+ member inline private x.HasMaxValue = store.Count % 2 = 1
+
+ /// Returns the minimum value in the range set or Int64.MaxValue if the range is empty.
member x.Min =
- match x.root |> FingerTreeNode.firstOpt with
- | Some f -> f.Value
+ match store.TryMinKeyV with
+ | ValueSome min -> min
| _ -> Int64.MaxValue
+ /// Returns the maximum value in the range set or Int64.MinValue if the range is empty.
member x.Max =
- match x.root |> FingerTreeNode.lastOpt with
- | Some f -> f.Value
- | _ -> Int64.MinValue
+ if x.HasMaxValue then Int64.MaxValue
+ else
+ match store.TryMaxKeyV with
+ | ValueSome max -> max - 1L
+ | _ -> Int64.MinValue
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ member inline x.Range =
+ Range1l(x.Min, x.Max)
+
+ /// Adds the given range to the set.
+ member x.Add(r : Range1l) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained Int64.MaxValue or we have overflown, we must not add an explicit right half-range.
+ // Int64.MaxValue is stored implicitly.
+ let fixRightBoundary =
+ if x.HasMaxValue || overflow then
+ id
+ else
+ MapExt.add max HalfRangeKind.Right
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.ofListV [
+ struct (min, HalfRangeKind.Left)
+ ]
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Left
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> fixRightBoundary
+
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+ |> MapExt.add max HalfRangeKind.Right
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ MapExt.union lm rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1l(newStore)
+
+ /// Removes the given range from the set.
+ member x.Remove(r : Range1l) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained Int64.MaxValue and we have not overflown, there is still a range [max, Int64.MaxValue]
+ let fixRightBoundary =
+ if x.HasMaxValue && not overflow then
+ MapExt.add max HalfRangeKind.Left
+ else
+ id
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.empty
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Right
+ |> fixRightBoundary
+
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add max HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ MapExt.union lm rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1l(newStore)
+
+ /// Returns the union of the set with the given set.
+ member inline x.Union(other : RangeSet1l) =
+ let mutable res = x
+ for r in other do
+ res <- res.Add r
+ res
+
+ /// Returns the intersection of the set with the given range.
+ member x.Intersect(r : Range1l) =
+ if r.Max < r.Min then
+ empty
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let inner =
+ store
+ |> MapExt.splitAt min |> sndv
+ |> if not overflow then MapExt.splitAt max >> fstv else id
+
+ let newStore =
+ inner
+ |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id
+ |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1l(newStore)
+
+ member private x.TryFindLeftBoundary(v : int64) =
+ let struct (l, s, _) = MapExt.neighboursV v store
+ match s with
+ | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone
+ | _ ->
+ match l with
+ | ValueSome (i, HalfRangeKind.Left) -> ValueSome i
+ | _ -> ValueNone
+
+ /// Returns whether the given value is contained in the range set.
+ member x.Contains(v : int64) =
+ x.TryFindLeftBoundary v |> ValueOption.isSome
+
+ /// Returns whether the given range is contained in the set.
+ member x.Contains(r : Range1l) =
+ if r.Max < r.Min then false
+ elif r.Min = r.Max then x.Contains r.Min
+ else
+ match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with
+ | ValueSome l, ValueSome r -> l = r
+ | _ -> false
+
+ /// Returns the number of disjoint ranges in the set.
+ member x.Count =
+ (store.Count + 1) / 2
+
+ /// Returns whether the set is empty.
+ member inline x.IsEmpty =
+ x.Count = 0
+
+ /// Builds an array from the range set.
+ member x.ToArray() =
+ let arr = Array.zeroCreate x.Count
+
+ let rec write (i : int) (l : struct (int64 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ arr.[i] <- Range1l(l, r - 1L)
+ write (i + 1) rest
+
+ | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->
+ arr.[i] <- Range1l(l, Int64.MaxValue)
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> ()
+
+ store |> MapExt.toListV |> write 0
+ arr
+
+ /// Builds a list from the range set.
+ member x.ToList() =
+ let rec build (accum : Range1l list) (l : struct (int64 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ build (Range1l(l, r - 1L) :: accum) rest
+
+ | [struct (l, HalfRangeKind.Left)] ->
+ build (Range1l(l, Int64.MaxValue) :: accum) []
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> List.rev accum
- member x.Range =
- match FingerTreeNode.firstOpt x.root, FingerTreeNode.lastOpt x.root with
- | Some min, Some max -> Range1l(min.Value, max.Value)
- | _ -> Range1l.Invalid
+ store |> MapExt.toListV |> build []
+
+ /// Views the range set as a sequence.
+ member x.ToSeq() =
+ x :> seq<_>
+
+ member inline private x.Equals(other : RangeSet1l) =
+ store = other.Store
+
+ override x.Equals(other : obj) =
+ match other with
+ | :? RangeSet1l as o -> x.Equals o
+ | _ -> false
+
+ override x.GetHashCode() =
+ store.GetHashCode()
+
+ member private x.AsString = x.ToString()
+
+ override x.ToString() =
+ let content =
+ x |> Seq.map (fun r ->
+ $"[{r.Min}, {r.Max}]"
+ )
+ |> String.concat "; "
+
+ $"ranges [{content}]"
+
+ member x.GetEnumerator() =
+ new RangeSetEnumerator1l((store :> seq<_>).GetEnumerator())
+
+ interface IEquatable with
+ member x.Equals(other) = x.Equals(other)
interface IEnumerable with
- member x.GetEnumerator() = new RangeSet64Enumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> IEnumerator
+ member x.GetEnumerator() = new RangeSetEnumerator1l((store :> seq<_>).GetEnumerator()) :> _
interface IEnumerable with
- member x.GetEnumerator() = new RangeSet64Enumerator(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> _
+ member x.GetEnumerator() = new RangeSetEnumerator1l((store :> seq<_>).GetEnumerator()) :> _
+// TODO: MapExt should use a struct enumerator and return it directly.
+// That way we could get rid of allocations.
+and RangeSetEnumerator1l =
+ struct
+ val private Inner : IEnumerator>
+ val mutable private Left : KeyValuePair
+ val mutable private Right : KeyValuePair
-and private RangeSet64Enumerator(i : IEnumerator) =
-
- let mutable last = HalfRange64()
- let mutable current = HalfRange64()
-
- member x.Current = Range1l(last.Value, current.Value - 1L)
+ internal new (inner : IEnumerator>) =
+ { Inner = inner
+ Left = Unchecked.defaultof<_>
+ Right = Unchecked.defaultof<_> }
- interface IEnumerator with
member x.MoveNext() =
- if i.MoveNext() then
- last <- i.Current
- if i.MoveNext() then
- current <- i.Current
+ if x.Inner.MoveNext() then
+ x.Left <- x.Inner.Current
+ if x.Inner.MoveNext() then
+ x.Right <- x.Inner.Current
true
else
- false
+ if x.Left.Value = HalfRangeKind.Left then
+ x.Right <- KeyValuePair(Int64.MinValue, HalfRangeKind.Right) // MaxValue + 1
+ true
+ else
+ failwithf "bad RangeSet"
else
false
- member x.Current = x.Current :> obj
-
member x.Reset() =
- i.Reset()
-
- interface IEnumerator with
- member x.Current = x.Current
- member x.Dispose() = i.Dispose()
+ x.Inner.Reset()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ member x.Current =
+ assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)
+ Range1l(x.Left.Key, x.Right.Key - 1L)
+
+ member x.Dispose() =
+ x.Inner.Dispose()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member x.MoveNext() = x.MoveNext()
+ member x.Current = x.Current :> obj
+ member x.Reset() = x.Reset()
+
+ interface IEnumerator with
+ member x.Dispose() = x.Dispose()
+ member x.Current = x.Current
+ end
[]
-module RangeSet64 =
- let private mm =
- {
- quantify = fun (r : HalfRange64) -> r
- mempty = HalfRange64(false, Int64.MinValue)
- mappend = fun l r -> if l.CompareTo r > 0 then l else r
- }
+module RangeSet1l =
+
+ /// Empty range set.
+ let empty = RangeSet1l.Empty
+
+ /// Returns the minimum value in the range set or Int64.MaxValue if the range is empty.
+ let inline min (set : RangeSet1l) = set.Min
+
+ /// Returns the maximum value in the range set or Int64.MinValue if the range is empty.
+ let inline max (set : RangeSet1l) = set.Max
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ let inline range (set : RangeSet1l) = set.Range
+
+ let inline private getHalfRanges (r : Range1l) =
+ [ struct (r.Min, HalfRangeKind.Left)
+ if r.Max < Int64.MaxValue then struct (r.Max + 1L, HalfRangeKind.Right) ]
+
+ let inline private ofRange (r : Range1l) =
+ RangeSet1l(MapExt.ofListV <| getHalfRanges r)
+
+ let private ofRanges (ranges : seq) =
+ let halves =
+ ranges
+ |> Seq.toList
+ |> List.collect getHalfRanges
+ |> List.sortBy fstv
+
+ let mutable level = 0
+ let result = ResizeArray()
+
+ for (struct (i, k) as h) in halves do
+ if k = HalfRangeKind.Left then
+ if level = 0 then result.Add h
+ level <- level + 1
+ else
+ level <- level - 1
+ if level = 0 then result.Add h
+
+ RangeSet1l(MapExt.ofSeqV result)
+
+ /// Builds a range set of the given list of ranges.
+ let ofList (ranges : Range1l list) =
+ match ranges with
+ | [] -> empty
+ | [r] -> ofRange r
+ | _ -> ofRanges ranges
+
+ /// Builds a range set of the given array of ranges.
+ let ofArray (ranges : Range1l[]) =
+ if ranges.Length = 0 then empty
+ elif ranges.Length = 1 then ofRange ranges.[0]
+ else ofRanges ranges
+
+ /// Builds a range set of the given sequence of ranges.
+ let inline ofSeq (ranges : seq) =
+ ofList <| Seq.toList ranges
+
+ /// Adds the given range to the set.
+ let inline add (range : Range1l) (set : RangeSet1l) = set.Add range
+
+ []
+ let inline insert (range : Range1l) (set : RangeSet1l) = set.Add range
+
+ /// Removes the given range from the set.
+ let inline remove (range : Range1l) (set : RangeSet1l) = set.Remove range
+
+ /// Returns the union of two sets.
+ let inline union (l : RangeSet1l) (r : RangeSet1l) = l.Union r
+
+ /// Returns the intersection of the set with the given range.
+ let inline intersect (range : Range1l) (set : RangeSet1l) = set.Intersect range
+
+ []
+ let inline window (range : Range1l) (set : RangeSet1l) = intersect range set
+
+ /// Returns whether the given value is contained in the range set.
+ let inline contains (value : int64) (set : RangeSet1l) = set.Contains value
- let private minRange = HalfRange64(false, Int64.MinValue)
+ /// Returns whether the given range is contained in the set.
+ let inline containsRange (range : Range1l) (set : RangeSet1l) = set.Contains range
- let inline private leq v = HalfRange64(true, v)
- let inline private geq v = HalfRange64(false, v)
+ /// Returns the number of disjoint ranges in the set.
+ let inline count (set : RangeSet1l) = set.Count
- let inline private (|Leq|Geq|) (r : HalfRange64) =
- if r.IsMax then Leq r.Value
- else Geq r.Value
+ /// Returns whether the set is empty.
+ let inline isEmpty (set : RangeSet1l) = set.IsEmpty
- let empty = { root = Empty }
+ /// Views the range set as a sequence.
+ let inline toSeq (set : RangeSet1l) = set :> seq<_>
- let insert (range : Range1l) (t : RangeSet64) =
- let rangeMax = range.Max + 1L
+ /// Builds a list from the range set.
+ let inline toList (set : RangeSet1l) = set.ToList()
- let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
- let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+ /// Builds an array from the range set.
+ let inline toArray (set : RangeSet1l) = set.ToArray()
- let max = leq rangeMax
- let min = geq range.Min
- match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
- | None, None ->
- { root = Deep(max, One(min), Empty, One(max)) }
+/// Set of ranges where overlapping and neighboring ranges are coalesced.
+/// Note that ranges describe closed intervals.
+[]
+type RangeSet1ul internal (store : MapExt) =
+ static let empty = RangeSet1ul(MapExt.empty)
- | Some lmax, None ->
- match lmax with
- | Leq _ -> { root = l |> FingerTreeNode.append mm min |> FingerTreeNode.append mm max }
- | Geq _ -> { root = l |> FingerTreeNode.append mm max }
+ /// Empty range set.
+ static member Empty = empty
- | None, Some rmin ->
- match rmin with
- | Leq _ -> { root = r |> FingerTreeNode.prepend mm min }
- | Geq _ -> { root = r |> FingerTreeNode.prepend mm max |> FingerTreeNode.prepend mm min }
+ member inline private x.Store = store
- | Some lmax, Some rmin ->
- match lmax, rmin with
- | Leq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min;max] r }
+ // We cannot directly describe a range that ends at UInt64.MaxValue since the right half-range is inserted
+ // at max + 1. In that case the right-half range will be missing and the total count is odd.
+ member inline private x.HasMaxValue = store.Count % 2 = 1
- | Geq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [] r }
+ /// Returns the minimum value in the range set or UInt64.MaxValue if the range is empty.
+ member x.Min =
+ match store.TryMinKeyV with
+ | ValueSome min -> min
+ | _ -> UInt64.MaxValue
- | Leq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+ /// Returns the maximum value in the range set or UInt64.MinValue if the range is empty.
+ member x.Max =
+ if x.HasMaxValue then UInt64.MaxValue
+ else
+ match store.TryMaxKeyV with
+ | ValueSome max -> max - 1UL
+ | _ -> UInt64.MinValue
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ member inline x.Range =
+ Range1ul(x.Min, x.Max)
+
+ /// Adds the given range to the set.
+ member x.Add(r : Range1ul) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained UInt64.MaxValue or we have overflown, we must not add an explicit right half-range.
+ // UInt64.MaxValue is stored implicitly.
+ let fixRightBoundary =
+ if x.HasMaxValue || overflow then
+ id
+ else
+ MapExt.add max HalfRangeKind.Right
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.ofListV [
+ struct (min, HalfRangeKind.Left)
+ ]
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Left
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> fixRightBoundary
+
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+ |> MapExt.add max HalfRangeKind.Right
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ MapExt.union lm rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1ul(newStore)
+
+ /// Removes the given range from the set.
+ member x.Remove(r : Range1ul) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained UInt64.MaxValue and we have not overflown, there is still a range [max, UInt64.MaxValue]
+ let fixRightBoundary =
+ if x.HasMaxValue && not overflow then
+ MapExt.add max HalfRangeKind.Left
+ else
+ id
- | Geq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.empty
+ |> fixRightBoundary
- let remove (range : Range1l) (t : RangeSet64) =
- let rangeMax = range.Max + 1L
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> fixRightBoundary
- let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
- let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Right
+ |> fixRightBoundary
- let max = geq rangeMax
- let min = leq range.Min
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
- match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
- | None, None ->
- { root = Empty }
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add max HalfRangeKind.Left
- | Some lmax, None ->
- match lmax with
- | Leq _ -> { root = l }
- | Geq _ -> { root = l |> FingerTreeNode.append mm min }
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ MapExt.union lm rm
- | None, Some rmin ->
- match rmin with
- | Leq _ -> { root = r |> FingerTreeNode.prepend mm max }
- | Geq _ -> { root = r }
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
- | Some lmax, Some rmin ->
- match lmax, rmin with
- | Leq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [] r }
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
- | Geq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min; max] r }
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
- | Leq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+ | _ ->
+ failwithf "impossible"
- | Geq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1ul(newStore)
- let ofSeq (s : seq) =
- let mutable res = empty
- for e in s do res <- insert e res
+ /// Returns the union of the set with the given set.
+ member inline x.Union(other : RangeSet1ul) =
+ let mutable res = x
+ for r in other do
+ res <- res.Add r
res
- let inline ofList (l : list) = ofSeq l
- let inline ofArray (l : Range1l[]) = ofSeq l
+ /// Returns the intersection of the set with the given range.
+ member x.Intersect(r : Range1ul) =
+ if r.Max < r.Min then
+ empty
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let inner =
+ store
+ |> MapExt.splitAt min |> sndv
+ |> if not overflow then MapExt.splitAt max >> fstv else id
+
+ let newStore =
+ inner
+ |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id
+ |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ RangeSet1ul(newStore)
+
+ member private x.TryFindLeftBoundary(v : uint64) =
+ let struct (l, s, _) = MapExt.neighboursV v store
+ match s with
+ | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone
+ | _ ->
+ match l with
+ | ValueSome (i, HalfRangeKind.Left) -> ValueSome i
+ | _ -> ValueNone
+
+ /// Returns whether the given value is contained in the range set.
+ member x.Contains(v : uint64) =
+ x.TryFindLeftBoundary v |> ValueOption.isSome
+
+ /// Returns whether the given range is contained in the set.
+ member x.Contains(r : Range1ul) =
+ if r.Max < r.Min then false
+ elif r.Min = r.Max then x.Contains r.Min
+ else
+ match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with
+ | ValueSome l, ValueSome r -> l = r
+ | _ -> false
+
+ /// Returns the number of disjoint ranges in the set.
+ member x.Count =
+ (store.Count + 1) / 2
+
+ /// Returns whether the set is empty.
+ member inline x.IsEmpty =
+ x.Count = 0
+
+ /// Builds an array from the range set.
+ member x.ToArray() =
+ let arr = Array.zeroCreate x.Count
+
+ let rec write (i : int) (l : struct (uint64 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ arr.[i] <- Range1ul(l, r - 1UL)
+ write (i + 1) rest
+
+ | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->
+ arr.[i] <- Range1ul(l, UInt64.MaxValue)
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> ()
+
+ store |> MapExt.toListV |> write 0
+ arr
+
+ /// Builds a list from the range set.
+ member x.ToList() =
+ let rec build (accum : Range1ul list) (l : struct (uint64 * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ build (Range1ul(l, r - 1UL) :: accum) rest
+
+ | [struct (l, HalfRangeKind.Left)] ->
+ build (Range1ul(l, UInt64.MaxValue) :: accum) []
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> List.rev accum
+
+ store |> MapExt.toListV |> build []
+
+ /// Views the range set as a sequence.
+ member x.ToSeq() =
+ x :> seq<_>
+
+ member inline private x.Equals(other : RangeSet1ul) =
+ store = other.Store
+
+ override x.Equals(other : obj) =
+ match other with
+ | :? RangeSet1ul as o -> x.Equals o
+ | _ -> false
+
+ override x.GetHashCode() =
+ store.GetHashCode()
+
+ member private x.AsString = x.ToString()
+
+ override x.ToString() =
+ let content =
+ x |> Seq.map (fun r ->
+ $"[{r.Min}, {r.Max}]"
+ )
+ |> String.concat "; "
+
+ $"ranges [{content}]"
+
+ member x.GetEnumerator() =
+ new RangeSetEnumerator1ul((store :> seq<_>).GetEnumerator())
+
+ interface IEquatable with
+ member x.Equals(other) = x.Equals(other)
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSetEnumerator1ul((store :> seq<_>).GetEnumerator()) :> _
+
+ interface IEnumerable with
+ member x.GetEnumerator() = new RangeSetEnumerator1ul((store :> seq<_>).GetEnumerator()) :> _
+
+// TODO: MapExt should use a struct enumerator and return it directly.
+// That way we could get rid of allocations.
+and RangeSetEnumerator1ul =
+ struct
+ val private Inner : IEnumerator>
+ val mutable private Left : KeyValuePair
+ val mutable private Right : KeyValuePair
+
+ internal new (inner : IEnumerator>) =
+ { Inner = inner
+ Left = Unchecked.defaultof<_>
+ Right = Unchecked.defaultof<_> }
+
+ member x.MoveNext() =
+ if x.Inner.MoveNext() then
+ x.Left <- x.Inner.Current
+ if x.Inner.MoveNext() then
+ x.Right <- x.Inner.Current
+ true
+ else
+ if x.Left.Value = HalfRangeKind.Left then
+ x.Right <- KeyValuePair(UInt64.MinValue, HalfRangeKind.Right) // MaxValue + 1
+ true
+ else
+ failwithf "bad RangeSet"
+ else
+ false
+
+ member x.Reset() =
+ x.Inner.Reset()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ member x.Current =
+ assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)
+ Range1ul(x.Left.Key, x.Right.Key - 1UL)
+
+ member x.Dispose() =
+ x.Inner.Dispose()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member x.MoveNext() = x.MoveNext()
+ member x.Current = x.Current :> obj
+ member x.Reset() = x.Reset()
+
+ interface IEnumerator with
+ member x.Dispose() = x.Dispose()
+ member x.Current = x.Current
+ end
+
+[]
+module RangeSet1ul =
+
+ /// Empty range set.
+ let empty = RangeSet1ul.Empty
+
+ /// Returns the minimum value in the range set or UInt64.MaxValue if the range is empty.
+ let inline min (set : RangeSet1ul) = set.Min
+
+ /// Returns the maximum value in the range set or UInt64.MinValue if the range is empty.
+ let inline max (set : RangeSet1ul) = set.Max
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ let inline range (set : RangeSet1ul) = set.Range
+
+ let inline private getHalfRanges (r : Range1ul) =
+ [ struct (r.Min, HalfRangeKind.Left)
+ if r.Max < UInt64.MaxValue then struct (r.Max + 1UL, HalfRangeKind.Right) ]
+
+ let inline private ofRange (r : Range1ul) =
+ RangeSet1ul(MapExt.ofListV <| getHalfRanges r)
+
+ let private ofRanges (ranges : seq) =
+ let halves =
+ ranges
+ |> Seq.toList
+ |> List.collect getHalfRanges
+ |> List.sortBy fstv
+
+ let mutable level = 0
+ let result = ResizeArray()
+
+ for (struct (i, k) as h) in halves do
+ if k = HalfRangeKind.Left then
+ if level = 0 then result.Add h
+ level <- level + 1
+ else
+ level <- level - 1
+ if level = 0 then result.Add h
+
+ RangeSet1ul(MapExt.ofSeqV result)
+
+ /// Builds a range set of the given list of ranges.
+ let ofList (ranges : Range1ul list) =
+ match ranges with
+ | [] -> empty
+ | [r] -> ofRange r
+ | _ -> ofRanges ranges
+
+ /// Builds a range set of the given array of ranges.
+ let ofArray (ranges : Range1ul[]) =
+ if ranges.Length = 0 then empty
+ elif ranges.Length = 1 then ofRange ranges.[0]
+ else ofRanges ranges
+
+ /// Builds a range set of the given sequence of ranges.
+ let inline ofSeq (ranges : seq) =
+ ofList <| Seq.toList ranges
+
+ /// Adds the given range to the set.
+ let inline add (range : Range1ul) (set : RangeSet1ul) = set.Add range
+
+ []
+ let inline insert (range : Range1ul) (set : RangeSet1ul) = set.Add range
+
+ /// Removes the given range from the set.
+ let inline remove (range : Range1ul) (set : RangeSet1ul) = set.Remove range
+
+ /// Returns the union of two sets.
+ let inline union (l : RangeSet1ul) (r : RangeSet1ul) = l.Union r
+
+ /// Returns the intersection of the set with the given range.
+ let inline intersect (range : Range1ul) (set : RangeSet1ul) = set.Intersect range
+
+ []
+ let inline window (range : Range1ul) (set : RangeSet1ul) = intersect range set
+
+ /// Returns whether the given value is contained in the range set.
+ let inline contains (value : uint64) (set : RangeSet1ul) = set.Contains value
- let toSeq (r : RangeSet64) = r :> seq<_>
- let toList (r : RangeSet64) = r |> Seq.toList
- let toArray (r : RangeSet64) = r |> Seq.toArray
+ /// Returns whether the given range is contained in the set.
+ let inline containsRange (range : Range1ul) (set : RangeSet1ul) = set.Contains range
- let inline min (t : RangeSet64) = t.Min
- let inline max (t : RangeSet64) = t.Max
- let inline range (t : RangeSet64) = t.Range
+ /// Returns the number of disjoint ranges in the set.
+ let inline count (set : RangeSet1ul) = set.Count
- let window (window : Range1l) (set : RangeSet64) =
- let rangeMax = window.Max + 1L
+ /// Returns whether the set is empty.
+ let inline isEmpty (set : RangeSet1ul) = set.IsEmpty
- let (l,rest) = set.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo window.Min > 0) minRange
- let (inner,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax >= 0) minRange
+ /// Views the range set as a sequence.
+ let inline toSeq (set : RangeSet1ul) = set :> seq<_>
- let inner =
- match FingerTreeNode.lastOpt l with
- | Some (Geq _) -> FingerTreeNode.prepend mm (geq window.Min) inner
- | _ -> inner
+ /// Builds a list from the range set.
+ let inline toList (set : RangeSet1ul) = set.ToList()
- let inner =
- match FingerTreeNode.firstOpt r with
- | Some (Leq _) -> FingerTreeNode.append mm (leq rangeMax) inner
- | _ -> inner
+ /// Builds an array from the range set.
+ let inline toArray (set : RangeSet1ul) = set.ToArray()
- { root = inner }
diff --git a/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_template.fs b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_template.fs
index 87c8143c9..412f4e753 100644
--- a/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_template.fs
+++ b/src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_template.fs
@@ -3,235 +3,500 @@
open System
open System.Collections
open System.Collections.Generic
-open FingerTreeImplementation
-
-//# foreach (var isLong in new[] { false, true }) {
-//# var halfrange = isLong ? "HalfRange64" : "HalfRange";
-//# var rangeset = isLong ? "RangeSet64" : "RangeSet";
-//# var rangesetenumerator = isLong ? "RangeSet64Enumerator" : "RangeSetEnumerator";
-//# var range = isLong ? "Range1l" : "Range1i";
-//# var systype = isLong ? "Int64" : "Int32";
-//# var ft = isLong ? "int64" : "int32";
-//# var one = isLong ? "1L" : "1";
-[]
-type private __halfrange__ =
- struct
- val mutable public IsMax : bool
- val mutable public Value : __ft__
+open Aardvark.Base
+
+type internal HalfRangeKind =
+ | Left = 0
+ | Right = 1
+
+module private RangeSetUtils =
+
+ let inline inc (value : 'T) =
+ let res = value + LanguagePrimitives.GenericOne<'T>
+ if res = Constant<'T>.ParseableMinValue then struct (Constant<'T>.ParseableMaxValue, true)
+ else struct (res, false)
+
+ module MapExt =
+ let inline splitAt (key : 'K) (map : MapExt<'K, 'V>) =
+ let struct (l, _, _, _, r) = MapExt.splitV key map
+ struct (l, r)
+
+ let inline tryMinValue (map : MapExt<'K, 'V>) =
+ MapExt.tryMinV map |> ValueOption.map (fun mk -> map.[mk])
+
+ let inline tryMaxValue (map : MapExt<'K, 'V>) =
+ MapExt.tryMaxV map |> ValueOption.map (fun mk -> map.[mk])
+
+ let inline maxValue (map : MapExt<'K, 'V>) =
+ map.[MapExt.max map]
+
+open RangeSetUtils
+
+//# var ltypes = new[] { "int32", "uint32", "int64", "uint64" };
+//# var sltypes = new[] { "Int32", "UInt32", "Int64", "UInt64" };
+//# var suffixes = new[] { "i", "ui", "l", "ul" };
+//# var literalSuffixes = new[] { "", "u", "L", "UL" };
+//#
+//# for (int i = 0; i < ltypes.Length; i++) {
+//# var ltype = ltypes[i];
+//# var suffix = suffixes[i];
+//# var range = "Range1" + suffix;
+//# var rangeset = "RangeSet1" + suffix;
+//# var enumerator = "RangeSetEnumerator1" + suffix;
+//# var one = "1" + literalSuffixes[i];
+//# var minvalue = sltypes[i] + ".MinValue";
+//# var maxvalue = sltypes[i] + ".MaxValue";
+/// Set of ranges where overlapping and neighboring ranges are coalesced.
+/// Note that ranges describe closed intervals.
+[]
+type __rangeset__ internal (store : MapExt<__ltype__, HalfRangeKind>) =
+ static let empty = __rangeset__(MapExt.empty)
- new(m,v) = { IsMax = m; Value = v }
+ /// Empty range set.
+ static member Empty = empty
- override x.GetHashCode() =
- if x.IsMax then 0
- else x.Value.GetHashCode()
+ member inline private x.Store = store
- override x.Equals o =
- match o with
- | :? __halfrange__ as o ->
- x.IsMax = o.IsMax && x.Value = o.Value
- | _ ->
- false
+ // We cannot directly describe a range that ends at __maxvalue__ since the right half-range is inserted
+ // at max + 1. In that case the right-half range will be missing and the total count is odd.
+ member inline private x.HasMaxValue = store.Count % 2 = 1
- member x.CompareTo (o : __halfrange__) =
- let c = x.Value.CompareTo o.Value
- if c = 0 then
- if x.IsMax = o.IsMax then 0
- else (if x.IsMax then 1 else -1)
- else
- c
+ /// Returns the minimum value in the range set or __maxvalue__ if the range is empty.
+ member x.Min =
+ match store.TryMinKeyV with
+ | ValueSome min -> min
+ | _ -> __maxvalue__
- interface IComparable with
- member x.CompareTo o =
- match o with
- | :? __halfrange__ as o -> x.CompareTo(o)
- | _ -> failwith "uncomparable"
- end
+ /// Returns the maximum value in the range set or __minvalue__ if the range is empty.
+ member x.Max =
+ if x.HasMaxValue then __maxvalue__
+ else
+ match store.TryMaxKeyV with
+ | ValueSome max -> max - __one__
+ | _ -> __minvalue__
+
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ member inline x.Range =
+ __range__(x.Min, x.Max)
+
+ /// Adds the given range to the set.
+ member x.Add(r : __range__) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained __maxvalue__ or we have overflown, we must not add an explicit right half-range.
+ // __maxvalue__ is stored implicitly.
+ let fixRightBoundary =
+ if x.HasMaxValue || overflow then
+ id
+ else
+ MapExt.add max HalfRangeKind.Right
+
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.ofListV [
+ struct (min, HalfRangeKind.Left)
+ ]
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Left
+ |> fixRightBoundary
+
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> fixRightBoundary
+
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+ |> MapExt.add max HalfRangeKind.Right
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add min HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ MapExt.union lm rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ __rangeset__(newStore)
+
+ /// Removes the given range from the set.
+ member x.Remove(r : __range__) =
+ if r.Max < r.Min then
+ x
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let struct (lm, inner) = MapExt.splitAt min store
+ let rm =
+ if overflow then MapExt.empty
+ else sndv <| MapExt.splitAt max inner
+
+ let before = MapExt.tryMaxValue lm
+ let after = MapExt.tryMinValue rm
+
+ // If the set contained __maxvalue__ and we have not overflown, there is still a range [max, __maxvalue__]
+ let fixRightBoundary =
+ if x.HasMaxValue && not overflow then
+ MapExt.add max HalfRangeKind.Left
+ else
+ id
+ let newStore =
+ match before, after with
+ | ValueNone, ValueNone ->
+ MapExt.empty
+ |> fixRightBoundary
-[]
-type __rangeset__ = private { root : FingerTreeNode<__halfrange__, __halfrange__> } with
-
- member private x.AsString =
- x |> Seq.map (sprintf "%A")
- |> String.concat "; "
- |> sprintf "set [%s]"
+ | ValueSome HalfRangeKind.Right, ValueNone ->
+ lm
+ |> fixRightBoundary
- member x.Min =
- match x.root |> FingerTreeNode.firstOpt with
- | Some f -> f.Value
- | _ -> __systype__.MaxValue
+ | ValueSome HalfRangeKind.Left, ValueNone ->
+ lm
+ |> MapExt.add min HalfRangeKind.Right
+ |> fixRightBoundary
- member x.Max =
- match x.root |> FingerTreeNode.lastOpt with
- | Some f -> f.Value
- | _ -> __systype__.MinValue
+ | ValueNone, ValueSome HalfRangeKind.Left ->
+ rm
+
+ | ValueNone, ValueSome HalfRangeKind.Right ->
+ rm
+ |> MapExt.add max HalfRangeKind.Left
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->
+ MapExt.union lm rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->
+ let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]
+ MapExt.union (MapExt.union lm self) rm
+
+ | _ ->
+ failwithf "impossible"
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ __rangeset__(newStore)
+
+ /// Returns the union of the set with the given set.
+ member inline x.Union(other : __rangeset__) =
+ let mutable res = x
+ for r in other do
+ res <- res.Add r
+ res
+
+ /// Returns the intersection of the set with the given range.
+ member x.Intersect(r : __range__) =
+ if r.Max < r.Min then
+ empty
+ else
+ let min = r.Min
+ let struct (max, overflow) = inc r.Max
+
+ let inner =
+ store
+ |> MapExt.splitAt min |> sndv
+ |> if not overflow then MapExt.splitAt max >> fstv else id
+
+ let newStore =
+ inner
+ |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id
+ |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id
+
+ assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)
+ __rangeset__(newStore)
+
+ member private x.TryFindLeftBoundary(v : __ltype__) =
+ let struct (l, s, _) = MapExt.neighboursV v store
+ match s with
+ | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone
+ | _ ->
+ match l with
+ | ValueSome (i, HalfRangeKind.Left) -> ValueSome i
+ | _ -> ValueNone
+
+ /// Returns whether the given value is contained in the range set.
+ member x.Contains(v : __ltype__) =
+ x.TryFindLeftBoundary v |> ValueOption.isSome
+
+ /// Returns whether the given range is contained in the set.
+ member x.Contains(r : __range__) =
+ if r.Max < r.Min then false
+ elif r.Min = r.Max then x.Contains r.Min
+ else
+ match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with
+ | ValueSome l, ValueSome r -> l = r
+ | _ -> false
+
+ /// Returns the number of disjoint ranges in the set.
+ member x.Count =
+ (store.Count + 1) / 2
+
+ /// Returns whether the set is empty.
+ member inline x.IsEmpty =
+ x.Count = 0
+
+ /// Builds an array from the range set.
+ member x.ToArray() =
+ let arr = Array.zeroCreate x.Count
+
+ let rec write (i : int) (l : struct (__ltype__ * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ arr.[i] <- __range__(l, r - __one__)
+ write (i + 1) rest
- member x.Range =
- match FingerTreeNode.firstOpt x.root, FingerTreeNode.lastOpt x.root with
- | Some min, Some max -> __range__(min.Value, max.Value)
- | _ -> __range__.Invalid
+ | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->
+ arr.[i] <- __range__(l, __maxvalue__)
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> ()
+
+ store |> MapExt.toListV |> write 0
+ arr
+
+ /// Builds a list from the range set.
+ member x.ToList() =
+ let rec build (accum : __range__ list) (l : struct (__ltype__ * HalfRangeKind) list) =
+ match l with
+ | struct (l, _) :: struct (r, _) :: rest ->
+ build (__range__(l, r - __one__) :: accum) rest
+
+ | [struct (l, HalfRangeKind.Left)] ->
+ build (__range__(l, __maxvalue__) :: accum) []
+
+ | [_] -> failwith "bad RangeSet"
+
+ | [] -> List.rev accum
+
+ store |> MapExt.toListV |> build []
+
+ /// Views the range set as a sequence.
+ member x.ToSeq() =
+ x :> seq<_>
+
+ member inline private x.Equals(other : __rangeset__) =
+ store = other.Store
+
+ override x.Equals(other : obj) =
+ match other with
+ | :? __rangeset__ as o -> x.Equals o
+ | _ -> false
+
+ override x.GetHashCode() =
+ store.GetHashCode()
+
+ member private x.AsString = x.ToString()
+
+ override x.ToString() =
+ let content =
+ x |> Seq.map (fun r ->
+ $"[{r.Min}, {r.Max}]"
+ )
+ |> String.concat "; "
+
+ $"ranges [{content}]"
+
+ member x.GetEnumerator() =
+ new __enumerator__((store :> seq<_>).GetEnumerator())
+
+ interface IEquatable<__rangeset__> with
+ member x.Equals(other) = x.Equals(other)
interface IEnumerable with
- member x.GetEnumerator() = new __rangesetenumerator__(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> IEnumerator
+ member x.GetEnumerator() = new __enumerator__((store :> seq<_>).GetEnumerator()) :> _
interface IEnumerable<__range__> with
- member x.GetEnumerator() = new __rangesetenumerator__(FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root) :> _
+ member x.GetEnumerator() = new __enumerator__((store :> seq<_>).GetEnumerator()) :> _
+// TODO: MapExt should use a struct enumerator and return it directly.
+// That way we could get rid of allocations.
+and __enumerator__ =
+ struct
+ val private Inner : IEnumerator>
+ val mutable private Left : KeyValuePair<__ltype__, HalfRangeKind>
+ val mutable private Right : KeyValuePair<__ltype__, HalfRangeKind>
-and private __rangesetenumerator__(i : IEnumerator<__halfrange__>) =
-
- let mutable last = __halfrange__()
- let mutable current = __halfrange__()
-
- member x.Current = __range__(last.Value, current.Value - __one__)
+ internal new (inner : IEnumerator>) =
+ { Inner = inner
+ Left = Unchecked.defaultof<_>
+ Right = Unchecked.defaultof<_> }
- interface IEnumerator with
member x.MoveNext() =
- if i.MoveNext() then
- last <- i.Current
- if i.MoveNext() then
- current <- i.Current
+ if x.Inner.MoveNext() then
+ x.Left <- x.Inner.Current
+ if x.Inner.MoveNext() then
+ x.Right <- x.Inner.Current
true
else
- false
+ if x.Left.Value = HalfRangeKind.Left then
+ x.Right <- KeyValuePair(__minvalue__, HalfRangeKind.Right) // MaxValue + 1
+ true
+ else
+ failwithf "bad RangeSet"
else
false
- member x.Current = x.Current :> obj
-
member x.Reset() =
- i.Reset()
-
- interface IEnumerator<__range__> with
- member x.Current = x.Current
- member x.Dispose() = i.Dispose()
+ x.Inner.Reset()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ member x.Current =
+ assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)
+ __range__(x.Left.Key, x.Right.Key - __one__)
+
+ member x.Dispose() =
+ x.Inner.Dispose()
+ x.Left <- Unchecked.defaultof<_>
+ x.Right <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member x.MoveNext() = x.MoveNext()
+ member x.Current = x.Current :> obj
+ member x.Reset() = x.Reset()
+
+ interface IEnumerator<__range__> with
+ member x.Dispose() = x.Dispose()
+ member x.Current = x.Current
+ end
[]
module __rangeset__ =
- let private mm =
- {
- quantify = fun (r : __halfrange__) -> r
- mempty = __halfrange__(false, __systype__.MinValue)
- mappend = fun l r -> if l.CompareTo r > 0 then l else r
- }
-
- let private minRange = __halfrange__(false, __systype__.MinValue)
- let inline private leq v = __halfrange__(true, v)
- let inline private geq v = __halfrange__(false, v)
+ /// Empty range set.
+ let empty = __rangeset__.Empty
- let inline private (|Leq|Geq|) (r : __halfrange__) =
- if r.IsMax then Leq r.Value
- else Geq r.Value
+ /// Returns the minimum value in the range set or __maxvalue__ if the range is empty.
+ let inline min (set : __rangeset__) = set.Min
- let empty = { root = Empty }
+ /// Returns the maximum value in the range set or __minvalue__ if the range is empty.
+ let inline max (set : __rangeset__) = set.Max
- let insert (range : __range__) (t : __rangeset__) =
- let rangeMax = range.Max + __one__
+ /// Returns the total range spanned by the range set, i.e. [min, max].
+ let inline range (set : __rangeset__) = set.Range
- let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
- let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+ let inline private getHalfRanges (r : __range__) =
+ [ struct (r.Min, HalfRangeKind.Left)
+ if r.Max < __maxvalue__ then struct (r.Max + __one__, HalfRangeKind.Right) ]
- let max = leq rangeMax
- let min = geq range.Min
+ let inline private ofRange (r : __range__) =
+ __rangeset__(MapExt.ofListV <| getHalfRanges r)
- match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
- | None, None ->
- { root = Deep(max, One(min), Empty, One(max)) }
+ let private ofRanges (ranges : seq<__range__>) =
+ let halves =
+ ranges
+ |> Seq.toList
+ |> List.collect getHalfRanges
+ |> List.sortBy fstv
- | Some lmax, None ->
- match lmax with
- | Leq _ -> { root = l |> FingerTreeNode.append mm min |> FingerTreeNode.append mm max }
- | Geq _ -> { root = l |> FingerTreeNode.append mm max }
+ let mutable level = 0
+ let result = ResizeArray()
- | None, Some rmin ->
- match rmin with
- | Leq _ -> { root = r |> FingerTreeNode.prepend mm min }
- | Geq _ -> { root = r |> FingerTreeNode.prepend mm max |> FingerTreeNode.prepend mm min }
-
- | Some lmax, Some rmin ->
- match lmax, rmin with
- | Leq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min;max] r }
-
- | Geq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [] r }
-
- | Leq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min] r }
-
- | Geq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [max] r }
-
- let remove (range : __range__) (t : __rangeset__) =
- let rangeMax = range.Max + __one__
+ for (struct (i, k) as h) in halves do
+ if k = HalfRangeKind.Left then
+ if level = 0 then result.Add h
+ level <- level + 1
+ else
+ level <- level - 1
+ if level = 0 then result.Add h
- let (l,rest) = t.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo range.Min >= 0) minRange
- let (_,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax > 0) minRange
+ __rangeset__(MapExt.ofSeqV result)
- let max = geq rangeMax
- let min = leq range.Min
+ /// Builds a range set of the given list of ranges.
+ let ofList (ranges : __range__ list) =
+ match ranges with
+ | [] -> empty
+ | [r] -> ofRange r
+ | _ -> ofRanges ranges
- match FingerTreeNode.lastOpt l, FingerTreeNode.firstOpt r with
- | None, None ->
- { root = Empty }
+ /// Builds a range set of the given array of ranges.
+ let ofArray (ranges : __range__[]) =
+ if ranges.Length = 0 then empty
+ elif ranges.Length = 1 then ofRange ranges.[0]
+ else ofRanges ranges
- | Some lmax, None ->
- match lmax with
- | Leq _ -> { root = l }
- | Geq _ -> { root = l |> FingerTreeNode.append mm min }
+ /// Builds a range set of the given sequence of ranges.
+ let inline ofSeq (ranges : seq<__range__>) =
+ ofList <| Seq.toList ranges
- | None, Some rmin ->
- match rmin with
- | Leq _ -> { root = r |> FingerTreeNode.prepend mm max }
- | Geq _ -> { root = r }
+ /// Adds the given range to the set.
+ let inline add (range : __range__) (set : __rangeset__) = set.Add range
- | Some lmax, Some rmin ->
- match lmax, rmin with
- | Leq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [] r }
+ []
+ let inline insert (range : __range__) (set : __rangeset__) = set.Add range
- | Geq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min; max] r }
+ /// Removes the given range from the set.
+ let inline remove (range : __range__) (set : __rangeset__) = set.Remove range
- | Leq _, Leq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [max] r }
+ /// Returns the union of two sets.
+ let inline union (l : __rangeset__) (r : __rangeset__) = l.Union r
- | Geq _, Geq _ ->
- { root = FingerTreeNode.concatWithMiddle mm l [min] r }
+ /// Returns the intersection of the set with the given range.
+ let inline intersect (range : __range__) (set : __rangeset__) = set.Intersect range
- let ofSeq (s : seq<__range__>) =
- let mutable res = empty
- for e in s do res <- insert e res
- res
+ []
+ let inline window (range : __range__) (set : __rangeset__) = intersect range set
- let inline ofList (l : list<__range__>) = ofSeq l
- let inline ofArray (l : __range__[]) = ofSeq l
+ /// Returns whether the given value is contained in the range set.
+ let inline contains (value : __ltype__) (set : __rangeset__) = set.Contains value
- let toSeq (r : __rangeset__) = r :> seq<_>
- let toList (r : __rangeset__) = r |> Seq.toList
- let toArray (r : __rangeset__) = r |> Seq.toArray
+ /// Returns whether the given range is contained in the set.
+ let inline containsRange (range : __range__) (set : __rangeset__) = set.Contains range
- let inline min (t : __rangeset__) = t.Min
- let inline max (t : __rangeset__) = t.Max
- let inline range (t : __rangeset__) = t.Range
+ /// Returns the number of disjoint ranges in the set.
+ let inline count (set : __rangeset__) = set.Count
- let window (window : __range__) (set : __rangeset__) =
- let rangeMax = window.Max + __one__
+ /// Returns whether the set is empty.
+ let inline isEmpty (set : __rangeset__) = set.IsEmpty
- let (l,rest) = set.root |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo window.Min > 0) minRange
- let (inner,r) = rest |> FingerTreeNode.splitFirstRight mm (fun v -> v.Value.CompareTo rangeMax >= 0) minRange
+ /// Views the range set as a sequence.
+ let inline toSeq (set : __rangeset__) = set :> seq<_>
- let inner =
- match FingerTreeNode.lastOpt l with
- | Some (Geq _) -> FingerTreeNode.prepend mm (geq window.Min) inner
- | _ -> inner
+ /// Builds a list from the range set.
+ let inline toList (set : __rangeset__) = set.ToList()
- let inner =
- match FingerTreeNode.firstOpt r with
- | Some (Leq _) -> FingerTreeNode.append mm (leq rangeMax) inner
- | _ -> inner
+ /// Builds an array from the range set.
+ let inline toArray (set : __rangeset__) = set.ToArray()
- { root = inner }
//# }
\ No newline at end of file
diff --git a/src/Aardvark.Base.FSharp/Interop/String.fs b/src/Aardvark.Base.FSharp/Interop/String.fs
deleted file mode 100644
index 40353c6de..000000000
--- a/src/Aardvark.Base.FSharp/Interop/String.fs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Aardvark.Base
-
-open System
-
-[]
-[]
-module Strings =
- let partRx = System.Text.RegularExpressions.Regex @"([A-Z][a-z0-9]*)[_]*"
-
- /// checks whether pattern is contained in str
- let contains pattern (str : string) = str.Contains pattern
-
- let toLower (str : string) = str.ToLower()
- let toUpper (str : string) = str.ToUpper()
-
- let inline split (sep : string) (str : string) = str.Split([| sep |], StringSplitOptions.None)
- let inline startsWith (s : string) (str : string) = str.StartsWith s
- let inline endsWith (s : string) (str : string) = str.EndsWith s
- let inline trim (str : string) = str.Trim()
-
-
-
diff --git a/src/Aardvark.Base.FSharp/Prelude/AverageWindow.fs b/src/Aardvark.Base.FSharp/Math/AverageWindow.fs
similarity index 100%
rename from src/Aardvark.Base.FSharp/Prelude/AverageWindow.fs
rename to src/Aardvark.Base.FSharp/Math/AverageWindow.fs
diff --git a/src/Aardvark.Base.FSharp/Interop/Converters.fs b/src/Aardvark.Base.FSharp/Math/Converters.fs
similarity index 100%
rename from src/Aardvark.Base.FSharp/Interop/Converters.fs
rename to src/Aardvark.Base.FSharp/Math/Converters.fs
diff --git a/src/Aardvark.Base.FSharp/Prelude/Math.fs b/src/Aardvark.Base.FSharp/Math/Math.fs
similarity index 100%
rename from src/Aardvark.Base.FSharp/Prelude/Math.fs
rename to src/Aardvark.Base.FSharp/Math/Math.fs
diff --git a/src/Aardvark.Base.FSharp/Interop/Matrix.fs b/src/Aardvark.Base.FSharp/Math/Matrix.fs
similarity index 100%
rename from src/Aardvark.Base.FSharp/Interop/Matrix.fs
rename to src/Aardvark.Base.FSharp/Math/Matrix.fs
diff --git a/src/Aardvark.Base.FSharp/SVDM33f.fs b/src/Aardvark.Base.FSharp/Math/SVDM33f.fs
similarity index 100%
rename from src/Aardvark.Base.FSharp/SVDM33f.fs
rename to src/Aardvark.Base.FSharp/Math/SVDM33f.fs
diff --git a/src/Aardvark.Base.FSharp/Interop/Vectors.fs b/src/Aardvark.Base.FSharp/Math/Vectors.fs
similarity index 100%
rename from src/Aardvark.Base.FSharp/Interop/Vectors.fs
rename to src/Aardvark.Base.FSharp/Math/Vectors.fs
diff --git a/src/Aardvark.Base.FSharp/Prelude/FSLibExtensions.fs b/src/Aardvark.Base.FSharp/Prelude/FSLibExtensions.fs
deleted file mode 100644
index c532e3e09..000000000
--- a/src/Aardvark.Base.FSharp/Prelude/FSLibExtensions.fs
+++ /dev/null
@@ -1,831 +0,0 @@
-namespace Aardvark.Base
-#nowarn "9"
-#nowarn "51"
-#nowarn "44"
-
-open System
-open FSharp.NativeInterop
-
-[]
-module Prelude =
-
- let inc (a:byref) = a <- a + 1
- let dec (a:byref) = a <- a - 1
-
- let inline isNull (a : 'a) =
- match a with
- | null -> true
- | _ -> false
-
- module Map =
- let union (l : Map<'k, 'v>) (r : Map<'k, 'v>) =
- let mutable result = l
- for KeyValue(k,v) in r do
- result <- Map.add k v result
- result
-
- let unionMany (input : seq