Previous week Up Next week

Hello

Here is the latest Caml Weekly News, for the week of 11 to 18 November, 2003.

  1. Rounding mode
  2. Caml and Lindows
  3. OCam'OLE 1.0
  4. A few Ocaml and Vim tricks

Rounding mode

Following a long discussion on rounding modes, Christophe Raffalli said:
(the start of this thread is at http://caml.inria.fr/archives/200311/msg00122.html)

At this address, you will find a very small library for changing the
rounding mode from OCaml (works on 6 processors, but only tested on i486)

ftp://www.lama.univ-savoie.fr/pub/users/RAFFALLI/OCaml-round.tgz

...

Is it possible to use "extended" instead of "double" in OCaml for float
(I am ready to recompile OCaml for this)

What was the reason to have only one type of "float" ? Three types of
float (float, double and extended) do not explode the complexity of the
optimization for float array or float in record (I think).

Ok, you should have three additions +. +.. and +... :-(

Is this the only reason ?
      
Xavier Leroy answered:
> At this address, you will find a very small library for changing the
> rounding mode from OCaml (works on 6 processors, but only tested on i486)

A general comment on the rounding mode issue and your question about
extended-precision floats.

While I agree it would be nice to have full IEEE 754 support in OCaml,
one has to keep in mind that the OCaml standard libraries are severely
constrained by the general requirement that the bytecoded part should
work on any "reasonable" platform, where "reasonable" is currently
defined as "ANSI C plus Unix 98".

Unfortunately, this combination of standards has very little to offer
in terms of advanced features of IEEE float arithmetic.  In
particular, there's no standardized API for controlling rounding
modes.

ISO C9X does provide functions (fegetround, fesetround) to control
rounding modes, and it might be a good idea to use them in your
library when available.  The problem is that very few platforms
implement these functions, let alone full ISO C9X.  For instance, glibc
is the only C library that I know of that provides fe[gs]etround.

So, between standards that few implement and processor-specific asm
statements like you did, there is very little hope of achieving portability.

> Is it possible to use "extended" instead of "double" in OCaml for float
> (I am ready to recompile OCaml for this)

You mean "long double"? :-)  (That's the ISO C9X name for
extended-precision floats.)  

The core bytecode system might keep working if you do this change,
except output_value/input_value on floats, which require 8-byte floats.
As for the native-code compiler, that would require non-trivial
changes throughout.

> What was the reason to have only one type of "float" ? Three types of
> float (float, double and extended) do not explode the complexity of the
> optimization for float array or float in record (I think).

If you want all three array types (float array, double array, extended array)
to be unboxed, it will certainly explode that complexity, turning (in
the polymorphic case) a 2-way branch into a 4-way branch.

> Ok, you should have three additions +. +.. and +... :-(

And much more, notably conversions between the various float types,
conversions to/from integers, to/from strings, printf formats, and so on.
Just look at the Int32, Int64 and Nativeint modules for an idea of the
combinatorics involved.

> Is this the only reason ?

No, there are two others.  The first is that single-precision floats
(32 bits) are nearly useless, since modern processors compute just as
fast over double-precision floats.  The only case where you'd want to
use single-precision floats is as a storage type, to halve the size of
large arrays of numbers, but that's an option supported by bigarrays.

The second is that extended-precision floats are not fully specified
(these can use 80, 96 or 128 bits if I remember correctly), and few
processors implement them efficiently in hardware: IA32, perhaps IA64,
maybe some IBM 360 series processors.  Even on IA32, the trend is to
use SSE2 for floating-point computation, which don't support 80-bit
floats.  So, again, if you program for the common denominator, you'd
use 64-bit floats and nothing else.
      
Brian Hurt asked and Diego Olivier Fernandez Pons answered:
> Actually, I wonder if type systems could be extended to detect
> numerical instabilities ?

I forgot to answer to that question...

There was a discusion on the types forum

http://www.cis.upenn.edu/~bcpierce/types/archives/current/msg01419.html

The main problem could be stated as "what properties do you want to
guarantee for your arithmetics" : algebraic properties ? topological
properties ? subtyping properties ?

Several examples violated algebraic properties were given by Tim
Sweeney in his post (Leibniz equalities, uniqueness of the zero,
forall x. x = x, etc.)

Several examples of topological properties were given by Joe Darcy :

- 'compactification' "IEEE 754 floating-point arithmetics is a
complete system; that is for all inputs, every arithmetic operation in
the standard has a defined IEEE 754 value as a result [...] There are
two ways to add infinite values to the field of real numbers : 1. a
single infinity 2. two affine infinities ..." Actually, there are much
more ways of compactifying a locally compact space and
'compactification' hasn't the same mathematical meaning than
'completion' or 'inner operations' but that is not the problem here.

- funny theorems on limits and series like 'if the general term of a
serie converges, then the whole serie converges'

The subtyping question seems to be related to commutative diagrams :
we want the surjection (e.g. 64 -> 32 bits) to commute with arithmetic
operations.

"Though one can losslessly convert from 32-bit to 64-bit and back,
performing a 32-bit arithmetic operation on such 32-bit numbers can
produce a different result than performing a 64-bit arithmetic
operation on their 64-bit extensions, and then converting back."


We surely can answer to some of these question : with respect to group
properties there is a well known theorem 'any subgroup of R either is
dense or has the form aZ'. In both cases they are infinite. Therefore
you cannot expect any floting points arithmetic to keep all group
properties.

For the typing question, we can give part of an answer :

(I use stochastic arithmetic because interval arithmetic is usually
too pessimistic. I am not a statistician but they all seem to agree
with the fact that in many cases being 'almost sure' is much more easy
than being 'absolutely sure')

Cestac allows you to compute the 'meaningful part' of a computation
(in a statistical sense). Then you can see a result like a couple
float * int where the integers gives the number of exact digits.

If you see a coercion like a surjection (f, n) -> (f, m) with m < n
(which just means that you loose accuracy) then :

(i) We can construct a 'clean' family of subtyping operators that is
such as there is at least one surjection that commutes with your
computations (which one of course depends on the stability of the
given computations).

(ii) We can construct a 'type system' which ensures dynamically that
every result is 'well typed'. Actually, this is exactly what CADNA
does but as a library.
      
Xavier Leroy answered as well:
> Hmm.  Actually, I wonder if type systems could be extended to detect
> numerical instabilities?

It's an extremely tough problem, but you might be interested in the
following papers:

"Static Analyses of the Precision of Floating-Point Operations",
Eric Goubault, Static Analysis Symposium 2001.

"Propagation of Roundoff Errors in Finite Precision Computations: a
Semantics Approach", Matthieu Martel, European Symposium on
Programming 2002. 
      

Caml and Lindows

Xavier Leroy let me know that ...:
A thread on the ocaml-debian-maint mailing list mentions the use of
OCaml in Lindows. You'll find the thread at:
http://lists.debian.org/debian-ocaml-maint/2003/debian-ocaml-maint-200311/msg00048.html
Here is a small excerpt, from David Fox:

We have done several projects here using ocaml, because me and two other senior
engineers here have a long history with functional programming languages.  I
wrote the back end of the Click-n-Run software warehouse in ocaml.  This takes
the Debian repository and reprocesses all the packages to generate the database
information used by the front end (the catalogue) and modifies the packages so
that they fit into our distribution, modifying and generating KDE menu entries
and so forth.  This turns out to be a little more complicated than it first
sounds, because you have to modify the version numbers on the packages, and
then you have to modify all the equals dependencies, and so on and so forth.

The other major use is in our new hardware detection system.  I basically did a
literal translation of a lot of perl code we inherited, which is my excuse why
it is still pretty ugly.  But it had to be drop-in compatible.  This version
isn't available for download yet, but it will be late in the year.  There are
ocaml components that manage the boot loader, the PCI device mapping, and the X
configuration.

There are also small programs that manage things like scanning the system for
mime types and building a mozilla configuration file.  There is also a build
environment creator, similar to pbuilder.  And I wrote a little cgi program
called jiffytask to turn bugzilla into more of a project manager.  So far the
only ocaml code whose source you can access from our website is
lindowsos-mimetypes - search for it in our warehouse and click on the
specifications page for the link.  It is completely uninteresting, another
translation job turning weird little xml files into another big weird xml file,
but it make Mozilla happy.  The detector will be available when our next
release comes out.  The warehouse program is, unfortunately, retired.  It is
being rewritten by others in (sniff) Perl.  We regret this somewhat, but we
didn't want to push people into a language they weren't comfortable with.
      

OCam'OLE 1.0

Nicolas Cannasse announced:
OCam'OLE, windows COM support for OCaml has turned from pre-release to 1.0.
This change include only minor updates (such as compiling with 3.07 and
fixed in problem with unsupported types). Since OCam'OLE has been around for
a while, it's now time for 1.0. Users please update from the website :
http://tech.motion-twin.com/ocamole
      

A few Ocaml and Vim tricks

Issac Trotts said (typo corrected by Aleksey Nogin):
For those who use Vim and have the matchit.vim plugin installed,
here are a few lines to put in $HOME/.vim/ftplugin/ocaml.vim :

let b:mw='\<let\>:\<and\>:\(\<in\>\|;;\),'
let b:mw=b:mw . '\<if\>:\<then\>:\<else\>,\<do\>:\<done\>,'
let b:mw=b:mw . '\<\(object\|sig\|struct\|begin\)\>:\<end\>'
let b:match_words=b:mw

Then the percent key jumps between begin...end, let...in, etc.

The only problem I've encountered with it is that it doesn't
go back to 'if' from 'then' when the 'else' clause is missing.
If someone knows how to fix this, I'd like to know.
      
Stefano Zacchiroli added:
> For those who use Vim and have the matchit.vim plugin installed,
> here are a few lines to put in $HOME/.vim/ftplugin/ocaml.vim :

Thanks! This is what I offer in exchange: support for switching from .ml
to .mli with ",s" and ",S" (the latter split a new window). It requires
vim-python in order to remember the previous position in a file:

    " switching between interfaces (.mli) and implementations (.ml)
  if !exists("g:did_ocaml_switch") && has("python")
    let g:did_ocaml_switch = 1
    map ,s :call OCaml_switch_switch()<CR>
    map ,S :call OCaml_switch_switch_new()<CR>
    fun OCaml_switch_pynit()
      python << EOF
  import vim
  positions = {}
  def ocaml_save_position():
      positions[vim.current.buffer.name] = vim.current.window.cursor
  def ocaml_restore_position():
      try:
          vim.current.window.cursor = positions[vim.current.buffer.name]
      except KeyError:
          pass
  EOF
    endfun
    call OCaml_switch_pynit()
    fun OCaml_switch_switch()
      if (match(bufname(""), "\\.mli$") >= 0)
        python ocaml_save_position()
        exec "edit " . substitute(bufname(""), "\\.mli$", ".ml", "")
        python ocaml_restore_position()
      elseif (match(bufname(""), "\\.ml$") >= 0)
        python ocaml_save_position()
        exec "edit " . bufname("") . "i"
        python ocaml_restore_position()
      endif
    endfun
    fun OCaml_switch_switch_new()  " as above but in a new window
      if (match(bufname(""), "\\.mli$") >= 0)
        python ocaml_save_position()
        exec "new " . substitute(bufname(""), "\\.mli$", ".ml", "")
        python ocaml_restore_position()
      elseif (match(bufname(""), "\\.ml$") >= 0)
        python ocaml_save_position()
        exec "new " . bufname("") . "i"
        python ocaml_restore_position()
      endif
    endfun
  endif
      

Using folding to read the cwn in vim 6+

Here is a quick trick to help you read this CWN if you are viewing it using vim (version 6 or greater).

:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'&lt;1':1
zM

If you know of a better way, please let me know.


Old cwn

If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a look at the archive or the RSS feed of the archives.

If you also wish to receive it every week by mail, you may subscribe online.


Alan Schmitt