replica nfl jerseysreplica nfl jerseyssoccer jerseyreplica nfl jerseys forums.silverfrost.com :: View topic - Passing .NET arrays of floats gives strange result
forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Passing .NET arrays of floats gives strange result

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
Developer1



Joined: 18 Mar 2010
Posts: 4

PostPosted: Wed Mar 24, 2010 11:57 am    Post subject: Passing .NET arrays of floats gives strange result Reply with quote

Dear all,

I have Visual Studio 2005 and use the FTN95 Personal Edition at the moment (how do I find the version number?). I have the Fortran code compiled into a DLL which I refrence in my calling code. I can see the Fortran function fine.

My task is to test whether I can do calculations using Fortran legacy code in a .NET v2 application.

The problem I encounter is that when I pass to my Fortran code two same size .NET arrays of floats and add the individual array items together to return a new array, I get quite some garbage.

This code generates the arrays in C#.NET:
Code:

            const int arraysize = 10;
            float[] a = new float[arraysize];
            float[] b = new float[arraysize];

            for (int i = 0; i < arraysize; i++)
            {
                a[i] = System.Convert.ToSingle(i.ToString());
                b[i] = System.Convert.ToSingle("0." + i.ToString());
            }
            a[0] = -1000F;
            b[arraysize - 1] = -1000F;

            float[] c = new float[arraysize];
            for (int i = 0; i < c.Length; i++)
            {
                if (a[i] == -1000F || b[i] == -1000F)
                {
                    c[i] =-1000F;
                }
                else
                {
                    c[i] =  a[i] + b[i];
                }
            }


            float[] d = FortranFunctions.Add(a, b);


The two arrays to add together are:
a:
-1000
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
b:
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
-1000

The task is that if the value is -1000, assign it, otherwise add the items of the arrays together.

The result expected is array c:
-1000
1.1
2.2
3.3
4.4
5.5
6.6
7.7
8.8
-1000

I pass arrays a and b to the following Fortran code:
Code:

REAL FUNCTION DIRECTCALL_ADD(A,B) RESULT(C)
    ASSEMBLY_INTERFACE(NAME="Add")
    REAL A(0:)
    REAL B(0:)
    REAL C(0:9)
    D=-1000.00
   
    DO i=0,9
        IF (A(i).EQ.D .OR. B(i).EQ.D) THEN
            C(i)=D
        ELSE
            C(i)=A(i)+B(i)
        ENDIF
    END DO
   
END FUNCTION


Apart from the result array being fixed size at the moment and the compiler moaning about my checking on the value -1000, the problem is more fundamental.
The Fortran result array d:
-1000
1
2.1
3.2
4.3
5.4
6.5
7.6
8.7
9.8
When I debug and step through the Fortran code, I can see the Fortran array A and its members, but I cannot access Fortran arrays B or C. Hovering over B gives "B, REAL*4 (*Invalid*)". Hovering over C gives "unknown variable".

I have these options set in the Fortran project (others installation default):
Configuration Properties
Compiler Options
Miscelleaneous
-Debug Target: somelocation\Modules.Calculations.Fortran.dll
-Output Filename: somelocation\Modules.Calculations.Fortran.dll
Linker Options
Linker Options
-Class name: Modules.Calculcations.Fortran.FortranFunctions
-Interface only: yes

So, my question is: what is going wrong?

Regards,
Alex
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8210
Location: Salford, UK

PostPosted: Mon Mar 29, 2010 8:44 am    Post subject: Reply with quote

I do not have the time to check this out for you and my C# is a little rusty but I guess that the C# arrays a essentially "safe arrays" and they are not stored as contiguous blocks in the way that the Fortran expects. For a one-dimensionall array you might get a contiguous block with some kind of header data.

Try a very simple test in which you create a simple array directly, set its first value, pass it to Fortran and then print out the first value.
Back to top
View user's profile Send private message AIM Address
Developer1



Joined: 18 Mar 2010
Posts: 4

PostPosted: Mon Mar 29, 2010 2:29 pm    Post subject: Reply with quote

Nevertheless, the first array is okay. It is the second array where the problem lies.

The most instantanious arrays that can be created in .NET is via a System.Collections.Generic.List<float>. First, filling the lists as above and then calling the ToArray() method.

I have tried to pass A.ToArray and B.ToArray() into the line
Code:
float[] D = Modules.Calculations.Fortran.FortranFunctions.Add(A.ToArray(), B.ToArray());


This way, these arrayes are the "freshest" I can ever generate. I still get the above result.

So, what do I have to do to .NET arrays to pass them to a Fortran function?
Back to top
View user's profile Send private message
Emanuele



Joined: 21 Oct 2009
Posts: 78
Location: Bologna (Italy)

PostPosted: Mon Mar 29, 2010 3:36 pm    Post subject: Reply with quote

I can confirm the problem. I got the same results as Developer1, also traslating the C# in VB. I also tried passing two identical vectors but the second (B) is *invalid* for Fortran debugger. Here is my VB code:

Code:
 Dim a(9), b(9), c(9), d(9) As Single
        For i As Integer = 0 To 9
            a(i) = CSng(i)
            b(i) = CSng(i)
        Next
        a(0) = -1000
        b(0) = -1000

        For i As Integer = 0 To 9
            If (a(i) = -1000 Or b(i) = -1000) Then
                c(i) = -1000
            Else
                c(i) = a(i) + b(i)
            End If
        Next

        d = FortranFunctions.Add(a, b)


Vector d results:
-1000.0
-1000.0
3.0
5.0
7.0
9.0
11.0
13.0
15.0
17.0

Looking at Developer1's and mine results, it seems that the first A element is added to the second B element, the second A element to the third B element and so on.
Shocked
Back to top
View user's profile Send private message
Emanuele



Joined: 21 Oct 2009
Posts: 78
Location: Bologna (Italy)

PostPosted: Mon Mar 29, 2010 3:59 pm    Post subject: Reply with quote

I modified the fortran code:

Code:
 REAL FUNCTION DIRECTCALL_ADD(A,B) RESULT(C)
    ASSEMBLY_INTERFACE(NAME="Add")
    REAL, intent(in):: A(:), B(:)
    REAL:: C(ubound(A,1))
    D=-1000.00
   
    DO i = 1, 10
        IF (A(i).EQ.D .OR. B(i).EQ.D) THEN
            C(i)=D
        ELSE
            C(i)=A(i)+B(i)
        ENDIF
    END DO
       
END FUNCTION


Results are correct. Shocked Shocked Shocked Shocked Shocked
Don't ask me why!!
Debugger, however, still says *invalid* B! Exclamation Question Exclamation
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8210
Location: Salford, UK

PostPosted: Mon Mar 29, 2010 4:05 pm    Post subject: Reply with quote

The place to look in FTN95.chm is .NET Platform->.NET Programming->Calling Fortran from other .NET languages

This provides an example and explains that the index starts at zero and the "column major" ordering of the elements is different in C# and Fortran.
Back to top
View user's profile Send private message AIM Address
Emanuele



Joined: 21 Oct 2009
Posts: 78
Location: Bologna (Italy)

PostPosted: Mon Mar 29, 2010 4:12 pm    Post subject: Reply with quote

Dear Paul,

Developer1's code looks perfectly consistent with provided example. Moreover in this case the arrays are one-dimensional, so there should be no problems with the dominant index.
Back to top
View user's profile Send private message
Sebastian



Joined: 20 Feb 2008
Posts: 177

PostPosted: Mon Mar 29, 2010 10:56 pm    Post subject: Reply with quote

Would this code work:
Code:
REAL FUNCTION DIRECTCALL_ADD(A,B) RESULT(C)
    ASSEMBLY_INTERFACE(NAME="Add")
    REAL A(1:)
    REAL B(1:)
    REAL C(1:10)
    D=-1000.00
   
    DO i=1,10
        IF (A(i).EQ.D .OR. B(i).EQ.D) THEN
            C(i)=D
        ELSE
            C(i)=A(i)+B(i)
        ENDIF
    END DO
   
END FUNCTION

If it does it would hint at a shift when arrays are passed, to simplify the transition from zero-based (c#) to default 1-based (fortran) arrays.
Back to top
View user's profile Send private message
Emanuele



Joined: 21 Oct 2009
Posts: 78
Location: Bologna (Italy)

PostPosted: Tue Mar 30, 2010 9:59 am    Post subject: Reply with quote

Dear Sebastian,
Your code works properly, too.

What I cannot understand are:

1) why the zero-index produces a shift which affects only the second array passed to the sub (the B(0) element is set to 1.4E-44);

2) why, in both zero and one-index cases, the visual studio debugger is able to show only the first array values while not the second ones, even if the two arrays are identical.


Last edited by Emanuele on Tue Mar 30, 2010 1:12 pm; edited 2 times in total
Back to top
View user's profile Send private message
Emanuele



Joined: 21 Oct 2009
Posts: 78
Location: Bologna (Italy)

PostPosted: Tue Mar 30, 2010 12:36 pm    Post subject: Reply with quote

To make some more confusion, I tried passing a third vector to the subroutine:

Code:
 REAL FUNCTION DIRECTCALL_ADD(A,B,E) RESULT(C)
    ASSEMBLY_INTERFACE(NAME="Add")
   
    REAL:: A(0:), B(0:), E(0:)


In this case arrays A and B were passed correctly, while array E showed that nasty shift (E(0) value 1E-44). Probably this bug (may I call it "bug"?) affects only the last argument.

The following shot to show the Local Variable window of Visual Studio. The image refers to a break-point inserted before the end subroutine statement.

Back to top
View user's profile Send private message
Developer1



Joined: 18 Mar 2010
Posts: 4

PostPosted: Tue Mar 30, 2010 1:49 pm    Post subject: Reply with quote

Thank you all for replying.

I first tried Sebastian's changes to let the arrays start 1. The code executed corretcly, but array B was still shiwn as invalid.

I then combined Sebastian's and Emanuele's approach:
Code:

REAL FUNCTION DIRECTCALL_ADD(A,B,C) RESULT(D)
    ASSEMBLY_INTERFACE(NAME="Add")
    REAL A(1:)
    REAL B(1:)
    REAL C(1:)
    REAL D(1:10)
    F=-1000.00
   
    DO i=1,10
        IF (A(i).EQ.F .OR. B(i).EQ.F) THEN
            D(i)=F
        ELSE
            D(i)=A(i)+B(i)
        ENDIF
    END DO
   
END FUNCTION


Array C is invalid as predicted.

So, any idea why that might be?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group