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-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-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-16 Thread Niklas Larsson
2012/9/15 Robby Findler :
>
> 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-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  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-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-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  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
>  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
>>  wrote:
>>>
>>> On Sep 12, 2012, at 1:03 PM, Jay McCarthy wrote:
>>>
 On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto  
 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 
> Assistant Professor / Brigham Young University
> http://faculty.cs.byu.edu/~jay
>
> "The glory of God is Intelligence" - D&C 93

_
  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
 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
>  wrote:
>>
>> On Sep 12, 2012, at 1:03 PM, Jay McCarthy wrote:
>>
>>> On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto  
>>> 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 
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93

_
  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 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
 wrote:
>
> On Sep 12, 2012, at 1:03 PM, Jay McCarthy wrote:
>
>> On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto  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 John Clements

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

> On Wed, Sep 12, 2012 at 8:31 AM, Neil Toronto  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-12 Thread Robby Findler
On Wed, Sep 12, 2012 at 3:47 PM, Matthew Flatt  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


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

2012-09-12 Thread Matthew Flatt
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.

_
  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  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 
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 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 11:24 AM, 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.
> 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 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 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 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 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


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

2012-09-12 Thread Neil Toronto
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))]))

I'm annoyed by the prospect of doing something similar to subtypes of 
Real-Distribution. It's nice right now that a probability is always a 
Flonum. Changing it would make things slower, more complicated, and more 
error-prone.


They can't be for speed. I just ran some tests. With TR's optimizer off 
or in untyped Racket, the performance gain using single flonums is 
negligible. With TR's optimizer on, doubles are at least twice as fast.


Compatibility with old code? No, they were enabled in 5.1.1.

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.


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.


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?

Neil ⊥

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