View Full Version : a fortran environment
danbaron
19-10-2011, 09:33
I've been trying both C and PBCC6 to make something, that for me, is relatively big.
So far, I find both of them to be somewhat unpleasant for big programs.
(This is just my thinking today, tomorrow may be different.)
I would say there is not enough encapsulation in either of them.
So, I decided to try going back to fortran.
I am trying GNU fortran, i.e., "gfortran".
It is at least partially complete through the Fortran 2008 standard (which includes OOP).
So far, I am content with the fact that it supports modules, which go back to the Fortran 90 standard.
Additionally, I found an IDE that, until now, seems to work really good with gfortran, "Code::Blocks".
I was able to make a project using Code::Blocks, that contains a main program file, and a module file.
Believe it or not, it compiled, linked, and ran correctly.
I just downloaded Code::Blocks a day or two ago, and tonight everything worked good.
And, the IDE looks good too.
(I checked, and the two files are actually compiled separately, i.e., there are two object files.)
------------------------------------------------------------------------------------------------------------------
gfortran Wiki:
http://gcc.gnu.org/wiki/GFortran
(http://gcc.gnu.org/wiki/GFortran)
Binaries available for gfortran:
http://gcc.gnu.org/wiki/GFortranBinaries
(http://gcc.gnu.org/wiki/GFortranBinaries)
If you want to get gfortran, go to the following link, and double click on the green button that says, "Download".
http://sourceforge.net/projects/mingw/files/MinGW/BaseSystem/GCC/Version4/
(http://sourceforge.net/projects/mingw/files/MinGW/BaseSystem/GCC/Version4/)
(Underneath, "Download", also on the green button it says, "mingw-get-inst-...exe".)
The download is approximately 0.5 MB.
When you get the exe file, run it.
You will see the MinGW-Get Setup Wizard.
You can check, "Use pre-packaged repository catalogues".
Accept the License Agreement, or, you'll be installing nothing.
You can put it in the default folder, "C:\MinGW".
When you get to the panel labeled, "Select Components", all you need to check is, "Fortran Compiler".
Click, "Install", and a console window will open, and all you need will download and install.
After it finishes, you have to put, "c:\mingw\bin", on you path.
To see if it is there, open a console window, and execute, "gfortran -v".
------------------------------------------------------------------------------------------------------------------
Code::Blocks website
http://darmar.vgtu.lt/
(http://darmar.vgtu.lt/)
If you have trouble compiling a fortran program: -->
Go to, "Settings" - "Compiler and debugger" - "Global compiler settings".
For, "Selected compiler", choose, "GNU Fortran Compiler".
Then, go below in the same dialog to the tab, "Toolchain executables".
Make sure for "Compiler's installation directory", it is, "c:\mingw\bin".
Below, still in the same dialog, for the tab, "Program Files", the choices for both, "C compiler", and "C++ compiler", should be, "gfortran.exe".
(Hopefully, that will work. My version of gfortran is actually somewhere else, "c:\program files\gfortran\bin". I have had it for awhile, I forget how I got it. I am going to download the latest version of gfortran, using the method shown above, but, I haven't done it yet.)
John Spikowski
19-10-2011, 17:46
Hi Dan,
Have you tried thinBasic or maybe even ScriptBasic with your project effort? Is this a CPU intensive application and only a compiled program makes sense?
John
danbaron
19-10-2011, 20:03
My idea, John, if it ever gets that far, is to make something which is compiled, and can be called from scripting languages.
(From experience, my conscience is not clear if I never post here about something that can ultimately be used with a scripting language.)
The Basic scripting languages work good, I know that.
But, like many programmers, I would like to create something, if I can.
If I ever can make something which can be called from scripting languages, or at least, if I am attempting to do so, then, that seems to be the best way.
(Actually, having an interpreter which can call compiled functions which other people create, seems like a great situation for everyone - in that way, all can feel a part of the project - then, I think, everyone wins.)
It seems to me, that, theoretically, a person could use any compiled language to create (I guess you call them), DLLs or SLLs.
But first, I think I have to make something which someone else would like to use, before I worry about DLLs and SLLs.
Dan
danbaron
21-10-2011, 07:59
So far, everything works.
I have two test files in a project, "main.f08", and, "reg.f08".
It compiles, links, and runs.
(And, as I said I would do, above, I have installed the latest version of gfortran into, c:\mingw\bin.)
' main.f08 -------------------------------------------------------------------------------------------
program something
use reg
implicit none
type(regtype)::r
call allocatereg(r,1000)
call zeroreg(r)
print *, r%d(r%ndigits - 1)
end program
' reg.f08 --------------------------------------------------------------------------------------------
module reg
type regtype
integer(4)::ndigits
integer(1),pointer,dimension(:)::d
integer(4)::maxpower
logical::sgn
end type regtype
contains
subroutine allocatereg(r,ndigits)
type(regtype),intent(inout)::r
integer(4),intent(in)::ndigits
r%ndigits = ndigits
r%maxpower = -1
r%sgn = .true.
allocate(r%d(ndigits))
end subroutine allocatereg
subroutine zeroreg(r)
type(regtype),intent(inout)::r
r%d(0:r%ndigits) = 0
end subroutine zeroreg
end module reg
John Spikowski
21-10-2011, 16:22
IMO, Basic and C are the only two languages one would ever need to use. Everything else is a derivative.
Basic for ease of use and minimal coding.
C for speed and low level access to resources.
danbaron
21-10-2011, 19:43
And, amazingly, Fortran existed before either of them!
Fortran
http://en.wikipedia.org/wiki/Fortran
Basic
http://en.wikipedia.org/wiki/BASIC
C
http://en.wikipedia.org/wiki/C_%28programming_language%29
John Spikowski
21-10-2011, 20:05
ScriptBasic was written in ANSI/ISO C back in 1998. This same code base has remained unchanged for the most part except for a couple deprecated gcc keywords that were compensated for. Going to 64 bit with ScriptBasic was nothing more than a compiler command line option change. (same for moving SB to the OS X)
I've never used Fortran so it's portability aspects are unknown to me.
John, if you would stop promoting ScriptBasic every chance you get, people might actually be more inclined to try it.
Dan, I toyed with Fortran a bit also and as I understand it, interfacing with C or Basic can be a bit tricky.
for simple types like integer or double there's no problem but arrays are another story.
John Spikowski
22-10-2011, 02:09
John, if you would stop promoting ScriptBasic every chance you get, people might actually be more inclined to try it.
I was just pointing out the portability aspect of writing a high level language in ANSI/ISO C. After almost fifteen years, the same code still compiles.
I don't make a penny promoting ScriptBasic which is a open source LGPL language. I have 6 years invested in supporting and keeping the language alive. If I make a comment using SB as an example, I don't understand what you're upset about. What if Ford or GM stopped promoting their cars and said people will buy them if they see them on the street?
Give SB a try Jack and if you think it sucks then I'll stop posting about it.
Dan, about code::blocks, it is also very easy to make it portable. That is to put onto a memory device and take with you to any other windows os device.
http://wiki.codeblocks.org/index.php?title=FAQ-Settings#Q:_How_do_I_make_Code::Blocks_portable.3F
Fortran was the first language I learned in the 1970's. It still makes very fast executable's. http://shootout.alioth.debian.org/u32/which-programming-languages-are-fastest.php
Found this a Fortran that is the best of Fortran 90 getting rid of what was bad.
http://www.fortran.com/F/
danbaron
22-10-2011, 07:12
So far, I think Code::Blocks is pretty nice, Kent.
I think it's fast.
I know all about F, it was made by Walt Brainerd.
Up to now, I don't need to worry about portability.
-------------------------------------------------------------------------
Below is from the Wikipedia Fortran link,
http://en.wikipedia.org/wiki/Fortran
Fortran 2003
Fortran 2003 is a major revision introducing many new features. A comprehensive summary of the new features of Fortran 2003 is available at the Fortran Working Group (WG5) official Web site.[13] (http://en.wikipedia.org/wiki/Fortran#cite_note-12)
From that article, the major enhancements for this revision include:
Derived type enhancements: parameterized derived types, improved control of accessibility, improved structure constructors, and finalizers.
Object-oriented programming (http://en.wikipedia.org/wiki/Object-oriented_programming) support: type extension and inheritance (http://en.wikipedia.org/wiki/Inheritance_%28computer_science%29), polymorphism (http://en.wikipedia.org/wiki/Type_polymorphism), dynamic type allocation, and type-bound procedures.
Data manipulation enhancements: allocatable components (incorporating TR 15581), deferred type parameters, VOLATILE attribute (http://en.wikipedia.org/wiki/Volatile_variable), explicit type specification in array constructors and allocate statements, pointer enhancements, extended initialization expressions, and enhanced intrinsic procedures.
Input/output enhancements: asynchronous (http://en.wikipedia.org/wiki/Asynchrony) transfer, stream access, user specified transfer operations for derived types, user specified control of rounding during format conversions, named constants for preconnected units, the FLUSH statement, regularization of keywords, and access to error messages.
Procedure pointers (http://en.wikipedia.org/wiki/Function_pointer).
Support for IEEE floating-point arithmetic (http://en.wikipedia.org/wiki/IEEE_754-2008) and floating point (http://en.wikipedia.org/wiki/Floating_point)exception handling (http://en.wikipedia.org/wiki/Exception_handling) (incorporating TR 15580).
Interoperability with the C programming language (http://en.wikipedia.org/wiki/C_%28programming_language%29).
Support for international usage: access to ISO 10646 (http://en.wikipedia.org/wiki/Universal_Character_Set) 4-byte characters and choice of decimal or comma in numeric formatted input/output.
Enhanced integration with the host operating system: access to command line (http://en.wikipedia.org/wiki/Command-line_interface) arguments, environment variables (http://en.wikipedia.org/wiki/Environment_variable), and processor error messages.
An important supplement to Fortran 2003 was the ISO technical report (http://en.wikipedia.org/wiki/International_Organization_for_Standardization) TR-19767: Enhanced module facilities in Fortran. This report provided submodules, which make Fortran modules more similar to Modula-2 (http://en.wikipedia.org/wiki/Modula-2) modules. They are similar to Ada (http://en.wikipedia.org/wiki/Ada_%28programming_language%29) private child subunits. This allows the specification and implementation of a module to be expressed in separate program units, which improves packaging of large libraries, allows preservation of trade secrets while publishing definitive interfaces, and prevents compilation cascades.
Notice, "Interoperability with the C programming language.".
I think they worked on that.
I have a book coming from Amazon, which has a chapter on that topic.
-------------------------------------------------------------------------
I looked a little at the ScriptBasic website.
My impression is that there is no IDE. If so, then, I think that will scare away a lot of people. It could be the best interpreter in the world, but, without an IDE, many people will pass it by (my opinion).
Under "Installation", for Windows, it only mentions up to WINME. Also, most or all of the web pages say, "Last updated May 22, 2006.". Those could give people the initial impression that development has been discontinued. In my opinion, if people think that, they leave.
In the forum, you must talk about programming. I think the thinBasic forum gets a lot of traffic, partly because, people feel free to discuss almost anything.
The thinBasic website does a lot better job of "selling" thinBasic. Relatively, the ScriptBasic website is bland.
thinBasic has the SDK. This gives programmers the hope of being able to contribute to the project, to become part of it. But, I see that ScriptBasic supports the same idea.
I see that ScriptBasic's documentation is available in multiple formats.
So, I would absolutely say that ScriptBasic's major handicaps are the fact that people could get the immediate impression that it is no longer being developed, and, the lack of an IDE. Like I said above, it could be the best language on Earth, but, without an IDE, most people will never know it. I think the same thing originally happened to Perl, Python, and Ruby. They didn't grow really fast until IDEs appeared.
John Spikowski
22-10-2011, 07:38
Thanks Dan for stopping by the ScriptBasic site.
1. ScriptBasic isn't a standalone interpreter, it's an embeddable scripting API engine. The scriba command line interpreter is an example of embedding the API. (in C in this case)
2. ScriptBasic has a debug preprocessor option that lets you step through a script line by line and display variable contents. IT also supports breakpoints and can even be run remotely over TCP with a telnet connection. I guess you could call that an IDE of sorts.
3. It's open source (LGPL) and you can use it commercially with no strings attached. It's used in a router I know of and the University of Toronto used SB embedded in dedicated controllers to control over 6 million square ft of their campus environmental systems.
What else can I say?
danbaron
22-10-2011, 08:03
I can see that it being embeddable, and, commercially usable, for free, are good things.
It just becomes a matter of how many people have use for them.
And, maybe it is unfair, but we have to live with it.
We don't have personalities that attract people, like, for instance, Eros does.
If you could turn ScriptBasic into a thinBasic module, that would be something.
danbaron
22-10-2011, 08:29
Here is an example of telepathic communication in Fortran.
I think it is a manifestation of the phenomenon of quantum entanglement.
http://en.wikipedia.org/wiki/Quantum_entanglement
' code ----------------------------------------------------------------------------------------------------------------
program magic
implicit none
integer::m,n
common/one/m
common/two/n
call a()
call b()
call c()
call d()
print *, m
print *, n
end program
subroutine a()
integer::i
common/one/i
i = 1
end subroutine
subroutine b()
integer::i
common/two/i
i = 3
end subroutine
subroutine c()
integer::i
common/one/i
i = i + 1
end subroutine
subroutine d()
integer::i
common/two/i
i = i + 1
end subroutine
' output --------------------------------------------------------------------------------------------------------------
2
4
Petr Schreiber
22-10-2011, 09:26
Hi Dan,
what does the slashed syntax mean, for example here:
common/two/i
Petr
danbaron
22-10-2011, 11:08
I forget this stuff somewhat, if I ever knew it, Petr.
In Fortran, there are different types of program units - programs, external subroutines and functions, internal subroutines and functions, modules, module subroutines and functions, probably there are more - this is before they added OOP.
A common block allows one program unit to share common data with another.
If I am correct, common blocks are the Fortran equivalent of global variables. In other words, in Fortran, variables can only be declared inside a program unit.
There are two types of common blocks, unnamed, and named.
The syntax for the unnamed type is,
common/i,j,k
The syntax for the named type is,
common/some_name/i,j,k
There can only be one common block of the unnamed type.
But, there can be many of the named type.
Each program unit that declares the same common block has access to its particular data.
It is not necessary that two program units sharing a common block use the same names for the common data, for instance,
subroutine e()
integer::m,n
common/dog/m,n
m = 1
n = 2
end subroutine
subroutine f()
integer::p,q
common/dog/p,q
p = p + 1
q = q + 1
end subroutine
Here, m and p are the same variables, and so are n and q.
I have read that beginning in Fortran 90, the use of common blocks is discouraged.
The exact same sharing of data can be accomplished by declaring shared data within a module (which may contain only data declarations if one so desires),
module boat
integer(8):: apple
real(10):: pear
end module
and then putting the statement,
use boat
within each program unit that needs to access the particular data.
(Modules can be put into separate files, but, they don't have to be. Above, "integer(8 )", means, an integer type that uses 8 bytes. And, modules can "use" other modules.)
There are advantages to instead doing it this way. For instance, then, I don't think you need to specify the types of the common data within the program units that use it. I guess there were a lot of hard to find errors when using common blocks.
The people who made/make the various official Fortran specifications over the years, Fortran 66, Fortran 77, Fortran 90, Fortran 95, Fortran 03, Fortran 08 (the number indicates the year of the specification), were/are not dummies. They were/are mostly numerical guys at big universities.
Petr Schreiber
22-10-2011, 13:33
I have old Fortran textbook (from 1973) at home, but this syntax was not discussed in it.
Thanks for the info!,
Petr
I have old Fortran textbook (from 1973) at home, but this syntax was not discussed in it.
Thanks for the info!,
Petr
I am glad you had that book Petr. I thought my mind was totally erased, as that code looked alien to me, from what I could remember :)
danbaron
03-11-2011, 11:22
In modern fortran, the random number generator takes a seed which is an array of integers.
You use the intrinsic command,
call random_seed()
The subroutine must be called with one of three values, "size", "put", "get".
If you call it like this,
integer::sz
call random_seed(size=sz)
sz will be set to the number of elements in the seed array, for the particular architecture.
For win32, it is 8 (4 byte integers), i.e., 256 bits.
If you call it like this,
call random_seed(put=seedarray)
the seed will be set to seedarray (so, for win32, seedarray should be an integer array of 8 elements).
If you call it like this,
call random_seed(get=seedarray)
seedarray will be set to the current value of the seed, i.e., the value (array) used for the next random number in the sequence.
You can get a random value like this,
double precision::ranval
call random_number(ranval)
0 <= ranval < 1.
! code ---------------------------------------------------------------------------------------------------------------------------------
module random
integer(4),dimension(:),allocatable::defaultseed,randomseed
integer::seedsize
!----------------------------------------------------------------------------------------------------------
contains
!----------------------------------------------------------------------------------------------------------
subroutine allocateseeds()
call random_seed(size=seedsize)
allocate(defaultseed(seedsize))
allocate(randomseed(seedsize))
endsubroutine
!----------------------------------------------------------------------------------------------------------
subroutine setdefaultseed()
! Seeds the random number generator to a constant value.
integer::i
do i= 1,seedsize
defaultseed(i)=0
enddo
call random_seed(put=defaultseed)
endsubroutine
!----------------------------------------------------------------------------------------------------------
subroutine setrandomseed()
! Seeds the random number generator to a random value.
integer::cnt,cntrate,cntmax,i
do i= 1,seedsize
call system_clock(cnt,cntrate,cntmax)
randomseed(i)=cnt
enddo
call random_seed(put=randomseed)
endsubroutine
!----------------------------------------------------------------------------------------------------------
subroutine resetdefaultseed()
call random_seed(put=defaultseed)
endsubroutine
!----------------------------------------------------------------------------------------------------------
subroutine resetrandomseed()
call random_seed(put=randomseed)
endsubroutine
!----------------------------------------------------------------------------------------------------------
end module random
!----------------------------------------------------------------------------------------------------------
!----------------------------------------------------------------------------------------------------------
subroutine printrandomvals()
double precision::ranval
integer::i
do i=1,5
call random_number(ranval)
print *,ranval
enddo
print *
endsubroutine
!----------------------------------------------------------------------------------------------------------
!----------------------------------------------------------------------------------------------------------
program test
use random
implicit none
integer::sz
character::c
call random_seed(size=sz)
print *
print '(a,i1,a)', 'The random number generator takes a seed array consisting of ', sz, ' elements.'
print *
print *
call allocateseeds()
call setdefaultseed()
print *, 'The first 5 doubles in the default sequence.'
print *
call printrandomvals()
call setrandomseed()
print *, 'The first 5 doubles in a random sequence.'
print *
call printrandomvals()
call resetrandomseed()
print *, 'The first 5 doubles again in the same random sequence.'
print *
call printrandomvals()
call setrandomseed()
print *, 'The first 5 doubles in a new random sequence.'
print *
call printrandomvals()
call resetdefaultseed()
print *, 'The first 5 doubles in the default sequence again.'
print *
call printrandomvals()
print *
print *, 'Enter a character to quit.'
print *
read *, c
end program test
! output -------------------------------------------------------------------------------------------------------------------------------
The random number generator takes a seed array consisting of 8 elements.
The first 5 doubles in the default sequence.
0.30901699450542608
0.80380552047952203
0.35249806832347486
0.99809236009560809
0.55022038741740864
The first 5 doubles in a random sequence.
0.35368386010621311
0.92495087746258120
2.79358793357609159E-002
0.43250869170195372
0.79918821411338958
The first 5 doubles again in the same random sequence.
0.35368386010621311
0.92495087746258120
2.79358793357609159E-002
0.43250869170195372
0.79918821411338958
The first 5 doubles in a new random sequence.
0.85485606414247872
0.22150034995476942
0.86076915663017317
0.17166310760556669
0.48618469153662536
The first 5 doubles in the default sequence again.
0.30901699450542608
0.80380552047952203
0.35249806832347486
0.99809236009560809
0.55022038741740864
Enter a character to quit.
danbaron
08-11-2011, 09:07
Here is a little program that numerically integrates the function,
f(x) = x^2*cos(x)/4,
from x = 0, to, x = 2*pi,
by the repeated application of Simpson's Rule.
It uses a function parameter.
There's probably an easier way to implement the function parameter, but, this way works.
' code ----------------------------------------------------------------------------------------------------------------
double precision function xsquaredcosxdiv4(x)
double precision,intent(in)::x
intrinsic cos
xsquaredcosxdiv4=x*x*cos(x)/4
end function
!-----------------------------------------------------------------------------------------------------------
double precision function simpsonintegrate(x1,x2,ndivisions,f)
double precision,intent(in)::x1,x2
integer, intent(in)::ndivisions
interface
double precision function f(x)
double precision, intent(in)::x
end function f
end interface
double precision::division,sum
integer::i
division=(x2-x1)/ndivisions
sum=f(x1)+f(x2))/2
do i=1,ndivisions-1
sum=sum+f(x1+division*i)
enddo
simpsonintegrate=division*sum
endfunction
!-----------------------------------------------------------------------------------------------------------
program test
implicit none
intrinsic atan
double precision,external::simpsonintegrate,xsquaredcosxdiv4
double precision::pi
pi=4*atan(1.0d0)
print*,'pi = ',pi
print*,'integral approx. = ',simpsonintegrate(0,2*pi,100000,xsquaredcosxdiv4)
end program
' output --------------------------------------------------------------------------------------------------------------
pi = 3.1415926535897931
integral approx. = 3.1415926546233215
We can verify that the correct answer is pi.
We start with the product rule of differentiation,
d(uv) = udv + vdu.
We integrate both sides and get,
uv = integral(udv) + integral(vdu).
Now, we re-arrange, to get the formula for integration by parts,
integral(udv) = uv - integral(vdu).
We apply integration by parts twice to the function,
f(x) = x^2*cos(x)/4,
and we get,
integral(x^2*cos(x)/4) = (x^2*sin(x) + 2*x*cos(x) - 2*sin(x))/4.
When we evaluate the formula at x = 2*pi, and then subtract the evaluation of the formula at x = 0, we get, pi.
danbaron
09-11-2011, 10:25
Here is a shorter version of the previous program.
I don't think Simpson's Rule is the fastest way to numerically integrate, but, you can get pretty good accuracy if you divide the interval into tiny sub-intervals.
Below the interval is divided into ten million equal sub-intervals, and the result is accurate to 1 part in 3,141,592,653,589 - approximately one part in three trillion.
' code ----------------------------------------------------------------------------------------------------------------
module integrate
contains
double precision function xsquaredcosxdiv4(x)
double precision::x
xsquaredcosxdiv4=x*x*cos(x)/4
end function
double precision function simpsonintegrate(x1,x2,ndivisions,f)
double precision::x1,x2,f
integer::ndivisions
double precision::division,sum
integer::i
division=(x2-x1)/ndivisions
sum=(f(x1)+f(x2))/2
do i= 1,ndivisions-1
sum=sum+f(x1+division*i)
enddo
simpsonintegrate=division*sum
end function
end module
!-----------------------------------------------------------------------------------------------------------
program test
use integrate
implicit none
double precision::pi
pi=4*atan(1d0)
print*,"pi = ",pi
print*,"integral approx. = ",simpsonintegrate(0d0,2*pi,10000000,xsquaredcosxdiv4)
end program
' output --------------------------------------------------------------------------------------------------------------
pi = 3.1415926535897931
integral approx. = 3.1415926535892416
danbaron
27-11-2011, 06:50
I'm at the point now in my "top secret" project, where I needed to find out if Fortran would do what I want with respect to recursion.
So, I made a test.
Amazingly, things worked the way I hoped.
' code -------------------------------------------------------------------------------------------------------------------------------------
recursive subroutine test(i)
integer::i
call dog(i)
if(mod(i,100)==0)print*,i
endsubroutine
!--------------------------------------------------------------
subroutine dog(i)
integer::i
if(i<4000) call test(i+1)
endsubroutine
!--------------------------------------------------------------
program x15
implicit none
call test(0)
end program
' output -----------------------------------------------------------------------------------------------------------------------------------
4000
3900
3800
3700
3600
3500
3400
3300
3200
3100
3000
2900
2800
2700
2600
2500
2400
2300
2200
2100
2000
1900
1800
1700
1600
1500
1400
1300
1200
1100
1000
900
800
700
600
500
400
300
200
100
0