* [Caml-list] Comparing floats @ 2015-07-23 8:35 Sébastien Hinderer 2015-07-23 8:46 ` Francois Berenger ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Sébastien Hinderer @ 2015-07-23 8:35 UTC (permalink / raw) To: caml-list Dear all, What's the most efficient way to compare floats, please? Is it the polymorphic compare function, or is there a more specialized version of it? I saw Float.compare mentionned on the web but that does not seem to exist any longer? Thanks, Sébastien. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 8:35 [Caml-list] Comparing floats Sébastien Hinderer @ 2015-07-23 8:46 ` Francois Berenger 2015-07-23 9:05 ` Mr. Herr 2015-07-23 9:01 ` Xavier Leroy 2015-07-23 11:34 ` Boris Yakobowski 2 siblings, 1 reply; 11+ messages in thread From: Francois Berenger @ 2015-07-23 8:46 UTC (permalink / raw) To: OCaml List On 07/23/2015 10:35 AM, Sébastien Hinderer wrote: > Dear all, > > What's the most efficient way to compare floats, please? > Is it the polymorphic compare function, or is there a more specialized > version of it? > > I saw Float.compare mentionned on the web but that does not seem to exist > any longer? It exists in Batteries for sure and in Core I believe. Also, maybe you can define: let cmp_f (x: float) (y: float) = x -. y > Thanks, > > Sébastien. > -- Regards, Francois. "When in doubt, use more types" ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 8:46 ` Francois Berenger @ 2015-07-23 9:05 ` Mr. Herr 0 siblings, 0 replies; 11+ messages in thread From: Mr. Herr @ 2015-07-23 9:05 UTC (permalink / raw) To: caml-list On 23.07.2015 10:46, Francois Berenger wrote: > On 07/23/2015 10:35 AM, Sébastien Hinderer wrote: >> Dear all, >> >> What's the most efficient way to compare floats, please? >> Is it the polymorphic compare function, or is there a more specialized >> version of it? >> >> I saw Float.compare mentionned on the web but that does not seem to exist >> any longer? > > It exists in Batteries for sure and in Core I believe. > > Also, maybe you can define: > > let cmp_f (x: float) (y: float) = x -. y hmm, this will return float instead of int. My test says that compare is compiled directly to the adequate internal function, and if this even in byte code: str@s131-intel:~/Projekte/Ocaml/ml> cat test_comparefl1.ml && echo -e "------------\n" && ocamlc -dinstr test_comparefl1.ml (* Frage auf mailing list: wie am besten floats vergleichen? *) print_endline ("Pervasives.compare 2 floats gives me " ^ (string_of_int (compare 2.0 3.99))) ------------ const 3.99 push const 2.0 ccall caml_float_compare, 2 push getglobal Pervasives! getfield 19 apply 1 push const "Pervasives.compare 2 floats gives me " push getglobal Pervasives! getfield 15 apply 2 push getglobal Pervasives! getfield 30 apply 1 makeblock 0, 0 setglobal Test_comparefl1! ------------------------------ /Str. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 8:35 [Caml-list] Comparing floats Sébastien Hinderer 2015-07-23 8:46 ` Francois Berenger @ 2015-07-23 9:01 ` Xavier Leroy 2015-07-23 9:35 ` Sébastien Hinderer 2015-07-23 9:54 ` Mr. Herr 2015-07-23 11:34 ` Boris Yakobowski 2 siblings, 2 replies; 11+ messages in thread From: Xavier Leroy @ 2015-07-23 9:01 UTC (permalink / raw) To: caml-list On 23/07/2015 10:35, Sébastien Hinderer wrote: > What's the most efficient way to compare floats, please? > Is it the polymorphic compare function, or is there a more specialized > version of it? You'll get good performance by type-specializing Pervasives.compare: let compare_float (x: float) (y: float) = compare x y If you're absolutely sure your floats are not NaN, you can shave a few CPU cycles: let compare_float (x: float) (y: float) = if x < y then -1 else if x > y then 1 else 0 - Xavier Leroy ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 9:01 ` Xavier Leroy @ 2015-07-23 9:35 ` Sébastien Hinderer 2015-07-23 9:54 ` Mr. Herr 1 sibling, 0 replies; 11+ messages in thread From: Sébastien Hinderer @ 2015-07-23 9:35 UTC (permalink / raw) To: caml-list Xavier Leroy (2015/07/23 11:01 +0200): > On 23/07/2015 10:35, Sébastien Hinderer wrote: > > What's the most efficient way to compare floats, please? > > Is it the polymorphic compare function, or is there a more specialized > > version of it? > > You'll get good performance by type-specializing Pervasives.compare: > > let compare_float (x: float) (y: float) = compare x y > > If you're absolutely sure your floats are not NaN, you can shave a few > CPU cycles: > > let compare_float (x: float) (y: float) = > if x < y then -1 else if x > y then 1 else 0 Thanks a lot Xavier! Sébastien. > > - Xavier Leroy > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 9:01 ` Xavier Leroy 2015-07-23 9:35 ` Sébastien Hinderer @ 2015-07-23 9:54 ` Mr. Herr 2015-08-04 9:06 ` Goswin von Brederlow 1 sibling, 1 reply; 11+ messages in thread From: Mr. Herr @ 2015-07-23 9:54 UTC (permalink / raw) To: caml-list On 23.07.2015 11:01, Xavier Leroy wrote: > On 23/07/2015 10:35, Sébastien Hinderer wrote: >> What's the most efficient way to compare floats, please? >> Is it the polymorphic compare function, or is there a more specialized >> version of it? > You'll get good performance by type-specializing Pervasives.compare: > > let compare_float (x: float) (y: float) = compare x y > > If you're absolutely sure your floats are not NaN, you can shave a few > CPU cycles: > > let compare_float (x: float) (y: float) = > if x < y then -1 else if x > y then 1 else 0 > The assembler code says compare_float is directly compiled to a function that compares the 2 values in xmm0 and xmm1 registers, while Pervasives.compare is a library function written in C doing the same thing. The assembler code looks very very good. But I doubt that you could measure a difference. The type system will always yield the float_compare function, doesn't it? So far my quickcheck... --- Assembler code of your suggested function: camlTest_comparefl3__compare_float_1008: .cfi_startproc .L102: movsd (%rbx), %xmm0 movsd (%rax), %xmm1 comisd %xmm1, %xmm0 jbe .L101 movq $-1, %rax ret .align 4 .L101: comisd %xmm0, %xmm1 jbe .L100 movq $3, %rax ret .align 4 .L100: movq $1, %rax ret .cfi_endproc --- C code of library function: CAMLprim value caml_float_compare(value vf, value vg) { double f = Double_val(vf); double g = Double_val(vg); if (f == g) return Val_int(0); if (f < g) return Val_int(-1); if (f > g) return Val_int(1); /* One or both of f and g is NaN. Order according to the convention NaN = NaN and NaN < x for all other floats x. */ if (f == f) return Val_int(1); /* f is not NaN, g is NaN */ if (g == g) return Val_int(-1); /* g is not NaN, f is NaN */ return Val_int(0); /* both f and g are NaN */ } ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 9:54 ` Mr. Herr @ 2015-08-04 9:06 ` Goswin von Brederlow 0 siblings, 0 replies; 11+ messages in thread From: Goswin von Brederlow @ 2015-08-04 9:06 UTC (permalink / raw) To: caml-list On Thu, Jul 23, 2015 at 11:54:38AM +0200, Mr. Herr wrote: > > > On 23.07.2015 11:01, Xavier Leroy wrote: > >On 23/07/2015 10:35, Sébastien Hinderer wrote: > >>What's the most efficient way to compare floats, please? > >>Is it the polymorphic compare function, or is there a more specialized > >>version of it? > >You'll get good performance by type-specializing Pervasives.compare: > > > >let compare_float (x: float) (y: float) = compare x y > > > >If you're absolutely sure your floats are not NaN, you can shave a few > >CPU cycles: > > > >let compare_float (x: float) (y: float) = > > if x < y then -1 else if x > y then 1 else 0 > > > The assembler code says compare_float is directly compiled to a function > that compares the 2 values > in xmm0 and xmm1 registers, while Pervasives.compare is a library function > written in C doing the same thing. > > The assembler code looks very very good. > > But I doubt that you could measure a difference. The type system will always > yield the float_compare function, doesn't it? So far my quickcheck... There are many cases where you have a polymorphic function (as in the code does not allow to infere that the type is float) doing lots of compares or you pass compare as argument to a polymorphic function. By specifically forcing the type to be float you can gain a lot of performance. If the type system already inferes the float type itself then you gain nothing. But that doesn't always happen (at the right time). MfG Goswin ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 8:35 [Caml-list] Comparing floats Sébastien Hinderer 2015-07-23 8:46 ` Francois Berenger 2015-07-23 9:01 ` Xavier Leroy @ 2015-07-23 11:34 ` Boris Yakobowski 2015-07-23 15:14 ` Jacques-Henri Jourdan 2 siblings, 1 reply; 11+ messages in thread From: Boris Yakobowski @ 2015-07-23 11:34 UTC (permalink / raw) To: Sébastien Hinderer, The Caml Mailing List [-- Attachment #1: Type: text/plain, Size: 1137 bytes --] Hi Sébastien, I feel obligated to point out that the _semantics_ of floating-point comparison is a bit tricky. IEEE 754 mandates that NaN == NaN should return false (as well as NaN != NaN), breaking all algebraic laws known to mankind :-). OCaml's operators '=' and '!=' follow this convention, but 'compare nan nan' returns 0, which is usually the desired behavior. However, 'compare 0. (-0.)' also returns 0, while you might want to distinguish those two values. HTH, On Thu, Jul 23, 2015 at 10:35 AM, Sébastien Hinderer < Sebastien.Hinderer@inria.fr> wrote: > Dear all, > > What's the most efficient way to compare floats, please? > Is it the polymorphic compare function, or is there a more specialized > version of it? > > I saw Float.compare mentionned on the web but that does not seem to exist > any longer? > > Thanks, > > Sébastien. > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > -- Boris [-- Attachment #2: Type: text/html, Size: 1918 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 11:34 ` Boris Yakobowski @ 2015-07-23 15:14 ` Jacques-Henri Jourdan 2015-07-23 16:34 ` Boris Yakobowski 0 siblings, 1 reply; 11+ messages in thread From: Jacques-Henri Jourdan @ 2015-07-23 15:14 UTC (permalink / raw) To: caml-list [-- Attachment #1.1: Type: text/plain, Size: 1440 bytes --] Le 23/07/2015 13:34, Boris Yakobowski a écrit : > Hi Sébastien, > > I feel obligated to point out that the _semantics_ of floating-point > comparison is a bit tricky. IEEE 754 mandates that NaN == NaN should > return false (as well as NaN != NaN), breaking all algebraic laws > known to mankind :-). Beaware: Nan <> Nan -> true Nan = Nan -> false Nan != Nan and Nan == Nan : depends on the memory layout. > OCaml's operators '=' and '!=' follow this convention, but 'compare > nan nan' returns 0, which is usually the desired behavior. However, > 'compare 0. (-0.)' also returns 0, while you might want to distinguish > those two values. > > HTH, > > On Thu, Jul 23, 2015 at 10:35 AM, Sébastien Hinderer > <Sebastien.Hinderer@inria.fr <mailto:Sebastien.Hinderer@inria.fr>> wrote: > > Dear all, > > What's the most efficient way to compare floats, please? > Is it the polymorphic compare function, or is there a more specialized > version of it? > > I saw Float.compare mentionned on the web but that does not seem > to exist > any longer? > > Thanks, > > Sébastien. > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > > > > > -- > Boris [-- Attachment #1.2: Type: text/html, Size: 3591 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 473 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 15:14 ` Jacques-Henri Jourdan @ 2015-07-23 16:34 ` Boris Yakobowski 2015-07-23 17:00 ` Xavier Leroy 0 siblings, 1 reply; 11+ messages in thread From: Boris Yakobowski @ 2015-07-23 16:34 UTC (permalink / raw) To: Jacques-Henri Jourdan; +Cc: The Caml Mailing List [-- Attachment #1: Type: text/plain, Size: 1924 bytes --] Indeed, thanks for the clarification... I got confused when negating OCaml's '=' operator (a dangerous side-effect of writing too much C!), hence the erroneous '!=' instead of <>. Regarding, 'nan <> nan', I had convinced myself that all comparisons with NaN returned false. I wonder why <>/!= got a special treatment since e.g. 'nan < 1.' and '1. < nan' both return false. On Thu, Jul 23, 2015 at 5:14 PM, Jacques-Henri Jourdan < jacques-henri.jourdan@inria.fr> wrote: > > > Le 23/07/2015 13:34, Boris Yakobowski a écrit : > > Hi Sébastien, > > I feel obligated to point out that the _semantics_ of floating-point > comparison is a bit tricky. IEEE 754 mandates that NaN == NaN should return > false (as well as NaN != NaN), breaking all algebraic laws known to mankind > :-). > > > Beaware: > > Nan <> Nan -> true > Nan = Nan -> false > Nan != Nan and Nan == Nan : depends on the memory layout. > > OCaml's operators '=' and '!=' follow this convention, but 'compare > nan nan' returns 0, which is usually the desired behavior. However, > 'compare 0. (-0.)' also returns 0, while you might want to distinguish > those two values. > > HTH, > > On Thu, Jul 23, 2015 at 10:35 AM, Sébastien Hinderer < > <Sebastien.Hinderer@inria.fr>Sebastien.Hinderer@inria.fr> wrote: > >> Dear all, >> >> What's the most efficient way to compare floats, please? >> Is it the polymorphic compare function, or is there a more specialized >> version of it? >> >> I saw Float.compare mentionned on the web but that does not seem to exist >> any longer? >> >> Thanks, >> >> Sébastien. >> >> -- >> Caml-list mailing list. Subscription management and archives: >> https://sympa.inria.fr/sympa/arc/caml-list >> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >> Bug reports: http://caml.inria.fr/bin/caml-bugs >> > > > > -- > Boris > > > -- Boris [-- Attachment #2: Type: text/html, Size: 4050 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] Comparing floats 2015-07-23 16:34 ` Boris Yakobowski @ 2015-07-23 17:00 ` Xavier Leroy 0 siblings, 0 replies; 11+ messages in thread From: Xavier Leroy @ 2015-07-23 17:00 UTC (permalink / raw) To: caml-list On 23/07/15 18:34, Boris Yakobowski wrote: > I got confused when negating OCaml's '=' operator (a dangerous side-effect > of writing too much C!), hence the erroneous '!=' instead of <>. Regarding, > 'nan <> nan', I had convinced myself that all comparisons with NaN returned > false. I wonder why <>/!= got a special treatment since e.g. 'nan < 1.' and > '1. < nan' both return false. Perhaps so that (using Caml syntax) "x <> y" is always equivalent to "not (x = y)". But I agree it can be viewed as yet another oddity with NaNs. Just to clarify my previous post: let compare_float (x: float) (y: float) = compare x y gives a total order over floats that behaves sensibly, if somewhat arbitrarily, over NaN arguments: two NaNs are equal, and any NaN is less than any non-NaN float. In contrast, let compare_float (x: float) (y: float) = if x < y then -1 else if x > y then 1 else 0 is not a proper order, because the implied equality is not transitive. Consider: compare_float 0.0 nan = 0 compare_float nan 1.0 = 0 compare_float 0.0 1.0 = -1 So, don't use the latter definition for e.g. sorting a list of floats that can contain NaN. The former definition is more robust. - Xavier Leroy ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2015-08-04 9:06 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-07-23 8:35 [Caml-list] Comparing floats Sébastien Hinderer 2015-07-23 8:46 ` Francois Berenger 2015-07-23 9:05 ` Mr. Herr 2015-07-23 9:01 ` Xavier Leroy 2015-07-23 9:35 ` Sébastien Hinderer 2015-07-23 9:54 ` Mr. Herr 2015-08-04 9:06 ` Goswin von Brederlow 2015-07-23 11:34 ` Boris Yakobowski 2015-07-23 15:14 ` Jacques-Henri Jourdan 2015-07-23 16:34 ` Boris Yakobowski 2015-07-23 17:00 ` Xavier Leroy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox