biniou icon indicating copy to clipboard operation
biniou copied to clipboard

test_biniou fails on ppc64

Open r4f4 opened this issue 9 years ago • 12 comments

A float comparison fails on ppc64 on line 264 of the test_biniou file. As it can be seen from the log below, I added a print to the respective line in the test and it fails although both numbers seem equal.

$ ./test_biniou x = 1.001470 y = 1.001470 Fatal error: exception File "bi_io.ml", line 265, characters 4-10: Assertion failed

r4f4 avatar Aug 10 '15 16:08 r4f4

Sorry I haven't found the time to look into it.

mjambon avatar Aug 17 '15 16:08 mjambon

This is a copy of the test from bi_io.ml:

let safety_test () =
  let s = "\x3f\xf0\x06\x05\x04\x03\x02\x01" in
  let x = 1.00146962706651288 in
  let y = read_untagged_float64 (Bi_inbuf.from_string s) in
  if x <> y then
    assert false;
  let ob = Bi_outbuf.create 8 in
  write_untagged_float64 ob x;
  if Bi_outbuf.contents ob <> s then
    assert false

Could you post the result of the following code:

let x = 1.00146962706651288 in
let ob = Bi_outbuf.create 8 in
Bi_io.write_untagged_float64 ob x;
Bi_outbuf.contents ob

It should end in \003\002\001 or \x03\x02\x01 like in the original s.

mjambon avatar Aug 17 '15 17:08 mjambon

Martin - my colleague is not an OCaml developer so he's not very familiar with using the compiler, toplevel and so on.

Rafael - here is how to get the results that Martin wants. This assumes: (1) You have ocaml-findlib installed. (2) You have ocaml-easy-format-devel installed. (3) You have the biniou source checked out somewhere and compiled (or you've compiled it using fedpkg build). You will have to change the path to the biniou source in the fragment below.

Step 1: Create a file called test.ml with the content below, but modify the #directory path to point to the location of the biniou source that you have checked out and compiled.

#use "topfind";;
#require "easy-format";;
#directory "/home/rjones/d/fedora/ocaml-biniou/master/biniou-1.0.9";;
#load "biniou.cma";;

open Printf;;

let s : string =
  let x = 1.00146962706651288 in
  let ob = Bi_outbuf.create 8 in
  Bi_io.write_untagged_float64 ob x;
  Bi_outbuf.contents ob

let () = printf "%S\n" s

Step 2: Run it using:

ocaml test.ml

The output on x86 (NOT affected by the bug) is:

"?\240\006\005\004\003\002\001"

rwmjones avatar Aug 18 '15 13:08 rwmjones

Of course there is (maybe?) the problem that by using ocaml you're testing the bytecode compiler, not the native code compiler. Using the native code compiler isn't too hard though:

Step 3: Remove all # lines from the test.ml file.

Step 4: Run these two command (again, changing the path):

ocamlfind ocamlopt -I /home/rjones/d/fedora/ocaml-biniou/master/biniou-1.0.9 -package easy-format -linkpkg biniou.cmxa test.ml -o test
./test

rwmjones avatar Aug 18 '15 14:08 rwmjones

Richard, thank you for the explanation.

Here is the result ('le' means little endian): ppc64le: "?\240\006\005\004\003?Z" ppc64: "?\240\006\005\004\003?Z"

r4f4 avatar Aug 18 '15 14:08 r4f4

Martin: When analyzing this, don't discount the possibility that there could be a bug in the compiler. We are using our own non-upstream ppc64 & ppc64le backends, and while they are generally reliable, we have found bugs before.

rwmjones avatar Aug 18 '15 14:08 rwmjones

Thanks guys. Here's a test that should tell us if the bug is in OCaml or in the biniou library:

File float_bits.ml:

open Printf

let read_bits_from_constant () =
  let expected = "3ff0060504030201" in
  let result =
    sprintf "%0Lx"
      (Int64.bits_of_float 1.00146962706651288)
  in
  printf "read_bits_from_constant: %s %s\n"
    result (if result = expected then "OK" else "ERROR")

let read_bits_from_string () =
  let expected = "3ff0060504030201" in
  let result =
    sprintf "%0Lx"
      (Int64.bits_of_float (float_of_string "1.00146962706651288"))
  in
  printf "read_bits_from_string: %s %s\n"
    result (if result = expected then "OK" else "ERROR")

let main () =
  read_bits_from_constant ();
  read_bits_from_string ()

let () = main ()

Test the bytecode version of the program with:

ocamlc -o float_bits.run float_bits.ml
./float_bits.run

Test the native code version of the program with:

ocamlopt -o float_bits.opt float_bits.ml
./float_bits.opt

In both cases, the output should be:

read_bits_from_constant: 3ff0060504030201 OK
read_bits_from_string: 3ff0060504030201 OK

mjambon avatar Aug 18 '15 19:08 mjambon

Bytecode version: read_bits_from_constant: 3ff0060504030201 OK read_bits_from_string: 3ff0060504030201 OK

Native version: read_bits_from_constant: 3ff0060504033f5a ERROR read_bits_from_string: 3ff0060504030201 OK

r4f4 avatar Aug 18 '15 19:08 r4f4

Thanks. That's interesting. It looks like a somewhat limited problem, which would affect folks who hardcode long constants.

As a workaround, I can modify the test in bi_io.ml so it passes on ppc64, by reading the float from a string at runtime.

I'm gonna file a report for this bug with the OCaml bug tracker. I'll post the link here.

mjambon avatar Aug 18 '15 20:08 mjambon

The bug report is at http://caml.inria.fr/mantis/view.php?id=6963 You may have to confirm the version of OCaml (I entered 4.02.3, which is the latest) or give other platform details.

mjambon avatar Aug 18 '15 21:08 mjambon

Martin, thank you for debugging the issue and filling the report. I added a comment there specifying the ocaml version used. And thank you for the detailed test code.

r4f4 avatar Aug 18 '15 21:08 r4f4

From what I see this has been fixed in upstream by providing a compiler with ppc64 support directly.

Leonidas-from-XIV avatar Aug 14 '17 12:08 Leonidas-from-XIV