value not updated when incrementing mutable ref - reference

Below is an extract of code :
(the problem is visible by testing only this extract)
let cptIdCO = ref 0;; (* compteur : id Classe et Object globale *)
let makeEtiClassOrObj =
cptIdCO := !cptIdCO + 1;
"ClObj_" ^ (string_of_int !cptIdCO) ^ ": NOP\n";;
let compileClass cls =
print_string "-- compileClass\n";
(*fillClass cls;*)
print_string makeEtiClassOrObj;
and compileObject obj =
print_string "\t-- compileObject \n";
print_string makeEtiClassOrObj;
When calling compileClass or compileObject several times, the output is always ClObj_1: NOP so it seems that the reference is not updated and I don't understand why.
I saw some uses of ^:= and !^ but it don't work and I don't understand the difference between the normal and ^ versions.

The problem is not the way you update the reference, but that makeEtiClass is not a function, just a variable holding a string, that happens to increment cptIdCO once before initializing it.
A function differs from a variable in that it takes arguments. You can use unit, (), if it doesn't need anything else.
This will do what you expect:
let cptIdCO = ref 0;; (* compteur : id Classe et Object globale *)
let makeEtiClassOrObj () =
cptIdCO := !cptIdCO + 1;
"ClObj_" ^ (string_of_int !cptIdCO) ^ ": NOP\n";;
let compileClass cls =
print_string "-- compileClass\n";
(*fillClass cls;*)
print_string (makeEtiClassOrObj ())
and compileObject obj =
print_string "\t-- compileObject \n";
print_string (makeEtiClassOrObj ())

Related

Auto-vectorization of a loop shuffling 4 int elements and taking absolute differences vs. the previous arrangement

I'm trying, without succeeding, to make the Rust compiler (rustc 1.66.0) auto-vectorize the following function (without using any unsafe intrinsics):
pub fn get_transforms(s: &mut [i32]) -> u32 {
assert_eq!(s.len(), 4);
let mut transforms = 1;
while s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0 {
// Calculate deltas
let d0 = s[0] - s[1];
let d1 = s[1] - s[2];
let d2 = s[2] - s[3];
let d3 = s[3] - s[0];
// Assign absolute values
s[0] = d0.abs();
s[1] = d1.abs();
s[2] = d2.abs();
s[3] = d3.abs();
transforms += 1;
}
transforms
}
My idea is to make it perform the subtractions and the abs() once (using 16 byte registers) instead of four times.
I've read that iterators might help, but I haven't found an easy way to use them here.
Compiler flags don't seem to able to help either.
Here's the link to the Compiler Explorer output I'm using as reference: https://godbolt.org/z/7sqq6bszT
As #ChayimFriedman noted in the comments, you need to add -Copt-level=3 to the command line. But additionally, you need to make sure that the boolean-expression is not evaluated lazily, i.e., use the | operator instead of || (requires parentheses around the comparisons):
while (s[0] > 0) | (s[1] > 0) | (s[2] > 0) | (s[3] > 0) {
// rest of code unmodified
Compiling this produces the following loop:
.LBB0_13:
vpshufd xmm2, xmm0, 57
vpsubd xmm0, xmm0, xmm2
vpabsd xmm0, xmm0
inc eax
vpcmpgtd xmm2, xmm0, xmm1
vmovmskps ecx, xmm2
test ecx, ecx
jne .LBB0_13
The reason why | instead of || helps the compiler is that for expressions like a || b the b expression shall not be evaluated if a is true already -- most of the time this requires a branch depending on the value of a. On the other hand, for a | b both a and b are evaluated every time. Of course, the compiler should be allowed to do any optimization under the "as-if" rule, i.e., if evaluating b does not have any side effects (and the compiler can prove that), a || b and a | b could be compiled to the same code.
N.B.: If you are sure that s[i] are never negative (which is obviously true, if the inputs are non-negative), you can replace s[i] > 0 by s[i] != 0, which will reduce the vpcmpgtd+vmovmskps+test to a single vptest.

How find integer in text

Help me figure out how to work with text
i have a string like: "word1 number: word2" for example : "result 0: Good" or "result 299: Bad"
i need print Undefined/Low or High
When string is null , print Undefined
When number 0-15, print Low
When number >15, print High
type GetResponse =
{
MyData: string voption
ErrorMessage: string voption }
val result: Result<GetResponse, MyError>
and then i try:
MyData =
match result with
| Ok value ->
if (value.Messages = null) then
ValueSome "result: Undefined"
else
let result =
value.Messages.FirstOrDefault(
(fun x -> x.ToUpperInvariant().Contains("result")),
"Undefined"
)
if (result <> "Undefined") then
ValueSome result
else
errors.Add("We don't have any result")
ValueNone
| Error err ->
errors.Add(err.ToErrorString)
ValueNone
ErrorMessage =
if errors.Any() then
(errors |> String.concat ", " |> ValueSome)
else
ValueNone
but i dont know gow check in string number and maybe there is some way print this without a billion if?
Parsing gets complex very quickly. I recommend using FParsec to simplify the logic and avoid errors. A basic parser that seems to meet your needs:
open System
open FParsec
let parseWord =
manySatisfy Char.IsLetter
let parseValue =
parseWord // parse any word (e.g. "result")
>>. spaces1 // skip whitespace
>>. puint32 // parse an unsigned integer value
.>> skipChar ':' // skip colon character
.>> spaces // skip whitespace
.>> parseWord // parse any word (e.g. "Good")
You can then use it like this:
type ParserResult = Undefined | Low | High
let parse str =
if isNull str then Result.Ok Undefined
else
match run parseValue str with
| Success (num, _ , _) ->
if num <= 15u then Result.Ok Low
else Result.Ok High
| Failure (errorMsg, _, _) ->
Result.Error errorMsg
parse null |> printfn "%A" // Ok Undefined
parse "result 0: Good" |> printfn "%A" // Ok Low
parse "result 299: Bad" |> printfn "%A" // Ok High
parse "invalid input" |> printfn "%A" // Error "Error in Ln: 1 Col: 9 ... Expecting: integer number"
There's definitely a learning curve with FParsec, but I think it's worth adding to your toolbelt.
I agree with Brian that parsing can become quite tricky very quickly. However if you have some well established format of the input and you're not very much into writing complex parsers, good old regular expressions can be of service ;)
Here is my take on the problem - please note that it has plenty of room to improve, this is just a proof of concept:
open System.Text.RegularExpressions
let test1 = "result 0: Good"
let test2 = "result 299: Bad"
let test3 = "some other text"
type ParserResult =
| Undefined
| Low of int
| High of int
let (|ValidNumber|_|) s =
//https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=net-6.0
let rx = new Regex("(\w\s+)(\d+)\:(\s+\w)")
let matches = rx.Matches(s)
if matches.Count > 0 then
let groups = matches.[0].Groups |> Seq.toList
match groups with
| [_; _; a; _] -> Some (int a.Value)
| _ -> None
else
None
let parseMyString str =
match str with
| ValidNumber n when n < 16 -> Low n
| ValidNumber n -> High n
| _ -> Undefined
//let r = parseMyString test1
printfn "%A" (parseMyString test1)
printfn "%A" (parseMyString test2)
printfn "%A" (parseMyString test3)
The active pattern ValidNumber returns the Some number if a match of the input string is found, otherwise it returns None. The parseMyString function uses the pattern and guards to initialise the final ParserOutput value.

extracting a substring in a string with some conditions

I hope you are well !
I present my problem to you. I have a string (on a single line) and the idea is to iterate the string from a given position in the string, go left character by character and stop when we meet a separator (the separators are in the list), and do the same on the right and at the end, put the two together to form the word you are looking for. I wrote the following function, but it doesn't quite work, when I position myself at the end of a word like in position 4, it returns me a string "" instead of returning "this". When I go to position 1, it sends me "his" and not "this". When I put myself in position 44, I output "tha" instead of "that". On the other hand, in the middle of the string as for position 36 or 40, it works.
Can anyone help me fix these bugs?
(* separators *)
let sep_list = [';';',';'(';')';'.';' ';]
(* my string to test *)
let my_str = "this is my string for testing purpose, only that"
(* my function *)
let search_word_in_cursor (str:string) (char_list:char list) (pos:int) : string =
let rec foo_left (str:string) (char_list:char list) (pos:int) (ret:string) : string =
if ((List.exists (fun x -> Char.equal x str.[pos]) char_list) || (pos <= 0)) then ret
else if (pos == 0) then String.make 1 str.[pos] ^ ret
else foo_left str char_list (pos - 1) ((String.make 1 str.[pos]) ^ ret)
in
let rec foo_right (str:string) (char_list:char list) (pos:int) (ret:string) : string =
if ((List.exists (fun x -> Char.equal x str.[pos]) char_list) || (pos >= (String.length str - 1))) then ret
else foo_right str char_list (pos + 1) (ret ^ (String.make 1 str.[pos]))
in
let sl = foo_left str char_list pos "" in
let sr = foo_right str char_list pos "" in
if (sr == "" && sl == "") then ""
else if (sr == "" && sl != "") then sl
else if (sr != "" && sl == "") then sr
else (String.sub sl 0 (String.length sl - 1)) ^ sr
(* expects and results *)
let () =
print_string (search_word_in_cursor my_str sep_list 4); (* expected:"this" output:"" *)
print_string (search_word_in_cursor my_str sep_list 1);(* expected:"this" output:"his" *)
print_string (search_word_in_cursor my_str sep_list 44);(* expected:"that" output:"tha" *)
print_string (search_word_in_cursor my_str sep_list 36);(* expected:"purpose" output:"purpose" *)
print_string (search_word_in_cursor my_str sep_list 40)(* expected:"only" output:"only" *)
Thank you, goog to y'all !

Ocaml - Check, given a list of transitions, the word is recognized

I created a function that returns a list of transitions. Transitions are of type int * char * int.
for example (0 'E' 1); (1 'A' 2). The valid alphabet for the transitions are A, C, G and T and the char 'E' represents epsilon.
type transition = int * char * int;;
let get_start (a,_,_) = a;;
let get_char (_,a,_) = a;;
let get_end (_,_,a) = a;;
The initial state and the final state are stored in the following variables.
...
let i_strt = ref !state_initial;;
let i_end = ref !state_end;;
exception Out_of_loop;;
let seq = read_line();;(* string to be tested *)
let len_seq = String.length seq -1;;
let lst_trs_length = List.length !aux_transitions -1;; (* aux_transitions -> all transitions*)
let i = ref 0;;
let f = ref 0;;
while !i <= len_seq do
let c_r = seq.[i]in (* c_r = 'A' seq = ACGT*)
try
while !j <= lst_trs_length do
let aux_trs = List.nth !aux_transitions !j in (* 0 'E' 1 -> 1 'A' 2 ....*)
if (get_start aux_trs) = !i_strt then (* *)
let aux_chr = get_char aux_trs in (* 'A' *)
if aux_chr = c_r then(
i_strt := get_end aux_trs; (* i_strt = 1*)
raise Out_of_loop
)
else if aux_chr = 'E' then(
i_strt := get_end aux_trs;
j := -1
);
j := !j+1
done;
with Out_of_loop ->();
i := !i +1
done;
I am trying to use these two cycles to check whether the string "seq" can be recognized or not by the list of transitions taking into account the initial state. I am having trouble writing this function ... I want a function that, given a list of transitions and a string, returns 'true' in case it is recognized or false in the negative case.

reading integers from a string

I want to read a line from a file, initialize an array from that line and then display the integers.
Why is is not reading the five integers in the line? I want to get output 1 2 3 4 5, i have 1 1 1 1 1
open Array;;
open Scanf;;
let print_ints file_name =
let file = open_in file_name in
let s = input_line(file) in
let n = ref 5 in
let arr = Array.init !n (fun i -> if i < !n then sscanf s "%d" (fun a -> a) else 0) in
let i = ref 0 in
while !i < !n do
print_int (Array.get arr !i);
print_string " ";
i := !i + 1;
done;;
print_ints "string_ints.txt";;
My file is just: 1 2 3 4 5
You might want to try the following approach. Split your string into a list of substrings representing numbers. This answer describes one way of doing so. Then use the resulting function in your print_ints function.
let ints_of_string s =
List.map int_of_string (Str.split (Str.regexp " +") s)
let print_ints file_name =
let file = open_in file_name in
let s = input_line file in
let ints = ints_of_string s in
List.iter (fun i -> print_int i; print_char ' ') ints;
close_in file
let _ = print_ints "string_ints.txt"
When compiling, pass str.cma or str.cmxa as an argument (see this answer for details on compilation):
$ ocamlc str.cma print_ints.ml
Another alternative would be using the Scanf.bscanf function -- this question, contains an example (use with caution).
The Scanf.sscanf function may not be particularly suitable for this task.
An excerpt from the OCaml manual:
the scanf facility is not intended for heavy duty lexical analysis and parsing. If it appears not expressive enough for your needs, several alternative exists: regular expressions (module Str), stream parsers, ocamllex-generated lexers, ocamlyacc-generated parsers
There is though a way to parse a string of ints using Scanf.sscanf (which I wouldn't recommend):
let rec int_list_of_string s =
try
Scanf.sscanf s
"%d %[0-9-+ ]"
(fun n rest_str -> n :: int_list_of_string rest_str)
with
| End_of_file | Scanf.Scan_failure _ -> []
The trick here is to represent the input string s as a part which is going to be parsed into a an integer (%d) and the rest of the string using the range format: %[0-9-+ ]", which will match the rest of the string, containing only decimal digits 0-9, the - and + signs, and whitespace .

Resources