Line | Exclusive | Inclusive | Code |
---|---|---|---|
1 | # This file is a part of Julia. License is MIT: https://julialang.org/license | ||
2 | |||
3 | ## types ## | ||
4 | |||
5 | """ | ||
6 | <:(T1, T2) | ||
7 | |||
8 | Subtype operator: returns `true` if and only if all values of type `T1` are | ||
9 | also of type `T2`. | ||
10 | |||
11 | # Examples | ||
12 | ```jldoctest | ||
13 | julia> Float64 <: AbstractFloat | ||
14 | true | ||
15 | |||
16 | julia> Vector{Int} <: AbstractArray | ||
17 | true | ||
18 | |||
19 | julia> Matrix{Float64} <: Matrix{AbstractFloat} | ||
20 | false | ||
21 | ``` | ||
22 | """ | ||
23 | (<:) | ||
24 | |||
25 | """ | ||
26 | >:(T1, T2) | ||
27 | |||
28 | Supertype operator, equivalent to `T2 <: T1`. | ||
29 | """ | ||
30 | (>:)(@nospecialize(a), @nospecialize(b)) = (b <: a) | ||
31 | |||
32 | """ | ||
33 | supertype(T::DataType) | ||
34 | |||
35 | Return the supertype of DataType `T`. | ||
36 | |||
37 | # Examples | ||
38 | ```jldoctest | ||
39 | julia> supertype(Int32) | ||
40 | Signed | ||
41 | ``` | ||
42 | """ | ||
43 | supertype(T::DataType) = (@_total_meta; T.super) | ||
44 | supertype(T::UnionAll) = (@_total_meta; UnionAll(T.var, supertype(T.body))) | ||
45 | |||
46 | ## generic comparison ## | ||
47 | |||
48 | """ | ||
49 | ==(x, y) | ||
50 | |||
51 | Generic equality operator. Falls back to [`===`](@ref). | ||
52 | Should be implemented for all types with a notion of equality, based on the abstract value | ||
53 | that an instance represents. For example, all numeric types are compared by numeric value, | ||
54 | ignoring type. Strings are compared as sequences of characters, ignoring encoding. | ||
55 | For collections, `==` is generally called recursively on all contents, | ||
56 | though other properties (like the shape for arrays) may also be taken into account. | ||
57 | |||
58 | This operator follows IEEE semantics for floating-point numbers: `0.0 == -0.0` and | ||
59 | `NaN != NaN`. | ||
60 | |||
61 | The result is of type `Bool`, except when one of the operands is [`missing`](@ref), | ||
62 | in which case `missing` is returned | ||
63 | ([three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic)). | ||
64 | For collections, `missing` is returned if at least one of the operands contains | ||
65 | a `missing` value and all non-missing values are equal. | ||
66 | Use [`isequal`](@ref) or [`===`](@ref) to always get a `Bool` result. | ||
67 | |||
68 | # Implementation | ||
69 | New numeric types should implement this function for two arguments of the new type, and | ||
70 | handle comparison to other types via promotion rules where possible. | ||
71 | |||
72 | [`isequal`](@ref) falls back to `==`, so new methods of `==` will be used by the | ||
73 | [`Dict`](@ref) type to compare keys. If your type will be used as a dictionary key, it | ||
74 | should therefore also implement [`hash`](@ref). | ||
75 | |||
76 | If some type defines `==`, [`isequal`](@ref), and [`isless`](@ref) then it should | ||
77 | also implement [`<`](@ref) to ensure consistency of comparisons. | ||
78 | """ | ||
79 | == | ||
80 | |||
81 | """ | ||
82 | isequal(x, y) -> Bool | ||
83 | |||
84 | Similar to [`==`](@ref), except for the treatment of floating point numbers | ||
85 | and of missing values. `isequal` treats all floating-point `NaN` values as equal | ||
86 | to each other, treats `-0.0` as unequal to `0.0`, and [`missing`](@ref) as equal | ||
87 | to `missing`. Always returns a `Bool` value. | ||
88 | |||
89 | `isequal` is an equivalence relation - it is reflexive (`===` implies `isequal`), symmetric | ||
90 | (`isequal(a, b)` implies `isequal(b, a)`) and transitive (`isequal(a, b)` and | ||
91 | `isequal(b, c)` implies `isequal(a, c)`). | ||
92 | |||
93 | # Implementation | ||
94 | The default implementation of `isequal` calls `==`, so a type that does not involve | ||
95 | floating-point values generally only needs to define `==`. | ||
96 | |||
97 | `isequal` is the comparison function used by hash tables (`Dict`). `isequal(x,y)` must imply | ||
98 | that `hash(x) == hash(y)`. | ||
99 | |||
100 | This typically means that types for which a custom `==` or `isequal` method exists must | ||
101 | implement a corresponding [`hash`](@ref) method (and vice versa). Collections typically | ||
102 | implement `isequal` by calling `isequal` recursively on all contents. | ||
103 | |||
104 | Furthermore, `isequal` is linked with [`isless`](@ref), and they work together to | ||
105 | define a fixed total ordering, where exactly one of `isequal(x, y)`, `isless(x, y)`, or | ||
106 | `isless(y, x)` must be `true` (and the other two `false`). | ||
107 | |||
108 | Scalar types generally do not need to implement `isequal` separate from `==`, unless they | ||
109 | represent floating-point numbers amenable to a more efficient implementation than that | ||
110 | provided as a generic fallback (based on `isnan`, `signbit`, and `==`). | ||
111 | |||
112 | # Examples | ||
113 | ```jldoctest | ||
114 | julia> isequal([1., NaN], [1., NaN]) | ||
115 | true | ||
116 | |||
117 | julia> [1., NaN] == [1., NaN] | ||
118 | false | ||
119 | |||
120 | julia> 0.0 == -0.0 | ||
121 | true | ||
122 | |||
123 | julia> isequal(0.0, -0.0) | ||
124 | false | ||
125 | |||
126 | julia> missing == missing | ||
127 | missing | ||
128 | |||
129 | julia> isequal(missing, missing) | ||
130 | true | ||
131 | ``` | ||
132 | """ | ||
133 | isequal(x, y) = (x == y)::Bool # all `missing` cases are handled in missing.jl | ||
134 | |||
135 | signequal(x, y) = signbit(x)::Bool == signbit(y)::Bool | ||
136 | signless(x, y) = signbit(x)::Bool & !signbit(y)::Bool | ||
137 | |||
138 | isequal(x::AbstractFloat, y::AbstractFloat) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y)::Bool | ||
139 | isequal(x::Real, y::AbstractFloat) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y)::Bool | ||
140 | isequal(x::AbstractFloat, y::Real ) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y)::Bool | ||
141 | |||
142 | """ | ||
143 | isless(x, y) | ||
144 | |||
145 | Test whether `x` is less than `y`, according to a fixed total order (defined together with | ||
146 | [`isequal`](@ref)). `isless` is not defined for pairs `(x, y)` of all types. However, if it | ||
147 | is defined, it is expected to satisfy the following: | ||
148 | - If `isless(x, y)` is defined, then so is `isless(y, x)` and `isequal(x, y)`, | ||
149 | and exactly one of those three yields `true`. | ||
150 | - The relation defined by `isless` is transitive, i.e., | ||
151 | `isless(x, y) && isless(y, z)` implies `isless(x, z)`. | ||
152 | |||
153 | Values that are normally unordered, such as `NaN`, | ||
154 | are ordered after regular values. | ||
155 | [`missing`](@ref) values are ordered last. | ||
156 | |||
157 | This is the default comparison used by [`sort!`](@ref). | ||
158 | |||
159 | # Implementation | ||
160 | Non-numeric types with a total order should implement this function. | ||
161 | Numeric types only need to implement it if they have special values such as `NaN`. | ||
162 | Types with a partial order should implement [`<`](@ref). | ||
163 | See the documentation on [Alternate Orderings](@ref) for how to define alternate | ||
164 | ordering methods that can be used in sorting and related functions. | ||
165 | |||
166 | # Examples | ||
167 | ```jldoctest | ||
168 | julia> isless(1, 3) | ||
169 | true | ||
170 | |||
171 | julia> isless("Red", "Blue") | ||
172 | false | ||
173 | ``` | ||
174 | """ | ||
175 | function isless end | ||
176 | |||
177 | isless(x::AbstractFloat, y::AbstractFloat) = (!isnan(x) & (isnan(y) | signless(x, y))) | (x < y) | ||
178 | isless(x::Real, y::AbstractFloat) = (!isnan(x) & (isnan(y) | signless(x, y))) | (x < y) | ||
179 | isless(x::AbstractFloat, y::Real ) = (!isnan(x) & (isnan(y) | signless(x, y))) | (x < y) | ||
180 | |||
181 | # Performance optimization to reduce branching | ||
182 | # This is useful for sorting tuples of integers | ||
183 | # TODO: remove this when the compiler can optimize the generic version better | ||
184 | # See #48724 and #48753 | ||
185 | isless(a::Tuple{BitInteger, BitInteger}, b::Tuple{BitInteger, BitInteger}) = | ||
186 | isless(a[1], b[1]) | (isequal(a[1], b[1]) & isless(a[2], b[2])) | ||
187 | |||
188 | """ | ||
189 | isgreater(x, y) | ||
190 | |||
191 | Not the inverse of `isless`! Test whether `x` is greater than `y`, according to | ||
192 | a fixed total order compatible with `min`. | ||
193 | |||
194 | Defined with `isless`, this function is usually `isless(y, x)`, but `NaN` and | ||
195 | [`missing`](@ref) are ordered as smaller than any regular value with `missing` | ||
196 | smaller than `NaN`. | ||
197 | |||
198 | So `isless` defines an ascending total order with `NaN` and `missing` as the | ||
199 | largest values and `isgreater` defines a descending total order with `NaN` and | ||
200 | `missing` as the smallest values. | ||
201 | |||
202 | !!! note | ||
203 | |||
204 | Like `min`, `isgreater` orders containers (tuples, vectors, etc) | ||
205 | lexicographically with `isless(y, x)` rather than recursively with itself: | ||
206 | |||
207 | ```jldoctest | ||
208 | julia> Base.isgreater(1, NaN) # 1 is greater than NaN | ||
209 | true | ||
210 | |||
211 | julia> Base.isgreater((1,), (NaN,)) # But (1,) is not greater than (NaN,) | ||
212 | false | ||
213 | |||
214 | julia> sort([1, 2, 3, NaN]; lt=Base.isgreater) | ||
215 | 4-element Vector{Float64}: | ||
216 | 3.0 | ||
217 | 2.0 | ||
218 | 1.0 | ||
219 | NaN | ||
220 | |||
221 | julia> sort(tuple.([1, 2, 3, NaN]); lt=Base.isgreater) | ||
222 | 4-element Vector{Tuple{Float64}}: | ||
223 | (NaN,) | ||
224 | (3.0,) | ||
225 | (2.0,) | ||
226 | (1.0,) | ||
227 | ``` | ||
228 | |||
229 | # Implementation | ||
230 | This is unexported. Types should not usually implement this function. Instead, implement `isless`. | ||
231 | """ | ||
232 | isgreater(x, y) = isunordered(x) || isunordered(y) ? isless(x, y) : isless(y, x) | ||
233 | |||
234 | """ | ||
235 | isunordered(x) | ||
236 | |||
237 | Return `true` if `x` is a value that is not orderable according to [`<`](@ref), such as `NaN` | ||
238 | or `missing`. | ||
239 | |||
240 | The values that evaluate to `true` with this predicate may be orderable with respect to other | ||
241 | orderings such as [`isless`](@ref). | ||
242 | |||
243 | !!! compat "Julia 1.7" | ||
244 | This function requires Julia 1.7 or later. | ||
245 | """ | ||
246 | isunordered(x) = false | ||
247 | isunordered(x::AbstractFloat) = isnan(x) | ||
248 | isunordered(x::Missing) = true | ||
249 | |||
250 | ==(T::Type, S::Type) = (@_total_meta; ccall(:jl_types_equal, Cint, (Any, Any), T, S) != 0) | ||
251 | !=(T::Type, S::Type) = (@_total_meta; !(T == S)) | ||
252 | ==(T::TypeVar, S::Type) = false | ||
253 | ==(T::Type, S::TypeVar) = false | ||
254 | |||
255 | ## comparison fallbacks ## | ||
256 | |||
257 | """ | ||
258 | !=(x, y) | ||
259 | ≠(x,y) | ||
260 | |||
261 | Not-equals comparison operator. Always gives the opposite answer as [`==`](@ref). | ||
262 | |||
263 | # Implementation | ||
264 | New types should generally not implement this, and rely on the fallback definition | ||
265 | `!=(x,y) = !(x==y)` instead. | ||
266 | |||
267 | # Examples | ||
268 | ```jldoctest | ||
269 | julia> 3 != 2 | ||
270 | true | ||
271 | |||
272 | julia> "foo" ≠ "foo" | ||
273 | false | ||
274 | ``` | ||
275 | """ | ||
276 | !=(x, y) = !(x == y) | ||
277 | const ≠ = != | ||
278 | |||
279 | """ | ||
280 | ===(x,y) -> Bool | ||
281 | ≡(x,y) -> Bool | ||
282 | |||
283 | Determine whether `x` and `y` are identical, in the sense that no program could distinguish | ||
284 | them. First the types of `x` and `y` are compared. If those are identical, mutable objects | ||
285 | are compared by address in memory and immutable objects (such as numbers) are compared by | ||
286 | contents at the bit level. This function is sometimes called "egal". | ||
287 | It always returns a `Bool` value. | ||
288 | |||
289 | # Examples | ||
290 | ```jldoctest | ||
291 | julia> a = [1, 2]; b = [1, 2]; | ||
292 | |||
293 | julia> a == b | ||
294 | true | ||
295 | |||
296 | julia> a === b | ||
297 | false | ||
298 | |||
299 | julia> a === a | ||
300 | true | ||
301 | ``` | ||
302 | """ | ||
303 | === | ||
304 | const ≡ = === | ||
305 | |||
306 | """ | ||
307 | !==(x, y) | ||
308 | ≢(x,y) | ||
309 | |||
310 | Always gives the opposite answer as [`===`](@ref). | ||
311 | |||
312 | # Examples | ||
313 | ```jldoctest | ||
314 | julia> a = [1, 2]; b = [1, 2]; | ||
315 | |||
316 | julia> a ≢ b | ||
317 | true | ||
318 | |||
319 | julia> a ≢ a | ||
320 | false | ||
321 | ``` | ||
322 | """ | ||
323 | !==(@nospecialize(x), @nospecialize(y)) = !(x === y) | ||
324 | const ≢ = !== | ||
325 | |||
326 | """ | ||
327 | <(x, y) | ||
328 | |||
329 | Less-than comparison operator. Falls back to [`isless`](@ref). | ||
330 | Because of the behavior of floating-point NaN values, this operator implements | ||
331 | a partial order. | ||
332 | |||
333 | # Implementation | ||
334 | New types with a canonical partial order should implement this function for | ||
335 | two arguments of the new type. | ||
336 | Types with a canonical total order should implement [`isless`](@ref) instead. | ||
337 | |||
338 | See also [`isunordered`](@ref). | ||
339 | |||
340 | # Examples | ||
341 | ```jldoctest | ||
342 | julia> 'a' < 'b' | ||
343 | true | ||
344 | |||
345 | julia> "abc" < "abd" | ||
346 | true | ||
347 | |||
348 | julia> 5 < 3 | ||
349 | false | ||
350 | ``` | ||
351 | """ | ||
352 | <(x, y) = isless(x, y) | ||
353 | |||
354 | """ | ||
355 | >(x, y) | ||
356 | |||
357 | Greater-than comparison operator. Falls back to `y < x`. | ||
358 | |||
359 | # Implementation | ||
360 | Generally, new types should implement [`<`](@ref) instead of this function, | ||
361 | and rely on the fallback definition `>(x, y) = y < x`. | ||
362 | |||
363 | # Examples | ||
364 | ```jldoctest | ||
365 | julia> 'a' > 'b' | ||
366 | false | ||
367 | |||
368 | julia> 7 > 3 > 1 | ||
369 | true | ||
370 | |||
371 | julia> "abc" > "abd" | ||
372 | false | ||
373 | |||
374 | julia> 5 > 3 | ||
375 | true | ||
376 | ``` | ||
377 | """ | ||
378 | >(x, y) = y < x | ||
379 | |||
380 | """ | ||
381 | <=(x, y) | ||
382 | ≤(x,y) | ||
383 | |||
384 | Less-than-or-equals comparison operator. Falls back to `(x < y) | (x == y)`. | ||
385 | |||
386 | # Examples | ||
387 | ```jldoctest | ||
388 | julia> 'a' <= 'b' | ||
389 | true | ||
390 | |||
391 | julia> 7 ≤ 7 ≤ 9 | ||
392 | true | ||
393 | |||
394 | julia> "abc" ≤ "abc" | ||
395 | true | ||
396 | |||
397 | julia> 5 <= 3 | ||
398 | false | ||
399 | ``` | ||
400 | """ | ||
401 | <=(x, y) = (x < y) | (x == y) | ||
402 | const ≤ = <= | ||
403 | |||
404 | """ | ||
405 | >=(x, y) | ||
406 | ≥(x,y) | ||
407 | |||
408 | Greater-than-or-equals comparison operator. Falls back to `y <= x`. | ||
409 | |||
410 | # Examples | ||
411 | ```jldoctest | ||
412 | julia> 'a' >= 'b' | ||
413 | false | ||
414 | |||
415 | julia> 7 ≥ 7 ≥ 3 | ||
416 | true | ||
417 | |||
418 | julia> "abc" ≥ "abc" | ||
419 | true | ||
420 | |||
421 | julia> 5 >= 3 | ||
422 | true | ||
423 | ``` | ||
424 | """ | ||
425 | >=(x, y) = (y <= x) | ||
426 | const ≥ = >= | ||
427 | |||
428 | # this definition allows Number types to implement < instead of isless, | ||
429 | # which is more idiomatic: | ||
430 | isless(x::Real, y::Real) = x<y | ||
431 | |||
432 | """ | ||
433 | cmp(x,y) | ||
434 | |||
435 | Return -1, 0, or 1 depending on whether `x` is less than, equal to, or greater than `y`, | ||
436 | respectively. Uses the total order implemented by `isless`. | ||
437 | |||
438 | # Examples | ||
439 | ```jldoctest | ||
440 | julia> cmp(1, 2) | ||
441 | -1 | ||
442 | |||
443 | julia> cmp(2, 1) | ||
444 | 1 | ||
445 | |||
446 | julia> cmp(2+im, 3-im) | ||
447 | ERROR: MethodError: no method matching isless(::Complex{Int64}, ::Complex{Int64}) | ||
448 | [...] | ||
449 | ``` | ||
450 | """ | ||
451 | cmp(x, y) = isless(x, y) ? -1 : ifelse(isless(y, x), 1, 0) | ||
452 | |||
453 | """ | ||
454 | cmp(<, x, y) | ||
455 | |||
456 | Return -1, 0, or 1 depending on whether `x` is less than, equal to, or greater than `y`, | ||
457 | respectively. The first argument specifies a less-than comparison function to use. | ||
458 | """ | ||
459 | cmp(<, x, y) = (x < y) ? -1 : ifelse(y < x, 1, 0) | ||
460 | |||
461 | # cmp returns -1, 0, +1 indicating ordering | ||
462 | cmp(x::Integer, y::Integer) = ifelse(isless(x, y), -1, ifelse(isless(y, x), 1, 0)) | ||
463 | |||
464 | """ | ||
465 | max(x, y, ...) | ||
466 | |||
467 | Return the maximum of the arguments (with respect to [`isless`](@ref)). See also the [`maximum`](@ref) function | ||
468 | to take the maximum element from a collection. | ||
469 | |||
470 | # Examples | ||
471 | ```jldoctest | ||
472 | julia> max(2, 5, 1) | ||
473 | 5 | ||
474 | ``` | ||
475 | """ | ||
476 | max(x, y) = ifelse(isless(y, x), x, y) | ||
477 | |||
478 | """ | ||
479 | min(x, y, ...) | ||
480 | |||
481 | Return the minimum of the arguments (with respect to [`isless`](@ref)). See also the [`minimum`](@ref) function | ||
482 | to take the minimum element from a collection. | ||
483 | |||
484 | # Examples | ||
485 | ```jldoctest | ||
486 | julia> min(2, 5, 1) | ||
487 | 1 | ||
488 | ``` | ||
489 | """ | ||
490 | min(x,y) = ifelse(isless(y, x), y, x) | ||
491 | |||
492 | """ | ||
493 | minmax(x, y) | ||
494 | |||
495 | Return `(min(x,y), max(x,y))`. | ||
496 | |||
497 | See also [`extrema`](@ref) that returns `(minimum(x), maximum(x))`. | ||
498 | |||
499 | # Examples | ||
500 | ```jldoctest | ||
501 | julia> minmax('c','b') | ||
502 | ('b', 'c') | ||
503 | ``` | ||
504 | """ | ||
505 | minmax(x,y) = isless(y, x) ? (y, x) : (x, y) | ||
506 | |||
507 | ## definitions providing basic traits of arithmetic operators ## | ||
508 | |||
509 | """ | ||
510 | identity(x) | ||
511 | |||
512 | The identity function. Returns its argument. | ||
513 | |||
514 | See also: [`one`](@ref), [`oneunit`](@ref), and [`LinearAlgebra`](@ref man-linalg)'s `I`. | ||
515 | |||
516 | # Examples | ||
517 | ```jldoctest | ||
518 | julia> identity("Well, what did you expect?") | ||
519 | "Well, what did you expect?" | ||
520 | ``` | ||
521 | """ | ||
522 | identity(@nospecialize x) = x | ||
523 | |||
524 | +(x::Number) = x | ||
525 | *(x::Number) = x | ||
526 | (&)(x::Integer) = x | ||
527 | (|)(x::Integer) = x | ||
528 | xor(x::Integer) = x | ||
529 | |||
530 | const ⊻ = xor | ||
531 | const ⊼ = nand | ||
532 | const ⊽ = nor | ||
533 | |||
534 | # foldl for argument lists. expand fully up to a point, then | ||
535 | # switch to a loop. this allows small cases like `a+b+c+d` to be managed | ||
536 | # efficiently, without a major slowdown for `+(x...)` when `x` is big. | ||
537 | # n.b.: keep this method count small, so it can be inferred without hitting the | ||
538 | # method count limit in inference | ||
539 | afoldl(op, a) = a | ||
540 | function afoldl(op, a, bs...) | ||
541 | l = length(bs) | ||
542 | i = 0; y = a; l == i && return y | ||
543 | #@nexprs 31 i -> (y = op(y, bs[i]); l == i && return y) | ||
544 | i = 1; y = op(y, bs[i]); l == i && return y | ||
545 | i = 2; y = op(y, bs[i]); l == i && return y | ||
546 | i = 3; y = op(y, bs[i]); l == i && return y | ||
547 | i = 4; y = op(y, bs[i]); l == i && return y | ||
548 | i = 5; y = op(y, bs[i]); l == i && return y | ||
549 | i = 6; y = op(y, bs[i]); l == i && return y | ||
550 | i = 7; y = op(y, bs[i]); l == i && return y | ||
551 | i = 8; y = op(y, bs[i]); l == i && return y | ||
552 | i = 9; y = op(y, bs[i]); l == i && return y | ||
553 | i = 10; y = op(y, bs[i]); l == i && return y | ||
554 | i = 11; y = op(y, bs[i]); l == i && return y | ||
555 | i = 12; y = op(y, bs[i]); l == i && return y | ||
556 | i = 13; y = op(y, bs[i]); l == i && return y | ||
557 | i = 14; y = op(y, bs[i]); l == i && return y | ||
558 | i = 15; y = op(y, bs[i]); l == i && return y | ||
559 | i = 16; y = op(y, bs[i]); l == i && return y | ||
560 | i = 17; y = op(y, bs[i]); l == i && return y | ||
561 | i = 18; y = op(y, bs[i]); l == i && return y | ||
562 | i = 19; y = op(y, bs[i]); l == i && return y | ||
563 | i = 20; y = op(y, bs[i]); l == i && return y | ||
564 | i = 21; y = op(y, bs[i]); l == i && return y | ||
565 | i = 22; y = op(y, bs[i]); l == i && return y | ||
566 | i = 23; y = op(y, bs[i]); l == i && return y | ||
567 | i = 24; y = op(y, bs[i]); l == i && return y | ||
568 | i = 25; y = op(y, bs[i]); l == i && return y | ||
569 | i = 26; y = op(y, bs[i]); l == i && return y | ||
570 | i = 27; y = op(y, bs[i]); l == i && return y | ||
571 | i = 28; y = op(y, bs[i]); l == i && return y | ||
572 | i = 29; y = op(y, bs[i]); l == i && return y | ||
573 | i = 30; y = op(y, bs[i]); l == i && return y | ||
574 | i = 31; y = op(y, bs[i]); l == i && return y | ||
575 | for i in (i + 1):l | ||
576 | y = op(y, bs[i]) | ||
577 | end | ||
578 | return y | ||
579 | end | ||
580 | setfield!(typeof(afoldl).name.mt, :max_args, 34, :monotonic) | ||
581 | |||
582 | for op in (:+, :*, :&, :|, :xor, :min, :max, :kron) | ||
583 | @eval begin | ||
584 | # note: these definitions must not cause a dispatch loop when +(a,b) is | ||
585 | # not defined, and must only try to call 2-argument definitions, so | ||
586 | # that defining +(a,b) is sufficient for full functionality. | ||
587 | 2 (1 %) |
2 (100 %)
samples spent calling
+
($op)(a, b, c, xs...) = (@inline; afoldl($op, ($op)(($op)(a,b),c), xs...))
|
|
588 | # a further concern is that it's easy for a type like (Int,Int...) | ||
589 | # to match many definitions, so we need to keep the number of | ||
590 | # definitions down to avoid losing type information. | ||
591 | end | ||
592 | end | ||
593 | |||
594 | function kron! end | ||
595 | |||
596 | const var"'" = adjoint | ||
597 | |||
598 | """ | ||
599 | \\(x, y) | ||
600 | |||
601 | Left division operator: multiplication of `y` by the inverse of `x` on the left. Gives | ||
602 | floating-point results for integer arguments. | ||
603 | |||
604 | # Examples | ||
605 | ```jldoctest | ||
606 | julia> 3 \\ 6 | ||
607 | 2.0 | ||
608 | |||
609 | julia> inv(3) * 6 | ||
610 | 2.0 | ||
611 | |||
612 | julia> A = [4 3; 2 1]; x = [5, 6]; | ||
613 | |||
614 | julia> A \\ x | ||
615 | 2-element Vector{Float64}: | ||
616 | 6.5 | ||
617 | -7.0 | ||
618 | |||
619 | julia> inv(A) * x | ||
620 | 2-element Vector{Float64}: | ||
621 | 6.5 | ||
622 | -7.0 | ||
623 | ``` | ||
624 | """ | ||
625 | \(x,y) = adjoint(adjoint(y)/adjoint(x)) | ||
626 | |||
627 | # Core <<, >>, and >>> take either Int or UInt as second arg. Signed shift | ||
628 | # counts can shift in either direction, and are translated here to unsigned | ||
629 | # counts. Integer datatypes only need to implement the unsigned version. | ||
630 | |||
631 | """ | ||
632 | <<(x, n) | ||
633 | |||
634 | Left bit shift operator, `x << n`. For `n >= 0`, the result is `x` shifted left | ||
635 | by `n` bits, filling with `0`s. This is equivalent to `x * 2^n`. For `n < 0`, | ||
636 | this is equivalent to `x >> -n`. | ||
637 | |||
638 | # Examples | ||
639 | ```jldoctest | ||
640 | julia> Int8(3) << 2 | ||
641 | 12 | ||
642 | |||
643 | julia> bitstring(Int8(3)) | ||
644 | "00000011" | ||
645 | |||
646 | julia> bitstring(Int8(12)) | ||
647 | "00001100" | ||
648 | ``` | ||
649 | See also [`>>`](@ref), [`>>>`](@ref), [`exp2`](@ref), [`ldexp`](@ref). | ||
650 | """ | ||
651 | function <<(x::Integer, c::Integer) | ||
652 | @inline | ||
653 | typemin(Int) <= c <= typemax(Int) && return x << (c % Int) | ||
654 | (x >= 0 || c >= 0) && return zero(x) << 0 # for type stability | ||
655 | oftype(x, -1) | ||
656 | end | ||
657 | function <<(x::Integer, c::Unsigned) | ||
658 | @inline | ||
659 | if c isa UInt | ||
660 | throw(MethodError(<<, (x, c))) | ||
661 | end | ||
662 | c <= typemax(UInt) ? x << (c % UInt) : zero(x) << UInt(0) | ||
663 | end | ||
664 | <<(x::Integer, c::Int) = c >= 0 ? x << unsigned(c) : x >> unsigned(-c) | ||
665 | |||
666 | """ | ||
667 | >>(x, n) | ||
668 | |||
669 | Right bit shift operator, `x >> n`. For `n >= 0`, the result is `x` shifted | ||
670 | right by `n` bits, filling with `0`s if `x >= 0`, `1`s if `x < 0`, preserving | ||
671 | the sign of `x`. This is equivalent to `fld(x, 2^n)`. For `n < 0`, this is | ||
672 | equivalent to `x << -n`. | ||
673 | |||
674 | # Examples | ||
675 | ```jldoctest | ||
676 | julia> Int8(13) >> 2 | ||
677 | 3 | ||
678 | |||
679 | julia> bitstring(Int8(13)) | ||
680 | "00001101" | ||
681 | |||
682 | julia> bitstring(Int8(3)) | ||
683 | "00000011" | ||
684 | |||
685 | julia> Int8(-14) >> 2 | ||
686 | -4 | ||
687 | |||
688 | julia> bitstring(Int8(-14)) | ||
689 | "11110010" | ||
690 | |||
691 | julia> bitstring(Int8(-4)) | ||
692 | "11111100" | ||
693 | ``` | ||
694 | See also [`>>>`](@ref), [`<<`](@ref). | ||
695 | """ | ||
696 | function >>(x::Integer, c::Integer) | ||
697 | @inline | ||
698 | if c isa UInt | ||
699 | throw(MethodError(>>, (x, c))) | ||
700 | end | ||
701 | typemin(Int) <= c <= typemax(Int) && return x >> (c % Int) | ||
702 | (x >= 0 || c < 0) && return zero(x) >> 0 | ||
703 | oftype(x, -1) | ||
704 | end | ||
705 | >>(x::Integer, c::Int) = c >= 0 ? x >> unsigned(c) : x << unsigned(-c) | ||
706 | |||
707 | """ | ||
708 | >>>(x, n) | ||
709 | |||
710 | Unsigned right bit shift operator, `x >>> n`. For `n >= 0`, the result is `x` | ||
711 | shifted right by `n` bits, filling with `0`s. For `n < 0`, this is equivalent | ||
712 | to `x << -n`. | ||
713 | |||
714 | For [`Unsigned`](@ref) integer types, this is equivalent to [`>>`](@ref). For | ||
715 | [`Signed`](@ref) integer types, this is equivalent to `signed(unsigned(x) >> n)`. | ||
716 | |||
717 | # Examples | ||
718 | ```jldoctest | ||
719 | julia> Int8(-14) >>> 2 | ||
720 | 60 | ||
721 | |||
722 | julia> bitstring(Int8(-14)) | ||
723 | "11110010" | ||
724 | |||
725 | julia> bitstring(Int8(60)) | ||
726 | "00111100" | ||
727 | ``` | ||
728 | |||
729 | [`BigInt`](@ref)s are treated as if having infinite size, so no filling is required and this | ||
730 | is equivalent to [`>>`](@ref). | ||
731 | |||
732 | See also [`>>`](@ref), [`<<`](@ref). | ||
733 | """ | ||
734 | function >>>(x::Integer, c::Integer) | ||
735 | @inline | ||
736 | typemin(Int) <= c <= typemax(Int) ? x >>> (c % Int) : zero(x) >>> 0 | ||
737 | end | ||
738 | function >>>(x::Integer, c::Unsigned) | ||
739 | @inline | ||
740 | if c isa UInt | ||
741 | throw(MethodError(>>>, (x, c))) | ||
742 | end | ||
743 | c <= typemax(UInt) ? x >>> (c % UInt) : zero(x) >>> 0 | ||
744 | end | ||
745 | >>>(x::Integer, c::Int) = c >= 0 ? x >>> unsigned(c) : x << unsigned(-c) | ||
746 | |||
747 | # operator alias | ||
748 | |||
749 | """ | ||
750 | rem(x, y) | ||
751 | %(x, y) | ||
752 | |||
753 | Remainder from Euclidean division, returning a value of the same sign as `x`, and smaller in | ||
754 | magnitude than `y`. This value is always exact. | ||
755 | |||
756 | See also: [`div`](@ref), [`mod`](@ref), [`mod1`](@ref), [`divrem`](@ref). | ||
757 | |||
758 | # Examples | ||
759 | ```jldoctest | ||
760 | julia> x = 15; y = 4; | ||
761 | |||
762 | julia> x % y | ||
763 | 3 | ||
764 | |||
765 | julia> x == div(x, y) * y + rem(x, y) | ||
766 | true | ||
767 | |||
768 | julia> rem.(-5:5, 3)' | ||
769 | 1×11 adjoint(::Vector{Int64}) with eltype Int64: | ||
770 | -2 -1 0 -2 -1 0 1 2 0 1 2 | ||
771 | ``` | ||
772 | """ | ||
773 | rem | ||
774 | const % = rem | ||
775 | |||
776 | """ | ||
777 | div(x, y) | ||
778 | ÷(x, y) | ||
779 | |||
780 | The quotient from Euclidean (integer) division. Generally equivalent | ||
781 | to a mathematical operation x/y without a fractional part. | ||
782 | |||
783 | See also: [`cld`](@ref), [`fld`](@ref), [`rem`](@ref), [`divrem`](@ref). | ||
784 | |||
785 | # Examples | ||
786 | ```jldoctest | ||
787 | julia> 9 ÷ 4 | ||
788 | 2 | ||
789 | |||
790 | julia> -5 ÷ 3 | ||
791 | -1 | ||
792 | |||
793 | julia> 5.0 ÷ 2 | ||
794 | 2.0 | ||
795 | |||
796 | julia> div.(-5:5, 3)' | ||
797 | 1×11 adjoint(::Vector{Int64}) with eltype Int64: | ||
798 | -1 -1 -1 0 0 0 0 0 1 1 1 | ||
799 | ``` | ||
800 | """ | ||
801 | div | ||
802 | const ÷ = div | ||
803 | |||
804 | """ | ||
805 | mod1(x, y) | ||
806 | |||
807 | Modulus after flooring division, returning a value `r` such that `mod(r, y) == mod(x, y)` | ||
808 | in the range ``(0, y]`` for positive `y` and in the range ``[y,0)`` for negative `y`. | ||
809 | |||
810 | With integer arguments and positive `y`, this is equal to `mod(x, 1:y)`, and hence natural | ||
811 | for 1-based indexing. By comparison, `mod(x, y) == mod(x, 0:y-1)` is natural for computations with | ||
812 | offsets or strides. | ||
813 | |||
814 | See also [`mod`](@ref), [`fld1`](@ref), [`fldmod1`](@ref). | ||
815 | |||
816 | # Examples | ||
817 | ```jldoctest | ||
818 | julia> mod1(4, 2) | ||
819 | 2 | ||
820 | |||
821 | julia> mod1.(-5:5, 3)' | ||
822 | 1×11 adjoint(::Vector{Int64}) with eltype Int64: | ||
823 | 1 2 3 1 2 3 1 2 3 1 2 | ||
824 | |||
825 | julia> mod1.([-0.1, 0, 0.1, 1, 2, 2.9, 3, 3.1]', 3) | ||
826 | 1×8 Matrix{Float64}: | ||
827 | 2.9 3.0 0.1 1.0 2.0 2.9 3.0 0.1 | ||
828 | ``` | ||
829 | """ | ||
830 | mod1(x::T, y::T) where {T<:Real} = (m = mod(x, y); ifelse(m == 0, y, m)) | ||
831 | |||
832 | |||
833 | """ | ||
834 | fld1(x, y) | ||
835 | |||
836 | Flooring division, returning a value consistent with `mod1(x,y)` | ||
837 | |||
838 | See also [`mod1`](@ref), [`fldmod1`](@ref). | ||
839 | |||
840 | # Examples | ||
841 | ```jldoctest | ||
842 | julia> x = 15; y = 4; | ||
843 | |||
844 | julia> fld1(x, y) | ||
845 | 4 | ||
846 | |||
847 | julia> x == fld(x, y) * y + mod(x, y) | ||
848 | true | ||
849 | |||
850 | julia> x == (fld1(x, y) - 1) * y + mod1(x, y) | ||
851 | true | ||
852 | ``` | ||
853 | """ | ||
854 | fld1(x::T, y::T) where {T<:Real} = (m = mod1(x, y); fld((x - m) + y, y)) | ||
855 | function fld1(x::T, y::T) where T<:Integer | ||
856 | d = div(x, y) | ||
857 | return d + (!signbit(x ⊻ y) & (d * y != x)) | ||
858 | end | ||
859 | |||
860 | """ | ||
861 | fldmod1(x, y) | ||
862 | |||
863 | Return `(fld1(x,y), mod1(x,y))`. | ||
864 | |||
865 | See also [`fld1`](@ref), [`mod1`](@ref). | ||
866 | """ | ||
867 | fldmod1(x, y) = (fld1(x, y), mod1(x, y)) | ||
868 | |||
869 | |||
870 | """ | ||
871 | widen(x) | ||
872 | |||
873 | If `x` is a type, return a "larger" type, defined so that arithmetic operations | ||
874 | `+` and `-` are guaranteed not to overflow nor lose precision for any combination | ||
875 | of values that type `x` can hold. | ||
876 | |||
877 | For fixed-size integer types less than 128 bits, `widen` will return a type with | ||
878 | twice the number of bits. | ||
879 | |||
880 | If `x` is a value, it is converted to `widen(typeof(x))`. | ||
881 | |||
882 | # Examples | ||
883 | ```jldoctest | ||
884 | julia> widen(Int32) | ||
885 | Int64 | ||
886 | |||
887 | julia> widen(1.5f0) | ||
888 | 1.5 | ||
889 | ``` | ||
890 | """ | ||
891 | widen(x::T) where {T} = convert(widen(T), x) | ||
892 | widen(x::Type{T}) where {T} = throw(MethodError(widen, (T,))) | ||
893 | widen(x::Type{Union{}}, slurp...) = throw(MethodError(widen, (Union{},))) | ||
894 | |||
895 | # function pipelining | ||
896 | |||
897 | """ | ||
898 | |>(x, f) | ||
899 | |||
900 | Infix operator which applies function `f` to the argument `x`. | ||
901 | This allows `f(g(x))` to be written `x |> g |> f`. | ||
902 | When used with anonymous functions, parentheses are typically required around | ||
903 | the definition to get the intended chain. | ||
904 | |||
905 | # Examples | ||
906 | ```jldoctest | ||
907 | julia> 4 |> inv | ||
908 | 0.25 | ||
909 | |||
910 | julia> [2, 3, 5] |> sum |> inv | ||
911 | 0.1 | ||
912 | |||
913 | julia> [0 1; 2 3] .|> (x -> x^2) |> sum | ||
914 | 14 | ||
915 | ``` | ||
916 | """ | ||
917 | |>(x, f) = f(x) | ||
918 | |||
919 | _stable_typeof(x) = typeof(x) | ||
920 | _stable_typeof(::Type{T}) where {T} = @isdefined(T) ? Type{T} : DataType | ||
921 | |||
922 | """ | ||
923 | f = Returns(value) | ||
924 | |||
925 | Create a callable `f` such that `f(args...; kw...) === value` holds. | ||
926 | |||
927 | # Examples | ||
928 | |||
929 | ```jldoctest | ||
930 | julia> f = Returns(42); | ||
931 | |||
932 | julia> f(1) | ||
933 | 42 | ||
934 | |||
935 | julia> f("hello", x=32) | ||
936 | 42 | ||
937 | |||
938 | julia> f.value | ||
939 | 42 | ||
940 | ``` | ||
941 | |||
942 | !!! compat "Julia 1.7" | ||
943 | `Returns` requires at least Julia 1.7. | ||
944 | """ | ||
945 | struct Returns{V} <: Function | ||
946 | value::V | ||
947 | Returns{V}(value) where {V} = new{V}(value) | ||
948 | Returns(value) = new{_stable_typeof(value)}(value) | ||
949 | end | ||
950 | |||
951 | (obj::Returns)(@nospecialize(args...); @nospecialize(kw...)) = obj.value | ||
952 | |||
953 | # function composition | ||
954 | |||
955 | """ | ||
956 | f ∘ g | ||
957 | |||
958 | Compose functions: i.e. `(f ∘ g)(args...; kwargs...)` means `f(g(args...; kwargs...))`. The `∘` symbol can be | ||
959 | entered in the Julia REPL (and most editors, appropriately configured) by typing `\\circ<tab>`. | ||
960 | |||
961 | Function composition also works in prefix form: `∘(f, g)` is the same as `f ∘ g`. | ||
962 | The prefix form supports composition of multiple functions: `∘(f, g, h) = f ∘ g ∘ h` | ||
963 | and splatting `∘(fs...)` for composing an iterable collection of functions. | ||
964 | The last argument to `∘` execute first. | ||
965 | |||
966 | !!! compat "Julia 1.4" | ||
967 | Multiple function composition requires at least Julia 1.4. | ||
968 | |||
969 | !!! compat "Julia 1.5" | ||
970 | Composition of one function ∘(f) requires at least Julia 1.5. | ||
971 | |||
972 | !!! compat "Julia 1.7" | ||
973 | Using keyword arguments requires at least Julia 1.7. | ||
974 | |||
975 | # Examples | ||
976 | ```jldoctest | ||
977 | julia> map(uppercase∘first, ["apple", "banana", "carrot"]) | ||
978 | 3-element Vector{Char}: | ||
979 | 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase) | ||
980 | 'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase) | ||
981 | 'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase) | ||
982 | |||
983 | julia> (==(6)∘length).(["apple", "banana", "carrot"]) | ||
984 | 3-element BitVector: | ||
985 | 0 | ||
986 | 1 | ||
987 | 1 | ||
988 | |||
989 | julia> fs = [ | ||
990 | x -> 2x | ||
991 | x -> x-1 | ||
992 | x -> x/2 | ||
993 | x -> x+1 | ||
994 | ]; | ||
995 | |||
996 | julia> ∘(fs...)(3) | ||
997 | 2.0 | ||
998 | ``` | ||
999 | See also [`ComposedFunction`](@ref), [`!f::Function`](@ref). | ||
1000 | """ | ||
1001 | function ∘ end | ||
1002 | |||
1003 | """ | ||
1004 | ComposedFunction{Outer,Inner} <: Function | ||
1005 | |||
1006 | Represents the composition of two callable objects `outer::Outer` and `inner::Inner`. That is | ||
1007 | ```julia | ||
1008 | ComposedFunction(outer, inner)(args...; kw...) === outer(inner(args...; kw...)) | ||
1009 | ``` | ||
1010 | The preferred way to construct an instance of `ComposedFunction` is to use the composition operator [`∘`](@ref): | ||
1011 | ```jldoctest | ||
1012 | julia> sin ∘ cos === ComposedFunction(sin, cos) | ||
1013 | true | ||
1014 | |||
1015 | julia> typeof(sin∘cos) | ||
1016 | ComposedFunction{typeof(sin), typeof(cos)} | ||
1017 | ``` | ||
1018 | The composed pieces are stored in the fields of `ComposedFunction` and can be retrieved as follows: | ||
1019 | ```jldoctest | ||
1020 | julia> composition = sin ∘ cos | ||
1021 | sin ∘ cos | ||
1022 | |||
1023 | julia> composition.outer === sin | ||
1024 | true | ||
1025 | |||
1026 | julia> composition.inner === cos | ||
1027 | true | ||
1028 | ``` | ||
1029 | !!! compat "Julia 1.6" | ||
1030 | ComposedFunction requires at least Julia 1.6. In earlier versions `∘` returns an anonymous function instead. | ||
1031 | |||
1032 | See also [`∘`](@ref). | ||
1033 | """ | ||
1034 | struct ComposedFunction{O,I} <: Function | ||
1035 | outer::O | ||
1036 | inner::I | ||
1037 | ComposedFunction{O, I}(outer, inner) where {O, I} = new{O, I}(outer, inner) | ||
1038 | ComposedFunction(outer, inner) = new{Core.Typeof(outer),Core.Typeof(inner)}(outer, inner) | ||
1039 | end | ||
1040 | |||
1041 | (c::ComposedFunction)(x...; kw...) = call_composed(unwrap_composed(c), x, kw) | ||
1042 | unwrap_composed(c::ComposedFunction) = (unwrap_composed(c.outer)..., unwrap_composed(c.inner)...) | ||
1043 | unwrap_composed(c) = (maybeconstructor(c),) | ||
1044 | call_composed(fs, x, kw) = (@inline; fs[1](call_composed(tail(fs), x, kw))) | ||
1045 | call_composed(fs::Tuple{Any}, x, kw) = fs[1](x...; kw...) | ||
1046 | |||
1047 | struct Constructor{F} <: Function end | ||
1048 | (::Constructor{F})(args...; kw...) where {F} = (@inline; F(args...; kw...)) | ||
1049 | maybeconstructor(::Type{F}) where {F} = Constructor{F}() | ||
1050 | maybeconstructor(f) = f | ||
1051 | |||
1052 | ∘(f) = f | ||
1053 | ∘(f, g) = ComposedFunction(f, g) | ||
1054 | ∘(f, g, h...) = ∘(f ∘ g, h...) | ||
1055 | |||
1056 | function show(io::IO, c::ComposedFunction) | ||
1057 | c.outer isa ComposedFunction ? show(io, c.outer) : _showcomposed(io, c.outer) | ||
1058 | print(io, " ∘ ") | ||
1059 | _showcomposed(io, c.inner) | ||
1060 | end | ||
1061 | |||
1062 | #shows !f instead of (!) ∘ f when ! is the outermost function | ||
1063 | function show(io::IO, c::ComposedFunction{typeof(!)}) | ||
1064 | print(io, '!') | ||
1065 | _showcomposed(io, c.inner) | ||
1066 | end | ||
1067 | |||
1068 | _showcomposed(io::IO, x) = show(io, x) | ||
1069 | #display operators like + and - inside parens | ||
1070 | _showcomposed(io::IO, f::Function) = isoperator(Symbol(f)) ? (print(io, '('); show(io, f); print(io, ')')) : show(io, f) | ||
1071 | #nesting for chained composition | ||
1072 | _showcomposed(io::IO, f::ComposedFunction) = (print(io, '('); show(io, f); print(io, ')')) | ||
1073 | #no nesting when ! is the outer function in a composition chain | ||
1074 | _showcomposed(io::IO, f::ComposedFunction{typeof(!)}) = show(io, f) | ||
1075 | |||
1076 | """ | ||
1077 | !f::Function | ||
1078 | |||
1079 | Predicate function negation: when the argument of `!` is a function, it returns a composed function which computes the boolean negation of `f`. | ||
1080 | |||
1081 | See also [`∘`](@ref). | ||
1082 | |||
1083 | # Examples | ||
1084 | ```jldoctest | ||
1085 | julia> str = "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε" | ||
1086 | "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε" | ||
1087 | |||
1088 | julia> filter(isletter, str) | ||
1089 | "εδxyδfxfyε" | ||
1090 | |||
1091 | julia> filter(!isletter, str) | ||
1092 | "∀ > 0, ∃ > 0: |-| < ⇒ |()-()| < " | ||
1093 | ``` | ||
1094 | |||
1095 | !!! compat "Julia 1.9" | ||
1096 | Starting with Julia 1.9, `!f` returns a [`ComposedFunction`](@ref) instead of an anonymous function. | ||
1097 | """ | ||
1098 | !(f::Function) = (!) ∘ f | ||
1099 | !(f::ComposedFunction{typeof(!)}) = f.inner #allows !!f === f | ||
1100 | |||
1101 | """ | ||
1102 | Fix1(f, x) | ||
1103 | |||
1104 | A type representing a partially-applied version of the two-argument function | ||
1105 | `f`, with the first argument fixed to the value "x". In other words, | ||
1106 | `Fix1(f, x)` behaves similarly to `y->f(x, y)`. | ||
1107 | |||
1108 | See also [`Fix2`](@ref Base.Fix2). | ||
1109 | """ | ||
1110 | struct Fix1{F,T} <: Function | ||
1111 | f::F | ||
1112 | x::T | ||
1113 | |||
1114 | Fix1(f::F, x) where {F} = new{F,_stable_typeof(x)}(f, x) | ||
1115 | Fix1(f::Type{F}, x) where {F} = new{Type{F},_stable_typeof(x)}(f, x) | ||
1116 | end | ||
1117 | |||
1118 | (f::Fix1)(y) = f.f(f.x, y) | ||
1119 | |||
1120 | """ | ||
1121 | Fix2(f, x) | ||
1122 | |||
1123 | A type representing a partially-applied version of the two-argument function | ||
1124 | `f`, with the second argument fixed to the value "x". In other words, | ||
1125 | `Fix2(f, x)` behaves similarly to `y->f(y, x)`. | ||
1126 | """ | ||
1127 | struct Fix2{F,T} <: Function | ||
1128 | f::F | ||
1129 | x::T | ||
1130 | |||
1131 | Fix2(f::F, x) where {F} = new{F,_stable_typeof(x)}(f, x) | ||
1132 | Fix2(f::Type{F}, x) where {F} = new{Type{F},_stable_typeof(x)}(f, x) | ||
1133 | end | ||
1134 | |||
1135 | (f::Fix2)(y) = f.f(y, f.x) | ||
1136 | |||
1137 | """ | ||
1138 | isequal(x) | ||
1139 | |||
1140 | Create a function that compares its argument to `x` using [`isequal`](@ref), i.e. | ||
1141 | a function equivalent to `y -> isequal(y, x)`. | ||
1142 | |||
1143 | The returned function is of type `Base.Fix2{typeof(isequal)}`, which can be | ||
1144 | used to implement specialized methods. | ||
1145 | """ | ||
1146 | isequal(x) = Fix2(isequal, x) | ||
1147 | |||
1148 | """ | ||
1149 | ==(x) | ||
1150 | |||
1151 | Create a function that compares its argument to `x` using [`==`](@ref), i.e. | ||
1152 | a function equivalent to `y -> y == x`. | ||
1153 | |||
1154 | The returned function is of type `Base.Fix2{typeof(==)}`, which can be | ||
1155 | used to implement specialized methods. | ||
1156 | """ | ||
1157 | ==(x) = Fix2(==, x) | ||
1158 | |||
1159 | """ | ||
1160 | !=(x) | ||
1161 | |||
1162 | Create a function that compares its argument to `x` using [`!=`](@ref), i.e. | ||
1163 | a function equivalent to `y -> y != x`. | ||
1164 | The returned function is of type `Base.Fix2{typeof(!=)}`, which can be | ||
1165 | used to implement specialized methods. | ||
1166 | |||
1167 | !!! compat "Julia 1.2" | ||
1168 | This functionality requires at least Julia 1.2. | ||
1169 | """ | ||
1170 | !=(x) = Fix2(!=, x) | ||
1171 | |||
1172 | """ | ||
1173 | >=(x) | ||
1174 | |||
1175 | Create a function that compares its argument to `x` using [`>=`](@ref), i.e. | ||
1176 | a function equivalent to `y -> y >= x`. | ||
1177 | The returned function is of type `Base.Fix2{typeof(>=)}`, which can be | ||
1178 | used to implement specialized methods. | ||
1179 | |||
1180 | !!! compat "Julia 1.2" | ||
1181 | This functionality requires at least Julia 1.2. | ||
1182 | """ | ||
1183 | >=(x) = Fix2(>=, x) | ||
1184 | |||
1185 | """ | ||
1186 | <=(x) | ||
1187 | |||
1188 | Create a function that compares its argument to `x` using [`<=`](@ref), i.e. | ||
1189 | a function equivalent to `y -> y <= x`. | ||
1190 | The returned function is of type `Base.Fix2{typeof(<=)}`, which can be | ||
1191 | used to implement specialized methods. | ||
1192 | |||
1193 | !!! compat "Julia 1.2" | ||
1194 | This functionality requires at least Julia 1.2. | ||
1195 | """ | ||
1196 | <=(x) = Fix2(<=, x) | ||
1197 | |||
1198 | """ | ||
1199 | >(x) | ||
1200 | |||
1201 | Create a function that compares its argument to `x` using [`>`](@ref), i.e. | ||
1202 | a function equivalent to `y -> y > x`. | ||
1203 | The returned function is of type `Base.Fix2{typeof(>)}`, which can be | ||
1204 | used to implement specialized methods. | ||
1205 | |||
1206 | !!! compat "Julia 1.2" | ||
1207 | This functionality requires at least Julia 1.2. | ||
1208 | """ | ||
1209 | >(x) = Fix2(>, x) | ||
1210 | |||
1211 | """ | ||
1212 | <(x) | ||
1213 | |||
1214 | Create a function that compares its argument to `x` using [`<`](@ref), i.e. | ||
1215 | a function equivalent to `y -> y < x`. | ||
1216 | The returned function is of type `Base.Fix2{typeof(<)}`, which can be | ||
1217 | used to implement specialized methods. | ||
1218 | |||
1219 | !!! compat "Julia 1.2" | ||
1220 | This functionality requires at least Julia 1.2. | ||
1221 | """ | ||
1222 | <(x) = Fix2(<, x) | ||
1223 | |||
1224 | """ | ||
1225 | splat(f) | ||
1226 | |||
1227 | Equivalent to | ||
1228 | ```julia | ||
1229 | my_splat(f) = args->f(args...) | ||
1230 | ``` | ||
1231 | i.e. given a function returns a new function that takes one argument and splats | ||
1232 | it into the original function. This is useful as an adaptor to pass a | ||
1233 | multi-argument function in a context that expects a single argument, but passes | ||
1234 | a tuple as that single argument. | ||
1235 | |||
1236 | # Example usage: | ||
1237 | ```jldoctest | ||
1238 | julia> map(splat(+), zip(1:3,4:6)) | ||
1239 | 3-element Vector{Int64}: | ||
1240 | 5 | ||
1241 | 7 | ||
1242 | 9 | ||
1243 | |||
1244 | julia> my_add = splat(+) | ||
1245 | splat(+) | ||
1246 | |||
1247 | julia> my_add((1,2,3)) | ||
1248 | 6 | ||
1249 | ``` | ||
1250 | """ | ||
1251 | splat(f) = Splat(f) | ||
1252 | |||
1253 | """ | ||
1254 | Base.Splat{F} <: Function | ||
1255 | |||
1256 | Represents a splatted function. That is | ||
1257 | ```julia | ||
1258 | Base.Splat(f)(args) === f(args...) | ||
1259 | ``` | ||
1260 | The preferred way to construct an instance of `Base.Splat` is to use the [`splat`](@ref) function. | ||
1261 | |||
1262 | !!! compat "Julia 1.9" | ||
1263 | Splat requires at least Julia 1.9. In earlier versions `splat` returns an anonymous function instead. | ||
1264 | |||
1265 | See also [`splat`](@ref). | ||
1266 | """ | ||
1267 | struct Splat{F} <: Function | ||
1268 | f::F | ||
1269 | Splat(f) = new{Core.Typeof(f)}(f) | ||
1270 | end | ||
1271 | (s::Splat)(args) = s.f(args...) | ||
1272 | print(io::IO, s::Splat) = print(io, "splat(", s.f, ')') | ||
1273 | show(io::IO, s::Splat) = print(io, s) | ||
1274 | |||
1275 | ## in and related operators | ||
1276 | |||
1277 | """ | ||
1278 | in(collection) | ||
1279 | ∈(collection) | ||
1280 | |||
1281 | Create a function that checks whether its argument is [`in`](@ref) `collection`, i.e. | ||
1282 | a function equivalent to `y -> y in collection`. See also [`insorted`](@ref) for use | ||
1283 | with sorted collections. | ||
1284 | |||
1285 | The returned function is of type `Base.Fix2{typeof(in)}`, which can be | ||
1286 | used to implement specialized methods. | ||
1287 | """ | ||
1288 | in(x) = Fix2(in, x) | ||
1289 | |||
1290 | function in(x, itr) | ||
1291 | anymissing = false | ||
1292 | for y in itr | ||
1293 | v = (y == x) | ||
1294 | if ismissing(v) | ||
1295 | anymissing = true | ||
1296 | elseif v | ||
1297 | return true | ||
1298 | end | ||
1299 | end | ||
1300 | return anymissing ? missing : false | ||
1301 | end | ||
1302 | |||
1303 | const ∈ = in | ||
1304 | ∉(x, itr) = !∈(x, itr) | ||
1305 | ∉(itr) = Fix2(∉, itr) | ||
1306 | |||
1307 | """ | ||
1308 | ∋(collection, item) -> Bool | ||
1309 | |||
1310 | Like [`in`](@ref), but with arguments in reverse order. | ||
1311 | Avoid adding methods to this function; define `in` instead. | ||
1312 | """ | ||
1313 | ∋(itr, x) = in(x, itr) | ||
1314 | |||
1315 | """ | ||
1316 | ∋(item) | ||
1317 | |||
1318 | Create a function that checks whether its argument contains the given `item`, i.e. | ||
1319 | a function equivalent to `y -> item in y`. | ||
1320 | |||
1321 | !!! compat "Julia 1.6" | ||
1322 | This method requires Julia 1.6 or later. | ||
1323 | """ | ||
1324 | ∋(x) = Fix2(∋, x) | ||
1325 | |||
1326 | ∌(itr, x) = !∋(itr, x) | ||
1327 | ∌(x) = Fix2(∌, x) | ||
1328 | |||
1329 | """ | ||
1330 | in(item, collection) -> Bool | ||
1331 | ∈(item, collection) -> Bool | ||
1332 | |||
1333 | Determine whether an item is in the given collection, in the sense that it is | ||
1334 | [`==`](@ref) to one of the values generated by iterating over the collection. | ||
1335 | Return a `Bool` value, except if `item` is [`missing`](@ref) or `collection` | ||
1336 | contains `missing` but not `item`, in which case `missing` is returned | ||
1337 | ([three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic), | ||
1338 | matching the behavior of [`any`](@ref) and [`==`](@ref)). | ||
1339 | |||
1340 | Some collections follow a slightly different definition. For example, | ||
1341 | [`Set`](@ref)s check whether the item [`isequal`](@ref) to one of the elements; | ||
1342 | [`Dict`](@ref)s look for `key=>value` pairs, and the `key` is compared using | ||
1343 | [`isequal`](@ref). | ||
1344 | |||
1345 | To test for the presence of a key in a dictionary, use [`haskey`](@ref) | ||
1346 | or `k in keys(dict)`. For the collections mentioned above, | ||
1347 | the result is always a `Bool`. | ||
1348 | |||
1349 | When broadcasting with `in.(items, collection)` or `items .∈ collection`, both | ||
1350 | `item` and `collection` are broadcasted over, which is often not what is intended. | ||
1351 | For example, if both arguments are vectors (and the dimensions match), the result is | ||
1352 | a vector indicating whether each value in collection `items` is `in` the value at the | ||
1353 | corresponding position in `collection`. To get a vector indicating whether each value | ||
1354 | in `items` is in `collection`, wrap `collection` in a tuple or a `Ref` like this: | ||
1355 | `in.(items, Ref(collection))` or `items .∈ Ref(collection)`. | ||
1356 | |||
1357 | See also: [`∉`](@ref), [`insorted`](@ref), [`contains`](@ref), [`occursin`](@ref), [`issubset`](@ref). | ||
1358 | |||
1359 | # Examples | ||
1360 | ```jldoctest | ||
1361 | julia> a = 1:3:20 | ||
1362 | 1:3:19 | ||
1363 | |||
1364 | julia> 4 in a | ||
1365 | true | ||
1366 | |||
1367 | julia> 5 in a | ||
1368 | false | ||
1369 | |||
1370 | julia> missing in [1, 2] | ||
1371 | missing | ||
1372 | |||
1373 | julia> 1 in [2, missing] | ||
1374 | missing | ||
1375 | |||
1376 | julia> 1 in [1, missing] | ||
1377 | true | ||
1378 | |||
1379 | julia> missing in Set([1, 2]) | ||
1380 | false | ||
1381 | |||
1382 | julia> (1=>missing) in Dict(1=>10, 2=>20) | ||
1383 | missing | ||
1384 | |||
1385 | julia> [1, 2] .∈ [2, 3] | ||
1386 | 2-element BitVector: | ||
1387 | 0 | ||
1388 | 0 | ||
1389 | |||
1390 | julia> [1, 2] .∈ ([2, 3],) | ||
1391 | 2-element BitVector: | ||
1392 | 0 | ||
1393 | 1 | ||
1394 | ``` | ||
1395 | """ | ||
1396 | in | ||
1397 | |||
1398 | """ | ||
1399 | ∉(item, collection) -> Bool | ||
1400 | ∌(collection, item) -> Bool | ||
1401 | |||
1402 | Negation of `∈` and `∋`, i.e. checks that `item` is not in `collection`. | ||
1403 | |||
1404 | When broadcasting with `items .∉ collection`, both `item` and `collection` are | ||
1405 | broadcasted over, which is often not what is intended. For example, if both arguments | ||
1406 | are vectors (and the dimensions match), the result is a vector indicating whether | ||
1407 | each value in collection `items` is not in the value at the corresponding position | ||
1408 | in `collection`. To get a vector indicating whether each value in `items` is not in | ||
1409 | `collection`, wrap `collection` in a tuple or a `Ref` like this: | ||
1410 | `items .∉ Ref(collection)`. | ||
1411 | |||
1412 | # Examples | ||
1413 | ```jldoctest | ||
1414 | julia> 1 ∉ 2:4 | ||
1415 | true | ||
1416 | |||
1417 | julia> 1 ∉ 1:3 | ||
1418 | false | ||
1419 | |||
1420 | julia> [1, 2] .∉ [2, 3] | ||
1421 | 2-element BitVector: | ||
1422 | 1 | ||
1423 | 1 | ||
1424 | |||
1425 | julia> [1, 2] .∉ ([2, 3],) | ||
1426 | 2-element BitVector: | ||
1427 | 1 | ||
1428 | 0 | ||
1429 | ``` | ||
1430 | """ | ||
1431 | ∉, ∌ |