Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fortran90 to C# Conversion Issue

I am converting some Fortran90 code to C#. I have some knowledge of Fortran77 but am not familiar with Fortran90. I have run across the following line of code that I am not certain how to translate.

C1 = real(product((/(-1,i1=1,m-1)/))*product((/(i1,i1=2,m)/)))

I am thinking this should be converted as:

int product1 = -1; int product2 = 1;
for (int i1 = 1 ; i1 <= (m-1); i1++)
{
    product1 *= -1;
}
for (int i2 = 2, i2 <= m; i2++)
{
    product2 *= i2;
}
float C1 = (float)(product1 * product2);

My uncertainty stems from the fact that there exists an implied do loop construction for initializing arrays; i.e.

A = (/2*I, I = 1,5/)

but I have never seen the word "product" used as in the Fortran statement in question. I know there is an intrinsic function for vector or matrix multiplication called PRODUCT but "product" is not an array in the code I am working with and the syntax of the intrisic function PRODUCT uses MASK so clearly my statement is not using this function.

Any insight or help would be greatly appreciated. Thank you.

like image 944
Zeos6 Avatar asked Feb 14 '12 00:02

Zeos6


1 Answers

If you decompose the parts and print them, you'll notice these are simply terms created using concise vectorized terms:

! given: (/(expr, start, end)/)
!
! (/(-1, i1=1, m-1)/) = vector, -1 repeated m-1 times
!
! (/(i1, i1=2, m)/)   = vector, 2..m
!
! Both are vectors with m-1 terms

The other thing to note is that product() does not require 3 arguments. The second argument (the dimension to use) and the third argument (an array mask) are not required.

At this point it becomes clear that the first product is actually -1m-1 and the second product is m!.

So, a proper (but not necessarily efficient) translation could be:

// product((/(-1,i1=1,m-1)/)) => -1^m-1
double i = (m % 2 == 0 ? -1 : 1);

// product((/(i1,i1=2,m)/))   => m!
double mfact = i;
for (int jj = 2; jj < m; ++jj)
{
    mfact *= jj;
} // C1 = mfact;

Succinct, close in "spirit" with the F90, but hardly efficient:

double i = (m % 2 == 0 ? -1 : 1);
double C1 = Enumerable.Range(2, m)
                      .Aggregate(i, (x, y) => x * y);
like image 114
user7116 Avatar answered Oct 05 '22 22:10

user7116