250
250
if VERSION < v " 1.8.0-DEV.487"
251
251
export eachsplit
252
252
253
- """
253
+ @doc """
254
254
eachsplit(str::AbstractString, dlm; limit::Integer=0)
255
255
eachsplit(str::AbstractString; limit::Integer=0)
256
256
@@ -275,7 +275,8 @@ if VERSION < v"1.8.0-DEV.487"
275
275
"Ma"
276
276
"rch"
277
277
```
278
- """
278
+ """ eachsplit
279
+
279
280
function eachsplit end
280
281
281
282
struct SplitIterator{S<: AbstractString ,F}
421
422
return nothing
422
423
end
423
424
424
- """
425
+ @doc """
425
426
pkgversion(m::Module)
426
427
427
428
Return the version of the package that imported module `m`,
433
434
434
435
To get the version of the package that imported the current module
435
436
the form `pkgversion(@__MODULE__)` can be used.
436
- """
437
+ """ pkgversion
438
+
437
439
function pkgversion (m:: Module )
438
440
path = pkgdir (m)
439
441
path === nothing && return nothing
@@ -457,7 +459,7 @@ if VERSION < v"1.9.0-DEV.1163"
457
459
import Base: IteratorSize, HasLength, HasShape, OneTo
458
460
export stack
459
461
460
- """
462
+ @doc """
461
463
stack(iter; [dims])
462
464
463
465
Combine a collection of arrays (or other iterable objects) of equal size
@@ -547,10 +549,11 @@ if VERSION < v"1.9.0-DEV.1163"
547
549
julia> hvcat(5, M...) |> size # hvcat puts matrices next to each other
548
550
(14, 15)
549
551
```
550
- """
552
+ """ stack
553
+
551
554
stack (iter; dims= :) = _stack (dims, iter)
552
555
553
- """
556
+ @doc """
554
557
stack(f, args...; [dims])
555
558
556
559
Apply a function to each element of a collection, and `stack` the result.
@@ -576,7 +579,8 @@ if VERSION < v"1.9.0-DEV.1163"
576
579
1.0 2.0 3.0 10.0 20.0 30.0 0.1 0.2 0.3
577
580
4.0 5.0 6.0 400.0 500.0 600.0 0.04 0.05 0.06
578
581
```
579
- """
582
+ """ stack (f, iter)
583
+
580
584
stack (f, iter; dims= :) = _stack (dims, f (x) for x in iter)
581
585
stack (f, xs, yzs... ; dims= :) = _stack (dims, f (xy... ) for xy in zip (xs, yzs... ))
582
586
@@ -803,6 +807,226 @@ if VERSION < v"1.11.0-DEV.1579"
803
807
Iterators. cycle (xs, n:: Integer ) = Iterators. flatten (Iterators. repeated (xs, n))
804
808
end
805
809
810
+ # https://github.com/JuliaLang/julia/pull/39071
811
+ if ! isdefined (Base, :logrange ) # VERSION < v"1.12.0-DEV.2" or appropriate 1.11.x after backporting
812
+
813
+ export logrange
814
+
815
+ @doc """
816
+ logrange(start, stop, length)
817
+ logrange(start, stop; length)
818
+
819
+ Construct a specialized array whose elements are spaced logarithmically
820
+ between the given endpoints. That is, the ratio of successive elements is
821
+ a constant, calculated from the length.
822
+
823
+ This is similar to `geomspace` in Python. Unlike `PowerRange` in Mathematica,
824
+ you specify the number of elements not the ratio.
825
+ Unlike `logspace` in Python and Matlab, the `start` and `stop` arguments are
826
+ always the first and last elements of the result, not powers applied to some base.
827
+
828
+ # Examples
829
+ ```
830
+ julia> logrange(10, 4000, length=3)
831
+ 3-element Base.LogRange{Float64, Base.TwicePrecision{Float64}}:
832
+ 10.0, 200.0, 4000.0
833
+
834
+ julia> ans[2] ≈ sqrt(10 * 4000) # middle element is the geometric mean
835
+ true
836
+
837
+ julia> range(10, 40, length=3)[2] ≈ (10 + 40)/2 # arithmetic mean
838
+ true
839
+
840
+ julia> logrange(1f0, 32f0, 11)
841
+ 11-element Base.LogRange{Float32, Float64}:
842
+ 1.0, 1.41421, 2.0, 2.82843, 4.0, 5.65685, 8.0, 11.3137, 16.0, 22.6274, 32.0
843
+
844
+ julia> logrange(1, 1000, length=4) ≈ 10 .^ (0:3)
845
+ true
846
+ ```
847
+
848
+ See the [`Compat.LogRange`](@ref Compat.LogRange) type for further details.
849
+
850
+ !!! compat "Julia 1.9"
851
+ The version of this struct in Compat.jl does not use `Base.TwicePrecision{Float64}`
852
+ before Julia 1.9, so it sometimes has larger floating-point errors on intermediate points.
853
+
854
+ !!! compat "Julia 1.11"
855
+ The printing of Compat.jl's version of the struct is also different,
856
+ less like `LinRange` and more like `Vector`.
857
+ """ logrange
858
+
859
+ logrange (start:: Real , stop:: Real , length:: Integer ) = LogRange (start, stop, Int (length))
860
+ logrange (start:: Real , stop:: Real ; length:: Integer ) = logrange (start, stop, length)
861
+
862
+ @doc """
863
+ LogRange{T}(start, stop, len) <: AbstractVector{T}
864
+
865
+ A range whose elements are spaced logarithmically between `start` and `stop`,
866
+ with spacing controlled by `len`. Returned by [`logrange`](@ref).
867
+
868
+ Like [`LinRange`](@ref), the first and last elements will be exactly those
869
+ provided, but intermediate values may have small floating-point errors.
870
+ These are calculated using the logs of the endpoints, which are
871
+ stored on construction, often in higher precision than `T`.
872
+
873
+ !!! compat "Julia 1.9"
874
+ The version of this struct in Compat.jl does not use `Base.TwicePrecision{Float64}`
875
+ before Julia 1.9. Therefore it has larger floating-point errors on intermediate
876
+ points than shown below.
877
+
878
+ !!! compat "Julia 1.11"
879
+ The printing of Compat.jl's version of the struct is also different,
880
+ less like `LinRange` and more like `Vector`.
881
+
882
+ # Examples
883
+ ```
884
+ julia> logrange(1, 4, length=5)
885
+ 5-element Base.LogRange{Float64, Base.TwicePrecision{Float64}}:
886
+ 1.0, 1.41421, 2.0, 2.82843, 4.0
887
+
888
+ julia> Base.LogRange{Float16}(1, 4, 5)
889
+ 5-element Base.LogRange{Float16, Float64}:
890
+ 1.0, 1.414, 2.0, 2.828, 4.0
891
+
892
+ julia> logrange(1e-310, 1e-300, 11)[1:2:end]
893
+ 6-element Vector{Float64}:
894
+ 1.0e-310
895
+ 9.999999999999974e-309
896
+ 9.999999999999981e-307
897
+ 9.999999999999988e-305
898
+ 9.999999999999994e-303
899
+ 1.0e-300
900
+
901
+ julia> prevfloat(1e-308, 5) == ans[2]
902
+ true
903
+ ```
904
+
905
+ Note that integer eltype `T` is not allowed.
906
+ Use for instance `round.(Int, xs)`, or explicit powers of some integer base:
907
+
908
+ ```
909
+ julia> xs = logrange(1, 512, 4)
910
+ 4-element Base.LogRange{Float64, Base.TwicePrecision{Float64}}:
911
+ 1.0, 8.0, 64.0, 512.0
912
+
913
+ julia> 2 .^ (0:3:9) |> println
914
+ [1, 8, 64, 512]
915
+ ```
916
+ """ LogRange
917
+
918
+ struct LogRange{T<: Real ,X} <: AbstractArray{T,1}
919
+ start:: T
920
+ stop:: T
921
+ len:: Int
922
+ extra:: Tuple{X,X}
923
+ function LogRange {T} (start:: T , stop:: T , len:: Int ) where {T<: Real }
924
+ if T <: Integer
925
+ # LogRange{Int}(1, 512, 4) produces InexactError: Int64(7.999999999999998)
926
+ throw (ArgumentError (" LogRange{T} does not support integer types" ))
927
+ end
928
+ if iszero (start) || iszero (stop)
929
+ throw (DomainError ((start, stop),
930
+ " LogRange cannot start or stop at zero" ))
931
+ elseif start < 0 || stop < 0
932
+ # log would throw, but _log_twice64_unchecked does not
933
+ throw (DomainError ((start, stop),
934
+ " LogRange does not accept negative numbers" ))
935
+ elseif ! isfinite (start) || ! isfinite (stop)
936
+ throw (DomainError ((start, stop),
937
+ " LogRange is only defined for finite start & stop" ))
938
+ elseif len < 0
939
+ throw (ArgumentError (string ( # LazyString(
940
+ " LogRange(" , start, " , " , stop, " , " , len, " ): can't have negative length" )))
941
+ elseif len == 1 && start != stop
942
+ throw (ArgumentError (string ( # LazyString(
943
+ " LogRange(" , start, " , " , stop, " , " , len, " ): endpoints differ, while length is 1" )))
944
+ end
945
+ ex = _logrange_extra (start, stop, len)
946
+ new {T,typeof(ex[1])} (start, stop, len, ex)
947
+ end
948
+ end
949
+
950
+ function LogRange {T} (start:: Real , stop:: Real , len:: Integer ) where {T}
951
+ LogRange {T} (convert (T, start), convert (T, stop), convert (Int, len))
952
+ end
953
+ function LogRange (start:: Real , stop:: Real , len:: Integer )
954
+ T = float (promote_type (typeof (start), typeof (stop)))
955
+ LogRange {T} (convert (T, start), convert (T, stop), convert (Int, len))
956
+ end
957
+
958
+ Base. size (r:: LogRange ) = (r. len,)
959
+ Base. length (r:: LogRange ) = r. len
960
+
961
+ Base. first (r:: LogRange ) = r. start
962
+ Base. last (r:: LogRange ) = r. stop
963
+
964
+ function _logrange_extra (a:: Real , b:: Real , len:: Int )
965
+ loga = log (1.0 * a) # widen to at least Float64
966
+ logb = log (1.0 * b)
967
+ (loga/ (len- 1 ), logb/ (len- 1 ))
968
+ end
969
+
970
+ function Base. getindex (r:: LogRange{T} , i:: Int ) where {T}
971
+ @inline
972
+ @boundscheck checkbounds (r, i)
973
+ i == 1 && return r. start
974
+ i == r. len && return r. stop
975
+ # Main path uses Math.exp_impl for TwicePrecision, but is not perfectly
976
+ # accurate, hence the special cases for endpoints above.
977
+ logx = (r. len- i) * r. extra[1 ] + (i- 1 ) * r. extra[2 ]
978
+ x = _exp_allowing_twice64 (logx)
979
+ return copysign (T (x), r. start)
980
+ end
981
+
982
+ function Base. show (io:: IO , r:: LogRange{T} ) where {T}
983
+ print (io, " LogRange{" , T, " }(" )
984
+ ioc = IOContext (io, :typeinfo => T)
985
+ show (ioc, first (r))
986
+ print (io, " , " )
987
+ show (ioc, last (r))
988
+ print (io, " , " )
989
+ show (io, length (r))
990
+ print (io, ' )' )
991
+ end
992
+
993
+ # Display LogRange like LinRange -- PR widened signature of print_range to allow this
994
+ # function Base.show(io::IO, ::MIME"text/plain", r::LogRange)
995
+ # isempty(r) && return show(io, r)
996
+ # summary(io, r)
997
+ # println(io, ":")
998
+ # print_range(io, r, " ", ", ", "", " \u2026 ")
999
+ # end
1000
+
1001
+ _exp_allowing_twice64 (x:: Number ) = exp (x)
1002
+
1003
+ if VERSION >= v " 1.9.0-DEV.318" # Julia PR #44717 allows this high-precision path:
1004
+
1005
+ _exp_allowing_twice64 (x:: Base.TwicePrecision{Float64} ) = Base. Math. exp_impl (x. hi, x. lo, Val (:ℯ ))
1006
+
1007
+ function _log_twice64_unchecked (x:: Float64 )
1008
+ xu = reinterpret (UInt64, x)
1009
+ if xu < (UInt64 (1 )<< 52 ) # x is subnormal
1010
+ xu = reinterpret (UInt64, x * 0x1 p52) # normalize x
1011
+ xu &= ~ Base. sign_mask (Float64)
1012
+ xu -= UInt64 (52 ) << 52 # mess with the exponent
1013
+ end
1014
+ Base. TwicePrecision (Base. Math. _log_ext (xu)... )
1015
+ end
1016
+
1017
+ function _logrange_extra (a:: Float64 , b:: Float64 , len:: Int )
1018
+ loga = _log_twice64_unchecked (a)
1019
+ logb = _log_twice64_unchecked (b)
1020
+ # The reason not to do linear interpolation on log(a)..log(b) in `getindex` is
1021
+ # that division of TwicePrecision is quite slow, so do it once on construction:
1022
+ (loga/ (len- 1 ), logb/ (len- 1 ))
1023
+ end
1024
+ end
1025
+ else
1026
+ # Ensure that Compat.LogRange is always this struct, not exported from Base
1027
+ using Base: LogRange
1028
+ end
1029
+
806
1030
include (" deprecated.jl" )
807
1031
808
1032
end # module Compat
0 commit comments