Food for thought: Numeric.Special

Hi all,
I am currently working on a module where I need some "special" math
functions (elliptic integrals and Jacobi elliptic functions). This got
me thinking that there may be a place in the Numeric hierarchy for a
Special branch.
I think the only sane way to do this is with FFI, and I think the GNU
Scientific Library (GSL) is the best target for this. Some people may
have access to the IMSL or NAG libraries, but I doubt that most do. I
also believe that GSL is available for all of the targets currently
served by the various Haskell compilers, including Windows
The best way to attack this is probably to have a module for each group
of functions. So there would be Numeric.Special.Gamma,
Numeric.Special.Zeta, etc. The Haskell names would match the GSL names
minus the gsl_sf prefix.
Most (all?) of the functions are pure, and basically accept doubles or
ints as parameters and return a double. So, it's not a hard job, but
there are a zillion functions. I am willing to (slowly) tackle the job
since I already have it started.
Thoughts? Comments?
--
Matthew Donadio

G'day all. On Thu, Jun 05, 2003 at 10:31:31PM -0400, Matthew Donadio wrote:
I am currently working on a module where I need some "special" math functions (elliptic integrals and Jacobi elliptic functions). This got me thinking that there may be a place in the Numeric hierarchy for a Special branch.
Charged, no doubt, with infiltrating and shutting down dissident modules. (Sorry, little Commonwealth joke there.) Cheers, Andrew Bromage

I think the only sane way to do this is with FFI, and I think the GNU Scientific Library (GSL) is the best target for this. Some people may have access to the IMSL or NAG libraries, but I doubt that most do. I also believe that GSL is available for all of the targets currently served by the various Haskell compilers, including Windows [..] Most (all?) of the functions are pure, and basically accept doubles or ints as parameters and return a double. So, it's not a hard job, but there are a zillion functions. I am willing to (slowly) tackle the job since I already have it started.
Thoughts? Comments?
Automate! You must avoid actually writing the import declarations for each function by hand. With any luck, you can write a script to automatically turn the .h file into a .hs file, and save yourself all the work. I believe there are tools to assist in this; see a recent posting on the Haskell FFI list by Simon Marlow:
You want to use a tool to make all this easier. There are various tools available: green-card, c2hs, and hsc2hs are the most commonly-used ones these days. Alastair Reid wrote a good comparison of the various tools (can't remember the link off hand though).
There are examples of hsc2hs code in the libraries - particularly fptools/libraries/unix has examples of doing defines, enums and structs. Examples of green-card stuff can be found in fptools/libraries/HGL and fptools/libraries/X11. Take a look at Manuel's GtkHS for c2hs examples. <<< --KW 8-)

Keith.Wansbrough writes:
Automate!
You must avoid actually writing the import declarations for each function by hand.
If the functions are all of the complexity of sin, cos, etc., it is hard to improve significantly on: foreign import ccall sin :: Double -> Double There's just not much information you can leave out of this. (Perhaps you could save the first three tokens but they're not that hard to cut and paste). You'll see some benefit from ffi preprocessors on functions with complex but regular marshalling requirements like passing arrays or tuples and returning Maybes, error codes and multiple return values. The GreenCard preprocessor is especially good here. Where you'll see most benefit from an ffi preprocessor is when you have to interact with non-primitive C datatypes (structs, unions, enums, typedefs). hsc2hs and c2hs are probably the strongest at this sort of thing.
With any luck, you can write a script to automatically turn the .h file into a .hs file, and save yourself all the work.
Manuel's c2hs tool can do some of this (and I think it's the only tool that does). IIRC, it parses header files to extract type information so that if you write: sin = {#call pure sin#} it can fill in the type information for you. [Manuel: please correct any errors in the above.] It is still up to you to decide which functions you want to interface to and for complex cases, you still have to say how to marshall the code. Note that with any tool which extracts information from header files, you will have to think about how to make your distribution portable. With hsc2hs, this means shipping the .hsc files it generates. With c2hs, it means that people need to install c2hs on their machine. -- Alastair Reid

Keith.Wansbrough writes:
Automate!
You must avoid actually writing the import declarations for each function by hand.
If the functions are all of the complexity of sin, cos, etc., it is hard to improve significantly on:
foreign import ccall sin :: Double -> Double
There's just not much information you can leave out of this. (Perhaps you could save the first three tokens but they're not that hard to cut and paste).
I was imagining a tool (or a hand-crafted Perl script if necessary)
that turned
double gsl_sf_sin(double x);
into
foreign import ccall "gsl_sf_sin" sin :: Double -> Double
That wouldn't be too hard, and if there really are zillions of
functions, it would save a lot of work for the straightforward cases.
--KW 8-)
--
Keith Wansbrough

On Friday 06 June 2003 11:38 am, Keith Wansbrough wrote:
That wouldn't be too hard, and if there really are zillions of functions, it would save a lot of work for the straightforward cases.
My experience is that there are an annoying number of non-straightforward cases where you need a programmer to read documentation and make sensible decisions. There's a tool for ML which directly translates header files into the obvious ML type. There's also swig which does much the same but for a wide range of languages (I think it started with python). The problem is that you end up with an idiomatic C interface like: getMousePos :: Ptr CInt -> Ptr CInt -> IO CInt instead of an idiomatic Haskell interface like: getMousePos :: IO (CInt,CInt) -- raises an exception if device not present Before anyone can use this function, they will have to read the documentation and figure it out and, since this is the hard part of creating the interface, it is best to have a human do it just once instead of having everyone who uses the library have to repeat the work. -- Alastair Reid
participants (4)
-
Alastair Reid
-
Andrew J Bromage
-
Keith Wansbrough
-
Matthew Donadio