I am studying an ancient source written in Fortran IV (it is the
programme "Free Stochastic Music" by Xenakis in [1]) and I do not
understand the blank in the following line of code:
HX=HINF+HM*X RANF(-1)
By reading the theoretical text, I assume that RANF(-1) should be a
random number in [0,1). Also I assume by reading the theoretical text,
that HX should be a random number between HINF and HINF+HM.
Compiling the code with g95 and using a random number, say TEMP,
instead of RANF(-1), I always get for HX the value HINF and not what I
expect (that is a random number between HINF and HINF+HM). Could
someone please explain what the above assignment in Fortran IV means? I
would be grateful.
Best Regards
Alexandros
[1] Iannis Xenakis, Formalized Music; Thought and Mathematics in
Composition, Pendragon Press, Stuyvesant New York
> I am studying an ancient source written in Fortran IV (it is the
> programme "Free Stochastic Music" by Xenakis in [1]) and I do not
> understand the blank in the following line of code:
>
> HX=HINF+HM*X RANF(-1)
>
> By reading the theoretical text, I assume that RANF(-1) should be a
> random number in [0,1). Also I assume by reading the theoretical text,
> that HX should be a random number between HINF and HINF+HM.
> Compiling the code with g95 and using a random number, say TEMP,
> instead of RANF(-1), I always get for HX the value HINF and not what I
> expect (that is a random number between HINF and HINF+HM). Could
> someone please explain what the above assignment in Fortran IV means? I
> would be grateful.
One can't tell for sure what is going on here without context (in
particular all the relevant declarations).
The simple answer is that blanks are insignificant in Fortran prior to
f90 (and in fixed source form in f90 as well). Thus the line means the
same as if the blank was not there. This would imply that the line was
referencing a function named xranf (or potentially an array of that name
- see above comment about the lack of adequate context).
The use of blanks like that is not a style of coding that I personally
like; I think it invites confucions such as yours. But it is legal.
There is no ranf or xranf in standard Fortran. I haven't even heard of
xranf as a common extension. The fact that your code reportedly runs at
all (if it didn't, I don't see how you could say what result it gets)
suggests that it is finding an xranf somewhere; possibly that function
is elsewhere in the source code you have. See again comment about lack
of adequate context.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
In Fortran I (not that I ever programmed in it) function names
were required to end in F. Functions returning a fixed point
value were required to start with X. (XRANF was not a function
included in the Fortran I library, though.)
Assuming this isn't a program with roots back to Fortran I days,
it might be that someone used to older systems kept the X naming
convention. The blank might have made it easier to change the
name when converting between systems. (Editing on cards isn't
quite the same as the editors available today.)
It would be interesting to see the rest of the program, which
might help explain the usage.
(snip)
-- glen
According to the documentation I have seen, user-written functions
didn't come in until Fortran II - it wasn't that they were required
to end in 'F', so much as the built-in ones did.
But a spurious blank could simply be accidental (the word 'error'
isn't right, as it is perfectly correct) - without seeing the rest
of the program, there's no way to tell.
Regards,
Nick Maclaren.
>>In Fortran I (not that I ever programmed in it) function names
>>were required to end in F. Functions returning a fixed point
>>value were required to start with X. (XRANF was not a function
>>included in the Fortran I library, though.)
> According to the documentation I have seen, user-written functions
> didn't come in until Fortran II - it wasn't that they were required
> to end in 'F', so much as the built-in ones did.
Depends on your definition of user-written. In a paragraph near
the end:
"Library subroutines exist on the master Fortran tape in relocatable
binary form. Placing new subroutines on that tape involves
(1) producing the routine in the form of relocatable binary cards
(2) transcribing those cards on to the master tape by means of
the program provided for that purpose."
It doesn't even mention an assembler, but I presume one was available.
-- glen
User-written in Fortran.
Regards,
Nick Maclaren.
>>Depends on your definition of user-written.
> User-written in Fortran.
Yes, not until Fortran II.
Though random number generators for many years were written in assembly.
Still my favorite are those for OS/360 which can be declared
either REAL or INTEGER and return the appropriate value.
-- glen
You could do that for DOUBLE PRECISION and COMPLEX as well :-)
Regards,
Nick Maclaren.
> In article <hcreo0$bth$1...@naig.caltech.edu>,
> glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
>>
>> In Fortran I (not that I ever programmed in it) function names
>> were required to end in F. Functions returning a fixed point
>> value were required to start with X. (XRANF was not a function
>> included in the Fortran I library, though.)
>
> According to the documentation I have seen, user-written functions
> didn't come in until Fortran II - it wasn't that they were required
> to end in 'F', so much as the built-in ones did.
The "F" at the end indicated that they had a single floating point
arguement that was passed in the accumulator. So SINF was one supplied
by the system with SIN in the library for the loader to find. User
functions rarely used this scheme although somthing like RANF would
be possible. In practice they had to be written in the assembley lanuage
for this to work. Non-"F" functions used an argument list as did subroutines.
Users who thought the trailing "F" was good style in Fortran had obscure
errors until they learned the naming rule.
HX=HINF+HM*X RANF(-1)
would mean
X=RANF(-1)
HX=HINF+HM*X
that is, RANF(-1) is assigned to X and then HX is computed.
Could this be possible in Fortran IV?
Best Regards
Alexandros
No.
If I interpret your original post correctly, you have a piece of code
you're attempting to read but not necessarily the entire working
application.
Assuming the blank is "real" and not simply an artifact of some
reproduction process, the interpretation would have to be that of
HX=HINF+HM*XRANF(-1)
since blanks were never significant and the most logical conclusion is
that there was a function XRANF() w/ the original application.
The assumption that it would have been a uniform prng function is
reasonable; to implement the code w/ a modern compiler either use the
supplied intrinsic function in its place or another of your choice.
--
> X=RANF(-1)
> HX=HINF+HM*X
If you just wanted to make this work, try:
call random_number(x)
hx = hinf+hm*x
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
No. It is not possible. Not even close.
I already said what the blank means. That answer isn't going to change
if you try reasking it in some other form. The blank means nothing and
the code has the same effect as if the blank were not there.
I am more than half suspicious that there might be a typo on this line,
but I have insufficient data to make a good guess as to the typo. (No,
I'm not prepared to go find a copy of the paper reference cited just to
answer this).
I went back and reread your original post carefully and noticed that you
did not say you had actually run this line of code as is, but rather
that you tried "using a random number, say TEMP, instead of RANF(-1)".
Another universal principle is that it is better to show code than to
describe it. In particular, show the code you actually ran rather than
showing code that you did not run and trying to describe the differences
between it and what you did run. If you did what I think you are trying
to describe above, then I can guess pretty well why you are getting the
described results.
I think you are saying that you coded
HX=HINF+HM*X TEMP
and TEMP was some variable that was assigned random values.
Reread my description of what blanks mean in versions of Fortran prior
to f90. They mean nothing. (Diversions into contexts where they can mean
something are not going to be helpful here; this isn't those contexts,
or close to them.) Instead of trying to guess that this description
might be incorrect, try to apply it to your code - the code that you
actually ran rather than what is in the book. It shouldn't be that hard,
but I'll help. Blanks mean nothing, so take it out as it is doing
nothing other than misleading you. That gives your line as
HX=HINF+HM*XTEMP
I hope you can tell me what that line means. If there are any
difficulties, I'll say that it means just what it looks like. No tricks.
And it involves something named XTEMP. It has nothing to do with
anything named TEMP, so it makes no difference what some TEMP thing
might be.
What, though, is XTEMP? This is probably a good place to mention the
merits of using IMPLICIT NONE. That wasn't available in Fortran IV, but
it will be available in any compiler you will find today (most certainly
including g95, which you mentioned). Of course, it can be a bother to
use with old code that is full of undeclared variables.
If you don't use IMPLICIT NONE, then typos and things like the above
just turn into implicitly declared variables. You didn't intentionally
declare a variable named XTEMP, but you appeared to be trying to use
one, so the compiler implicitly declared it for you. You probably never
gave XTEMP a value (since you didn't even intend for it to exist). That
means it is technically undefined and invalid to use, but odds are at
least reasonable that it might act as though it had the value zero,
which would match your reported results.
Well, my simple attempt to show that doesn't use zero, but then I don't
know what switches you used or anything else about the context. I used
g95 with
program clf
HINF = 42.
HM = 2.
HX=HINF+HM*XTEMP
write (*,*) hx
end
and it gave me 38.000263; evidently some random garbage in XTEMP. Note,
however, that even if old code might makek it painful to use IMPLICIT
NONE, there are other things compilers can do to help you. For example,
if I use g95's -Wall switch to turn on most warnings, it tells me
HX=HINF+HM*XTEMP
1
Warning (113): Variable 'xtemp' at (1) is used but not set
I don't believe that would happen for any Fortran version
in a million years. (Wait for Fortran 1002010)
C has the assignment operator, instead of assignment statement,
such that you could write:
hx=inf+hm*(x=ranf(-1));
The parentheses are required, as = has a low precedence. That is
extremely unlikely in Fortran IV, and there are no () in yours.
There were Fortran IV compilers that allowed multiple statements
on a line using unusual characters, such as the X'ff' character
(that is, char(255) in Fortran 90 terms). The X'ff' character
would be unprintable, and might print as blank on some printers,
such as the 1403. In that case, the statements would be executed
left to right, and there would have to be an = operator.
There might have been some Fortran IV compilers that accepted
= in place of .EQ., the relational equality operator. That also
seems unlikely to help your problem.
-- glen
>>Still my favorite are those for OS/360 which can be declared
>>either REAL or INTEGER and return the appropriate value.
> You could do that for DOUBLE PRECISION and COMPLEX as well :-)
Well, not for a 31 or 32 bit generator. If you don't care
about wasting bits you might as well go for COMPLEX*16 and REAL*16,
or even COMPLEX*32.
For those not following the discussion, the OS/360 calling
convention returns INTEGER values in general register 0, REAL
in floating point register 0, COMPLEX*8 in F0 and F2.
Also, REAL*16 also in F0 and F2, and finally COMPLEX*32
in all four floating point registers.
-- glen
Thanks for all answers. No I understand what's wrong with the code (and
the rewritten code in Fortran 95 in [1] that I used).
The rewritten code translates
HX=HINF+HM*X RANF(-1)
of Fortran IV in
CALL RANDOM_NUMBER(TEMP)
HX=HINF+HM*X TEMP
of Fortran 95. This compiled with g95 does simply HX=HINF, as there is
not a variable XTEMP in the source, except this point (that is, XTEMP
has the value 0 for the assignment of HX). So XTEMP is a "problem" of
the translated code.
Now, the original
HX=HINF+HM*X RANF(-1)
must be a typo. I have reasons to believe that the correct should be
HX=HINF+HM*RANF(-1)
Thank you all for your very valuable comments and excuse me for
bothering you with this probable typo of this "ancient" source. ;)
Best Regards
Alexandros
[1] http://users.on.net/~parisdownes/code/FORTRAN/XENAKIS.FOR
I meant: "Now I understand [...]"
Why not? I did it. I hope that you aren't assuming that a
pseudo-random number generator returns its state as the result.
All sane ones use hidden state, and separate initialisation (and,
if supported, saving and restoring calls).
>For those not following the discussion, the OS/360 calling
>convention returns INTEGER values in general register 0, REAL
>in floating point register 0, COMPLEX*8 in F0 and F2.
>Also, REAL*16 also in F0 and F2, and finally COMPLEX*32
>in all four floating point registers.
And the top half of a REAL*8 number was the REAL*4 value, with
least significant bits lost.
Regards,
Nick Maclaren.
The above url is clearly the code AFTER you changed it to use TEMP. I for
one am very curious to see original.
--
Qolin
Email: my qname at domain dot com
Domain: qomputing
Exactly, this is the tranlsation of the original (Fortran IV) in Fortran
95 (not by me, I just experimented with it). Unfortunately I have the
original only in paper form.
Alexandros
Would any of these help?
xranf: A random number in range -1 .. +1
http://www.linuxsir.com/bbs/thread304809.html
xranf: random number in range 0 .. 1
http://read.pudn.com/downloads21/sourcecode/graph/71499/gems/FastJitter.c__.htm
xranf: random integer in range 0 .. (argument value)
lss.fnal.gov/archive/other/mura/MURA-580.pdf
This would make -1 a 'funny' number
xranf: random number in range 0 .. 1
http://www.google.com/codesearch/p?hl=en&sa=N&cd=2&ct=rc#91PXtzWoYR8/cpmd/src/util.F&q=xranf%20lang:fortran
Thanks for this list! Item 3 is very interesting,
but, as you mention, xranf(-1) ist not defined.
Items 2 and 3 would do the job, but.. the code I'm studying is from
1963.
HAND
Alexandros
I found the source of the original source code online. It is in
the book is at
http://books.google.com/books?id=y6lL3I0vmMwC&printsec=frontcover&dq=formalized+music#v=onepage&q=&f=false
The source is on pages 145-152 (jump from contents page to
chapter VI and then a few pages backwards).
Best Regards
Alexandros
Interesting. It says Fortran IV for the 7090, but it still uses
Fortran II style I/O statements and functions (with the trailing F).
(OS/360 Fortran IV supports the Fortran II I/O statements, but as
far as I know not the function names with the trailing F.)
It looks like a mistake. All other references are to RANF.
Two statements before, a value is assignned to X, so it is possible
that it should be X*RANF(-1), or maybe just X or just RANF(-1).
It might be that one could tell from the text what was expected
at that point.
Note that the version on the previously mentioned web site still
has the X TEMP in it, presumably an undefined variable.
-- glen
I googled this book and found a site which has a pdf version for
download. It's a different edition/pressing and the offending line of
code here simply reads:
520 HX=HINF+HM*X
So it appears to be an error in the edition the OP is using.
Erik.
No.
For many years they were written in the same language as
the source program.
They were trivial to write, and assuming that one had a HLL,
they would be written in that same HLL and incorporated as an
ordinary function or subroutine.
| I am studying an ancient source written in Fortran IV (it is the
| programme "Free Stochastic Music" by Xenakis in [1]) and I do not
| understand the blank in the following line of code:
|
| HX=HINF+HM*X RANF(-1)
Either a typo, or the name of the random generator is XRANF.
Are there other exaples like that in the code?
Very interesting! I searched for this and found it (Indiana University
Press), but I think that is an error as well, because 3 lines above we
read:
IF (HPR.LE.0.0) GO TO 520
Thus, if HPR <= 0 (which always is for the 1st time of the loop), then X
has no value assigned, and the assigment of HX after 3 lines
(HX=HINF+HM*X) becomes deterministic; therefore X has no meaning to be
used there. If here Xenakis did mean
520 HX=HINF+HM*RANF(-1)
then HX is distributed uniformly in [HINF, HINF+HM), as for all other
iterations of the loop, which maybe makes more sense according to the
theory of Xenakis.
HAND
Alexandros
Here I assume that a variable with no assigned value has the value
0. Is this so for Fortran IV?
Alexandros
No. It can happen to be so for some compilers, but it is not and has not
been part of the language specification. It did used to be fairly common
for some users to code with such an assumption. But then, most people
didn't pay much attention to the language specifications or portability
in those days. If it happened to work on the particular compiler and
machine they were using, then that was all they cared about. After all,
odds were that they wouldn't see a different machine for many years, so
portability wasn't typically on the top of their mind.
I didn't study all the code yet, but as far as I looked, no.
Lookng at the listing in the text you referenced, the line is as you
have listed it. It's very odd in context. I saw no other variables
where an extra blank appears in the middle of an identifier, nor did I
see any other references to XRANF().
To me, the interesting line is "Translated into Fortran IV" - from
what? IIRC function names ending in F were earlier than Fortran IV.
For example the listing contains FLOATF() instead of the expected FLOAT
(). I distinctly remember FLOAT() and CALL EXIT from late '62 or early
'63 (Wayne State University).
-- Elliot
As in my first post, that would seem most likely.
Being a pragmatist first, if I were trying to do something w/ this code,
I'd go w/ that and run w/ it until I got a result that indicated that
wasn't working so good. :)
Note the caveat Richard M responded to on your assumption about
zero-initialized variables by default.
The other thing I'd do w/ any code like this before the above "plow
ahead" approach would be to add
IMPLICIT NONE
and fix those errors thus arising and then use compiler diagnostics to
ensure find and fix those uninitialized variables and other such
"tidying up".
Then, see what happens...after all, given the subject matter WW III
isn't _too_ likely... :)
--
No.
C does require static variables to be initialized to zero.
Some Fortran compilers based on the back end of a C compiler
will then also do that for static variables.
Many (maybe most) Fortran IV compilers generated all variables
as static, but that was before C and C compilers.
One systems that I used in the Fortran IV days had modified
the linker, which actually fills in the initial value for
otherwise uninitialized (not in DATA statement) variables,
to initialize to X'81'. That resulted in large negative integers,
and very small floating point values, which were often visible
in the results. (and 'a' as a character value)
-- glen
It would seem to me Fortran II.
I believe the 7090 had both Fortran II and Fortran IV compilers,
and the latter supported some Fortran II features to make conversion
easier.
> IIRC function names ending in F were earlier than Fortran IV.
> For example the listing contains FLOATF() instead of the expected FLOAT
> (). I distinctly remember FLOAT() and CALL EXIT from late '62 or early
> '63 (Wayne State University).
FLOAT is still in Fortran 2003, as a specific version of the
generic REAL.
EXIT I believe didn't make it into Fortran IV or 66, except as a
back compatibility feature.
-- glen
> Alexandros Droseltis <usen...@alex-droseltis.com> wrote:
>
> > On 2009-11-05, Alexandros Droseltis <usen...@alex-droseltis.com> wrote:
> > >
> > > Thus, if HPR <= 0 (which always is for the 1st time of the loop), then X
> > > has no value assigned, and the assigment of HX after 3 lines
> > > (HX=HINF+HM*X) becomes deterministic; therefore X has no meaning to be
> > > used there.
> >
> > Here I assume that a variable with no assigned value has the value
> > 0. Is this so for Fortran IV?
>
> No. It can happen to be so for some compilers, but it is not and has not
> been part of the language specification....
On rereading what I wrote, I think that, while it was accurate, it
wasn't the most appropriate tone or message for the specific audience
(the OP). I was writing more as though to a programmer (much of the
audience here) instead of to someone trying to understand an existing
program. So to take the same message, but rephrase it for a different
audience, I'd say...
1. No, this isn't so for the language. (I have to stick with that part).
But it might well have been something that the author of the original
code assumed anyway. If you need to make an assumption like that for the
code to make sense, then that might be what was originally intended. If
that is the case, you want to fix the code by making the initial 0 value
explicit.
2. I'd alternatively guess there to be significant chance that the
author of the original code simply failed to notice that it used an
undefined value. It does take a certain level of discipline to watch for
such things. I know that my own younger self was less careful about such
things than my older, more experienced self (see signature).
At this point, it looks like a mistake in the original code.
> 2. I'd alternatively guess there to be significant chance that the
> author of the original code simply failed to notice that it used an
> undefined value. It does take a certain level of discipline to watch for
> such things. I know that my own younger self was less careful about such
> things than my older, more experienced self (see signature).
In the case of programs using random numbers, it can be difficult to
detect 'wrong' results from the program output. It might be slightly
less random than it should be, or maybe slightly more. For some
programs, you can supply specific input data and check that the
output agrees with the input. That is very difficult for programs
using random numbers.
Though IBM compilers used to be pretty good about printing out
a table of all the variables and their location in memory.
(Especially useful when debugging from memory dumps.) A quick
look through that table can identify unexpected variable names.
-- glen
Particularly useful for this kind of problem was the CDC listing
cross-reference that also identified the first use of each variable that
went a long way towards being able to find uninitialized. Couldn't
catch everything, of course (COMMON being most obvious), but better than
most compilers for PC I've seen yet (not that I have a very large sample).
--
> 1. No, this isn't so for the language. (I have to stick with that part).
> But it might well have been something that the author of the original
> code assumed anyway. If you need to make an assumption like that for the
> code to make sense, then that might be what was originally intended. If
> that is the case, you want to fix the code by making the initial 0 value
> explicit.
...
I suppose it wouldn't be too far off base here to point out that many
compilers have an option that will do that so that one can as a shortcut
bypass having to find/fix all occurrences.
While certainly not the best solution in the long run nor my
recommendation as a final fix, it might help in getting somewhere more
or less quickly.
The other thing one can do that way is to start the rng w/ same sequence
and compare results with and without the "zero-memory" flag. If is a
difference, it'll identify there is a problem that needs addressed.
--
No. That was so in the days of FORTRAN IV,
and is sstill so for virtually all implementations of Fortran now.
I decided to check my university library and I just borrowed this book,
but the interesting lines in my version are:
-----
510 X=RANF(-1)
IF (N.GT.1) GO TO 530
520 HX=HINF+HM*X
GO TO 560
-----
My version is also slightly different to yours:
Xenakis (1971) Formalized music, Indiana University Press:
Bloomington/London, ISBN: 0-253-32378-9.
>
> I suppose it wouldn't be too far off base here to point out that many
> compilers have an option that will do that so that one can as a shortcut
> bypass having to find/fix all occurrences.
Even better is when the compiler has the option to initialize variables
to something other than zero, such as NaN for floating point variables
or large negative values for integers. I find these kinds of options
work much better at tracking down these kinds of program bugs.
$.02 -Ron Shepard
Some compilers (e.g. Silverfrost FTN95) flag some uninitialised usages.
Others (such as PL/C) used one value as a flag and tested
for uninitialised at run time.
IBM's PL/I F-compiler (1966) could produce a complete cross-reference,
including line numbers of all references to any given variable,
where declared, and the attributes of the variable.
Their PL/I compilers can still do that.
OS/360 didn't, in general, have 16-byte reals.
real F.P. occupied 32 bits and 64 bits.
How function results were returned depended not on the
OS but on the hardware and the particular compilers.
It wasn't until the S/370 that quad precision was available
(and then only for +. -. * but not division),
and the OS then was OS/370. (And once again, the OS has nothing
to do with the way that function results are returned.)
It was supported in hardware on the 360/85, and software
on other processors. My first hand dissassembly was from
a hex dump of the OS/360 DXR emulation routine.
> How function results were returned depended not on the
> OS but on the hardware and the particular compilers.
Mixed language programming is much easier if they use the
same convention. Even more between different compilers
for the same language.
> It wasn't until the S/370 that quad precision was available
> (and then only for +. -. * but not division),
Yes only +, -, and * (until about half way through ESA/390
when DXR was finally supported by hardware). IBM did a
study on the cost vs. advantage of each and decided that
divide was relatively less common, and software, which used
the other operations in hardware, was the best way to go.
(Published in IBM Systems Journal.)
> and the OS then was OS/370. (And once again, the OS has nothing
> to do with the way that function results are returned.)
There is no OS/370. OS/360 ran on S/370 hardware, otherwise
there is OS/VS1, OS/VS2 and MVS/370.
-- glen
Only if the compiler and/or run-time can't detect uninitialized variables.