# Inner Product

 WARNING: This example assumes spaces are ignored for the I and F descriptors and the output is sent to a printer.

### Problem Statement

The inner product of two sequences of numbers x1, x2, x3,...., xn and y1, y2, y3,...., yn is defined to be the sum of products of corresponding elements. More precisely, the inner product is

x1y1 + x2y2 + x3y3 + ... + xnyn

Write a Fortran to read in two sequences of numbers and computes their inner product.

Suppose we have an input like the following. The first line gives the number of input values. Each of the input line has two fields with 10 positions each. You should use only one format to read all data items.

```         1
....5....0
5
4    7
2    -1
6    2
-3   4
-2   -3
```
Your program should produce the following output report.
```         1    1    2    2    3
....5....0....5....0....5....0
Input Data

No    X    Y
1    4    7
2    2   -1
3    6    2
4   -3    4
5   -2   -3

Input product =      32
```

### Solution

```PROGRAM  InnerProduct
IMPLICIT  NONE
INTEGER, PARAMETER         :: SIZE = 50
INTEGER                    :: Number, Sum, i
INTEGER, DIMENSION(1:SIZE) :: x, y
CHARACTER(LEN=80)          :: Fmt1, Fmt2, Fmt3

Fmt1 = "(I5/(2I5))"
Fmt2 = "(1X,A//1X,3A5/(1X,3I5))"
Fmt3 = "(/1X, A, I7)"

READ(*,Fmt1)   Number, (x(i), y(i), i = 1, Number)
WRITE(*,Fmt2)  "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number)
Sum = 0
DO i = 1, Number
Sum = Sum + x(i)*y(i)
END DO
WRITE(*,Fmt3)  "Input product = ", Sum
END PROGRAM  InnerProduct
```

### Program Input and Output

Suppose we have the following input:
```         1
....5....0
5
4    7
2    -1
6    2
-3   4
-2   -3
```
The output of the program is:
```         1    1    2    2    3
....5....0....5....0....5....0
Input Data

No    X    Y
1    4    7
2    2   -1
3    6    2
4   -3    4
5   -2   -3

Input product =      32
```

### Discussion

• Let us study the way of reading in the input with only one format. The number of data items can be read in with I5 and each subsequent input line can be read in with 2I5. We can read the input with two READs and two formats. But, if you recall the meaning of /, you will know that after reading in the number of data items, we can use / to terminate the current line. At a first glance, we could use (I5/2I5). But, this is incorrect, because this format is equivalent to (I5/I5,I5/I5/I5,I5/....). More precisely, it reads in one integer from the odd numbered lines and two integers from the even-numbered lines. This certainly cannot fit our input.

Since I5 is used only once and 2I5 is used a number of times, to repeat 2I5, what we have to do is enclosing 2I5 in a pair of parenthesis: (I5/(2I5)). By the way, (I5/2(I5)) would do the job (why?); but I prefer (I5/(2I5)). So, the following is the READ statement and the format:

```Fmt1 = "(I5/(2I5))"

READ(*,Fmt1)   Number, (x(i), y(i), i = 1, Number)
```
• Now let us turn to the output. The WRITE and format are shown below:
```Fmt2 = "(1X,A//1X,3A5/(1X,3I5))"

WRITE(*,Fmt2)  "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number)
```
1X,A prints the title Input Data. Then, // produces a blank line between the title and the table heading. No, X and Y are printed with 1X,3A5. The next / terminates the heading line, meaning that subsequent output starts with the next output line. Now, we see the grouping again, which means 1X,3I5 will be used over and over until all data items are printed.

Let me remind you that there is no need to have a / after 3I5 like this:

```Fmt2 = "(1X,A//1X,3A5/(1X,3I5/))"

WRITE(*,Fmt2)  "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number)
```
Reason? Recall that when the closing right parenthesis is reached, Fortran always terminates the current input or output line and all subsequent input and output will be on the next line. If we have (1X,3I5/), this means after printing three integers, the current line is terminated and output will be performed on the next line. Then, Fortran sees the closing right parenthesis, which terminates the current line. Therefore, this line has nothing but spaces. This implies that the table is double-spaced:
```         1    1    2
....5....0....5....0
Input Data

No    X    Y
1    4    7    <--- 1X,3I5/
<--- printed due to end of format
2    2   -1    <--- 1X,3I5/
<--- printed due to end of format
3    6    2    <--- 1X,3I5/
<--- printed due to end of format
4   -3    4    <--- 1X,3I5/
<--- printed due to end of format
5   -2   -3    <--- 1X,3I5/
<--- printed due to end of format
```
• The result (i.e., inner product) is printed the following way:
```Fmt3 = "(/1X, A, I7)"

WRITE(*,Fmt3)  "Input product = ", Sum
```
After the table is printed, printing stops at the last line of the table and subsequent printing should be below this last line. Therefore, the above format starts with / so that we will have a blank line between the table and the result. Thus, this tells you that / can be used to produce blank lines.
• Could the two formats for writing be combined into a single format? Because we have shown examples of combining a number of formats into one, this is a natural question. Unfortunately, this cannot be done at this moment. Suppose the format is combined as follows:
```Fmt = "(1X,A//1X,3A5/(1X,3I5)//1X, A, I7)"

WRITE(*,Fmt)  "Input Data", "No", "X", "Y",   &
(i, x(i), y(i), i = 1, Number), &
"Input product = ", Sum
```
Note that we have // between (1X,3I5) and 1X,A,I7. This is because we need a blank line between the table and the result. This format does not work, simply because it is equivalent to the following:
```(1X, A // 1X, 3A5 / 1X, 3I5 // 1X, A, I7 /
1X, 3I5 // 1X, A, I7 /
1X, 3I5 // 1X, A, I7 /
.....)

WRITE(*,Fmt)  "Input Data", "No", "X", "Y",   &
(i, x(i), y(i), i = 1, Number), &
"Input product = ", Sum
```
As you can see, 3I5 is followed by a blank line, followed by 1X, A, I7. This is incorrect since A is not allowed to print INTEGERs.

Of course, if we know the number of repetitions of 1X,I5, say 25, then the format can be rewritten as

```Fmt = "(1X,A//1X,3A5/25(1X,3I5)//1X, A, I7)"
^^