Julia: Inexact error when trying to get the integer part of a BigFloat - type-conversion

I am interested in getting the digits of a BigFloat in the form of bytes. I get a very strange error that I cannot debug. I provide a minimal example where the error appears.
function floatToBytes(x::BigFloat)
ret = zeros(UInt8, 4)
xs = significand(x)/2
b = UInt8(0)
for i = 1:4
xs *= 256
b = trunc(UInt8, xs)
ret[i] = b
xs -= b
end
return ret
end
println( floatToBytes(BigFloat(0.9921875001164153)) )
println( floatToBytes(BigFloat(0.9960937501164153)) )
What I get when running this is
UInt8[0xfe, 0x00, 0x00, 0x00]
ERROR: LoadError: InexactError()
Stacktrace:
[1] trunc(::Type{UInt8}, ::BigFloat) at ./mpfr.jl:201
etc.
It seems that it doesn't want to turn 255 into a UInt8. I can circumvent the problem by defining the function as
function floatToBytes(x::BigFloat)
ret = zeros(UInt8, 4)
xs = significand(x)/2
b = UInt8(0)
for i = 1:4
xs *= 256
try
b = trunc(UInt8, xs)
catch
b = trunc(UInt8, xs-1)+UInt8(1)
end
ret[i] = b
xs -= b
end
return ret
end
But this is highly unsatisfactory. What is going on here?

The problem looks like a bug in trunc for BigFloat. The problem is the current code does (typemin(T) <= x <= typemax(T)) || throw(InexactError(:trunc, T, x)) which throws an error because x is larger than 255 which is the typemax.
It actually needs to do the trunc in BigFloat domain and then cast to T (and have the cast check for typemax).
I've opened an issue regarding this at: https://github.com/JuliaLang/julia/issues/24041
In the meantime, a solution could be to do:
UInt8(trunc(xs))
i.e. trunc first and cast later. For example:
julia> UInt8(trunc(BigFloat(0.9960937501164153)*256))
0xff

Related

How can I make a code that tells VB6 that tells VB6 that you're inputting something other than Whole numbers?

Introduction: Hi, everyone! I'm new to VB6! How can I make a code that tells VB6 that tells VB6 that you're inputting something other than Whole numbers?
Details: I'm making an arithmetic progression calculator (I think the code is not needed? but I'll just provide just in case.) Here is my code:
Option Explicit
Private Sub btCalc_Click()
Dim A As Long
Dim N As Long
Dim D As Long
Dim R As Long
Dim F As Long
A = Val(txtInitterm.Text)
N = Val(txtTermint.Text)
D = Val(txtFinterm.Text)
R = Val(txtTermint.Text)
F = N / 2 * (2 * A + (N - 1) * D)
lblOutput.Caption = F
End Sub
and I wanna notify or tell VB6 that I'm putting in a fraction, not an integer and uses that fraction to do operations.
NOTE: String Fraction to Value in VBA this doesn't answer my question... :D
Thank you for helping me, everyone! it's much appreciated.
There is no Application.Evaluate(...) in Vb6 like in VBA, so you have to do it like the "question" in "String Fraction to Value in VBA". Extract the logic to a function for re-use, and replace the Val(...) calls with the function for use.
Something like below would likely work, although you may want to provide better error handling in the obvious bad-math cases. I simply return zero and mark them with a comment.
Option Explicit
Private Sub btCalc_Click()
Dim A As Long, N As Long, D As Long, R As Long, F As Long
A = GetFrac(txtInitterm)
N = GetFrac(txtTermint)
D = GetFrac(txtFinterm)
R = GetFrac(txtTermint)
F = N / 2 * (2 * A + (N - 1) * D)
lblOutput.Caption = F
End Sub
Public Function GetFrac(ByVal S As String) As Double
GetFrac = 0 ' default return on error
If InStr(S, "/") = 0 Then GetFrac = Val(S): Exit Function
Dim P() As String, N As Double, D As Double
P = Split(S, "/")
If UBound(P) <> 1 Then Exit Function ' bad input -- multiple /'s
N = Val(P(0))
D = Val(P(1))
If D = 0 Then Exit Function ' div by 0
GetFrac = N / D
End Function

Julia macro for transforming `f(dim1,dim2,..) = value` into `f(value,dim1,dim2,..)`

I am trying to write a Julia macro that transforms this:
[par1!( par2(d1,d2)+par3(d1,d2) ,d1,d2,dfix3) for d1 in DIM1, d2 in DIM2]
(not very inspiring) into something much more readable, like this:
#meq par1!(d1 in DIM1, d2 in DIM2, dfix3) = par2(d1,d2)+par3(d1,d2)
where par1!() is a function to set some multi-dimensional data and par2() is a getData()-type of function.
I am trying to implement it using a macro, but as I am on my first experience with julia marcro, I'm not sure how to "assemble" the final expression from the various pieces..
Here is what I done so far:
macro meq(eq)
# dump(eq)
lhs_par = eq.args[1].args[1]
rhs = eq.args[2]
lhs_dims = eq.args[1].args[2:end]
loop_counters = [d.args[2] for d in lhs_dims if typeof(d) == Expr]
loop_sets = [d.args[3] for d in lhs_dims if typeof(d) == Expr]
loop_wholeElements = [d for d in lhs_dims if typeof(d) == Expr]
lhs_dims_placeholders = []
for d in lhs_dims
if typeof(d) == Expr
push!(lhs_dims_placeholders,d.args[2])
else
push!(lhs_dims_placeholders,d)
end
end
outExp = quote
[$(lhs_par)($(rhs),$(lhs_dims_placeholders ...)) for $(loop_wholeElements ...) ]
end
#show(outExp)
return outExp
end
However the above macro doesn't compile and returns a syntax error (“invalid iteration specification”) due to the for $(loop_wholeElements) part… indeed I don’t know how to treat the expressions in lhs_dims_placeholders and loop_wholeElements in order to “assemble” the expanded expression…
EDIT:
The example posted, with d1, d2 and dfix3, is only a specific case, but the macro should be able to handle whichever dimensions are looped for..
I think the macro up there does that, but I don't know how to build the final expression.. :-(
Instead of manually doing those hard-coded args matching stuff, we could use MacroTools.jl as a handy tool for template matching:
julia> using MacroTools
julia> macro meq(ex)
#capture(ex, f_(d1_ in dim1_, d2_ in dim2_, dfix3_) = body__)
ret = :([$f($(body[]), $d1, $d2, $dfix3) for $d1 in $dim1, $d2 in $dim2])
end
#meq (macro with 1 method)
julia> prettify(#macroexpand #meq par1!(d1 in DIM1, d2 in DIM2, dfix3) = par2(d1,d2)+par3(d1,d2))
:([(Main.par1!)((Main.par2)(lobster, redpanda) + (Main.par3)(lobster, redpanda), lobster, redpanda, Main.dfix3) for lobster = Main.DIM1, redpanda = Main.DIM2])
UPDATE:
The desired final expression is a comprehension, it seems that for some reason Julia couldn't figure out for expr(where $expr #=> XXX in XXX) is a comprehension. The workaround is directly using its lowered form:
julia> using MacroTools
julia> par1(a, b, c, d) = a + b + c + d
par1 (generic function with 1 method)
julia> par2(a, b) = a + b
par2 (generic function with 1 method)
julia> macro meq(ex)
#capture(ex, par_(dims__) = rhs_)
loopElements = []
dimsPlaceholders = []
for d in dims
#capture(d, di_ in DIMi_) || (push!(dimsPlaceholders, d); continue)
# push!(loopElements, x)
push!(loopElements, :($di = $DIMi))
push!(dimsPlaceholders, di)
end
ret = Expr(:comprehension, :($par($(rhs),$(dimsPlaceholders...))), loopElements...)
end
#meq (macro with 1 method)
julia> prettify(#macroexpand #meq par1!(d1 in DIM1, d2 in DIM2, dfix3) = par2(d1,d2)+par3(d1,d2))
:($(Expr(:comprehension, :((Main.par1!)(begin
(Main.par2)(bee, wildebeest) + (Main.par3)(bee, wildebeest)
end, bee, wildebeest, Main.dfix3)), :(bee = Main.DIM1), :(wildebeest = Main.DIM2))))
julia> #meq par1(m in 1:2, n in 4:5, 3) = par2(m,n) + par2(m,n)
2×2 Array{Int64,2}:
18 21
21 24
Note that, the variable scope of d1,d2 in generated expression will be wrong if we use push!(loopElements, x) rather than push!(loopElements, :($di = $DIMi)). Let's wait for someone knowledgeable to give a thorough explanation.
If you do not want to rely on an external package for this, the solution I provided on the Julia discourse should also work
return :([$(Expr(:generator,:($(Expr(:call,lhs_par,rhs,lhs_dims_placeholders...))),loop_wholeElements...))])
The key is to use the :generator constructor to make the loop expression
Also, rhs can be replaced with rhs.args[n] in order to eliminate the quote block and insert the expression directly.
This then produces the exact expression:
:([(par1!(par2(d1, d2) + par3(d1, d2), d1, d2, dfix3) for d1 in DIM1, d2 in DIM2)])
EDIT:
Alright, so I went ahead and tested this:
return Expr(:comprehension,Expr(:generator,Expr(:call,lhs_par,rhs.args[2],lhs_dims_placeholders...),loop_wholeElements...))
end
Then computing the result like this
meq(:(par1!(d1 = 1:2, d2 = 1:2, 3) = par2(d1,d2)+par3(d1,d2))) |> eval

Reading the Fortran real data type into Matlab from a hex dump

As the title says I am writing a large amount of real arrays from Fortran into an unformatted file, and then trying to read that binary file into Matlab. I have successfully made my script work for strings and integers, but It does not correctly read my real numbers from the hex dump.
As a test case I was using the number 5.49. Interesting side note, according to an online converter that is 40 af ae 14, yet when I check my hexfile that portion of my code is reading 14 ae af 40. I have tried reading it in as a float32 and double, and I have changed fro neutral to little endian to big endian. Any ideas?
Here is a simple example of my code:
First the Fortran write statements
REAL :: floating = 5.49
open(unit = 2, file = "anxietySource", form = "unformatted", status = "new", action = "readwrite")
write(unit = 2 ) floating
Now the Matlab read statement
fid = fopen('anxietySource', 'rb');
h1 = fread(fid, 1, 'int32'); %this is just reading off the starter bits that tell me how long my write statement is
floating = fread(fid,1,'float32');
display(floating);
fclose(fid);
My guess is that there is something funky with the Fortran REAL type. Maybe it's not quite a floating point?
Good job on the bit level work getting this far, you are almost there.
"Big Endien versus little..."
https://gcc.gnu.org/onlinedocs/gfortran/CONVERT-specifier.html
http://www.lahey.com/docs/lfenthelp/F95ARINQUIREStmt.htm
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/270026
There is also manually shifting it https://www.nsc.liu.se/~boein/f77to90/a5.html#section10
MODULE Shifty
PRIVATE
INTERFACE Shift
MODULE PROCEDURE Shift4 !,Shift8
END INTERFACE
CONTAINS
REAL FUNCTION Shift4(MyFloat)
IMPLICIT NONE
REAL, INTENT(IN) :: MyFloat
INTEGER*4 :: Float1
INTEGER*4 :: Float2
INTEGER*4 :: Float3
INTEGER*4 :: Float4
INTEGER*4 :: MyInt
EQUIVALENCE(MyInt, MyFloat)
INTEGER*4 :: MyIntOut
EQUIVALENCE(MyIntOut, Shift4)
WRITE(*,20) MyInt
20 FORMAT('Incoming Real=',1PE12.5,' ==",Z8.8,'"')
Float1 = IBITS(MyInt, 0, 8)
Float2 = IBITS(MyInt, 8, 8)
Float3 = IBITS(MyInt,16, 8)
Float4 = IBITS(MyInt,24, 8)
WRITE(*,30) 1, Float1 !Check
WRITE(*,30) 2, Float2
WRITE(*,30) 3, Float3
WRITE(*,30) 4, Float4
30 FORMAT('Float',I1,'="',Z2.2,'"')
Float1 = ISHFT(Float1, 24)
Float2 = ISHFT(Float2, 16)
Float3 = ISHFT(Float3, 8)
Float4 = ISHFT(Float4, 0)
MyIntOut = IOR(Float1 , Float2)
MyIntOut = IOR(MyIntOut, Float3)
MyIntOut = IOR(MyIntOut, Float4)
WRITE(*,20) MyInt, MyIntOut
20 FORMAT('Incoming Real="',Z8.8,' Outgoing="',Z8.8,'"')
RETURN
END FUNCTION Shift4
END MODULE Shifty
PROGRAM MAT2F90
USE Shifty
IMPLICIT NONE
TYPE MATLAB_HEADER
CHARACTER(LEN=120) :: Descriptor !should be 116 and INT*8 !!
INTEGER*4 :: Offset
INTEGER*2 :: Version
CHARACTER(LEN=2) :: Endien
END TYPE MATLAB_HEADER
TYPE MATLAB_SUBHEADER
INTEGER*4 :: Type
INTEGER*4 :: Bytes
END TYPE MATLAB_SUB_HEADER
TYPE(MATLAB_HEADER) :: Head
TYPE(MATLAB_SUB_HEADER),DIMENSION(20) :: Tag
CHARACTER(LEN=12), DIMENSION(18) :: Matlab_Version = RESHAPE(&
['miINT8 ','miUINT8 ','miINT16 ','miUINT16 ', &
'miINT32 ','miUINT32 ','miSINGLE ','Reserved ', &
'miDOUBLE ','Reserved ','Reserved ','miINT64 ', &
'miUINT64 ','miMATRIX ','miCOMPRESSED','miUTF8 ', &
'miUTF16 ','miUTF32 '],[18])
LOGICAL :: Swap
...
OPEN(UNIT=22,FILE='<somename>',ACCESS='STREAM',FORM='UNFORMATTED',IOSTAT=Status)
IF(Status =/0 ) ...Do something
READ(20,IOSTAT=Status) Head
IF(Status =/0 ) ...Do something
WRITE(*,*)'Head.Descriptor="',Head.Descriptor,'"'
WRITE(*,*)'Head.Offset = ',Head.Offset
WRITE(*,*)'Head.Version = ',Head.Version
WRITE(*,*)'Head.Endien ="',Head.Endian,'"'
IF(Head.Endian == 'IM') THEN
SWAP = .FALSE.
ELSEIF(Head.Endian == 'MI') THEN
SWAP = .TRUE.
ELSE
WRITE(*,*)'Unknown Endien="',Head.Endian,'"'
STOP
ENDIF
READ(20,IOSTAT=Status) Tag(1)
IF(Status =/0 ) ...Do something
WRITE(*,*)'Tag(1).Type = ',Tag(1).Type,' == "',Matlab_Version(Tag(1).Type),'"'
WRITE(*,*)'Tag(1).Bytes= ',Tag(1).Bytes
!read and swap if need be...
!There is padding to an 8type boundary
!Read the next tag and data... etc
Section 1-5 to 1-9 https://data.cresis.ku.edu/data/mat_reader/matfile_format.pdf . You may notice like I did that type15 is 'miCOMPRESSED', so at that point one needs the uncompressor to make sense of it.
You'll need to test it like you did before, because it is easy for me to get the order wrong, and I am doing this by memory.(Updated as I was doing this today, but in a subroutine, so it should work as a function??)
I made it 4 in case you need an '8' version... And then you just call Shifty() and you can get the one that matches your data.

local variable T conflicts with a static parameter warining

I'm getting warning that I don't understand.
I first run the following code:
type PDF{T <: Real}
𝛑::Vector{Float64} # K
μs::Matrix{T} # D x K
Σs::Vector{Matrix{T}} # K{D x D}
end
type Q{T <: Real}
w::Union{Float64, Vector{Float64}}
μpair::Union{Vector{T}, Matrix{T}}
Σpair::Union{Matrix{T}, Tuple{Matrix{T}, Matrix{T}} } # K{D x D}
end
type Smod{T <: Real}
H::Matrix{T} # D x D
Σs::Vector{Matrix{T}} # K{D x D}
qs::Vector{Q{T}}
end
type Scale{T <: Real}
μ::Vector{T} # D
Σ::Matrix{T} # D x D
end
type Parameters{T <: Real}
scale::Scale{T}
w::Vector{Float64}
maxNumCompsBeforeCompression::Integer
numComponentsAbsorbed::Integer
end
type KDE{T}
pdf::PDF{T}
smod::Smod{T}
params::Parameters{T}
end
And when after this I run the following snippet in IJulia
function initializeKDE{T <: Real}(x::Vector{T})
d = size(x,1)
T = typeof(x)
𝛑 = ones(Float64, 1)
μs = Array(T, d,1)
μs[:,1] = x
Σs = Array(Matrix{T}, 0)
pdf = PDF(𝛑, μs, Σs)
H = zeros(T, d,d)
qs = Array(Q{T}, 0)
smod = Smod(H, Σs, qs)
scale = Scale(x, H)
w = [0.0, 1.0]
maxNumCompsBeforeCompression = min(10, (0.5d^2 + d))
numComponentsAbsorbed = 0
params = Params(scale, w, maxNumCompsBeforeCompression, numComponentsAbsorbed)
kde = KDE(pdf, smod, params)
return kde::KDE
end
I get the following warning:
WARNING: local variable T conflicts with a static parameter in initializeKDE at In[4]:3.
where In[4]:3 corresponds to the 3rd line of the 2nd snippet.
Can anyone explain in human english what this warning is saying?
This is saying that you are trying to use T in two different ways: once as a "static parameter" and once as a local variable.
Firstly, you are using T as the parameter with which you are parametrising the function initializeKDE:
function initializeKDE{T <: Real}(x::Vector{T})
But then you are trying to redefine a new T in that third line:
T = typeof(x)
What are you trying to do here? If you are trying to define T to be the type of the elements that the vector x contains, then you should just delete this line and everything should just work -- T will automatically take the element type (eltype) of the vector that you pass to the initializeKDE function.

Imprecise Assigned value

In a simple program I want to build a matrix by defining a function. The problem is that a variable declared and initialized in the program has the exact assinged value of zero (zero_test)and some components of the matrix(D(4,1), D(1,4) etc.) which are assigned to 0., are not exactly zero. The latter have a value of order E-308 or E-291etc. I wonder why is there a difference.
Due to some articles I read, like this, the other components(D(1,1), D(1,2) etc.) are imprecise because of the transformation to the binary format.
System info: IA-32, Intel Visual Fortran 11.1.048 integrated with Microsoft Visual Studio 2008
The code:
program test
implicit none
real(8),parameter :: LAMBDA=75.e9,MU=50.e9
integer,parameter :: ndi=3,ntens=4
real(8) :: D(ntens,ntens),zero_test=0.
D = clcElasticStiffnessMatrix(LAMBDA,MU,ndi,ntens)
contains
function clcElasticStiffnessMatrix(LAMBDA,MU,ndi,ntens)
implicit none
integer :: ndi,ntens,i,j
real(8) :: clcElasticStiffnessMatrix(ntens,ntens),LAMBDA,MU
do i=1,ndi
do j=i,ndi
if(i .eq. j) then
clcElasticStiffnessMatrix(i,j) = 2.*MU + LAMBDA
else
clcElasticStiffnessMatrix(i,j) = LAMBDA
clcElasticStiffnessMatrix(j,i) = clcElasticStiffnessMatrix(i,j)
end if
end do
end do
do i=ndi+1,ntens
do j=i,ntens
if(i .eq. j) then
clcElasticStiffnessMatrix(i,j) = MU
else
clcElasticStiffnessMatrix(i,j) = 0.
clcElasticStiffnessMatrix(j,i) = clcElasticStiffnessMatrix(i,j)
end if
end do
end do
end function
end program
Matrix D in break mode:
D:
174999994368.000 74999996416.0000 74999996416.0000 2.641443384627243E-308
74999996416.0000 174999994368.000 74999996416.0000 2.640433316727162E-308
74999996416.0000 74999996416.0000 174999994368.000 -1.051992669438322E-291
2.640110775815455E-308 0.000000000000000E+000 6.151018477594351E-318 49999998976.0000
The problem is that you are assigning real(4) values to real(8) variables when you write
LAMBDA=75.e9,MU=50.e9
or
clcElasticStiffnessMatrix(i,j) = 0.
Try with d instead e and specify always:
LAMBDA=75.d9,MU=50.d9
clcElasticStiffnessMatrix(i,j) = 0.d0