Using F# and SIMD to search for index of value - f#

I'm working on putting together an algorithm for searching through an array to find the index of a given value. I'm trying to follow a similar technique found in the .NET Core CLR.
Where I am confused is the value for the idx that is returned by the call to BitOperations.TrailingZeroCount. When I search for 2 it should return an index value of 1 for the data that I am searching. What I get is a 4. Do I need to do some conversion from the byte offset back to whatever the actual type is? Is this the most efficient way to write this? There are not many docs on using intrinsics with .NET.
open System
open System.Runtime.Intrinsics.X86
open System.Runtime.Intrinsics
open System.Numerics
#nowarn "9"
#nowarn "20"
[<EntryPoint>]
let main argv =
let searchSpace : Span<int32> = Span [| 1 .. 8 |]
let pSearchSpace = && (searchSpace.GetPinnableReference ())
let search = Sse2.LoadVector128 (pSearchSpace)
let value = 2
let values = Vector128.Create value
let comparison = Sse2.CompareEqual (values, search)
let matches = Sse2.MoveMask (comparison.AsByte())
if matches > 0 then
let idx = BitOperations.TrailingZeroCount matches
printfn "%A" idx // <--- This prints 4 instead of 1
0 // return an integer exit code

Sse2.MoveMask (comparison.AsByte()) (i.e. vpmovmskb) gives you 4 mask bits per int32 match result, one from each Byte like you asked for.
Either use vmovmskps (perhaps MoveMask(cmp.AsFloat()), if that's how F# does it?) or deal with the byte instead of element indices you get from bsf / tzcnt.

Related

How do I make a mutable argument in a function through F#?

Sorry for my question but I did not understand the answers that was related to this question so I hope someone can enlighten me further.
I am a new data science student and we are going to learn how to program in the functional language F#. We are learning about algorithms and I wanted to write the algorithms as F# functions to check if my calculations on paper were correct.
I get the following error saying:
"This value is not mutable. Consider using the mutable keyword let mutable n = expression"
My code looks like this:
let loop5( n ) =
let mutable x = 0
while n > 0 do
x <- x + 1
n <- n + 1
printfn "loop5(): x=%i for n=%i" x n
loop5(4)
I'm trying to write a function looking like this (pseudocode):
loop5(n)
x = 0
while n > 0
x = x + 1
n = n + 1
return x
Hope I made a clear question and someone can help me out here :-) Have a nice weekend
You're trying to mutate the loop's parameter n. The parameter is not mutable, so the compiler doesn't let you. That's exactly what the error tells you.
Now, normally, to make the error go away, you'd make the variable mutable. However, you can't make a function parameter mutable, so that's not an option.
Here you want to think what the meaning of your program should be. Does the loop function need to pass the updated value of n back to its caller, or is the whole mutation its internal business? If it's the former, please see #AnyMoose's answer, but from your example and explanation, I suspect it's the latter. If that is the case, simply make a mutable copy of the parameter and work with it:
let loop n' =
let mutable x = 0
let mutable n = n'
...
Separately, I want to point out that your program, as written, would actually loop indefinitely (or until it wraps around the max int value anyway), because instead of decreasing n at each step you're increasing it. If you want your program to actually finish before the next Ice Age, you need to make n decrease with each iteration:
n <- n - 1
Ref cells
Ref cells get around some of the limitations of mutables. In fact, ref cells are very simple datatypes which wrap up a mutable field in a record type. Ref cells are defined by F# as follows:
type 'a ref = { mutable contents : 'a }
The F# library contains several built-in functions and operators for working with ref cells:
let ref v = { contents = v } (* val ref : 'a -> 'a ref *)
let (!) r = r.contents (* val (!) : 'a ref -> 'a *)
let (:=) r v = r.contents <- v (* val (:=) : 'a ref -> 'a -> unit *)
The ref function is used to create a ref cell, the ! operator is used to read the contents of a ref cell, and the := operator is used to assign a ref cell a new value. Here is a sample in fsi:
let x = ref "hello";;
val x : string ref
x;; (* returns ref instance *)
val it : string ref = {contents = "hello";}
!x;; (* returns x.contents *)
val it : string = "hello"
x := "world";; (* updates x.contents with a new value *)
val it : unit = ()
!x;; (* returns x.contents *)
val it : string = "world"
Since ref cells are allocated on the heap, they can be shared across multiple functions:
open System
let withSideEffects x =
x := "assigned from withSideEffects function"
let refTest() =
let msg = ref "hello"
printfn "%s" !msg
let setMsg() =
msg := "world"
setMsg()
printfn "%s" !msg
withSideEffects msg
printfn "%s" !msg
let main() =
refTest()
Console.ReadKey(true) |> ignore
main()
The withSideEffects function has the type val withSideEffects : string ref -> unit.
This program outputs the following:
hello
world
Assigned from withSideEffects function
The withSideEffects function is named as such because it has a side-effect, meaning it can change the state of a variable in other functions. Ref Cells should be treated like fire. Use it cautiously when it is absolutely necessary but avoid it in general. If you find yourself using Ref Cells while translating code from C/C++, then ignore efficiency for a while and see if you can get away without Ref Cells or at worst using mutable. You would often stumble upon a more elegant and more maintanable algorithm
Aliasing Ref Cells
Note: While imperative programming uses aliasing extensively, this practice has a number of problems. In particular it makes programs hard to follow since the state of any variable can be modified at any point elsewhere in an application. Additionally, multithreaded applications sharing mutable state are difficult to reason about since one thread can potentially change the state of a variable in another thread, which can result in a number of subtle errors related to race conditions and dead locks.
A ref cell is very similar to a C or C++ pointer. Its possible to point to two or more ref cells to the same memory address; changes at that memory address will change the state of all ref cells pointing to it. Conceptually, this process looks like this:
Let's say we have 3 ref cells looking at the same address in memory:
Three references to an integer with value 7
cell1, cell2, and cell3 are all pointing to the same address in memory. The .contents property of each cell is 7. Let's say, at some point in our program, we execute the code cell1 := 10, this changes the value in memory to the following:
Three references to an integer with value 10
By assigning cell1.contents a new value, the variables cell2 and cell3 were changed as well. This can be demonstrated using fsi as follows:
let cell1 = ref 7;;
val cell1 : int ref
let cell2 = cell1;;
val cell2 : int ref
let cell3 = cell2;;
val cell3 : int ref
!cell1;;
val it : int = 7
!cell2;;
val it : int = 7
!cell3;;
val it : int = 7
cell1 := 10;;
val it : unit = ()
!cell1;;
val it : int = 10
!cell2;;
val it : int = 10
!cell3;;
val it : int = 10

Declaring a variable without assigning workaround

i'm writing a small console application in F#.
[<EntryPoint>]
let main argv =
high_lvl_funcs.print_opt
let opt = Console.ReadLine()
match opt with
| "0" -> printfn "%A" (high_lvl_funcs.calculate_NDL)
| "1" -> printfn ("not implemented yet")
| _ -> printfn "%A is not an option" opt
from module high_lvl_funcs
let print_opt =
let options = [|"NDL"; "Deco"|]
printfn "Enter the number of the option you want"
Array.iteri (fun i x -> printfn "%A: %A" i x) options
let calculate_NDL =
printfn ("enter Depth in m")
let depth = lfuncs.m_to_absolute(float (Console.ReadLine()))
printfn ("enter amount of N2 in gas (assuming o2 is the rest)")
let fn2 = float (Console.ReadLine())
let table = lfuncs.read_table
let tissue = lfuncs.create_initialise_Tissues ATM WATERVAPOUR
lfuncs.calc_NDL depth fn2 table lfuncs.loading_constantpressure tissue 0.0
lfuncs.calc_NDL returns a float
this produces this
Enter the number of the option you want
0: "NDL"
1: "Deco"
enter Depth in m
which means it prints what it's suppose to then jumps straight to high_lvl_funcs.calculate_NDL
I wanted it to produce
Enter the number of the option you want
0: "NDL"
1: "Deco"
then let's assume 0 is entered, and then calculate high_lvl_funcs.calculate_NDL
after some thinking and searching i assume this is because F# wants to assign all values before it starts the rest. Then i thought that i need to declaring a variable without assigning it. but people seem to agree that this is bad in functional programming. From another question: Declaring a variable without assigning
so my question is, is it possible to rewrite the code such that i get the flow i want and avoid declaring variables without assigning them?
You can fix this by making calculate_NDL a function of no arguments, instead of a closure that evaluates to a float:
let calculate_NDL () =
Then call it as a function in your match like this:
match opt with
| "0" -> printfn "%A" (high_lvl_funcs.calculate_NDL())
However I'd suggest refactoring this code so that calculate_NDL takes any necessary inputs as arguments rather than reading them from the console i.e. read the inputs from the console separately and pass them to calculate_NDL.
let calculate_NDL depth fn2 =
let absDepth = lfuncs.m_to_absolute(depth)
let table = lfuncs.read_table
let tissue = lfuncs.create_initialise_Tissues ATM WATERVAPOUR
lfuncs.calc_NDL absDepth fn2 table lfuncs.loading_constantpressure tissue 0.0
It's generally a good idea to write as much code as possible as pure functions that don't rely on I/O (like reading from stdin).

F# how to write a function which provides a counter number in serial order

So if you go to a bank there is a device from which you can pull a number out.
I want to write a function like that. So everytime this function is called we get a next number in the series.
So if this function is called first time, we get 1. second time we get 2.... so on and so forth.
this is what I have written so far
let X =
let myseq = seq {1 .. 100}
let GetValue =
Seq.head (Seq.take 1 myseq)
GetValue;;
let p = X;;
p;;
p;;
p;;
But it always return 1. My hope was that since the sequence is a closure, everytime I do a take, I will get the next number.
I also tried this
let X =
let mutable i = 1
let GetValue =
i <- i + 1
i
GetValue;;
let p = X;;
p;;
p;;
p;;
This one only prints 2...
You have to return a function. And to it, you have to pass something every time, i.e. your +1 has to be deferred.
let factory =
let counter = ref 0
fun () ->
counter.Value <- !counter + 1
!counter
and now you get
> factory();;
val it : int = 1
> factory();;
val it : int = 2
doing it this way has the nice side-effect, that you completely hide the mutable reference cell inside the function and thus there is no way to somehow tamper with your counter.
Just for a reference, if you wanted a version that uses sequences (just like the first approach in your question), you can do that using the IEnumerable interface:
let factory =
// Infinite sequence of numbers & get enumerator
let numbers = Seq.initInfinite id
let en = numbers.GetEnumerator()
fun () ->
// Move to the next number and return it
en.MoveNext() |> ignore
en.Current
It behaves the same way as factory in Daniel's answer. This still uses mutable state - but it is hidden inside the enumerator (which keeps the current state of the sequence between MoveNext calls).
In this simple case, I'd use Daniel's version, but the above might be handy if you want to iterate over something else than just increasing numbers.
You need to move the variable outside the declaration. You also need to declare a function so that it gets evaluated each time it is called.
let mutable i = 1
let X() =
i <- i + 1
i
This ensures that the function is called each time and that the variable is correctly incremented.

Why is this function saying "Only simple variable patterns can be bound in 'let rec' constructs"?

I am just getting started with F# and am trying Problem Euler problem #3. To find primes I came up with the following code to compute all primes up to a maximum number:
let rec allPrimes foundPrimes, current, max =
// make sure the current number isn't too high
// or the current number isn't divisible by any known primes
if current >= max then
foundPrimes
else
let nextValue = current + 1
if not List.exists (fun x -> current % x = 0L) foundPrimes then
allPrimes foundPrimes nextValue max
else
allPrimes (foundPrimes :: current) nextValue max
Unfortunately, this gives the error:
Only simple variable patterns can be bound in 'let rec' constructs
Why am I getting this error?
You don't want to put the commas in the declaration - change
let rec allPrimes foundPrimes, current, max =
to
let rec allPrimes foundPrimes current max =
The correct version of your original would be
let rec allPrimes (foundPrimes, current, max) =
note the brackets around the tuple. However, this would require modifying the recursive calls to also use tuple form. In the original version the compiler thinks you are trying to do something like
let a,b,c=1,2,3
which won't work for recursive functions.

Random array element in F#

I'm attempting to learn myself up on F#, and I fear I'm not understanding something as well as I should.
I'm trying to recreate the functionality of a book I rather like (Creative Cursing from Royal and Panarese).
In a nutshell, you have two separate wordlists from which two random words can be chosen, resulting in an odd phrase. Simple enough?
Here's what I have:
#light
open System
open System.IO
let getWordList file =
File.ReadAllLines( file )
let getRandArrElement (arr : string[]) =
let rnd = Random( 0 )
arr |> Seq.nth (rnd.Next arr.Length)
let wordList1 = getWordList "words1.txt"
let wordList2 = getWordList "words2.txt"
let word1 = getRandArrElement wordList1
let word2 = getRandArrElement wordList2
printf "%s %s" word1 word2
It works, too. With the exception that it returns the same phrase every time it's run.
I have a feeling that what it's doing is calculating one random value per call to "getRandArrElement" at compile time, then using that value as THE value (which I think is weird, but what do I know?).
Whats wrong with my logic, and how do I fix it?
Your problem is here:
let getRandArrElement (arr : string[]) =
let rnd = Random( 0 )
arr |> Seq.nth (rnd.Next arr.Length
Random numbers aren't really truly random. They take a seed value, compute a random number between 0.0 and 1.0; that new value is used as the next seed. In other words, Random i spurely deterministic, so seeding with the same value over and over yields the same output sequence.
And since you're always constructor a new Random with the same seed, you're getting the same random number as output everytime.
I suggest a few improvements:
use let rnd = Random(). The default constructor uses the system clock as a seed, so that you'll get a different sequence. (Its still possible to get the same sequence. The system clock has a resolution of about 10 ms, so construction two Randoms in that interval will result, with high probability, of being seeded with the same value.
If you use let rnd = Random(0), even if rnd is outside your function, you'll get the same sentences in the exact same order everytime your run your program.
You can move the declaration of rnd outside your function so you're not constructing it over and over. As an alternative, you can write this:
let getRandArrElement =
let rnd = Random()
fun (arr : string[]) -> ...
F# executes all parameterless values when you open a module, so rnd will be assigned right away, and getRandArrElement is assigned the value of fun (arr : string[]) -> ....
Use arr.[index] instead of arr |> Seq.nth (rnd.Next arr.Length). Its not only more concise, but its also O(1). Seq.nth treats it like a sequence, it walks one element at a time until it gets to the element matching the given index, making the operation O(n).
The final result should be something like:
let getRandArrElement =
let rnd = Random()
fun (arr : string[]) -> arr.[rnd.Next(arr.Length)]
You are using a new Random with the same seed every time, this is expected behavior - if the same seed is used repeatedly, the same series of numbers is generated. I would suggest you move the declaration of rnd out of the function, that will solve your problem:
let rnd = Random();
let getRandArrElement (arr : string[]) =
arr |> Seq.nth (rnd.Next arr.Length)

Resources