Skip to content

Strong types for logical operators #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
noughtmare opened this issue Nov 6, 2019 · 4 comments
Closed

Strong types for logical operators #20

noughtmare opened this issue Nov 6, 2019 · 4 comments
Assignees
Labels
enhancement New feature or request

Comments

@noughtmare
Copy link

For example lt, gt, le, ge, eq, neq should have type AFType a => Array a -> Array a -> Array CBool.

And functions like and, or should have type Array CBool -> Array CBool -> Array CBool.

And not should have type Array CBool -> Array CBool.

By the way why is Bool not an instance of AFType? Would it be possible to write an instance that uses CBool under the hood?

@dmjio
Copy link
Member

dmjio commented Nov 6, 2019

For example lt, gt, le, ge, eq, neq should have type AFType a => Array a -> Array a -> Array CBool.

Thanks, I can adjust this to make the types more narrow.

By the way why is Bool not an instance of AFType? Would it be possible to write an instance that uses CBool under the hood?

CBool maps more correctly to the ArrayFire C API.

http://hackage.haskell.org/package/base-4.12.0.0/docs/Foreign-C-Types.html#t:CBool

Note bool in

af_err af_lt    (af_array *out, const af_array lhs, const af_array rhs, const bool batch); 

The Storable on Bool is actually a 32-bit Int and not a C bool.

We could attempt to munge the two. That's more or less what I've done with the Eq and Ord instances.

instance (AFType a, Eq a) => Eq (Array a) where
  x == y = toEnum . fromIntegral $ A.getScalar @CBool @a $! A.eq x y
  x /= y = toEnum . fromIntegral $ A.getScalar @CBool @a $! A.neq x y

Come to think of it. I bet we should be using af_all_true after calling A.eq before fetching the scalar out, to ensure equality across all dimensions. Thanks for bringing this to light.

@dmjio
Copy link
Member

dmjio commented Nov 6, 2019

Since Array a is not a Functor (and can't be), it's not as straightforward to map CBool to Bool. One thing we could try is to castArray from Array CBool to Array Int32 and then peek the values off as if they were Bool. Otherwise, calling fmap (toEnum . fromIntegral) . toList :: Array CBool -> [Bool] might be best

@dmjio dmjio self-assigned this Nov 9, 2019
@dmjio
Copy link
Member

dmjio commented Nov 9, 2019

image

The spec says only the output is b8, I'll return CBool. Similarly, not sure what logical and would be on floating point numbers, but its technically allowed.

> (8 :: Array Double) `A.and` (2 :: Array Double)
[1 1 1 1] 
        1

@dmjio dmjio added the enhancement New feature or request label Nov 9, 2019
@dmjio
Copy link
Member

dmjio commented Nov 9, 2019

#24 should solve all our problems, please review and re-open this issue if it does not.

@dmjio dmjio closed this as completed Nov 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants