mirror of
https://github.com/Smaug123/dotnet-classical-ciphers
synced 2025-10-05 12:38:40 +00:00
136 lines
3.8 KiB
Forth
136 lines
3.8 KiB
Forth
namespace CipherSuite
|
|
|
|
#if DEBUG
|
|
#else
|
|
#nowarn "9"
|
|
#endif
|
|
|
|
open Microsoft.FSharp.NativeInterop
|
|
|
|
[<Struct>]
|
|
#if DEBUG
|
|
type Arr4D<'a> =
|
|
{
|
|
Elements : 'a array
|
|
Width : int
|
|
WidthTimesHeight : int
|
|
WidthTimesHeightTimesDepth : int
|
|
}
|
|
|
|
member this.Depth = this.Elements.Length / this.WidthTimesHeightTimesDepth
|
|
#else
|
|
type Arr4D<'a when 'a : unmanaged> =
|
|
{
|
|
Elements : nativeptr<'a>
|
|
Length : int
|
|
Width : int
|
|
WidthTimesHeight : int
|
|
WidthTimesHeightTimesDepth : int
|
|
}
|
|
|
|
member this.Depth = this.Length / this.WidthTimesHeightTimesDepth
|
|
#endif
|
|
|
|
[<RequireQualifiedAccess>]
|
|
module Arr4D =
|
|
|
|
/// It's faster to iterate forward over the first argument, `x`, and then the
|
|
/// second argument, `y`, and then the third argument, `z`.
|
|
let inline get (arr : Arr4D<'a>) (x : int) (y : int) (z : int) (i : int) : 'a =
|
|
#if DEBUG
|
|
arr.Elements.[i * arr.WidthTimesHeightTimesDepth
|
|
+ z * arr.WidthTimesHeight
|
|
+ y * arr.Width
|
|
+ x]
|
|
#else
|
|
NativePtr.get
|
|
arr.Elements
|
|
(i * arr.WidthTimesHeightTimesDepth
|
|
+ z * arr.WidthTimesHeight
|
|
+ y * arr.Width
|
|
+ x)
|
|
#endif
|
|
|
|
let inline set (arr : Arr4D<'a>) (x : int) (y : int) (z : int) (i : int) (newVal : 'a) : unit =
|
|
#if DEBUG
|
|
arr.Elements.[i * arr.WidthTimesHeightTimesDepth
|
|
+ z * arr.WidthTimesHeight
|
|
+ y * arr.Width
|
|
+ x] <- newVal
|
|
#else
|
|
NativePtr.write
|
|
(NativePtr.add
|
|
arr.Elements
|
|
(i * arr.WidthTimesHeightTimesDepth
|
|
+ z * arr.WidthTimesHeight
|
|
+ y * arr.Width
|
|
+ x))
|
|
newVal
|
|
#endif
|
|
|
|
#if DEBUG
|
|
/// In lieu of a meaningful name for the ana-kata axis, I am just going to call it katana.
|
|
let create (width : int) (height : int) (depth : int) (katana : int) (value : 'a) : Arr4D<'a> =
|
|
let arr = Array.create (width * height * depth * katana) value
|
|
|
|
{
|
|
Width = width
|
|
WidthTimesHeight = width * height
|
|
WidthTimesHeightTimesDepth = width * height * depth
|
|
Elements = arr
|
|
}
|
|
#else
|
|
/// In lieu of a meaningful name for the ana-kata axis, I am just going to call it katana.
|
|
/// The input array must be at least of size width * height * depth * katana.
|
|
let create
|
|
(arr : nativeptr<'a>)
|
|
(width : int)
|
|
(height : int)
|
|
(depth : int)
|
|
(katana : int)
|
|
(value : 'a)
|
|
: Arr4D<'a>
|
|
=
|
|
{
|
|
Width = width
|
|
Elements = arr
|
|
Length = width * height * depth * katana
|
|
WidthTimesHeight = width * height
|
|
WidthTimesHeightTimesDepth = width * height * depth
|
|
}
|
|
#endif
|
|
|
|
[<RequiresExplicitTypeArguments>]
|
|
#if DEBUG
|
|
let zeroCreate<'a when 'a : unmanaged> (width : int) (height : int) (depth : int) (katana : int) : Arr4D<'a> =
|
|
{
|
|
Elements = Array.zeroCreate (width * height * depth * katana)
|
|
Width = width
|
|
WidthTimesHeight = width * height
|
|
WidthTimesHeightTimesDepth = width * height * depth
|
|
}
|
|
#else
|
|
let zeroCreate<'a when 'a : unmanaged>
|
|
(elts : nativeptr<'a>)
|
|
(width : int)
|
|
(height : int)
|
|
(depth : int)
|
|
(katana : int)
|
|
: Arr4D<'a>
|
|
=
|
|
{
|
|
Elements = elts
|
|
Width = width
|
|
WidthTimesHeight = width * height
|
|
WidthTimesHeightTimesDepth = width * height * depth
|
|
Length = width * height * depth * katana
|
|
}
|
|
#endif
|
|
|
|
let inline clear (a : Arr4D<'a>) : unit =
|
|
#if DEBUG
|
|
System.Array.Clear a.Elements
|
|
#else
|
|
NativePtr.initBlock a.Elements 0uy (uint32 sizeof<'a> * uint32 a.Length)
|
|
#endif
|