How to pass two dimensional array to a function in F#? - arrays

I am trying to create a function in F# that takes as input a two dimensional array of integers (9 by 9), and prints its content afterwards. The following code shows what I have done :
let printMatrix matrix=
for i in 0 .. 8 do
for j in 0 .. 8 do
printf "%d " matrix.[i,j]
printf "\n"
The problem is that F# does not automatically infer the type of the matrix, and it gives me the following error: "The operator 'expr.[idx]' has been used an object of indeterminate type based on information prior to this program point. Consider adding further type constraints".
I tried to use type annotation in the definition of the function, but I think I did it wrong. Any idea how I can overcome this issue?

Change it to
let printMatrix (matrix:int [,])=
for i in 0 .. 8 do
for j in 0 .. 8 do
printf "%d " matrix.[i,j]
printf "\n"
This is due to how the F# type infrence algorithm works

The type inference algorithm doesn't really likes the bracket operator, because it can't guess which type is the object.
A workaround would be to give the matrix to a function that the compiler knows the type, in that example, Array2D.get does the same thing as the bracket operator. It knows it's an int matrix because of the "%d" on the printf
let printMatrix matrix =
for i in 0..8 do
for j in 0..8 do
printf "%d" <| Array2D.get matrix i j
printf "\n"

Related

Fortran Array Splice Initialization

I'm trying to initialize an array with equal spacing between 0 and 1 in fortran.
My code is :
program test
double precision :: h
double precision, dimension(:), allocatable :: x
h = 1./11
if(.not. allocated(x)) allocate(x(10))
x(1:10) = [h:(1-h):h] (*)
end program
The error I am given is "The highest data type rank permitted is INTEGER(KIND=8)" at the stared line.
I've tried to change it with
x(1:10) = h:(1-h):h
x = h:(1-h):h
x(1:10) = (/(h:(1-h):h)/)
and various other forms with no luck.
The syntax you're using is not valid Fortran and implied DO loops can't have non-integer bounds. You want something like this:
x = h * real([(i,i=1,size(x))],kind(h))
For more information, look up "array constructors" in the standard or a textbook.
Don't use (1:10) on the left side - see https://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this
This expression
[h:(1-h):h]
is, from a Fortran point of view, broken. It looks a bit like an array slice, but that would require integers, not reals, and ( and ) rather than the [ and ]. And it looks a bit like an array constructor, for which [ and ] are correct, but h:(1-h):h isn't.
Try this
x = REAL([(ix,ix=1,10)],real64)/11
(having declared ix to be an integer). The expression (ix,ix=1,10) is an implied do-loop and, inside the [ and ] produces an array with integers from 1 to 10. I trust the rest is obvious.
Incidentally, since the lhs of my suggested replacement is the whole of x you don't actually need to explicitly allocate it, Fortran will automatically do that for you. This is one of the differences between a whole array section, such as your x(1:10) and the whole array, x.
And if that doesn't produce the results you want let us know.

How to define and access array in GNUplot?

This is rather easy question or maybe too easy question. But i tried to find the way to done these already and could not find even in GNUplot document. Might be my mistake or misunderstood something about array concept in GNUplot. My question is How to define and access array in GNUplot?
Please just provide easy example of array declaration, assign value of array over loop. i think that's enough and i think this will be useful for other people too.
If you are using Gnuplot 5.1 or superior and need a 1-d array, you simply define the array with size N, remembering that the indices go from 1 to N:
gnuplot> array A[3] #Array definition
gnuplot> A[1]=2
gnuplot> A[3]=4
gnuplot> print A[1]
2
gnuplot> print A #Print the array, with empty A[2]
[2,,4]
If you need more than one dimension or are using previous versions of Gnuplot, you can do the following:
Since there are no vector variables in previous versions of Gnuplot, two functions can be defined to get and set values to a behind the scenes variable whose name include the index. The functions are:
aGet(name, i) = value(sprintf("_%s_%i", name, i))
aSet(name, i, value) = sprintf("_%s_%i = %.16e", name, i, value)
To assign and retrieve values on the array A you do
eval aSet("A",2,3)
print aGet("A",2)
What these functions do is to access a variable called _A_2.
You can build similar function to work with matrices:
mGet(name, i, j) = value(sprintf("_%s_%i_%i", name, i, j))
mSet(name, i, j, value) = sprintf("_%s_%i_%i = %.16e", name, i, j, value)
(This answer will be obsolete with the next stable gnuplot release, as the 5.1 development tree now has native support for array variables.)
(The "splot" command in gnuplot uses the keyword "array" to define the size of NxM matrix that contains function values for a 3D plot. Nothing to do with array variables.)
Arrays like what a programmer knows from C, Pascal, Python, etc. do not exist in gnuplot today (gp5.0). They might get implemented one day, because they'd be highly useful to plot a family of curves with arbitrary (e.g. fitted) parameters.
If you are desperate about arrays in gnuplot, you can (ab)use the word() function (and other string functions) to achieve a somewhat limited substitute. It's also a bit cumbersome:
array = ""
f(a,x) = a*x
do for [i=1:5] {array = array.sprintf(" %.3f",i+rand(0)) }
print "array = ".array
set xr [0:]; set yr [0:30]
plot for [i=1:5] f(word(array,i),x) title word(array,i)." x"
This example writes a set of random numbers to a string variable named "array", and afterwards uses it to plot five linear functions that use the numbers in "array" for their slope. It's handy here that gnuplot autopromotes strings to numerics if used e.g. in an equation.
Inspired by #Karl 's answer, it looks even more like an array when putting the word function into another function:
array(n) = word("1 2 3 4 5 6 7 8 9", n)
print array(3)
This prints 3. So the indexing is one-based.
"Multiply" the array by 2:
print (b="", sum[i=1:9](b=b.(array(i)*2)." ", 0), b)
This prints 2 4 6 8 10 12 14 16 18. Here the sum function is (ab)used to loop over the array and its result is ignored.
And here is shorter, through less generic variant of #bmello's answer:
A_1=1.1; A_2=2.2; A_3=3.3
A(i) = value("A_".i)
print A(3)
For me it feels more intuitiv. The underscore _ can be seen simply as the set function. Also it is not limited to integer indices. Strings are also possible which give some dictionary-like behaviour.

Fortran 77: How to use array output from function or subroutine

I've only been learning Fortran 77 (and its syntax) the last few days, and tried finding answers throughout the site and textbooks already and come up still confused, so I'd appreciate any help. I'm sorry if the formatting on this post is off; this is my first post, and I'm crunched for time.
I'm creating a program to multiply matrices. I want to create a subroutine or a function that will take two matrices as inputs (two 2x2 arrays), and return the multiplied matrix (one 2x2 array). I can't figure out how to get either a subroutine or a function to return an array of fixed size, or how to use the array once it's returned.
I tried using a function, which compiled on its own. But when I tried calling the function from my main program, I couldn't call it on its own:
MATMULT(MAT0, MAT0, MAT0)
1
Error: Unclassifiable statement at (1)
or assign it to another variable (I tried different REALs and arrays):
BLAH = MATMULT(MAT0, MAT0, MAT0)
1
Error: Return type mismatch of function 'matmult' at (1) (INTEGER(4)/REAL(4))
MATRIX1.f:26.22:
BLAH = MATMULT(MAT0, MAT0, MAT0)
1
Warning: Type mismatch in argument 'x' at (1); passed INTEGER(4) to REAL(4)
BLAH = MATMULT(MAT0, MAT0, MAT0)
1
Warning: Rank mismatch in argument 'x' at (1) (scalar and rank-2)
Since arrays are passed by reference, I'm really not sure what the function is returning, so how can I use the output matrix, if that is indeed the function's output?
I also tried using a subroutine, but (in addition to still not knowing what it's returning or where) then I get a "Two main PROGRAMs" error - so the compiler isn't differentiating between the main program and the subroutine. This might be a problem with my syntax on subroutines? I tried a few different things, but here's my most recent iteration of the code (I'm just trying to get the array-passing to work, so there's not actual matrix multiplication in here yet):
PROGRAM MATRIX1
INTEGER N
REAL A, B, MAT0(2,2), MATF(2,2), X(2,2), Y(2,2), Z(2,2)
REAL BLAH
PRINT *, " ENTER THE VALUE OF A: "
READ *, A
PRINT *, " ENTER THE VALUE OF B: "
READ *, B
PRINT *, " ENTER THE NUMBER OF MULTIPLICATIONS: "
READ *, N
C Creates the initial matrix
MAT0(1,1) = 1.0 - A
MAT0(1,2) = A
MAT0(2,1) = B
MAT0(2,2) = 1.0 - B
PRINT *, "M = ", MAT0
CALL MATMULT(MAT0, MAT0, MAT0)
PRINT *, "FINAL "
STOP
END PROGRAM
REAL SUBBROUTINE MATMULT(X, Y, Z)
END SUBROUTINE
Or (edited to add some of the recommended changes) with a function:
PROGRAM MATRIX1
INTEGER N
REAL A, B, MAT0(2,2), MATF(2,2), X(2,2), Y(2,2), Z(2,2)
REAL MATMULT(2,2)
PRINT *, " ENTER THE VALUE OF A: "
READ *, A
PRINT *, " ENTER THE VALUE OF B: "
READ *, B
PRINT *, " ENTER THE NUMBER OF MULTIPLICATIONS: "
READ *, N
C Creates the initial matrix
MAT0(1,1) = 1.0 - A
MAT0(1,2) = A
MAT0(2,1) = B
MAT0(2,2) = 1.0 - B
PRINT *, "M = ", MAT0
Z = MATMULT(X, Y)
STOP
END PROGRAM
FUNCTION MATMULT(X, Y)
REAL X(2,2), Y(2,2), Z(2,2), MATMULT(2,2)
RETURN
END
I'm still getting errors:
Z = MATMULT(X, Y)
1
Warning: Legacy Extension: REAL array index at (1)
MATRIX1.f:28.19:
Z = MATMULT(X, Y)
1
Error: Array index at (1) is an array of rank 2
In this era there is no reason for use FORTRAN 77. Fortran 90/95/2003 is easier to use, more powerful, and better assists the programer in finding mistakes. gfortran is an excellent open-source compiler.
Here is an example in Fortran 95 of a similar program/function: a function that implements a vector-cross product. The example shows the function and program in the same file (there are other approaches) with the function receiving two vectors and returning one vector. Example: Computing the cross product of two vectors in Fortran 90
You mention several problems in your question. Certainly your work will be enhanced using more recent Fortran dialects, as given in the answers by M. S. B. and Ilmirus. And you really should be using implicit none (even for Fortran 77 a lot of compilers support that - and lower case - as an extension).
Coming to the conceptual part, I must say that you need to continue your learning. However, if you want a function which returns the matrix product then you will have something like
function matmult(x, y)
real x(2,2), z(2,2), matmult(2,2)
... calculation of matmult
end function matmult
Followed by
z = matmult(x,y)
in the main program, where z is real z(2,2), rather than the scalar blah you have in your example, and is your result.
Coming to your subroutine, there are indeed problems: real subroutine matmult(x,y,z) requires not the real. Then calling this with call matmult(mat0, mat0, mat0) where you intend to update mat0 with a result is asking for aliasing problems. call matmult(x,y,z) will "store the result" where the subroutine calculations put it. Using intent as given by Ilmirus is a good guide to the behaviour desired by the programmer.
Finally, if you just want to get the result of multiplying A and B as matrices and storing in C: use C = matmul(A,B) with a later-than-F77 compiler.
However, in Fortran 77 one doesn't return array results, so the subroutine approach is the one to go for. In response to your edit:
REAL MATMULT(2,2)
is declaring matmult an array, not a function, so references to matmult(X,Y) give rise to your error.
There are two ways to do this:
1) Subroutine. Declare a subroutine like you did. However, specify input and output parameters:
REAL, INTENT(IN) :: X(2,2), Y(2,2)
REAL, INTENT(OUT) :: Z(2,2)
and call the subroutine using call keyword: CALL MATMULT
2) Function. Also specify input parameter, but now return value of the function:
! Insert calculation
MALMULT = ...
Don't forget to declare it in proper way: FUNCTION MATMULT(x,Y)
Call it: Z = MATMULT(X,Y)

Extract integers from string in Fortran

I'm using Fortran 90. I have a string declared as CHARACTER(20) :: Folds, which is assigned its value from a command line argument that looks like x:y:z where x, y, and z are all integers. I then need to pick out the numbers out of that string and to assign them to appropriate variables. This is how I tried doing it:
i=1
do j=1, LEN_TRIM(folds)
temp_fold=''
if (folds(j).neqv.':') then
temp_fold(j)=folds(j)
elseif (i.eq.1) then
read(temp_fold,*) FoldX
i=i+1
elseif (i.eq.2) then
read(temp_fold,*) FoldY
i=i+1
else
read(temp_fold,*) FoldZ
endif
enddo
When I compile this I get errors:
unfolder.f90(222): error #6410: This name has not been declared as an array or a function. [FOLDS]
[stud2#feynman vec2ascii]$ if (folds(j).neqv.':') then
syntax error near unexpected token `j'
[stud2#feynman vec2ascii]$ --------^
unfolder.f90(223): error #6410: This name has not been declared as an array or a function. [TEMP_FOLD]
[stud2#feynman vec2ascii]$ temp_fold(j)=folds(j)
syntax error near unexpected token `j'
How can I extract those numbers?
You can use the index intrinsic function to locate the position in the string of the first colon, say i. Then use an internal read to read the integer xfrom the preceding sub-string: read (string (1:i-1), *) x. Then apply this procedure to the sub-string starting at i+1 to obtain y. Repeat for z.
P.S. Are your error messages from bash rather than a Fortran compiler?
With folds a character variable, to access a substring one needs a (.:.). That is, to access the single character with index j: folds(j:j).
Without this, the compiler thinks that folds must be either an array (which it isn't) or a function (which isn't what you want). This is what is meant by:
This name has not been declared as an array or a function.
But in terms of then solving your problem, I second the answer given by #M.S.B. as it is more elegant. Further, with the loop as it is (with the (j:j) correction in both folds and temp_fold) you're relying on each x, y, and z being single digit integers. This other answer is much more general.

"Direction" of bidimensional arrays in C

as a C newcomer I'm a bit confused about bidimensional arrays.
If I want to represent a matrix of 3 rows and 5 columns, I guess the correct declaration is:
char a[3][5];
So, is this an array of 3 pointers to 5 arrays of chars or what?
How come whenever I try to cycle through it like the following it seems to read the wrong results?
int x, y;
for( x=0; x<3; x++ ){
for( y=0; y<3; y++ ){
printf( "%c", a[x][y] );
}
}
Are the following equivalent and correct ways to initialize it?
char a[3][5] = {
{1,0,0,0,1},
{1,0,0,0,1},
{1,0,0,0,1},
};
char a[3][5] = {1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1};
Thanks for any eventual upcoming explanation.
EDIT
Sorry the typos, the code is not copied. By the way, I keep on having them read like they where read in a vertical way, not in a horizontal one.
Also in the example in this tutorial http://www.cplusplus.com/doc/tutorial/arrays/ it reads the array in a way that is not streight-forward to me as it seems to work on a 5x3, HeightWidth, yx, colsrows structure instead of a 3x5, WidthHeight, xy. rowscols one:
#define WIDTH 5
#define HEIGHT 3
int jimmy [HEIGHT][WIDTH];
int n,m;
int main ()
{
for (n=0;n<HEIGHT;n++)
for (m=0;m<WIDTH;m++)
{
jimmy[n][m]=(n+1)*(m+1);
}
return 0;
}
Just for what it is and what not.
char a[3][5];
There are no pointers involved. A multi dimensional array like that is an array of arrays of .... and so on. In your case, you have an array of 3 arrays of 5 characters. It becomes clearer when you do it with typedefs.
typedef char T[5];
T a[3];
No pointers are involved whatsoever. If you want to access the first array of those 3 ones, you can do so:
a[0];
And it will give you back an object of type char[5]. Normally, you don't notice that because normally you index all dimensions. So the array that's returned by a[0] is subscript by the next index, for example a[0][1]. The [1] will be applied to the array that was returned by a[0], which as we have figured out earlier has type char[5].
So, is this an array of 3 pointers to 5 arrays of chars or what?
Let's create that type and see how it's different to the above. Creating it is simple, once you get the basic declarators:
Creating a pointer: *D
Creating an array: D[N]
D is just an existing another declarator. So now let's go on. First you say array of 3 pointers to 5 arrays of chars.... I think you meant array of 3 pointers to arrays of 5 chars. First, array of 5 is created like
D1[5]
Now, let's replace D1 by a pointer to declarator:
(*D2)[5]
We had to insert parentheses, because the subscript operator [N] binds better than the dereference operator *, and it would otherwise be read as *(D2[5]) which isn't what we want. Now we have pointer to array of 5.
Now let's do the array of 3. Replacing D2 by D3[3] yields this:
(*D3[3])[5]
Great, now we have got a array of 3 pointer to array of 5. Just putting the base type that that declarator appertains to yields the complete declaration:
char (*D3[3])[5];
That's of course a complete different thing :) You could use it to store pointers to your other array which was of type array of 3 arrays of 5 char. Let's store a pointer to the first sub-array of a into D3[0]. We figured out earlier that a[0] has type char[5]. We can store a pointer to that array into D3[0], because D3 is an array of pointers to char[5], what a coincidence!
D3[0] = &a[0]; // works!
I hope this little exercise has shown you some of the relations between pointers and arrays. Cheers!
I see a couple of problems with your code. First (copied from above):
int x, y;
for( x=0; x<3; x++ ){
for( x=0; x<3; x++ ){
printf( a[x][y] );
}
}
In your inner-loop, it looks like you want to use y instead of x, and you want y to go from 0..5. Currently, you are repeating the variable x. Also, you have a problem with your printf() statement. Here's some corrected code:
int x, y;
for( x=0; x<3; x++ ){
for( y=0; y<5; y++ ){
printf("%d\n", a[x][y] );
}
}
Second, when you initialize your array, your code is almost correct. Here's the corrected version:
char a[3][5] = {
{1,0,0,0,1},
{1,0,0,0,1},
{1,0,0,0,1}
};
(I removed the , after the very last "row" of data - that was a syntax error.)
The 2nd syntax you posted is incorrect (the one with no curly braces).
You've got wrong results because you're using x twice (looks like a copy/paste error). Try
int x, y;
for (x = 0; x < 3; x++) {
for (y = 0; y < 5; y++) {
printf("%c", a[x][y]); // Emil H says "%d" might be more useful
}
}
Edit: I'm not sure what's confusing about that tutorial. It's precisely equivalent to your code, except instead of printing the array, it's setting each element to (row*column) (where both row and column are one-based, hence the +1's).
The image that is in the tutorial is a great representation of the data:
alt text http://www.cplusplus.com/doc/tutorial/arrays/bidimensional_arrays3.gif
From the example, the nested for loops traverses across (left -> right) the array row by row and fills in a value for each column.
The small errors like using "%c" when you probably want "%d" and such are not what you really want to get answered I humbly think. You say you are a bit confused about arrays and also mentions that you expect to see pointers as the array-elements of the array containing arrays. You
The last comma in your definition of the array-of-arrays is NOT a syntax error. It is permitted as of C99.
What really will clear up things is to know that arrays are not pointers. It is true that an array name may be used as a constant pointer (to the first element) and that pointers can be indexed like they were arrays. This does not mean, however, that arrays and pointers are the same. They are not.
You ask about what the symbol "a" in your program actually is. It is an array of arrays. The memory layout may be visualized like a long line cut in three parts but still on a continuous line. Then cut each of these in five parts in the same manner. When addressing one element you must use two indexes; first for which five-element-array you want and then for which fifth of this element you want.
The memory layout is not like a grid of rows and columns. The memory is addressed by one scalar, so its linear. Pointer arithmetic may be the next thing you could look into, and see how an increment on a pointer works.
int x, y;
for( x=0; x<3; x++ ){
for( x=0; x<3; x++ ){
printf( a[x][y] );
}
}
You need to change the 2nd for loop to refer to 'y' instead of 'x'.
hope that helps.
You're using printf in the wrong way. Try:
printf("%d", a[x][y]);
I'm not sure whether you'll want to use %c or %d. If you want to print the number, use %d. If you want to print an actual character, use %c.
char a[3][5];
So, is this an array of 3 pointers to
5 arrays of chars or what?
Yes, that's what it is. Although you could also manipulate it as a consecutive set of 15 chars.
By convention, most people would think of it as representing a matrix with 3 rows and 5 columns (I think), but there's nothing about the data structure itself that requires that. You could just as easily use it to represent 5 rows and 3 columns. Or 3 sets that each include 5 elements but have no meaningful relationship to each other at all.
A particular library for doing matrix manipulation would have a convention for this.

Resources