Skip to content
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

Add Common.lean #15

Merged
merged 1 commit into from
Jan 3, 2025
Merged

Add Common.lean #15

merged 1 commit into from
Jan 3, 2025

Conversation

seanmcl
Copy link
Collaborator

@seanmcl seanmcl commented Jan 2, 2025

Common is a module with a grabbag of functionality required by later files.

@seanmcl seanmcl force-pushed the sm/01-common branch 2 times, most recently from 0e17abc to e365e9d Compare January 3, 2025 01:53
Copy link
Collaborator

@govereau govereau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.
I have a small question about the ForIn, but I may just be confused.

def natDivCeil (num denom : Nat) : Nat :=
let div := num / denom
let mod := Nat.mod num denom
if mod != 0 then div + 1 else div
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this better (num + denom - 1) / denom ? (one division, no if)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Tried to prove in Lean and Dafny that they're the same. Proof automation fails, and I gave up after not finding many lemmas via Loogle. Some dafny folks pointed out it's actually hard in Dafny, requiring triggers. Was able to prove for any fixed either numerator or denominator that it's equivalent, but not for both being free.

--! The number of elements in a tensor. All that's needed is the shape for this calculation.
-- TODO: cache this? Not sure how this works in Lean. Do we need to make Shape a struct and
-- put it in the record?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it a structure, which gives this flexibility later. I was uncomfortable having such a prominent concept being an abbrev anyway.

so this is just the default case.
-/
def unitStrides (s : Shape) (dataOrder : DataOrder) : Strides := match dataOrder with
| DataOrder.Fortran => [] -- Unimplemented
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just not support Fortran order and give an error when loading the file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped DataOrder after some discussion. The Npy.lean file will have instructions for turning a fortran-order .npy file to C-order so we can manage it.

let (_, idx) := strides.foldl foldFn (n, [])
idx.reverse

-- One-based strides. Note there is a Mathlib conversion from `List Nat` to `List Int` here
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vestigial. Removed, thanks.

#guard dimIndexToOffset [3, 1] [1, 1] == 4

-- In general you should use DimsIter instead of this, which is equivalent
-- to `DimIter.toList` but I left it here because it is obviously terminating.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DimsIter.toList (not DimIter)

match <- f dims res with
| .yield k
| .done k => res := k
return res
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the done case not exit the loop?
What happens if you use break or return inside of one of these for loops?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof, nice find. I just didn't grok the signature. I only used it on well-behaved iterators like lists without break or return. Fixed and added tests.

let x4 := x.get (Fin.mk _ H4)
let x5 := x.get (Fin.mk _ H5)
let x6 := x.get (Fin.mk _ H6)
let x7 := x.get (Fin.mk _ H7)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, how does the Fin get converted to the inputs for get?
Seems like you need the components of the Fin as separate arguments to get.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For ByteArray, the argument is a Fin.

@[extern "lean_byte_array_fget"]
def get : (a : @& ByteArray) → (@& Fin a.size) → UInt8

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think it is just a version thing. Int 4.15 it is:

@[extern "lean_byte_array_fget"]
def get : (a : @& ByteArray) → (i : @& Nat) → (h : i < a.size := by get_elem_tactic) → UInt8 

Copy link
Collaborator Author

@seanmcl seanmcl Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah nice, that is better. Will update when I can update to 4.15 without Aesop crashing. If this seems like it will take time to be fixed, I can go through and copy/paste the aesop tactic scripts. Maybe should do that anyway.

`Common` is a module with a grabbag of functionality
required by later files.
@seanmcl seanmcl merged commit de0ae62 into main Jan 3, 2025
1 check passed
@seanmcl seanmcl deleted the sm/01-common branch January 3, 2025 22:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants