This question already has answers here:
Print a Fortran 2D array as a matrix
(3 answers)
Closed 4 years ago.
I need to print DFGRD1, a matrix, in a file. I have written these lines
open(105,file='C:\temp17\FM.mtx')
WRITE(105,*) DFGRD1
close(105)
c To check in .dat file
DO i=1,3
WRITE (7,*) (DFGRD1(i,j),j=1,3)
END DO
However, the answers are not the same. They are the transpose of each other. Since I cannot access the real value of DFGRD1, I do not know which one is correct. I would really appreciate if someone could help me with it.
Fortran is a Column major so change the DO loop to be over the J not the I. It should be something like this:
DO j=1,3
WRITE (7,*) (DFGRD1(i,j),i=1,3)
END DO
Take care that optimum Fortran codes should have outer loop that iterates over the columns.
It is not a good idea to print some matrix to a file to check its values. You need to learn how to use a debugger (I recommend GDB) with basic tutorials you can set breakpoints and print the values.
All arrays are stored in 1d -- that's just the way memory is laid out.
The question is how its stored. Fortran stores it as 'column-major', that is:
A(1, 1) -> A(2, 1) -> A(3, 1) -> A(1, 2) -> ... -> A(3, 3)
Most other languages store the arrays row-major, that is
A(1, 1) -> A(1, 2) -> A(1, 3) -> A(2, 1) -> ... -> A(3, 3)
(In fact, most languages start indexing at 0 by default.)
So it's no surprise that you get different outputs when you write it in one go (where Fortran would store it the way it's laid out in memory) compared to when you specifically write it in row-major by looping over the j index.
As for what is 'correct' -- well, that's up to your code. You just have to be consistent.
Related
This is a very simple question, but unfortunately, I am stuck and do not know what to do. My program is a simple program that keeps on accepting 3 numbers and outputs the largest of the 3. The program keeps on running until the user inputs a character.
As the tittle says, my question is how I can make this execute faster ( There will be a large amount of input data ). Any sort of help which may include using a different algorithm or using different functions or changing the entire code is accepted.
I'm not very experienced in C++ Standard, and thus do not know about all the different functions available in the different libraries, so please do explain your reasons and if you're too busy, at least try and provide a link.
Here is my code
#include<stdio.h>
int main()
{
int a,b,c;
while(scanf("%d %d %d",&a,&b,&c))
{
if(a>=b && a>=c)
printf("%d\n",a);
else if(b>=a && b>=c)
printf("%d\n",b);
else
printf("%d\n",c);
}
return 0;
}
It's working is very simple. The while loop will continue to execute until the user inputs a character. As I've explained earlier, the program accepts 3 numbers and outputs the largest. There is no other part of this code, this is all. I've tried to explain it as much as I can. If you need anything more from my side, please ask, ( I'll try as much as I can ).
I am compiling on an internet platform using CPP 4.9.2 ( That's what is said over there )
Any sort of help will be highly appreciated. Thanks in advance
EDIT
The input is made by a computer, so there is no delay in input.
Also, I will accept answers in c and c++.
UPDATE
I would also like to ask if there are any general library functions or algorithms, or any other sort of advise ( certain things we must do and what we must not do ) to follow to speed up execution ( Not just for this code, but in general ). Any help would be appreciated. ( and sorry for asking such an awkward question without giving any reference material )
Your "algorithm" is very simple and I would write it with the use of the max() function, just because it is better style.
But anyway...
What will take the most time is the scanf. This is your bottleneck. You should write your own read function which reads a huge block with fread and processes it. You may consider doing this asynchronously - but I wouldn't recommend this as a first step (some async implementations are indeed slower than the synchronous implementations).
So basically you do the following:
Read a huge block from file into memory (this is disk IO, so this is the bottleneck)
Parse that block and find your three integers (watch out for the block borders! the first two integers may lie within one block and the third lies in the next - or the block border splits your integer in the middle, so let your parser just catch those things)
Do your comparisions - that runs as hell compared to the disk IO, so no need to improve that
Unless you have a guarantee that the three input numbers are all different, I'd worry about making the program get the correct output. As noted, there's almost nothing to speed up, other than input and output buffering, and maybe speeding up decimal conversions by using custom parsing and formatting code, instead of the general-purpose scanf and printf.
Right now if you receive input values a=5, b=5, c=1, your code will report that 1 is the largest of those three values. Change the > comparisons to >= to fix that.
You can minimize the number of comparisons by remembering previous results. You can do this with:
int d;
if (a >= b)
if (a >= c)
d = a;
else
d = c;
else
if (b >= c)
d = b;
else
d = c;
[then output d as your maximum]
That does exactly 2 comparisons to find a value for d as max(a,b,c).
Your code uses at least two and maybe up to 4.
I am implementing a genetic algorithm to numerically estimate some coefficients in a system of ODEs based on experimental data. I am just learning Fortran along as I implement the algorithms. My config is a Intel Fortran 2015 running on Windows 7/Visual Studio 2013, on an old i7 processor.
I have the following piece among a multitude of lines of code:
DO i = 1, N_CROMOSOMES
IF (population(9,i) < 0.0_DOUBLE) population(9, i) = square_error(population(1:8, i))
END DO
Where I just defined DOUBLE to be:
INTEGER, PARAMETER :: DOUBLE = 16
N_CROMOSOMES is an INTEGER argument to the function, that defines the size of the array population, which in turn is a (9 x N_CROMOSOMES) array of type REAL(KIND=DOUBLE). For each column on this array, its first 8 elements represent the 8 coefficients that I am estimating, and the ninth element is the error associated with that particular 8 guesses for the coefficients. square_error is the function that determines it.
In this point of the program, I have marked columns that were just created or that were altered as having an error of -1. Hence, the "IF (population(9,i)<0.0_DOUBLE)": I am checking the columns of the array whose error is -1 in order to compute their error.
The thing is, I just rewrote most of my code, and spent the past few days correcting mysterious bugs. Before this, the code worked just fine with a FORALL instead of DO. Now it says gives an error "stack overflow" when I use FORALL, but works with DO. But it takes a lot more time to do its job.
Does anyone knows the cause of this, and also, how to solve it? It is clear to me that my code can highly benefit from paralellization, but I am not so sure how to do it.
Thanks for your time.
Im new to using fortran and im having some problems with an if statement. Im trying to write something along the lines of if element in array 1 is larger than element in array 2 then let h = some expression, else h = 0. I have coppied my code below
DO I=1,NPOIN
IF ((X(I)*COS(0.0)+0.0*Y(I)*COS(0.0)+0.1)*0.15 .GT. ZF(I)) THEN
H%R(I) =0.15*((X(I)*COS(0.0))+(0.0*Y(I)*COS(0.0))+0.1)
ELSE
H%R(I) = 1
ENDIF
ENDDO
The error im getting is:
IF ((X(I)*COS(0.0)+0.0*Y(I)*COS(0.0)+0.1)*0.15 .GT. ZF(I)) THEN
Error: Syntax error in IF-expression at (1)
Apologies if this is somethign really obvious but ive tried all sorts to fix it with no joy so far. Any help would be appreciated.
There may be a better way to compare the two arrays but yeah essentially im trying have ZF as my main array, but where H is larger than ZF i want the ZF value to be replaced with the H value. SO essentially i have a new array with the maximum value possible between the two arrays.
Thanks in advance
There may be a better way to compare the two arrays but yeah essentially im trying have ZF as my main array, but where H is larger than ZF i want the ZF value to be replaced with the H value. SO essentially i have a new array with the maximum value possible between the two arrays.
If h and zf have the same shape you can simply write:
where (h>zf)
zf = h
end where
If they don't have the same shape clarify what you are trying to do.
(Modern) Fortran is an array language (up to a first approximation) so think whole-array operations rather than loops. They may be faster, more likely they're not, but they're quicker to write and easier to understand. If performance isn't good enough then think about a do loop replacement.
I'm having a trouble with my math:
Assume that we have a function: F(x,y) = P; And my question is: what would be the most efficient way of counting up suitable (x,y) plots for this function ? It means that I don't need the coordinates themself, but I need a number of them. P is in a range: [0 ; 10^14]. "x" and "y" are integers. Is it solved using bruteforce or there are some advanced tricks(math / programming language(C,C++)) to solve this fast enough ?
To be more concrete, the function is: x*y - ((x+y)/2) + 1.
x*y - ((x+y)/2) + 1 == P is equivalent to (2x-1)(2y-1) == (4P-3).
So, you're basically looking for the number of factorizations of 4P-3. How to factor a number in C or C++ is probably a different question, but each factorization yields a solution to the original equation. [Edit: in fact two solutions, since if A*B == C then of course (-A)*(-B) == C also].
As far as the programming languages C and C++ are concerned, just make sure you use a type that's big enough to contain 4 * 10^14. int won't do, so try long long.
You have a two-parameter function and want to solve it for a given constant.
This is a pretty big field in mathematics, and there are probably dozens of algorithms of solving your equation. One key idea that many use is the fact that if you find a point where F<P and then a point F>P, then somewhere between these two points, F must equal P.
One of the most basic algorithms for finding a root (or zero, which you of course can convert to by taking F'=F-P) is Newton's method. I suggest you start with that and read your way up to more advanced algorithms. This is a farily large field of study, so happy reading!
Wikipedia has a list of root-finding algorithms that you can use as a starting place.
I have 2 dimensional table in file, which look like this:
11, 12, 13, 14, 15
21, 22, 23, 24, 25
I want it to be imported in 2 dimensional array. I wrote this code:
INTEGER :: SMALL(10)
DO I = 1, 3
READ(UNIT=10, FMT='(5I4)') SMALL
WRITE(UNIT=*, FMT='(6X,5I4)') SMALL
ENDDO
But it imports everything in one dimensional array.
EDIT:
I've updated code:
program filet
integer :: reason
integer, dimension(2,5) :: small
open(10, file='boundary.inp', access='sequential', status='old', FORM='FORMATTED')
rewind(10)
DO
READ(UNIT=10, FMT='(5I4)', iostat=reason) SMALL
if (reason /= 0) exit
WRITE(UNIT=*, FMT='(6X,5I4)') SMALL
ENDDO
write (*,*) small(2,1)
end program
Here is output:
11 12 13 14 15
21 22 23 24 25
12
Well, you have defined SMALL to be a 1-D array, and Fortran is just trying to be helpful. You should perhaps have defined SMALL like this;
integer, dimension(2,5) :: small
What happened when the read statement was executed was that the system ran out of edit descriptor (you specified 5 integers) before either SMALL was full or the end of the file was encountered. If I remember rightly Fortran will re-use the edit descriptor until either SMALL is full or the end-of-file is encountered. But this behaviour has been changed over the years, according to Fortran standards, and various compilers have implemented various non-standard features in this part of the language, so you may need to check your compiler's documentation or do some more experiments to figure out exactly what happens.
I think your code is also a bit peculiar in that you read from SMALL 3 times. Why ?
EDIT: OK, we're getting there. You have just discovered that Fortran stores arrays in column-major order. I believe that most other programming languages store them in row-major order. In other words, the first element of your array is small(1,1), the second (in memory) is small(2,1), the third is small(1,2) and so forth. I think that your read (and write) statements are not standard but widely implemented (which is not unusual in Fortran compilers). I may be wrong, it may be standard. Either way, the read statement is being interpreted to read the elements of small in column-major order. The first number read is put in small(1,1), the second in small(2,1), the third in small(1,2) and so on.
Your write statement makes use of the same feature; you might have discovered this for yourself if you had written out the elements in loops with the indices printed too.
The idiomatic Fortran way of reading an array and controlling the order in which elements are placed into the array, is to include an implied-do loop in the read statement, like this:
READ(UNIT=10, FMT='(5I4)', iostat=reason) ((SMALL(row,col), col = 1,numCol), row=1,numRow)
You can also use this approach in write statements.
You should also study your compiler documentation carefully and determine how to switch on warnings for all non-standard features.
Adding to what High Performance Mark wrote...
If you want to use commas to separate the numbers, then you should use list-directed IO rather than formatted IO. (Sometimes this is called format-free IO, but that non-standard term is easy to confuse with binary IO). This is easier to use since you don't have to arrange the numbers precisely in columns and can separate them with spaces or commas. The read is simply "read (10, *) variables"
But sticking to formatted IO, here is some sample code:
program demo1
implicit none
integer, dimension (2,5) :: small
integer :: irow, jcol
open ( unit=10, file='boundary.txt', access='sequential', form='formatted' )
do irow=1, ubound (small, 1)
read (10, '(5I4)') (small (irow, jcol), jcol=1, ubound (small, 2))
end do
write (*, '( / "small (1,2) =", I2, " and small (2,1)=", I2 )' ) small (1,2), small (2,1)
end program demo1
Using the I4 formatted read, the data need to be in columns:
12341234123412341234
11 12 13 14 15
21 22 23 24 25
The data file shouldn't contain the first row "1234..." -- that is in the example to make the alignment required for the format 5I4 clear.
With my example program, there is an outer do loop for irow and an "implied do loop" as part of the read statement. You could also eliminate the outer do loop and use two implied do loops on the read statement, as High Performance Mark showed. In this case, if you kept the format specification (5I4), it would get reused to read the second line -- this is called format reversion. (On a more complicated format, one needs to read the rules to understand which part of the format is reused in format reversion.) This is standard, and has been so at least since FORTRAN 77 and probably FORTRAN IV. (Of course, the declarations and style of my example are Fortran 90).
I used "ubound" so that you neither have to carry around variables storing the dimensions of the array, nor use specific numeric values. The later method can cause problems if you later decide to change the dimension of the array -- then you have to hunt down all of the specific values (here 2 and 5) and change them.
There is no need for a rewind after an open statement.