How to input/output and format data in classic Fortran? - fortran

I'm an enthusiast for retro stuff and I was checking out the first manuals of Fortran. After investigating seems like the input/output instructions and formatting them has remained relatively similar. There is one example in the manual where it reads N numbers (you specify N and then the N numbers in a punch card), and its written as:
READ 1, N, (A(I), I=1,N)
1 FORMAT (I3/(12F6.2)) `
I understand that, with the format of 1, it grabs N and then the N elements. I understand that I3 stands for a 3 digits integer, and 12F6.2 stands for a repetition of 12 elements of width 6 with 2 decimals. However, I don't really get what the slash between I3 and 12F6.2 does. Also, I'm not sure how to input the data from the command line. I know I could simply use READ(,) but I'd really like to learn how to format first. I've changed the floating point from 12F6.2 to 12F6.0 so that I can just type integers.
Also, I would really appreciate why there's a 12 in front of F6.2. I know it repeats the input data, but if I wanted to type 15 numbers, would it still work since I only specified the first 12? I'm quite confused with the syntax. Thanks in advance!
I've tried everything! From writing the data as 3 2 5 6 (N=3, elements 2, 5, 6) to 3, 2, 5, 6, to first type 3, then ENTER, and then the numbers, to change the 12F6.0 to I3 (which doesn't work)...

Related

Calculating bytes from sextets in C/C++ for steganography

This should be a simple question. I'm well advanced in developing steganographic code in C, which required manipulating the least significant bit in each R, G, and B channel of a 24 bit (3 byte) pixel of an image. A pair of pixels has 6 bits (which I call a sextet for want of a better word) that can be used, and I have developed code that converts a buffer in bytes to a buffer in sextets, where each byte in the latter buffer only uses the 6 lower order bits, with the upper 2 bits being discarded when changing pixels. This all works correctly, and I can encode text in any language in an image.
In doing this the application calculates the number of sextets that can be embedded in an image. However, it is useful to know how many bytes can be processed, as both the input is originally in bytes, and the output is recovered in bytes. As 4 sextets correspond to 3 bytes, I'm using the statement:
maxNumBytes = (3 * maxNumSexts - 2 * (maxNumSexts % 4)) / 4;
which converts and rounds down to a multiple of 3, where maxNumSexts and maxNumBytes are respectively the maximum number of sextets and bytes that can be hidden in an RGB image, and these two variable have the type int32_t. This formula works but is rather cumbersome, and I was wondering if someone could find something simpler that works correctly.
Incidentally, although the code is in C, this applies exactly in C++, hence that has been included as a tag, and some C++ code may be added later.
Many thanks for any suggestions.
I want all values between 24 and 27 to evaluate to 18, and likewise values between 28 and 31 to evaluate to 21, etc.
Since you want only multiples of 3, the last operation should be the multiplication by 3. And the "steps" on the input value is by 4 increments. So you can use this formula in integer arithmetic:
maxNumBytes = 3 * (maxNumSexts / 4);
Note 1: However, the actual number of bytes encoded by 27 sextets is 20, because 27 sextets contain 81 bits.
Note 2: Yes, a half byte is called a "nibble", from the verb. The form "nybble" is known, but rarely used.

What does this syntax mean in fortran?

I am working on a project and as I have not coded with Fortran before, I am struggling a lot. My professor gave me a code file which I need to fix but I don't understand the syntax.
So, in the file he has
g = some formula,
1 some formula
2 * some formula
3 / some formula.
What does 1, 2, 3, * and / do?
I asked my Professor, and he said that this is Fortran 77 code and 1, 2, 3 are used as indexing in column 6 and the g is in column 7 as that's how the Fortran code is written. But I was very confused why Fortran 77 only accepts code after column 7?
Thank you for all the replies.
What you are most likely looking at is Fixed source-form statement continuation which is part of the Fixed source form.
Fixed-form formatting is an old way of formatting code which still stems from the old punched-cards. Lines could only be 72 characters long, but sometimes you needed more. Hence, the statement-continuation character:
Except within commentary, character position 6 is used to indicate continuation. If character position 6 contains a blank or zero, the line is the initial line of a new statement, which begins in character position 7. If character position 6 contains any character other than blank or zero, character positions 7–72 of the line constitute a continuation of the preceding non-comment line.
source: Fortran 2018 Standard, Section 6.3.3.3
Which character is used as statement-continuation marker, is up to the programmer and his style. Often you see a <ampersand>-character (&), or <dollar>-character ($) or the <asterisk>-character (*) like so:
c23456789012345678901234567890123456789012345678901234567890123456789012
g = something long
& + something_longer
& + something_even_longer
However, in the really old days, people often numbered their lines.
c23456789012345678901234567890123456789012345678901234567890123456789012
0g = something long
1 + something_longer
2 + something_even_longer
and because space was limited, they removed all spaces, which sometimes becomes very confusing when you have numbers in your line:
c23456789012345678901234567890123456789012345678901234567890123456789012
0g=1.2345+
10.35697-
22.5789
This does not add 10.35697 and subtract 22.5789, but adds 0.35697 and subtracts 2.5789
The usage of numbers as statement continuation markers is again inherited from the punched-cards. A single punched-card represented a single Fortran statement. And on the card, the row and column numbers were printed (Thanks to High Performance Mark for this information)
Note: the asterisk and slash in the OP are nothing more than the normal multiplication and division.

Regex on binary data in python 3.6 shows weird behaviour

I'm trying to write a small script that reads binary data from a file before processing it further, with e.g. regex for simplifying some steps.
During the regex I'm seeing some weird behavior I just can't figure out of. Code basically goes like this (heavily stripped down to just include the relevant part):
fh = open(filename,'rb')
bd = fh.read(32) # binary data
xlen = bd[3] # byte that specifies length of a command - this may vary for each 32h byte read
bd_x = bd[4:4+xlen] # pick out interesting part of the data. for the data I see the weird behavior the length of bd_x will always be 7
if re.match(b'\x00((.*?){%d})\x30'%(xlen-2),bd_x):
update some other lists, etc
Just need to check if start of interesting data is \x00 and if end is \x30 with 5 other elements in between, for which value is irrelevant. Total length, including start and end I'm trying to match is thus 7, as mentioned.
In a sample file I have with random data, this works on about 100 of 130 32h byte chunks, for which it should match on all 130 and not just 100.
I did print out out the content of bd_x for both cases, e.g. for chunks where it worked and chunks where it didn't. Output from print(xlen,hexlify(bd_x)) (n for negative, p for positive).
n 7 b'000000290a0030'
n 7 b'0000002b0a0030'
n 7 b'0000002d0a0030'
n 7 b'0000002f0a0030'
n 7 b'000000310a0030'
n 7 b'000000330a0030'
p 7 b'00000003000030'
p 7 b'00000005000030'
p 7 b'00000000000030'
p 7 b'00000000020030'
As far as I can see, all samples should have matched in the regex. If I change to re.search it matches on all 130 chunks, but tbh I don't know why re.match isn't working for all chunks of data as the start always matches with \x00 and the rest should match too.
I've manually checked all the entries of the test file that fail in a hex-editor, and I just can't see why it doesn't work on those entries.
I know I can probably just do hexlify(bd_x) and just operate on the output from that function instead, but for now I'm interested in figuring out why this doesn't work.
Suggestions / solutions are appreciated.

Controlling newlines when writing out arrays in Fortran

So I have some code that does essentially this:
REAL, DIMENSION(31) :: month_data
INTEGER :: no_days
no_days = get_no_days()
month_data = [fill array with some values]
WRITE(1000,*) (month_data(d), d=1,no_days)
So I have an array with values for each month, in a loop I fill the array with a certain number of values based on how many days there are in that month, then write out the results into a file.
It took me quite some time to wrap my head around the whole 'write out an array in one go' aspect of WRITE, but this seems to work.
However this way, it writes out the numbers in the array like this (example for January, so 31 values):
0.00000 10.0000 20.0000 30.0000 40.0000 50.0000 60.0000
70.0000 80.0000 90.0000 100.000 110.000 120.000 130.000
140.000 150.000 160.000 170.000 180.000 190.000 200.000
210.000 220.000 230.000 240.000 250.000 260.000 270.000
280.000 290.000 300.000
So it prefixes a lot of spaces (presumably to make columns line up even when there are larger values in the array), and it wraps lines to make it not exceed a certain width (I think 128 chars? not sure).
I don't really mind the extra spaces (although they inflate my file sizes considerably, so it would be nice to fix that too...) but the breaking-up-lines screws up my other tooling. I've tried reading several Fortran manuals, but while some of the mention 'output formatting', I have yet to find one that mentions newlines or columns.
So, how do I control how arrays are written out when using the syntax above in Fortran?
(also, while we're at it, how do I control the nr of decimal digits? I know these are all integer values so I'd like to leave out any decimals all together, but I can't change the data type to INTEGER in my code because of reasons).
You probably want something similar to
WRITE(1000,'(31(F6.0,1X))') (month_data(d), d=1,no_days)
Explanation:
The use of * as the format specification is called list directed I/O: it is easy to code, but you are giving away all control over the format to the processor. In order to control the format you need to provide explicit formatting, via a label to a FORMAT statement or via a character variable.
Use the F edit descriptor for real variables in decimal form. Their syntax is Fw.d, where w is the width of the field and d is the number of decimal places, including the decimal sign. F6.0 therefore means a field of 6 characters of width with no decimal places.
Spaces can be added with the X control edit descriptor.
Repetitions of edit descriptors can be indicated with the number of repetitions before a symbol.
Groups can be created with (...), and they can be repeated if preceded by a number of repetitions.
No more items are printed beyond the last provided variable, even if the format specifies how to print more items than the ones actually provided - so you can ask for 31 repetitions even if for some months you will only print data for 30 or 28 days.
Besides,
New lines could be added with the / control edit descriptor; e.g., if you wanted to print the data with 10 values per row, you could do
WRITE(1000,'(4(10(F6.0,:,1X),/))') (month_data(d), d=1,no_days)
Note the : control edit descriptor in this second example: it indicates that, if there are no more items to print, nothing else should be printed - not even spaces corresponding to control edit descriptors such as X or /. While it could have been used in the previous example, it is more relevant here, in order to ensure that, if no_days is a multiple of 10, there isn't an empty line after the 3 rows of data.
If you want to completely remove the decimal symbol, you would need to rather print the nearest integers using the nint intrinsic and the Iw (integer) descriptor:
WRITE(1000,'(31(I6,1X))') (nint(month_data(d)), d=1,no_days)

c++ seekg() read specific number

I have a text file:
1 2 3 4 5 6 7 8 9
I want to read a specific number by using seekg()
ifstream fr("duomenys.txt");
fr.seekg(2,ios::beg);
int n;
fr >> n;
cout << n;
If I set position to 1, 2 or 3, readed number is correct, but using other positions, it returns earlier numbers, for example positions 3 and 4 both return 3, positions 5 and 6 both return 4. If I'm right, this is happening because of the spaces between numbers, but I don't get it, why if position is 3, it returns number 3, not 2 as expected because of the space between 2 and 3? And a question, how should I make my function, that I can get specific number from the file using his position? I'm trying to do like an array, which is in a file, for example, A[i] returns item from array at index i, so my function(i) should return item at index i from file.
The simple answer is that you can't. In a text file, the
arguement to seekg must be a value returned from a previous
tellg, with a few exceptions to allow you to seek to the
beginning or the end of the file. Seeking to position 5, for
example, has no meaning.
If you open the file in binary, you can do a little bit more,
but the seek position will still be in bytes; you have to know
the exact position of each number in the file. In the file
you've presented, the positions would be 0, 2, 4... etc. But
this assumes exactly one digit per number, and exactly one space
separating them, which may not be realistic.
For small data sets like yours (in the example, at least), the
obvious solution is just to read all of the data into an
std::vector, and index into that. For very large data sets:
the file must be written expressedly to support the reads, in
binary mode, with a fixed number of characters per number
(including any separators). You could then seek to i * n,
where i is the position you want, and n the number of characters
per number. But again, only in binary mode, both reading and
writing.