ekmett / linear

Low-dimensional linear algebra primitives for Haskell.
http://hackage.haskell.org/package/linear
Other
198 stars 50 forks source link

Use generalized Boolean for Epsilon #88

Open tobbebex opened 9 years ago

tobbebex commented 9 years ago

In GPipe, and many other shader DSLs, you use lifted numeric types for shader expressions (in GPipe for example a Float is lifted to S V Float in the vertex shader). These lifted shader values cannot be evaluated in the non-lifted world, which is why I use the Boolean package for lifted booleans.

The Epsilon class has the nearZero member that returns (a non-lifted) Bool, thus making it impossible to use for shader DSLs like GPipe. Some unfortunate consequences of this is that functions like lookAt and normalize also cannot be used directly in shader code.

If Epsilon were using the generalized booleans from the Boolean package it would enable linear to be more fully usable in the lifted shader domain.

Related to this is also the many functions in the Linear.Quaternion package that has a constraint on RealFloat. This class has several members that return (unlifted) Bools and thus cannot be implemented for GPipes shader types. But I guess asking for dropping that constraint is pushing it :)

acowley commented 9 years ago

I really like this idea as my motivations are very similar to @tobbebex's. What are some reasons for not doing this? I think the user who doesn't want generalized booleans would just be stuck with worse-looking types, but there wouldn't be any actual breakage or ambiguity. Is that right?

ekmett commented 9 years ago

If we implement #34 we'd have a weaker Quaternion and Complex with slightly fewer guarantees that was more suited to those applications. This would let you use Linear.Quaternion.Simple and get a type that worked in more situations, but without my fancy branchy tricks.

The main problem with the proposal here is that it complicates the Complex and Quaternion stories.

You can't use the existing containers on existing number types that we don't know about and which incur no dependency on linear. e.g. ad primitives today know nothing of linear and the two packages can remain ignorant of each other.

The only thing that incurs an Epsilon constraint in quaternion at all is axisAngle, which tries to avoid normalizing when the magnitude of the vector we're rotating around is near 0 (because we're being dumb) or 1 (because it was already normalized). The Simple version for #34 would just elide that check leading to less branchy code, and eliminating this need. Then any super-fancy Epsilon is relegated to a secondary concern, and is not driven by this application. We could then revisit if we wanted it, or if we wanted to push it out into a separate package on its own merits without this as a driver.

tobbebex commented 9 years ago

That solution would work for me!

Then we just need a simpler lookAt as well (normalize already has the signorm alternative that doesn't use Epsilon).