Determine machine epsilon in fortran - fortran

How can I write a program in FORTRAN 90 that determines the machine epsilon in any computer ?
type ErrorOrT[M[+_], A] = EitherT[M, Throwable, A]
type ErrorOr[A] = ErrorOrT[IO, A]

You'd read to the back of your favourite Fortran reference where you'd find the intrinsic function epsilon
And, if you think the code you've posted is Fortran you've been misled.

Related

Is there a built in Chi square CDF function in C++

I am trying to find a builtin CDF for chi square distribution.
Basically, I wish to have a CDF function like pchisq in R, where
chisquare(x,p,q) gives you the probability. x is the distribution of the function, p is the dof and q is the noncentrality parameter. I tried looking for some packages, but some library does not take in the q parameter.
To answer your question, unfortunately, no, this doesn’t exist in C++ as of C++20.
I needed to compute this CDF earlier today for a project and ended up just coding it up as a Riemann sum. For the special case where for k = 1, where the Riemann integral is hard to evaluate accurately because of the blowup of the PDF at x = 0, is used the fact that the CDF is given by erf(sqrt(x)), and those functions do exist in C++ in the <cmath> header.

Fortran compiler differences in treating properties as 'save attributes'?

We have this old Fortran script that we're trying to recompile using Intel's Visual Fortran but we get calculation errors and different results than the old compiled version of the code.
We found what we believe to be the problem in the code below (which is loosely from Numerical Recipes).
The problem is that the 'it' parameter is reset for each call, it should however be stored between the function calls.
Our best guess for what might be the problem is that an older compiler might have treated 'it' as a 'save attribute' and therefore stored it between the function calls.
We may be completely wrong here and if some Fortran-guru can confirm this or have a better explenation we would love some help!
subroutine TrapezoidalRule(Func, a, b, s, n)
*
* This routine performs the trapezoidal rule, see Numerical Recipes
*
implicit none
real*8 Func, a, b, s
Integer*4 n
external Func
*
real*8 del, x, sum
Integer*4 it, tnm, j
*
if (n .eq. 1) then
*
s=0.5d0*(b-a)*(Func(a)+Func(b))
it=1
*
else
*
tnm=it
del=(b-a)/dble(tnm)
x=a+0.5d0*del
sum=0.d0
do 11 j=1,it
*
sum=sum+Func(x)
x=x+del
*
11 continue
*
s=0.5d0*(s+(b-a)*sum/dble(tnm))
it=2*it
*
endif
*
return
end
Yes, the explanation is plausible. The code accesses variable it at
tnm=it
and this value is undefined when it is not save.
The old compile might not have used stack at all and might have used static storage for all variables. It also might have used stack, but it never got overwritten and the value happened to be at the same place. Who knows, we don't have the information to know.
There are compiler options to force the save attribute to all variables for bad codes like this (the SAVE for all was never standard!). It is just -save for Intel Fortran.

GNU Fortran ctime equivalent in IBM xl fortran

I am trying to build a Fortran codebase on an IBM xl system with one source file giving compilation error as follows:
line 152.16: 1516-036 (S) Entity ctime has undefined type
After some Googling, I figure that ctime is a GNU Fortran function which is why the xl compilers are not liking it. Can someone suggest if there is any alternative function for ctime in IBM xl fortran compilers.
The ctime function converts a system time value to string. Ref section 9.74 pp. 124 of https://gcc.gnu.org/onlinedocs/gfortran.pdf
Fortran, since the 1990 standard if I remember correctly, defines a standard subroutine called date_and_time which will return the current date and time (if the computer it is running on is capable of telling a program that) in character and in numeric forms. Consult your favourite documentation set for details.
If your problem is to convert a date and time value stored in some numeric format to a string, that's what internal writes are for. If you don't know how to use internal writes to transform numbers into strings then (a) tut, and (b) ask for clarification.
If your entire codebase is infected with ctime you could write your own implementation and have the IBM compiler compile it for you.
The equivalent subroutine is ctime_, as mentioned in one of the answers, but note that the order of the arguments is different.
gfortran:
call ctime(time, result)
where time is an intent(in) integer argument
and result is an intent(out) character argument
XL Fortran:
call ctime_(str, time)
where str is the intent(out) character argument
and time is the intent(in) integer argument
You can find the full documentation of ctime_ in the XL Fortran language reference in the service and utility procedures chapter. Here is a link to the function in the XL Fortran 15.1 language reference:

How are the types in this COMMON statement specified?

I have an old fortran code that I am attempting to decipher and understand what is going on so I can modify it. Unfortunately I am a bit of a neophyte in fortran so I am having trouble figuring out this statement.
C 15/04/97 IBM VERSION ECIS96 CALC-000
SUBROUTINE CALC(W,NW,DW,IDMX) CALC-001
C MAIN SUBROUTINE OF THE PROGRAMME CALC-002
C W,NW,DW ARE THE WORKING SPACE IN EQUIVALENCE BY CALL,STARTING AS CALC-003
C REAL*8. THEY ARE RESPECTIVELY REAL, INTEGER AND DOUBLE PRECISION. CALC-004
C IDMX IS THE LENGTH OF DW. CALC-005
C CALC-006
C ADDRESSES IN THE WORKING FIELD DEFINED HERE (FOR OTHERS, SEE CALX) CALC-007
C IN COMMON /DECOU/ CALC-008
C 34- NT HERE, ALSO REDUCED NUCLEAR MATRIX ELEMENTS CALC-009
C 35- NIVQ TABLE OF MULTIPOLES CALC-010
C 36- NIVY TABLE OF FORM FACTOR IDENTIFICATION IVY (FOR COMPUTATION)CALC-011
C 37- NIVZ TABLE OF FORM FACTOR IDENTIFICATION IVZ (FOR USE) CALC-012
C 38- NCOI ADDRESS OF THE TABLE FOR DISCRETISATION OF CONTINUUM CALC-013
C 39- MIPI SAME AS NIPI FOR THE DISCRETISATION OF CONTINUUM CALC-014
C 40- NXD ADDRESS OF WEIGHTS AND STEPS OF CONTINUUM CALC-015
C 41- MWV SAME AS NWV FOR THE DISCRETISATION OF CONTINUUM CALC-016
C 42- NIXT TRANSMISSION COEFFICIENTS OF UNCOUPLED STATES CALC-017
C 43- NTY TEMPORARY RESULTS OF COMPOUND NUCLEUS FOR INTERPOLATION CALC-018
C 44- NTX PARTIAL REACTION CROSS SECTIONS AND COMPOUND NUCLEUS CALC-019
C 45- NRY COMPOUND NUCLEUS COEFFICIENTS CALC-020
C 46- NRCO STRENGTH OF COULOMB CENTRAL POTENTIALS FOR CORRECTIONS CALC-021
C 47- NRDO STRENGTH OF COULOMB TRANSITION POTENTIALS FOR CORRECTIONSCALC-022
C 48- NVC1 REAL POTENTIALS CALC-023
C 49- NVC2 IMAGINARY POTENTIALS CALC-024
C 50- NNC FIRST FREE ADDRESS AFTER COMPUTATION OF POTENTIALS CALC-025
C 51- NCX FIRST FREE ADDRESS FOR COMPUTATION OF POTENTIALS CALC-026
C OTHER INTEGER DATA OF COMMON /DECOU/ CALC-027
C 52- IDMT TOTAL WORKING FIELD LENGTH AS SINGLE PRECISION CALC-028
C 53-98 SEE CALX CALC-029
C 99- KXT NUMBER OF PENETRABILITIES FOR UNCOUPLED STATES CALC-030
C100- NRZ NUMBER OF RESULTS TO SAVE FOR MINIMUM CHI2 CALC-031
C101- NTZ NUMBER OF MEMRIES TO INITIALISE TO ZERO FOR SCATTERING CALC-032
C MATRIX AND COMPOUND NUCLEUS RESULTS CALC-033
C102- LMAX3 EFFECTIVE NUMBER OF COULOMB FUNCTIONS CALC-034
C103- IPM NUMBER PF J VALUES USED FOR SCATTERING MATRIX (IN CAL1) CALC-035
C104- IPK NUMBER PF J VALUES USED FOR COMPOUND NUCLEUS (IN CAL1) CALC-036
C105-110 SEE CALX CALC-037
C CALC-038
C IN COMMON /DBLPR/ CHI2,CHI2M: CHI-SQUARE AND MINIMUM CHI-SQUARE CALC-039
C CM,CHB: NUCLEAR MASS AND H BAR CALC-040
C CK,CMB,CCZ: DERIVED CONSTANTS CALC-041
C XE,XM,XN: RELATIVISTIC ENERGY AND MASS (COLF) CALC-042
C XZ: CONVERSION FACTOR TO MILLIBARNS CALC-043
C FOR COMMONS /POTE1/ AND /POTE2/ SEE REDM CALC-044
C FOR COMMON /NCOMP/ SEE CALX, LECT AND COLF CALC-045
C CALC-046
C*some information on logical variables that is unimportant to this*
DOUBLE PRECISION CHI2,CHI2M,CM,CK,CHB,CMB,CZ,CCZ,XE,XM,XN,XZ,DW(1)CALC-095
LOGICAL LO(250) CALC-096
DIMENSION W(1),NW(1) CALC-097
COMMON /DECOU/ NJIT,NIPP,NIPI,NWV,NIPH,NSCN,NPAR,NNIV,NFIS,NGAM,NPCALC-098
1OT,NBETA,NFM,NTGX,NDONN,NRC,NIW,NDE,NISE,NNVI,NNWI,NCC,MCC,NXA,NAMCALC-099
21,NFAC,NFAM,NPAD,NFG,NXG,NSM,NRES,NXX,NT,NIVQ,NIVY,NIVZ,NCOI,MIPI,CALC-100
3NXD,MWV,NIXT,NTY,NTX,NRY,NRCO,NRDO,NVC1,NVC2,NNC,NCX,IDMT,NCOLL,NJCALC-101
4MAX,ITERM,NPP,JDM,JIT,NSEC,LMD,MCM(2),NCOLS,NCOLT,KMAX,KMIN,NVA,NBCALC-102
5ET,NBT1,LMX,LMAX1,NLT,ISM,IQM,IQMAX,MS1,MS2,NCT(6),KBA,KAB,KBC,KCCCALC-103
6,NJC,JTX,JTH,NCOLR,NREC,NTOT,NFA,LMAX2,KE,ITEMM,NPLACE,KXT,NRZ,NTZCALC-104
7,LMAX3,IPM,IPK,H,BJM,EITER,ACONV,CONJ,ASPIN CALC-105
COMMON /DBLPR/ CHI2,CHI2M,CM,CK,CHB,CMB,CCZ,XE,XM,XN,XZ CALC-106
COMMON /POTE1/ ITX(16),IMAX,INTC,INLS,INVC,INVD,ITXM CALC-107
COMMON /POTE2/ ITY(8),INVT,INTV,INSL,NPX CALC-108
COMMON /NCOMP/ NSP(3),NFISS,NRD,NCONT,NCOJ,ACN1,ACN2,NCONS,NIE,NCOCALC-109
1LX,NDP,NDQ,AZ(6),BZ1,BZ2,BZ3,TG0,BN,FNUG,EGD,GGD,TG1,SGSQ CALC-110
If it helps this is how the function is called.
C 18/12/87 IBM VERSION CONVEX ECIS88 ECIS-000
REAL*8 W(600000) ECIS-001
COMMON W ECIS-002
CALL CALC(W,W,W,600000) ECIS-003
STOP ECIS-004
END ECIS-005
I already understand the line continuations and that for lines CALC-099 through CALC-105 the first non-whitespace numbers are just counting the continuations since the compiler is jumping to column 7 for the continuation.
What I do not understand is how the types are decided. Is it something automatically determined on first assignment, my understanding of how common blocks work makes this seem unlikely. Is it something in the naming, is the first character somehow determining it?
Also, what are the dimension statements doing here? If the array is 600,000 long why is the dimension statement "setting" its length to 1, or is it doing something I am not seeing?
Both parts of your question are something that horrifies modern people.
First, implicit typing. Variables, unless they have an explicit type, take an implicit type. Variables beginning I-Nare INTEGER and others are REAL. The IMPLICIT statement overrides this, however, so look out for that (never underestimate what evils programmers can do). Also, note that IMPLICIT NONE is a later addition to the standard.
Second, in subroutines DIMENSION(1) (or equivalent) was an alternative to DIMENSION(*).
The default typing in FORTRAN77 is
IMPLICIT REAL(A-H, O-Z), INTEGER(I-N)
Which means variables that start with letters i,j,..,n are INTEGER and the rest are REAL.
Reference URL

Fortran 90 kind parameter

I am having trouble understanding Fortran 90's kind parameter. As far as I can tell, it does not determine the precision (i.e., float or double) of a variable, nor does it determine the type of a variable.
So, what does it determine and what exactly is it for?
The KIND of a variable is an integer label which tells the compiler which of its supported kinds it should use.
Beware that although it is common for the KIND parameter to be the same as the number of bytes stored in a variable of that KIND, it is not required by the Fortran standard.
That is, on a lot of systems,
REAl(KIND=4) :: xs ! 4 byte ieee float
REAl(KIND=8) :: xd ! 8 byte ieee float
REAl(KIND=16) :: xq ! 16 byte ieee float
but there may be compilers for example with:
REAL(KIND=1) :: XS ! 4 BYTE FLOAT
REAL(KIND=2) :: XD ! 8 BYTE FLOAT
REAL(KIND=3) :: XQ ! 16 BYTE FLOAT
Similarly for integer and logical types.
(If I went digging, I could probably find examples. Search the usenet group comp.lang.fortran for kind to find examples. The most informed discussion of Fortran occurs there, with some highly experienced people contributing.)
So, if you can't count on a particular kind value giving you the same data representation on different platforms, what do you do? That's what the intrinsic functions SELECTED_REAL_KIND and SELECTED_INT_KIND are for. Basically, you tell the function what sort of numbers you need to be able to represent, and it will return the kind you need to use.
I usually use these kinds, as they usually give me 4 byte and 8 byte reals:
!--! specific precisions, usually same as real and double precision
integer, parameter :: r6 = selected_real_kind(6)
integer, parameter :: r15 = selected_real_kind(15)
So I might subsequently declare a variable as:
real(kind=r15) :: xd
Note that this may cause problems where you use mixed language programs, and you need to absolutely specify the number of bytes that variables occupy. If you need to make sure, there are enquiry intrinsics that will tell you about each kind, from which you can deduce the memory footprint of a variable, its precision, exponent range and so on. Or, you can revert to the non-standard but commonplace real*4, real*8 etc declaration style.
When you start with a new compiler, it's worth looking at the compiler specific kind values so you know what you're dealing with. Search the net for kindfinder.f90 for a handy program that will tell you about the kinds available for a compiler.
I suggest using the Fortran 2008 and later; INT8, INT16, INT32, INT64, REAL32, REAL64, REAL128. This is done by calling ISO_FORTRAN_ENV in Fortran 2003 and later. Kind parameters provides inconsistent way to ensure you always get the appropriate number of bit representation
Just expanding the other (very good) answers, specially Andrej Panjkov's answer:
The KIND of a variable is an integer label which tells the compiler
which of its supported kinds it should use.
Exactly. Even though, for all the numeric intrinsic types, the KIND parameter is used to specify the "model for the representation and behavior of numbers on a processor" (words from the Section 16.5 of the standard), that in practice means their bit model, that's not the only thing a KIND parameter may represent.
A KIND parameter for a type is any variation in its nature, model or behavior that is avaliable for the programmer to choose at compile time. For example, for the intrinsic character type, the kind parameter represents the character sets avaliable on the processor (ASCII, UCS-4,...).
You can even define your own model/behaviour variations on you defined Derived Types (from Fortran 2003 afterwards). You can create a Transform Matrix type and have a version with KIND=2 for 2D space (in which the underlying array would be 3x3) and KIND=3 for 3D space (with a 4x4 underlying array). Just remember that there is no automatic kind conversion for non-intrinsic types.
From the Portland Group Fortran Reference, the KIND parameter "specifies a precision for intrinsic data types." Thus, in the declaration
real(kind=4) :: float32
real(kind=8) :: float64
the variable float64 declared as an 8-byte real (the old Fortran DOUBLE PRECISION) and the variable float32 is declared as a 4-byte real (the old Fortran REAL).
This is nice because it allows you to fix the precision for your variables independent of the compiler and machine you are running on. If you are running a computation that requires more precision that the traditional IEEE-single-precision real (which, if you're taking a numerical analysis class, is very probable), but declare your variable as real :: myVar, you'll be fine if the compiler is set to default all real values to double-precision, but changing the compiler options or moving your code to a different machine with different default sizes for real and integer variables will lead to some possibly nasty surprises (e.g. your iterative matrix solver blows up).
Fortran also includes some functions that will help pick a KIND parameter to be what you need - SELECTED_INT_KIND and SELECTED_REAL_KIND - but if you are just learning I wouldn't worry about those at this point.
Since you mentioned that you're learning Fortran as part of a class, you should also see this question on Fortran resources and maybe look at the reference manuals from the compiler suite that you are using (e.g. Portland Group or Intel) - these are usually freely available.
One of the uses of kind could be to make sure that for different machine or OS, they truly use the same precision and the result should be the same. So the code is portable. E.g.,
integer, parameter :: r8 = selected_real_kind(15,9)
real(kind=r8) :: a
Now this variable a is always r8 type, which is a true "double precision" (so it occupies 64 bits of memory on the electronic computer), no matter what machine/OS the code is running on.
Also, therefore you can write things like,
a = 1.0_r8
and this _r8 make sure that 1.0 is converted to r8 type.
To summarize other answers: the kind parameter specifies storage size (and thus indirectly, the precision) for intrinsic data types, such as integer and real.
However, the recommended way now is NOT to specify the kind value of variables in source code, instead, use compiler options to specify the precision we want. For example, we write in the code: real :: abc and then compile the code by using the compiling option -fdefault-real-8 (for gfortran) to specify a 8 byte float number. For ifort, the corresponding option is -r8.
Update:
It seems Fortran experts here strongly object to the recommended way stated above. In spite of this, I still think the above way is a good practice that helps reduce the chance of introducing bugs in Fortran codes because it guarantees that you are using the same kind-value throughout your program (the chance that you do need use different kind-values in different parts of a code is rare) and thus avoids the frequently encountered bugs of kind-value mismatch between dummy and actual arguments in a function call.