-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Well, what "set operations" mean in APL, which is not quite what math wants because duplicate entries are allowed. See https://aplwiki.com/wiki/Intersection for some background. The operations are union, intersect, and unique. Implementing these required an interesting internal change, because to check set membership, one must be able to do 'a' == 1 but prior to this CL, this expression gave an error because binary operations promote the types before the operation, and chars and ints cannot be compared. To get around this, and honestly to fix what was arguably a bug anyway, I changed exec/context.go to handle == and != specially, before promotion happens. That required a new function, EvalCharEqual, in the value package. (While working this out, I noticed a similar hack for "text", which could be handled more cleanly as part of the operator's definition.) So that's solved, but it gets harder. In ivy, unlike in APL, there are many ways to say "one": an integer, a float, a rational, a big int, even a complex. But when doing those set operations, you need to be sure you don't make 1.0 and 1 be different values. Also, you need to be able ask if any element of a vector is equal to any other element, which means asking ridiculous things like 'a' == 1j3 so that must work too. It does now, it didn't before. But the hardest part is that to make any of this efficient, you need a fast way to see whether a value is contained in a vector; otherwise you end up with n² time. @rsc put in a 'membership' function that serves this purpose well, sorting the vector and doing binary search, but that requires the existence of an ordering, and not only can you not reasonably ask if 'a' < 1 you certainly can't ask if 1j2 < 1j3 because < doesn't work at all on complex numbers. I therefore added OrderedCompare, which is a compare (signum) operator that introduces a total ordering over all scalar values, while honoring the desire that 1 == 1j0 == 1.0 == 1/1. To do this, we say that all chars sort under all other scalars, and that all non-real complex numbers sort above all other scalars, while complex numbers themselves are ordered first by real part, and if that is equal, by imaginary part. I then modified membership to use OrderedCompare instead of == and >=, and there you have it. That also fixes a latent issue that could have arisen with crazy cases involving membership even before sets arose. For the record, the naive n² algorithm handles this calculation: x=iota 100*1000; y = x intersect x in about 2 minutes on my Mac Studio; the current code takes about 30ms, which is not fast but is plenty fast enough. I believe the structure is mostly in place now to provide these operations for major blocks of matrices, but that's for another day. Tip of the hat to @Blackmane for suggestion the addition of unique and prodding me into a few fun days that also fixed some internal problems.
- Loading branch information
Showing
32 changed files
with
1,035 additions
and
344 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
gofmt seems to have inserted smart quotes here that i don't think are desired.