View previous topic :: View next topic |
Author |
Message |
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Mon Apr 13, 2015 6:51 am Post subject: Compiler problem dealing with arrays of .NET booleans |
|
|
Hello,
This has had me stumped for a while but I am now fairly certain it is either a problem with the compiler itself or the way I have configured my FORTRAN project.
But basically I have an array of .NET bools, I then pass them into the FORTRAN code where it seems to simply interpret them incorrectly when reading them from the .NET array.
I believe this has something to do with the varying number of bytes a bool will use when in an array as opposed to where a bool represents a single member. This StackOverflow question delves into it a bit: Why in .NET System.Boolean takes 4 byte?
Anyway I have done up a sample application to demonstrate what I am talking about which you can download from here:
[LINK REMOVED - SEE POST FURTHER DOWN FOR UPDATED VERSION]
Here is the FORTRAN code:
Code: |
SUBROUTINE MapData(inputData, outputData)
IMPLICIT NONE
ASSEMBLY_INTERFACE(NAME="MapData")
! Declare params
INTEGER :: i
LOGICAL, DIMENSION(1:12) :: logicalData
OBJECT("DataLibrary.FortranData"), INTENT(IN) :: inputData
OBJECT("DataLibrary.FortranData"), INTENT(OUT) :: outputData
! Perform input mapping
logicalData = .FALSE.
DO i = 1, 12
logicalData = inputData%MonthlyValues(i-1)
END DO
! Perform output mapping
outputData = NEW@("DataLibrary.FortranData")
DO i = 1, 12
outputData%MonthlyValues(i-1) = logicalData(i)
END DO
END SUBROUTINE MapData
|
So basically the input array MonthlyValues should end up being exactly the same as the output array MonthlyValues. However this is not the case as logicalData will be filled with an odd mutation of values which can actually change between application runs and even adding break points seem to affect this behaviour...
However here is a screenshot of some sample output:
This is kind of causing me headaches with a bit of a schedule to keep so if anyone could suggest a work around that would be awesome, are there some settings I should try changing in my project configuration.
Thanks,
Alex.
Last edited by alex21 on Tue Apr 14, 2015 12:35 am; edited 1 time in total |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7933 Location: Salford, UK
|
Posted: Mon Apr 13, 2015 7:57 am Post subject: |
|
|
I don't have a quick answer to your query but you may need to make sure that your .NET implementation is "locked down" in memory. .NET problems can arise because of garbage collection and the resulting movement of objects in memory. DBK_LINKx.exe is designed to handle this for the Fortran but sometimes the programmer must handle this on the .NET side. You might be able to track memory position changes to test this (e.g. using LOC in Fortran, off hand I don't remember how to do this in C# etc.). |
|
Back to top |
|
|
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Mon Apr 13, 2015 9:17 am Post subject: |
|
|
Hmmm I will have a look into this but I don't think it is the problem as other value type and object arrays seem to work just fine. In the actual application I am working on its maps a few hundred arrays and the only ones that do not work are boolean arrays.
Could this possibly be due to the nature of how booleans are stored in .NET as described in the StackOverflow question I linked to?
Quote: |
A bool is actually only 1 byte, but alignment may cause 4 bytes to be used on a 32-bit platform, or even 8 bytes on a 64-bit platform. For example, the Nullable<bool> (aka bool?) type uses a full 32 or 64 bits�depending on platform�even though it's comprised of just two bools. EDIT: As pointed out by Jon Skeet, padding for alignment isn't always present. As an example, an array of Nullable<bool>s takes only 2 bytes per object instead of 4 or 8.
|
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7933 Location: Salford, UK
|
Posted: Mon Apr 13, 2015 11:50 am Post subject: |
|
|
On the Fortran side you can have logical*1, *2 or *4 (the default).
The kinds are 1,2 and 3 respectively. |
|
Back to top |
|
|
jalih
Joined: 30 Jul 2012 Posts: 196
|
Posted: Mon Apr 13, 2015 12:04 pm Post subject: Re: Compiler problem dealing with arrays of .NET booleans |
|
|
alex21 wrote: | Here is the FORTRAN code:
Code: |
SUBROUTINE MapData(inputData, outputData)
IMPLICIT NONE
ASSEMBLY_INTERFACE(NAME="MapData")
! Declare params
INTEGER :: i
LOGICAL, DIMENSION(1:12) :: logicalData
OBJECT("DataLibrary.FortranData"), INTENT(IN) :: inputData
OBJECT("DataLibrary.FortranData"), INTENT(OUT) :: outputData
! Perform input mapping
logicalData = .FALSE.
DO i = 1, 12
logicalData = inputData%MonthlyValues(i-1)
END DO
! Perform output mapping
outputData = NEW@("DataLibrary.FortranData")
DO i = 1, 12
outputData%MonthlyValues(i-1) = logicalData(i)
END DO
END SUBROUTINE MapData
|
So basically the input array MonthlyValues should end up being exactly the same as the output array MonthlyValues. However this is not the case as logicalData will be filled with an odd mutation of values which can actually change between application runs and even adding break points seem to affect this behaviour...
|
There is probably an error in input mapping part of your code. Your statement seems to be missing array index.
It should probably be written as :
Code: |
! Perform input mapping
DO i = 1, 12
logicalData(i) = inputData%MonthlyValues(i-1)
END DO
|
|
|
Back to top |
|
|
jalih
Joined: 30 Jul 2012 Posts: 196
|
Posted: Mon Apr 13, 2015 7:39 pm Post subject: |
|
|
Hi, i just tested this...
FTN95 compiler can properly convert logical data type into .NET framework System.Boolean data type. However, when you try to assign array of logical into array of System.Boolean you get a "System.IndexOutOfRangeException" exception.
Easy solution is to always use .NET System.Boolean data type instead of the Fortran logical data type.
So, change:
Code: |
logical, dimension(0:4) :: logicalData
|
to:
Code: |
object("System.Boolean[]") logicalData
logicalData = new@("System.Boolean[]",5)
|
Hope this helps... |
|
Back to top |
|
|
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Mon Apr 13, 2015 11:48 pm Post subject: Re: Compiler problem dealing with arrays of .NET booleans |
|
|
jalih wrote: | alex21 wrote: | Here is the FORTRAN code:
Code: |
SUBROUTINE MapData(inputData, outputData)
IMPLICIT NONE
ASSEMBLY_INTERFACE(NAME="MapData")
! Declare params
INTEGER :: i
LOGICAL, DIMENSION(1:12) :: logicalData
OBJECT("DataLibrary.FortranData"), INTENT(IN) :: inputData
OBJECT("DataLibrary.FortranData"), INTENT(OUT) :: outputData
! Perform input mapping
logicalData = .FALSE.
DO i = 1, 12
logicalData = inputData%MonthlyValues(i-1)
END DO
! Perform output mapping
outputData = NEW@("DataLibrary.FortranData")
DO i = 1, 12
outputData%MonthlyValues(i-1) = logicalData(i)
END DO
END SUBROUTINE MapData
|
So basically the input array MonthlyValues should end up being exactly the same as the output array MonthlyValues. However this is not the case as logicalData will be filled with an odd mutation of values which can actually change between application runs and even adding break points seem to affect this behaviour...
|
There is probably an error in input mapping part of your code. Your statement seems to be missing array index.
It should probably be written as :
Code: |
! Perform input mapping
DO i = 1, 12
logicalData(i) = inputData%MonthlyValues(i-1)
END DO
|
|
Indeed I completely missed that in the sample! The sample actually works fine with that mistake fixed... I am now going through my application code looking for the same mistake because the sample was producing the same kind of weirdness.
EDIT: Actually the output produced is now correct however the values in FORTRAN are still incorrect..... I will make another post to show this soon. |
|
Back to top |
|
|
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Tue Apr 14, 2015 12:10 am Post subject: Re: |
|
|
PaulLaidler wrote: | On the Fortran side you can have logical*1, *2 or *4 (the default).
The kinds are 1,2 and 3 respectively. |
Yeah I tried using different LOGICAL kinds however it does not seem to affect the output. |
|
Back to top |
|
|
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Tue Apr 14, 2015 12:13 am Post subject: Re: |
|
|
jalih wrote: | Hi, i just tested this...
FTN95 compiler can properly convert logical data type into .NET framework System.Boolean data type. However, when you try to assign array of logical into array of System.Boolean you get a "System.IndexOutOfRangeException" exception.
Easy solution is to always use .NET System.Boolean data type instead of the Fortran logical data type.
So, change:
Code: |
logical, dimension(0:4) :: logicalData
|
to:
Code: |
object("System.Boolean[]") logicalData
logicalData = new@("System.Boolean[]",5)
|
Hope this helps... |
Due to the restrictions on me for the FORTRAN project I am working with, I am unable to use .NET types in the actual simulation code this is why it needs to be mapped to the variables that the simulation code is already using.
However I do not get a System.IndexOutOfRangeException because I am mapping one index at a time? and taking 1 from the .NET array index to account for zero-based vs counting number-based indexes. |
|
Back to top |
|
|
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Tue Apr 14, 2015 12:45 am Post subject: |
|
|
After a bit more messing around I am again starting to think this is a Silverfrost problem, as pointed out by jalih there was a mistake in my original sample application, after fixing this it actually started to behave a bit stranger.
Basically the values mapped into the FORTRAN are interpreted incorrectly in the FORTRAN, however if these values are not manipulated in the FORTRAN mapping them back to .NET objects actually yields the same values that were mapped into the FORTRAN.
So if you try to use the values in the FORTRAN code they seem to be interpreted like this:
Also here is the updated sample application and a snippet of the updated FORTRAN code for those who do not want to download it:
Code: |
SUBROUTINE MapData(inputData, outputData)
IMPLICIT NONE
ASSEMBLY_INTERFACE(NAME="MapData")
! Declare params
INTEGER :: i
LOGICAL, DIMENSION(1:12) :: logicalData
OBJECT("DataLibrary.FortranData"), INTENT(IN) :: inputData
OBJECT("DataLibrary.FortranData"), INTENT(OUT) :: outputData
! Map .NET methods
ASSEMBLY_EXTERNAL("DataLibrary.FortranData.LogMessage") :: LogMessage
ASSEMBLY_EXTERNAL("DataLibrary.FortranData.LogBool") :: LogBool
! Perform input mapping
logicalData = .FALSE.
DO i = 1, 12
logicalData(i) = inputData%MonthlyValues(i-1)
END DO
! Display FORTRAN interpretation
CALL LogMessage(inputData, "FORTRAN Values")
DO i = 1, 12
CALL LogBool(inputData, logicalData(i))
END DO
CALL LogMessage(inputData, "")
! Perform output mapping
outputData = NEW@("DataLibrary.FortranData")
DO i = 1, 12
outputData%MonthlyValues(i-1) = logicalData(i)
END DO
END SUBROUTINE MapData
|
Currently I am thinking I might simply wrap my boolean arrays in another array which converts them to integers of 0 or 1, as the FORTRAN seems to interpret these fine.
Thanks,
Alex. |
|
Back to top |
|
|
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Fri Jun 21, 2019 5:50 am Post subject: |
|
|
Also this is still an issue for me, the sample application I provided is no longer available but I am willing to build another to demonstrate this issue again for further investigation. I am 90% sure it is because booleans use a different number of bytes in a .NET array if certain conditions are met, whatever is converting byte representations between LOGICAL and System.Boolean needs to account for this. |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Mon Jun 24, 2019 12:45 am Post subject: |
|
|
Quote: | , the sample application I provided is no longer available |
?????? _________________ ''Computers (HAL and MARVIN excepted) are incredibly rigid. They question nothing. Especially input data.Human beings are incredibly trusting of computers and don't check input data. Together cocking up even the simplest calculation ... " |
|
Back to top |
|
|
alex21
Joined: 20 Apr 2011 Posts: 75 Location: Australia
|
Posted: Mon Jun 24, 2019 1:09 am Post subject: Re: |
|
|
John-Silver wrote: | Quote: | , the sample application I provided is no longer available |
?????? |
It was available at the time of posting, but I did not maintain the dropbox account so it was deleted years ago. Robert has the latest example of some other issues in a sample I put on github more recently. |
|
Back to top |
|
|
|