Re: [racket-dev] What are single flonums good for?

2012-09-17 Thread Neil Toronto

On 09/16/2012 04:10 PM, Matthias Felleisen wrote:


Suppose we had started Racket long ago and maintained it until now. Then we'd 
be looking at 8bit, 16, 32, and 64 precision. In some N years from now, we may 
need 128. (Actually there were machines in the past that did, but never mind.)

Could we separate precision and type into separate dimensions so that we could 
state types like this:

   ∀ p : precision. FP[p] - FP[p]

where we see FP as a type constructor that consumes a precision value to 
generate the right kind of type. This might be a dependent type but it could be 
a useful one. Of course, it isn't really a parametric form of polymorphism as 
Neil's functions show (and better still Vincent's rewrites).


80-bit, and then 128-bit flonums are inevitable.

After TR has type classes or something like them, this would work really 
well. The C++ Boost libraries use templates to achieve something 
similar. Functions with an FPU implementation (sin, exp, etc.) just 
dispatch to the proper bare-metal function. Functions without an FPU 
implementation (gamma, erf, etc.) also dispatch depending on precision, 
but can share implementation details when the algorithms are similar. 
(Example: the gamma function uses a different Lanczos polynomial for 
each precision, but always uses it in the same way.) Compositions of 
either kind are fully polymorphic.


Neil ⊥

_
 Racket Developers list:
 http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-17 Thread Vincent St-Amour
At Sun, 16 Sep 2012 17:10:01 -0500,
Matthias Felleisen wrote:
 Suppose we had started Racket long ago and maintained it until
 now. Then we'd be looking at 8bit, 16, 32, and 64 precision. In some N
 years from now, we may need 128. (Actually there were machines in the
 past that did, but never mind.)
 
 Could we separate precision and type into separate dimensions so that
 we could state types like this:
 
   ∀ p : precision. FP[p] - FP[p] 
 
 where we see FP as a type constructor that consumes a precision value
 to generate the right kind of type. This might be a dependent type but
 it could be a useful one. Of course, it isn't really a parametric form
 of polymorphism as Neil's functions show (and better still Vincent's
 rewrites).

I think row types can give us that, and clean up other parts of the
numeric tower, too. That's something we've been thinking about for some
time.

Vincent

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-16 Thread Niklas Larsson
2012/9/15 Robby Findler ro...@eecs.northwestern.edu:

 At this point, I'm still left wondering if Single-Flonums are good for
 anything, but I can imagine that they are good for not breaking old
 programs, so probably best to leave well enough alone.


One use case for singles is offloading computations to a graphics
card. GPUs are heavily optimized for single precision floats, some
cards still don't support doubles at all, most have much lower
performance with them.
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-16 Thread Matthias Felleisen

Suppose we had started Racket long ago and maintained it until now. Then we'd 
be looking at 8bit, 16, 32, and 64 precision. In some N years from now, we may 
need 128. (Actually there were machines in the past that did, but never mind.) 

Could we separate precision and type into separate dimensions so that we could 
state types like this: 

  ∀ p : precision. FP[p] - FP[p] 

where we see FP as a type constructor that consumes a precision value to 
generate the right kind of type. This might be a dependent type but it could be 
a useful one. Of course, it isn't really a parametric form of polymorphism as 
Neil's functions show (and better still Vincent's rewrites). 

-- Matthias



 


On Sep 15, 2012, at 9:31 AM, Vincent St-Amour wrote:

 At Fri, 14 Sep 2012 23:45:43 -0500,
 Robby Findler wrote:
 The original message in this thread suggests that there is a type
 Single-Flonum and that it is making Neil wrangle his code to be
 careful about it.
 
 Right, TR supports `Single-Flonum's, but not `f32vector's.
 
 Part of the complexity in Neil's code is due to types, part of it is not.
 
 Assuming he wrote the math library in untyped Racket:
 
(define (foo x)
   (cond [(double-flonum? x)  (flfoo x)]
 [(single-flonum? x)  (real-single-flonum
   (flfoo (real-double-flonum x)))]
 [else  (flfoo (real-double-flonum x))]))
 
 The code is exactly the same as before. The complexity comes from the
 fact that this function, when given single-precision inputs, wants to
 produce single-precision outputs, hence the special case.
 
 If Neil wants `foo' to be as flexible as Racket's built-in operations
 (which, when given single-precision inputs, produce single-precision
 outputs), he needs that special case, types or not.
 
 If he gives up on that flexibility, things become a lot simpler:
 
(define (foo x)
   (flfoo (real-double-flonum x)))
 
 This version still accepts single-precision inputs, but always produces
 doubles.
 
 The types simply mirror that distinction:
 
(: foo (case- (Single-Flonum - Single-Flonum)
(Flonum - Flonum)
(Real - Real)))
 
 vs
 
(: foo (Real - Flonum))
 
 This kind of complexity gets worse for functions with multiple arguments,
 and types make it worse. When expressing coercion rules, the
 implementation can take shortcuts that the type system cannot currently
 express, leading to unwieldy types.
 
 These issues only come up when writing libraries that aim to propagate
 Racket's numeric flexibility, such as the math library or TR's base
 environment. Clients of either don't need to worry about any of that.
 
 Single-precision floats are not the source of this problem (you would
 run into the same issues, in both the untyped and typed worlds, with a
 function that takes ints to ints and floats to floats), but they do add
 one more type to worry about.
 
 Vincent
 _
  Racket Developers list:
  http://lists.racket-lang.org/dev


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-15 Thread Vincent St-Amour
At Fri, 14 Sep 2012 23:45:43 -0500,
Robby Findler wrote:
 The original message in this thread suggests that there is a type
 Single-Flonum and that it is making Neil wrangle his code to be
 careful about it.

Right, TR supports `Single-Flonum's, but not `f32vector's.

Part of the complexity in Neil's code is due to types, part of it is not.

Assuming he wrote the math library in untyped Racket:

(define (foo x)
   (cond [(double-flonum? x)  (flfoo x)]
 [(single-flonum? x)  (real-single-flonum
   (flfoo (real-double-flonum x)))]
 [else  (flfoo (real-double-flonum x))]))

The code is exactly the same as before. The complexity comes from the
fact that this function, when given single-precision inputs, wants to
produce single-precision outputs, hence the special case.

If Neil wants `foo' to be as flexible as Racket's built-in operations
(which, when given single-precision inputs, produce single-precision
outputs), he needs that special case, types or not.

If he gives up on that flexibility, things become a lot simpler:

(define (foo x)
   (flfoo (real-double-flonum x)))

This version still accepts single-precision inputs, but always produces
doubles.

The types simply mirror that distinction:

(: foo (case- (Single-Flonum - Single-Flonum)
(Flonum - Flonum)
(Real - Real)))

vs

(: foo (Real - Flonum))

This kind of complexity gets worse for functions with multiple arguments,
and types make it worse. When expressing coercion rules, the
implementation can take shortcuts that the type system cannot currently
express, leading to unwieldy types.

These issues only come up when writing libraries that aim to propagate
Racket's numeric flexibility, such as the math library or TR's base
environment. Clients of either don't need to worry about any of that.

Single-precision floats are not the source of this problem (you would
run into the same issues, in both the untyped and typed worlds, with a
function that takes ints to ints and floats to floats), but they do add
one more type to worry about.

Vincent
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-15 Thread Robby Findler
Thanks for the explanation. I see how this is not a typed-specific
problem (indeed, it is probably a Good Thing that TR helps us be
careful about this distinction when it matters).

At this point, I'm still left wondering if Single-Flonums are good for
anything, but I can imagine that they are good for not breaking old
programs, so probably best to leave well enough alone.

Thanks again,
Robby

On Sat, Sep 15, 2012 at 9:31 AM, Vincent St-Amour stamo...@ccs.neu.edu wrote:
 At Fri, 14 Sep 2012 23:45:43 -0500,
 Robby Findler wrote:
 The original message in this thread suggests that there is a type
 Single-Flonum and that it is making Neil wrangle his code to be
 careful about it.

 Right, TR supports `Single-Flonum's, but not `f32vector's.

 Part of the complexity in Neil's code is due to types, part of it is not.

 Assuming he wrote the math library in untyped Racket:

 (define (foo x)
(cond [(double-flonum? x)  (flfoo x)]
  [(single-flonum? x)  (real-single-flonum
(flfoo (real-double-flonum x)))]
  [else  (flfoo (real-double-flonum x))]))

 The code is exactly the same as before. The complexity comes from the
 fact that this function, when given single-precision inputs, wants to
 produce single-precision outputs, hence the special case.

 If Neil wants `foo' to be as flexible as Racket's built-in operations
 (which, when given single-precision inputs, produce single-precision
 outputs), he needs that special case, types or not.

 If he gives up on that flexibility, things become a lot simpler:

 (define (foo x)
(flfoo (real-double-flonum x)))

 This version still accepts single-precision inputs, but always produces
 doubles.

 The types simply mirror that distinction:

 (: foo (case- (Single-Flonum - Single-Flonum)
 (Flonum - Flonum)
 (Real - Real)))

 vs

 (: foo (Real - Flonum))

 This kind of complexity gets worse for functions with multiple arguments,
 and types make it worse. When expressing coercion rules, the
 implementation can take shortcuts that the type system cannot currently
 express, leading to unwieldy types.

 These issues only come up when writing libraries that aim to propagate
 Racket's numeric flexibility, such as the math library or TR's base
 environment. Clients of either don't need to worry about any of that.

 Single-precision floats are not the source of this problem (you would
 run into the same issues, in both the untyped and typed worlds, with a
 function that takes ints to ints and floats to floats), but they do add
 one more type to worry about.

 Vincent
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-14 Thread John Clements

On Sep 12, 2012, at 1:03 PM, Jay McCarthy wrote:

 On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto neil.toro...@gmail.com wrote:
 Compatibility with C code? Why not have the FFI convert them?
 
 Save space? I can see that. It won't help much if they're sent to math
 library functions, though. Those will convert them to flonums and usually
 box the converted values.
 
 I think these are big deals with respect to libraries that you deliver
 large float matrices to where you want to efficiently store a big
 f32vector rather than an f64vector. Examples of this include OpenGL
 where vector coordinates, colors, etc are typically floats and not
 doubles.

Jay's concern is the same as mine; there are situations (getting rarer) where a 
huge c-style array of f32s is the only way to interact with a library. For 
instance, in the extremely popular JACK library (Golly, I wish it worked on 
windows…), all audio data is represented as 32-bit floating point values 
(from their web page). 

I haven't followed the conversation closely enough to understand the 
ramifications of the proposed change, though; my guess is that the ffi can 
still address such arrays, it's just that computing with these values will 
require coercion. I could be okay with that; based on my understanding of the 
IEEE floating-point spec, such a translation could be pretty fast; 32bit - 
64bit looks like it would just be adding zeros, and 32bit to 64bit would 
require checking for exponent overflow; either way, this sounds like something 
that might be done on-chip by modern processors, and in fact might *already* be 
taking place in floating point 32-bit operations. (Anyone know whether Intel 
chips internally represent 32-bit floats as 64-bit ones?)

John



smime.p7s
Description: S/MIME cryptographic signature
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-14 Thread Robby Findler
As far as I can tell, if this pollutes TR programs in any interesting
way, then it would be a cause for concern.

Robby

On Fri, Sep 14, 2012 at 12:21 PM, John Clements
cleme...@brinckerhoff.org wrote:

 On Sep 12, 2012, at 1:03 PM, Jay McCarthy wrote:

 On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto neil.toro...@gmail.com wrote:
 Compatibility with C code? Why not have the FFI convert them?

 Save space? I can see that. It won't help much if they're sent to math
 library functions, though. Those will convert them to flonums and usually
 box the converted values.

 I think these are big deals with respect to libraries that you deliver
 large float matrices to where you want to efficiently store a big
 f32vector rather than an f64vector. Examples of this include OpenGL
 where vector coordinates, colors, etc are typically floats and not
 doubles.

 Jay's concern is the same as mine; there are situations (getting rarer) where 
 a huge c-style array of f32s is the only way to interact with a library. For 
 instance, in the extremely popular JACK library (Golly, I wish it worked on 
 windows…), all audio data is represented as 32-bit floating point values 
 (from their web page).

 I haven't followed the conversation closely enough to understand the 
 ramifications of the proposed change, though; my guess is that the ffi can 
 still address such arrays, it's just that computing with these values will 
 require coercion. I could be okay with that; based on my understanding of the 
 IEEE floating-point spec, such a translation could be pretty fast; 32bit - 
 64bit looks like it would just be adding zeros, and 32bit to 64bit would 
 require checking for exponent overflow; either way, this sounds like 
 something that might be done on-chip by modern processors, and in fact might 
 *already* be taking place in floating point 32-bit operations. (Anyone know 
 whether Intel chips internally represent 32-bit floats as 64-bit ones?)

 John


 _
   Racket Developers list:
   http://lists.racket-lang.org/dev


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-14 Thread Eli Barzilay
Two hours ago, John Clements wrote:
 
 I haven't followed the conversation closely enough to understand the
 ramifications of the proposed change, though; my guess is that the
 ffi can still address such arrays, it's just that computing with
 these values will require coercion. I could be okay with that; based
 on my understanding of the IEEE floating-point spec, such a
 translation could be pretty fast; 32bit - 64bit looks like it would
 just be adding zeros, and 32bit to 64bit would require checking for
 exponent overflow; either way, this sounds like something that might
 be done on-chip by modern processors, and in fact might *already* be
 taking place in floating point 32-bit operations. (Anyone know
 whether Intel chips internally represent 32-bit floats as 64-bit
 ones?)

The main cost is that such a back-and-forth translation will require
allocation.

-- 
  ((lambda (x) (x x)) (lambda (x) (x x)))  Eli Barzilay:
http://barzilay.org/   Maze is Life!
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-14 Thread Jay McCarthy
TR doesn't support them anyways because there are only typed f64
vectors and not typed f32 vectors.

Jay

On Fri, Sep 14, 2012 at 11:28 AM, Robby Findler
ro...@eecs.northwestern.edu wrote:
 As far as I can tell, if this pollutes TR programs in any interesting
 way, then it would be a cause for concern.

 Robby

 On Fri, Sep 14, 2012 at 12:21 PM, John Clements
 cleme...@brinckerhoff.org wrote:

 On Sep 12, 2012, at 1:03 PM, Jay McCarthy wrote:

 On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto neil.toro...@gmail.com 
 wrote:
 Compatibility with C code? Why not have the FFI convert them?

 Save space? I can see that. It won't help much if they're sent to math
 library functions, though. Those will convert them to flonums and usually
 box the converted values.

 I think these are big deals with respect to libraries that you deliver
 large float matrices to where you want to efficiently store a big
 f32vector rather than an f64vector. Examples of this include OpenGL
 where vector coordinates, colors, etc are typically floats and not
 doubles.

 Jay's concern is the same as mine; there are situations (getting rarer) 
 where a huge c-style array of f32s is the only way to interact with a 
 library. For instance, in the extremely popular JACK library (Golly, I 
 wish it worked on windows…), all audio data is represented as 32-bit 
 floating point values (from their web page).

 I haven't followed the conversation closely enough to understand the 
 ramifications of the proposed change, though; my guess is that the ffi can 
 still address such arrays, it's just that computing with these values will 
 require coercion. I could be okay with that; based on my understanding of 
 the IEEE floating-point spec, such a translation could be pretty fast; 32bit 
 - 64bit looks like it would just be adding zeros, and 32bit to 64bit would 
 require checking for exponent overflow; either way, this sounds like 
 something that might be done on-chip by modern processors, and in fact might 
 *already* be taking place in floating point 32-bit operations. (Anyone know 
 whether Intel chips internally represent 32-bit floats as 64-bit ones?)

 John


 _
   Racket Developers list:
   http://lists.racket-lang.org/dev




-- 
Jay McCarthy j...@cs.byu.edu
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

The glory of God is Intelligence - DC 93

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-14 Thread Robby Findler
The original message in this thread suggests that there is a type
Single-Flonum and that it is making Neil wrangle his code to be
careful about it.

Robby

On Fri, Sep 14, 2012 at 3:55 PM, Jay McCarthy jay.mccar...@gmail.com wrote:
 TR doesn't support them anyways because there are only typed f64
 vectors and not typed f32 vectors.

 Jay

 On Fri, Sep 14, 2012 at 11:28 AM, Robby Findler
 ro...@eecs.northwestern.edu wrote:
 As far as I can tell, if this pollutes TR programs in any interesting
 way, then it would be a cause for concern.

 Robby

 On Fri, Sep 14, 2012 at 12:21 PM, John Clements
 cleme...@brinckerhoff.org wrote:

 On Sep 12, 2012, at 1:03 PM, Jay McCarthy wrote:

 On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto neil.toro...@gmail.com 
 wrote:
 Compatibility with C code? Why not have the FFI convert them?

 Save space? I can see that. It won't help much if they're sent to math
 library functions, though. Those will convert them to flonums and usually
 box the converted values.

 I think these are big deals with respect to libraries that you deliver
 large float matrices to where you want to efficiently store a big
 f32vector rather than an f64vector. Examples of this include OpenGL
 where vector coordinates, colors, etc are typically floats and not
 doubles.

 Jay's concern is the same as mine; there are situations (getting rarer) 
 where a huge c-style array of f32s is the only way to interact with a 
 library. For instance, in the extremely popular JACK library (Golly, I 
 wish it worked on windows…), all audio data is represented as 32-bit 
 floating point values (from their web page).

 I haven't followed the conversation closely enough to understand the 
 ramifications of the proposed change, though; my guess is that the ffi can 
 still address such arrays, it's just that computing with these values will 
 require coercion. I could be okay with that; based on my understanding of 
 the IEEE floating-point spec, such a translation could be pretty fast; 
 32bit - 64bit looks like it would just be adding zeros, and 32bit to 64bit 
 would require checking for exponent overflow; either way, this sounds like 
 something that might be done on-chip by modern processors, and in fact 
 might *already* be taking place in floating point 32-bit operations. 
 (Anyone know whether Intel chips internally represent 32-bit floats as 
 64-bit ones?)

 John


 _
   Racket Developers list:
   http://lists.racket-lang.org/dev




 --
 Jay McCarthy j...@cs.byu.edu
 Assistant Professor / Brigham Young University
 http://faculty.cs.byu.edu/~jay

 The glory of God is Intelligence - DC 93

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-12 Thread Vincent St-Amour
Single-precision float support used to be enabled via a configure
option, which meant that some Racket installations would support them,
and some would not.

Since zo files are meant to be portable, they could not contain
single-precision floats. So, compilation would promote single literals
to doubles.

This meant that compilation could change the behavior of a program.
Here's an example:

stamourv@ahuntsic:small-float-test$ cat test2.rkt
#lang racket
(define (f x) (displayln (flonum? x)))
(f (if (with-input-from-string #t read) 1.0f0 2.0f0))
stamourv@ahuntsic:small-float-test$ racket test2.rkt
#f
stamourv@ahuntsic:small-float-test$ raco make test2.rkt
stamourv@ahuntsic:small-float-test$ racket test2.rkt
#t
stamourv@ahuntsic:small-float-test$

This example has to be a bit convoluted to defeat constant folding,
which makes the problem disappear:

stamourv@ahuntsic:small-float-test$ cat test.rkt
#lang racket
(flonum? 1.0f0)
stamourv@ahuntsic:small-float-test$ racket test.rkt
#f
stamourv@ahuntsic:small-float-test$ raco make test.rkt
stamourv@ahuntsic:small-float-test$ racket test.rkt
#f
stamourv@ahuntsic:small-float-test$ raco decompile test.rkt
(begin
  (module test 
(#%apply-values |_print-values@(lib racket/private/modbeg.rkt)| '#f)))
stamourv@ahuntsic:small-float-test$

This can make for pretty elusive bugs. This gets especially problematic
when you add unsafe float operations to the mix, which can turn these
issues into segfaults.

The solution we picked was to support single-precision floats by default
and to allow them in zos, which makes these discrepancies go away.

I agree that having to handle single floats when reasoning about numbers
complicates things, and it annoys me too. But I still think it's less
problematic than what I describe above.


At Wed, 12 Sep 2012 08:31:29 -0600,
Neil Toronto wrote:
 
 I ask because I'm tired of worrying about them. More precisely, I'm 
 tired of Typed Racket (rightly) making me worry about them.
 
 I'm also a little bit tired of this:
 
 (: foo (case- (Single-Flonum - Single-Flonum)
 (Flonum - Flonum)
 (Real - Real)))
 (define (foo x)
(cond [(double-flonum? x)  (flfoo x)]
  [(single-flonum? x)  (real-single-flonum
(flfoo (real-double-flonum x)))]
  [else  (flfoo (real-double-flonum x))]))

This function already converts rationals to doubles, and it seems
`flfoo' produces doubles too. You could drop the second clause, always
produce doubles, change the type to `(Real - Flonum)' and leave the
conversion to single to the client. Since the math library always
operates on doubles internally anyway, this would also eliminate
unnecessary conversions to singles between stages of a pipeline.

 They make it easy to write wrong code, because it's easy to use 
 `exact-inexact' when you really should use `real-double-flonum'. Plot, 
 for example, fails to render functions that return single flonums. I'm 
 surprised it doesn't segfault.

Good point, that's a problem.

 I'm sure plot isn't the only one. Every use of `exact-inexact' in the 
 standard library is suspect. If followed by applying an unsafe op, it's 
 wrong.
 
 Why do we have these things?

I don't know why they were added originally (as an option). In my limited
experience, I don't think I've seen non-test code that uses them.

Vincent
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-12 Thread Stephen Bloch

On Sep 12, 2012, at 12:24 PM, Vincent St-Amour wrote:

 Single-precision float support used to be enabled via a configure
 option, which meant that some Racket installations would support them,
 and some would not.
 
 Since zo files are meant to be portable, they could not contain
 single-precision floats. So, compilation would promote single literals
 to doubles.
 
 This meant that compilation could change the behavior of a program.
 ...
 The solution we picked was to support single-precision floats by default
 and to allow them in zos, which makes these discrepancies go away.
 
 I agree that having to handle single floats when reasoning about numbers
 complicates things, and it annoys me too. But I still think it's less
 problematic than what I describe above.

Would it be even less problematic to get rid of them entirely, except in FFI?


Stephen Bloch
sbl...@adelphi.edu

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-12 Thread Neil Toronto

On 09/12/2012 10:24 AM, Vincent St-Amour wrote:

I agree that having to handle single floats when reasoning about numbers
complicates things, and it annoys me too. But I still think it's less
problematic than what I describe above [compilation could change the behavior

 of a program].

Interesting!

I think the least problematic solution would be to separate them from 
the rest of the numeric tower, and give them their own set of 
single-flonum-only functions: sf+, sfabs, etc. They could even operate 
on single-precision complex numbers.


Hindsight, etc., though.


(: foo (case- (Single-Flonum - Single-Flonum)
 (Flonum - Flonum)
 (Real - Real)))
(define (foo x)
(cond [(double-flonum? x)  (flfoo x)]
  [(single-flonum? x)  (real-single-flonum
(flfoo (real-double-flonum x)))]
  [else  (flfoo (real-double-flonum x))]))


This function already converts rationals to doubles, and it seems
`flfoo' produces doubles too. You could drop the second clause, always
produce doubles, change the type to `(Real - Flonum)' and leave the
conversion to single to the client. Since the math library always
operates on doubles internally anyway, this would also eliminate
unnecessary conversions to singles between stages of a pipeline.


It's not just slower. The unnecessary conversions lose precision because 
of double rounding. I hadn't thought of that yet, so thanks.



Why do we have these things?


I don't know why they were added originally (as an option). In my limited
experience, I don't think I've seen non-test code that uses them.


This gets at the design decision I'm facing now. Would anybody care if 
the math library just treated them like other non-double-flonum reals, 
and made no effort to preserve single-flonum-ness? I'm leaning toward 
doing that now.


Neil ⊥

_
 Racket Developers list:
 http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-12 Thread Eli Barzilay
Two hours ago, Stephen Bloch wrote:
 
 Would it be even less problematic to get rid of them entirely,
 except in FFI?

(They're not really an issue for the FFI, since you'd just translate
the numbers to them when needed.  IOW, racket doesn't even need
exact integers to have an FFI with them.)

-- 
  ((lambda (x) (x x)) (lambda (x) (x x)))  Eli Barzilay:
http://barzilay.org/   Maze is Life!
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-12 Thread Robby Findler
On Wed, Sep 12, 2012 at 11:24 AM, Vincent St-Amour stamo...@ccs.neu.edu wrote:
 Single-precision float support used to be enabled via a configure
 option, which meant that some Racket installations would support them,
 and some would not.

 Since zo files are meant to be portable, they could not contain
 single-precision floats. So, compilation would promote single literals
 to doubles.

 This meant that compilation could change the behavior of a program.
 Here's an example:

 stamourv@ahuntsic:small-float-test$ cat test2.rkt
 #lang racket
 (define (f x) (displayln (flonum? x)))
 (f (if (with-input-from-string #t read) 1.0f0 2.0f0))
 stamourv@ahuntsic:small-float-test$ racket test2.rkt
 #f
 stamourv@ahuntsic:small-float-test$ raco make test2.rkt
 stamourv@ahuntsic:small-float-test$ racket test2.rkt
 #t
 stamourv@ahuntsic:small-float-test$

 This example has to be a bit convoluted to defeat constant folding,
 which makes the problem disappear:

 stamourv@ahuntsic:small-float-test$ cat test.rkt
 #lang racket
 (flonum? 1.0f0)
 stamourv@ahuntsic:small-float-test$ racket test.rkt
 #f
 stamourv@ahuntsic:small-float-test$ raco make test.rkt
 stamourv@ahuntsic:small-float-test$ racket test.rkt
 #f
 stamourv@ahuntsic:small-float-test$ raco decompile test.rkt
 (begin
   (module test 
 (#%apply-values |_print-values@(lib racket/private/modbeg.rkt)| 
 '#f)))
 stamourv@ahuntsic:small-float-test$

 This can make for pretty elusive bugs. This gets especially problematic
 when you add unsafe float operations to the mix, which can turn these
 issues into segfaults.

 The solution we picked was to support single-precision floats by default
 and to allow them in zos, which makes these discrepancies go away.

 I agree that having to handle single floats when reasoning about numbers
 complicates things, and it annoys me too. But I still think it's less
 problematic than what I describe above.

This rationale does not explain why we have single precision floats at all, tho.

Robby
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-12 Thread Jay McCarthy
On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto neil.toro...@gmail.com wrote:
 Compatibility with C code? Why not have the FFI convert them?

 Save space? I can see that. It won't help much if they're sent to math
 library functions, though. Those will convert them to flonums and usually
 box the converted values.

I think these are big deals with respect to libraries that you deliver
large float matrices to where you want to efficiently store a big
f32vector rather than an f64vector. Examples of this include OpenGL
where vector coordinates, colors, etc are typically floats and not
doubles.

Jay

-- 
Jay McCarthy j...@cs.byu.edu
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

The glory of God is Intelligence - DC 93
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] What are single flonums good for?

2012-09-12 Thread Robby Findler
On Wed, Sep 12, 2012 at 3:47 PM, Matthew Flatt mfl...@cs.utah.edu wrote:
 At Wed, 12 Sep 2012 08:31:29 -0600, Neil Toronto wrote:
 Why do we have these things?

 I'm not sure this reason from 1996 is still relevant, but FWIW:
 Originally, there were drawing-related `float' computations in C code
 that I wanted to replicate exactly in Racket (ok, MzScheme).
 Eventually, I solved my specific consistency problem by changing the C
 code to use `double's; in other cases, someone might not be free to
 change the calculation.

Would today's FFI make it easy (enough) to do those precise
calculations? (Or maybe if we added a little library to help?)

Robby
_
  Racket Developers list:
  http://lists.racket-lang.org/dev