Manual
The MicroFloatingPoints
module
The central element of the MicroFloatingPoints
package is the floating-point type Floatmu
; it is parameterized by the sizes of the exponent field and the fractional part field.
MicroFloatingPoints.Floatmu
— TypeFloatmu{szE,szf} <: AbstractFloat
IEEE 754-compliant floating-point number with szE
bits for the exponent and szf
bits for the fractional part.
A Floatmu
object must always have a precision smaller or equal to that of a single precision float. As a consequence, the following constraints hold:
\[\left\{\begin{array}{l} \text{szE}\in[2,8]\\ \text{szf}\in[2,23] \end{array}\right.\]
Examples
Creating a Floatmu
type equivalent to Float32
:
julia> MyFloat32 = Floatmu{8,23}
Floatmu{8, 23}
julia> a=MyFloat32(0.1)
0.1
julia> a == 0.1f0
true
Creating a Floatmu
float
A Floatmu
object may be created from a float from a standard floating-point type (Float16
, Float32
, Float64
).
julia> Floatmu{8,23}(Float16(0.1))
0.099975586
julia> Floatmu{8,23}(0.1f0)
0.1
julia> Floatmu{8,23}(0.1)
0.1
Note that, depending on the value and the size of the Floatmu
type, some rounding may occur.
julia> Floatmu{2,2}(0.1f0)
0.0
julia> Floatmu{8,7}(0.1f0)
0.1
Each Floatmu
object retains the sign of the error due to rounding the value used to create it. That sign may be obtained with the method errorsign
. If one is only interested in obtaining a boolean to know whether some rounding took place or not, one can use the isinexact
method instead.
MicroFloatingPoints.errorsign
— Methoderrorsign(x::Floatmu{szE,szf}) where {szE,szf}
Return 1
if x
was rounded by excess when created as a Floatmu{szE,szf}
, -1
if it was rounded by default, and 0
if no rounding took place.
An NaN is never in error. An infinite is in error only if created from a finite value.
See
Examples
julia> errorsign(Floatmu{2, 2}(0.5))
0
julia> errorsign(Floatmu{2, 2}(1.7))
1
julia> errorsign(Floatmu{2, 2}(-2.8))
-1
MicroFloatingPoints.isinexact
— Methodisinexact(x::Floatmu{szE,szf}) where {szE,szf}
Return true
if the value x
was rounded when created as a Floatmu{szE,szf}
and false
otherwise.
An NaN is never inexact. An infinite is inexact only if created from a finite value.
See:
Examples
julia> isinexact(Floatmu{2, 2}(0.25)+Floatmu{2, 2}(2.0))
true
julia> isinexact(Floatmu{2, 2}(0.25)+Floatmu{2, 2}(1.5))
false
Be wary of the fact that a Floatmu
object is completely oblivious to rounding that may have occurred before the call of its constructor.
julia> isinexact(Floatmu{8,23}(Float16(0.1)))
false
In the preceding example, no rounding is reported even though 0.1
is not representable in binary because the Floatmu
is created from a Float16
approximation of it and a Floatmu{8,23}
object has more precision than a Float16
. The rounding that took place when creating the Float16
in the first place goes unreported.
It is also possible to create a Floatmu
float from an integer of the type Int64
:
julia> Floatmu{8,7}(10)
10.0
Due to the limited precision of the Floatmu
type, some rounding may still occur:
julia> Floatmu{8,7}(303)
304.0
It is possible to know the largest positive integer such that all smaller integers are represented without rounding using the Base.maxintfloat
method:
julia> maxintfloat(Floatmu{8,7})
256.0
julia> Floatmu{8,7}(257)
256.0
Lastly, a Floatmu
may be created from another Floatmu
with the same or a different precision and range.
julia> Floatmu{5,10}(0.1)==Floatmu{8,7}(Floatmu{5,10}(0.1))
false
Characteristics of a Floatmu
It is possible to obtain some characteristics of a Floatmu
type by using standard Julia methods. Most of them are usually undocumented, being internal to the Base
package. Since the intended audience for the MicroFloatingPoints
package is probably more interested in these methods than the general public, we document them here.
The Base.precision()
method returns the number of bits in the significand:
julia> Base.precision(Floatmu{8,23})
24
The Base.exponent_max
and Base.exponent_raw_max
return, respectively, the maximum unbiased exponent and the maximum biased exponent.
julia> Base.exponent_max(Floatmu{8,23})
127
julia> Base.exponent_raw_max(Floatmu{8,23})
255
Some other methods in the MicroFloatingPoints
package are related to the exponent of a Floatmu
:
MicroFloatingPoints.Emax
— MethodEmax(::Type{Floatmu{szE,szf}}) where {szE, szf}
Maximum unbiased exponent for a Floatmu{szE,szf}
returned as an UInt32
.
See: exponent_max
, exponent_raw_max
, Emin
Examples
julia> Emax(Floatmu{8, 23})
0x0000007f
MicroFloatingPoints.Emin
— MethodEmin(::Type{Floatmu{szE,szf}}) where {szE, szf}
Minimum unbiased exponent for a Floatmu{szE,szf}
returned as an Int32
.
See: exponent_max
, exponent_raw_max
, Emax
Examples
julia> Emin(Floatmu{8, 23})
-126
MicroFloatingPoints.bias
— Methodbias(::Type{Floatmu{szE,szf}}) where {szE, szf}
Bias of the exponent for a Floatmu{szE,szf}
.
Examples
julia> bias(Floatmu{8, 23})
0x0000007f
Other methods return remarkable values for the type:
MicroFloatingPoints.Infμ
— MethodInfμ(::Type{Floatmu{szE,szf}}) where {szE,szf}
Positive infinite value in the format Floatmu{szE,szf}
.
Examples
julia> Infμ(Floatmu{8, 23}) == Inf32
true
MicroFloatingPoints.NaNμ
— MethodNaNμ(::Type{Floatmu{szE,szf}}) where {szE, szf}
NaN in the format Floatmu{szE,szf}
.
The canonical NaN value has a sign bit set to zero and all bits of the fractional part set to zero except for the leftmost one.
Examples
julia> isnan(NaNμ(Floatmu{2, 2}))
true
julia> NaNμ(Floatmu{2, 2})
NaNμ{2, 2}
Base.Math.ldexp
— Methodldexp(x::Floatmu{szE,szf}, n::Integer) where {szE, szf}
Return $x \times 2^n$.
This is a quick-and-dirty implementation.
Examples
julia> ldexp(Floatmu{5,3}(2.5),3)
20.0
Base.eps
— Methodeps(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return the epsilon of the type Floatmu{szE,szf}
, which is the difference between 1.0 and the next float.
Examples
julia> eps(Floatmu{2, 2})
0.25
julia> eps(Floatmu{3, 5})
0.031
julia> eps(Floatmu{8, 23})==eps(Float32)
true
MicroFloatingPoints.λ
— Methodλ(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return λ, the smallest positive normal number of the type Floatmu{szE,szf}
.
Examples
julia> λ(Floatmu{2, 2})
1.0
julia> λ(Floatmu{8, 23})==floatmin(Float32)
true
MicroFloatingPoints.μ
— Methodμ(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return μ, the smallest positive subnormal number of type Floatmu{szE,szf}
.
Examples
julia> μ(Floatmu{2, 2})
0.25
Base.sign
— Methodsign(x::Floatmu{szE,szf}) where {szE, szf}
Return x
if x
is zero, 1.0 if x
is strictly positive and -1.0 if x
is strictly negative. Return NaN
if x is a Not a Number.
Examples
julia> sign(Floatmu{2, 3}(-1.6))
-1.0
julia> sign(Floatmu{2, 3}(1.6))
1.0
julia> sign(Floatmu{2, 3}(NaN))
NaNμ{2, 3}
julia> sign(Floatmu{2, 3}(-0.0))
-0.0
Base.floatmax
— Methodfloatmax(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return the largest positive normal number of the type Floatmu{szE,szf}
.
Examples
julia> floatmax(Floatmu{2, 2})
3.5
julia> floatmax(Floatmu{8, 23})==floatmax(Float32)
true
Base.floatmin
— Methodfloatmin(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return λ, the smallest positive normal number of the type Floatmu{szE,szf}
.
Examples
julia> floatmin(Floatmu{2, 2})
1.0
julia> floatmin(Floatmu{8, 23})==floatmin(Float32)
true
Base.typemin
— Methodtypemin(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return the negative infinite of the type Floatmu{szE,szf}
.
Examples
julia> typemin(Floatmu{3, 5})
-Infμ{3, 5}
Base.typemax
— Methodtypemax(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return the positive infinite of the type Floatmu{szE,szf}
.
Examples
julia> typemax(Floatmu{3, 5})
Infμ{3, 5}
Base.maxintfloat
— Methodmaxintfloat(::Type{Floatmu{szE,szf}}) where {szE,szf}
Return the smallest positive integer $n$ such that $n+1$ is not representable in the type Floatmu{szE,szf}
. The number $n$ is returned as a Floatmu{szE,szf}
.
The function returns an infinite value if all integers are representable in the domain of normal values.
Examples
julia> maxintfloat(Floatmu{3,2})
8.0
julia> maxintfloat(Floatmu{2,2})
Infμ{2, 2}
julia> maxintfloat(Floatmu{8,23})==maxintfloat(Float32)
true
Lastly, some methods test properties on the different parts of a Floatmu
:
MicroFloatingPoints.fractional_even
— Methodfractional_even(x::Floatmu{szE,szf}) where {szE,szf}
Return true
if the fractional part of x
has a zero as the rightmost bit.
BEWARE: the function does not check whether x
is an NaN or an infinite value.
Tests
Base.signbit
— Methodsignbit(x::Floatmu{szE,szf}) where {szE, szf}
Return true
if x
is signed and false
otherwise. The result for a NaN may vary, depending on the value of its sign bit.
Examples
julia> signbit(Floatmu{2, 3}(1.5))
false
julia> signbit(Floatmu{2, 3}(-1.5))
true
The function differentiates between $-0.0$ and $+0.0$ even though both values test equal.
julia> signbit(Floatmu{2, 3}(-0.0))
true
julia> signbit(Floatmu{2, 3}(0.0))
false
Base.isnan
— Methodisnan(x::Floatmu{szE,szf}) where {szE,szf}
Return true
if x
is a Not an Number and false
otherwise.
Examples
julia> isnan(Floatmu{2, 3}(1.5))
false
julia> isnan(Floatmu{2, 3}(NaN))
true
Base.isinf
— Methodisinf(x::Floatmu{szE,szf}) where {szE,szf}
Return true
if x
is an infinity and false
otherwise.
Examples
julia> isinf(Floatmu{2, 2}(1.5))
false
julia> isinf(Floatmu{2, 2}(-Inf))
true
julia> isinf(Floatmu{2, 2}(9.8))
true
Base.isfinite
— Methodisfinite(x::Floatmu{szE,szf}) where {szE,szf}
Return true
if x
is finite and false
otherwise. An NaN is not finite.
Examples
julia> isfinite(Floatmu{2, 2}(1.5))
true
julia> isfinite(Floatmu{2, 2}(3.8))
false
julia> isfinite(Floatmu{2, 2}(NaN))
false
Base.issubnormal
— Methodissubnormal(x::Floatmu{szE,szf}) where {szE,szf}
Return true
if x
is a subnormal number and false
otherwise. According to the definition, ±0.0 is not a subnormal number.
Examples
julia> issubnormal(Floatmu{2, 2}(1.0))
false
julia> issubnormal(Floatmu{2, 2}(0.25))
true
julia> issubnormal(Floatmu{2, 2}(0.0))
false
Conversions
A Floatmu
may be converted from and to any of the standard floating-point type (Float16
, Float32
, Float64
).
Base.convert
— Functionconvert(::Type{Float64}, x::Floatmu{szE,szf}) where {szE, szf}
convert(::Type{Float32}, x::Floatmu{szE,szf}) where {szE, szf}
convert(::Type{Float16}, x::Floatmu{szE,szf}) where {szE, szf}
convert(::Type{Floatmu{szE,szf} where {szE,szf}}, x::Float64)
convert(::Type{Floatmu{szE,szf} where {szE,szf}}, x::Float32)
convert(::Type{Floatmu{szE,szf} where {szE,szf}}, x::Float16)
Convert a Floatmu
to a double, single or half precision float, or vice-versa. For the double precision, the conversion never introduces errors since Float64
objects have at least twice the precision of the fractional part of a Floatmu
object.
Examples
julia> convert(Float64,Floatmu{8, 23}(0.1))
0.10000000149011612
julia> convert(Float32,Floatmu{8, 23}(0.1)) == 0.1f0
true
julia> convert(Float32,Floatmu{5, 10}(0.1)) == Float16(0.1)
true
julia> convert(Floatmu{2, 4},0.1)
0.12
julia> convert(Floatmu{2, 4},0.1f0)
0.12
julia> convert(Floatmu{2, 4},Float16(0.1))
0.12
julia> Floatmu{5, 10}(0.1)==Float16(0.1)
true
A Floatmu
may also be created from a string:
Base.parse
— Methodparse(::Type{Floatmu{szE,szf}}, str::AbstractString) where {szE, szf}
Parse the string str
representing a floating-point number and convert it to a Floatmu{szE,szf}
object.
Examples
julia> parse(Floatmu{5, 7},"0.1")
0.1
julia> parse(Floatmu{5, 7},"1.0e10")
Infμ{5, 7}
The string is first converted to a Float64
and then rounded to the precision of the Floatmu
object. If the string cannot be converted to a Float64
, the ArgumentError
exception is thrown.
Examples
julia> parse(Floatmu{5, 7},"0.1a")
ERROR: ArgumentError: cannot parse "0.1a" as a Floatmu{5, 7}
Base.tryparse
— Methodtryparse(::Type{Floatmu{szE,szf}}, str::AbstractString) where {szE, szf}
Parse the string str
representing a floating-point number and convert it to a Floatmu{szE,szf}
object.
Examples
julia> tryparse(Floatmu{5, 7},"0.1")
0.1
julia> tryparse(Floatmu{5, 7},"1.0e10")
Infμ{5, 7}
The string is first converted to a Float64
and then rounded to the precision of the Floatmu
object. Contrary to parse
, if the string cannot be converted to a Float64
, the value nothing
is returned.
Examples
julia> tryparse(Floatmu{5, 7},"0.1a") == nothing
true
Display
Contrary to a Float16
or a Float32
, which are displayed by default with an indication of their type, a Floatmu
is displayed as a number alone with no indication of its type (much like a Float64
).
julia> Floatmu{2,2}(0.25)
0.25
It is also possible to display the internal representation of a Floatmu{szE,szf}
as an $1+\text{szE}+\text{szf}$ bit string:
Base.bitstring
— Methodbitstring(x::Floatmu{szE,szf}) where {szE,szf}
Return the string of bits representing internally the value x
.
Examples
julia> bitstring(Floatmu{2, 2}(1.5))
"00110"
julia> bitstring(Floatmu{2, 2}(0.5))
"00010"
julia> bitstring(Floatmu{8, 23}(0.1))==bitstring(0.1f0)
true
julia> bitstring(Floatmu{8, 23}(Inf)) == bitstring(Inf32)
true
Iterating through floats
As for the standard floating-point types, it is possible to go from one Floatmu
to the next using nextfloat
and prevfloat
.
Base.prevfloat
— Methodprevfloat(x::Floatmu{szE,szf}, n::UInt32 = 1) where {szE,szf}
Return the Floatmu{szE,szf}
float that is n
floats before x
in the natural order of floats. Return NaNμ{szE,szf}
if x
is Not a Number. Return -Infμ{szE,szf}
if there are less than n
finite floats before x
on the real line.
Examples
julia> prevfloat(Floatmu{2, 2}(1.0),2)
0.5
julia> prevfloat(Floatmu{2, 2}(-0.0))
-0.25
julia> prevfloat(Floatmu{2, 2}(Inf))
3.5
julia> prevfloat(Floatmu{2, 2}(0.25))
0.0
Base.nextfloat
— Methodnextfloat(x::Floatmu{szE,szf}, n::UInt32 = 1) where {szE,szf}
Return the Floatmu{szE,szf}
float that is n
floats after x
in the natural order of floats. Return NaNμ{szE,szf}
if x
is Not a Number. Return Infμ{szE,szf}
if there are less than n
finite floats after x
on the real line.
Examples
julia> nextfloat(Floatmu{2, 2}(3.5))
Infμ{2, 2}
julia> nextfloat(Floatmu{2, 2}(0.0),3)
0.75
julia> nextfloat(Floatmu{2, 2}(-Inf))
-3.5
julia> nextfloat(Floatmu{2, 2}(-0.25))
-0.0
A FloatmuIterator
allows to iterate on a range of Floatmu
in a more systematic way:
MicroFloatingPoints.FloatmuIterator
— TypeFloatmuIterator(start::Floatmu{szE,szf},stop::Floatmu{szE,szf},
step::Floatmu{szE,szf}) where {szE,szf}
FloatmuIterator(start::Floatmu{szE,szf},stop::Floatmu{szE,szf},
step::Float64) where {szE,szf}
FloatmuIterator(start::Floatmu{szE,szf},stop::Floatmu{szE,szf},
step::Int = 1) where {szE,szf}
FloatmuIterator(::Type{Floatmu{szE,szf}},start::Float64,stop::Float64,
step::Int = 1) where {szE,szf}
FloatmuIterator(::Type{Floatmu{szE,szf}},start::Float64,stop::Float64,
step::Float64) where {szE,szf}
Iterator to generate all Floatmu{szE,szf}
in the domain [start,stop]
. The iterator can be initialized with two Floatmu{szE,szf}
or with two Float64
.
One may iterate from one float to the next (the default) or choose some step. The step may be a number of floats or an amount to add.
An ArgumentError is raised if the bounds are NaNs, if the step chosen is zero (or rounds to zero when converted to a Floatmu{szE,szf}
), or if the step is a value smaller than the largest distance between two consecutive floats in [last, stop]
(use eligible_step
to know the smallest value allowed).
When the step is an amount to add, the bounds cannot be infinities.
When the step is a number of floats, infinities are allowed for the bounds and are always part of the resulting range:
julia> collect(FloatmuIterator(Floatmu{2,2},-Inf,Inf,5))
6-element Vector{Floatmu{2, 2}}:
-Infμ{2, 2}
-1.8
-0.5
0.75
2.0
Infμ{2, 2}
Examples
julia> L=[x for x = FloatmuIterator(Floatmu{2, 2}(0.0), Floatmu{2, 2}(1.0))]
5-element Vector{Floatmu{2, 2}}:
0.0
0.25
0.5
0.75
1.0
julia> L2=[x for x = FloatmuIterator(Floatmu{2, 2}, 0.0, 1.0, 2)]
3-element Vector{Floatmu{2, 2}}:
0.0
0.5
1.0
Keep in mind that the bounds of the iterator may need rounding when converted to a Floatmu
, so that the number of iterations may not be the one expected. Additionnally, the step chosen may induce more rounding at each iteration.
Example
julia> [x for x in FloatmuIterator(Floatmu{2,2},-1.2,-0.2,0.3)]
4-element Vector{Floatmu{2,2}}:
-1.25
-1.0
-0.75
-0.5
julia> FloatmuIterator(Floatmu{2,2},-1.2,-0.2,0.3)
FloatmuIterator{2,2}(-1.25, -0.25, 0.25)
It is possible to know in advance the number of floats in the resulting range with the length
function.
As stated in the documentation for FloatmuIterator
above, one cannot use a floating-point step smaller than the largest gap in the domain we iterate through. The function eligible_step
gives the smallest value allowed when given two bounds.
MicroFloatingPoints.eligible_step
— Functioneligible_step(start::Floatmu{szE,szf}, stop::Floatmu{szE,szf}) where {szE,szf}
eligible_step(::Type{Floatmu{szE,szf}}, start::Float64, stop::Float64) where {szE,szf}
Return the smallest Floatmu{szE,szf}
eligible step allowed to iterate through the domain [start,stop]
.
Examples
julia> eligible_step(Floatmu{2,2}(-0.5),Floatmu{2,2}(2.5))
0.5
Rounding
We have seen in section Creating a Floatmu
float that each Floatmu
retains the information whether the value it was created from required rounding or not.
In addition to that mechanism, the MicroFloatingPoints
module keeps a global state that is set to true
every time a Floatmu
is created and rounding takes place. It has a sticky behavior (once true, it stays true until reset explictly to false
). It can be checked with the inexact()
method and reset with the reset_inexact()
method.
MicroFloatingPoints.inexact
— Methodinexact()
Return the value of the inexact flag. Each task possesses its own copy of the variable.
See also reset_inexact
.
MicroFloatingPoints.reset_inexact
— Methodreset_inexact()
Reset the inexact flag to false
. Each task possesses its own copy of the variable.
See also inexact
.
With these methods, one can check whether some computation needed rounding at some point:
julia> reset_inexact()
julia> inexact()
false
julia> Floatmu{2,2}(2.0)+Floatmu{2,2}(0.25)
2.0
julia> inexact()
true
julia> reset_inexact()
julia> Floatmu{2,2}(2.0)+Floatmu{2,2}(0.25)+Floatmu{2,2}(0.25)
2.0
julia> inexact()
true
Note that, in the first example, the result of the computation needed rounding, while in the second example, the output is representable but one of the intermediary computation needed rounding.
The MicroFloatingPoints.MFPUtils
module
The MicroFloatingPoints.MFPUtils
module offers some utiliy functions to be used either by other modules of the MicroFloatingPoints
package or directly by the end user.
MicroFloatingPoints.MFPUtils.vertical_popcount
— Methodvertical_popcount(T::Vector{Floatmu{szE,szf}}) where {szE,szf}
Return a vector R
of size 1+szE+szf
where R[i]
is the number of times the i
-th bit of the values in T
was equal to 1
.
For this function, the rightmost bit of the binary representation of a Floatmu
has index 1
and not 0
as usual.
Examples
julia> join(string.(reverse(vertical_popcount(Floatmu{2,2}[1.5])))) == bitstring(Floatmu{2,2}(1.5))
true
Note that, in the preceding example, we have to revert the array obtained from vertical_popcount
because the number of times bit i
is 1
is saved at position i
. As a consequence, the value for the rightmost bit of a Floatmu
appears at the leftmost position of the counting array.
julia> println(vertical_popcount(Floatmu{2,2}[0.25,1.5,3.0]))
[1, 2, 1, 1, 0]
The MicroFloatingPoints.MFPRandom
module
The MicroFloatingPoints.MFPRandom
module overloads rand
to offer Floatmu
floating-point numbers drawn at random in $[0,1)$. The method uses Random.rand
under the hood. It is then affected in the same way by Random.seed!
.
julia> Random.seed!(42);
julia> rand(Floatmu{2,2})
0.5
julia> rand(Floatmu{2,2})
0.25
It is possible to draw Floatmu
values at random in the same way as with other floating-point types:
julia> rand(Floatmu{2,2},5)
5-element Vector{Floatmu{2, 2}}:
0.25
0.5
0.5
0.0
0.5
Using the Distributions
package, one can also draw Floatmu
numbers with other distributions:
julia> rand(Uniform(Floatmu{2,2}(-1.0),Floatmu{2,2}(1.0)))
0.25
One must be wary of very small Floatmu
types when using other distributions than $U[0,1)$ as the computation necessary to compute another distribution may easily involve larger numbers than can be represented with the type. Consider, for example, the type Floatmu{2,2}
whose largest positive finite value is 3.0
. If we decide to draw numbers in the domain $[-2,2)$, we will call:
rand(Uniform(Floatmu{2,2}(-2.0),Floatmu{2,2}(2.0)))
To translate the distribution from $[0,1)$ to $[-2,2)$, the Uniform
method will draw a value $x$ in $[0,1)$ and apply the formula $a+(b-a)x$, with $a=-2$ and $b=2$. Unfortunately, $b-a$ will then be $\text{Floatmu\{2,2\}}(2.0)-\text{Floatmu}\{2,2\}(-2.0)$, which is rounded to Infμ{2,2}
. Consequently, we will always draw the same infinite value:
julia> rand(Uniform(Floatmu{2,2}(-2.0),Floatmu{2,2}(2.0)))
Infμ{2, 2}
julia> rand(Uniform(Floatmu{2,2}(-2.0),Floatmu{2,2}(2.0)))
Infμ{2, 2}
The MicroFloatingPoints.MFPPlot
module
The MicroFloatingPoints.MFPPlot
module offers some methods to easily represent floating-point numbers. It currently supports both PyPlot
and PythonPlot
backends, one of which must be loaded. To use PythonPlot
, replace references to PyPlot
with PythonPlot
below and create the following alias for plt
.
const plt = PythonCall.pyplot
MicroFloatingPoints.MFPPlot.real_line
— Functionreal_line(start::Floatmu{szE,szf}, stop::Floatmu{szE,szf};
ticks = true,
fpcolorsub = "purple", fpcolornorm = "blue") where {szE,szf}
real_line(::Type{Floatmu{szE,szf}};
ticks = true,
fpcolorsub = "purple", fpcolornorm = "blue",
fpcolorinf="orange") where {szE,szf}
real_line(T::Vector{Floatmu{szE,szf}};
ticks = true, fpcolorsub = "purple", fpcolornorm = "blue",
fpcolorinf="orange") where {szE,szf}
Draw floats on the real line.
The first version draws the real line between start
and stop
and displays all floating-point numbers with sze
bits exponent and szf
bits fractional part. The second version draws all finite floating-point for the format Floatmu{szE,szf}
and adds the infinities where the next/previous float would be with the format Floatmu{szE+1,szf}
. The third version draws all floats in the vector T
.
In the first version, both parameters start
and stop
must be finite. An ArgumentError
exception is raised otherwise. The same goes for all values in T
for the third version.
All versions return the figure used for the plot.
The figure may be customized through the named parameters:
ticks
: iftrue
, draws a vertical line for each float and adds the value below. Iffalse
, represent each float by a dot on the real line, without its value;fpcolorsub
: color of the line or dot used to represent subnormals;fpcolornorm
: color of the line or dot used to represent normal values;fpcolorinf
[for the second version only]: color of the line or dot used to represent infinite values.
Examples of calls
real_line(-floatmax(Floatmu{2,2}),floatmax(Floatmu{2,2}));
real_line(Floatmu{2,2});
real_line(Floatmu{2,2}[-3.5,0.25,1.5,2.0])
Examples
julia> real_line(Floatmu{2,3}(-2.5),Floatmu{2,3}(1.0));
julia> real_line(Floatmu{2,3});
MicroFloatingPoints.MFPPlot.bits_histogram
— Functionbits_histogram(T::Vector{Floatmu{szE,szf}};
signcolor = "magenta",
expcolor = "darkolivegreen",
fraccolor = "blue") where {szE,szf}
Draw an histogram of the probability of each bit of the representation of a float to be 1
in the sample T
.
julia> T=collect(FloatmuIterator(Floatmu{3,5},0.0,1.0,2.0^-6));
julia> bits_histogram(T)