Trying to understand implied do loops

I have just cited the OP’s code :slight_smile:

The integer kind for variables indexing the arrays/string could probably be just plain default.
int64 makes sense for the product calculations.

1 Like

True, but I feel like I don’t trust the compiler to fully make the conversion if I just use int64 for the product. If I mix kinds for the integer type, would that be cause for concern ?

Where did you cite it :smiley:

Sorry, I should have made a regular quote, not just the code snippet.

1 Like

Thank you :+1:

Not unless you would want to process input files greater than 2GB :slight_smile: Otherwise
array_pos,parser_stop_var, number_array_size, i - could be default integer
greatest_product, product_tmp, number_array_tmp(:),number_array_best(:) - int64

The code could be further improved in terms of speed by noticing that the two adjacent products are related by
\prod_{i+1}^{i+m+1}N_i = (\prod_{i}^{i+m}N_i)/N_{i}\cdot N_{i+m+1}\quad if N_{i}\neq 0

It would speed up the code if the whole string was first read into array, thus avoiding repeated reads of the same characters.

One should also be aware of possible overflow of product which is easy to get into with longer sub-arrays but not that easy to detect/overcome.


Something like this may help:

integer function safe_mult( i, j )
   implicit none
   integer, intent(in) :: i, j
   safe_mult = 0
   if ( i == 0 ) return
   if ( j == 0 ) return
   if ( abs(j) > huge(i)/abs(i) ) error stop 'i*j overflow'
   safe_mult = i * j
end function safe_mult
1 Like

Thank you for this. It’s very useful

@RonShepard’s safe_mult looks good as a general solution to the integer overflow multiplication problem. But for OP’s problem it is less applicable.

  1. You could not use product intrinsic function
  2. If you do not use product, doing the multiplications yourself, for the specific problem being solved (non-negative results, multiplication by a number less or equal to 9), it would be sufficient to check (before every multiplication) if the current product value is less than huge(1_int64)/9_int64 - that value could be defined as a parameter.
    2a. Also, using regular multiplications instead of product function would make the computing of the rolling product by dividing-out its first element and multiplying-in the new last one.
1 Like

Right. Another thing to prevent overflow could be that, perhaps instead of calculating that big product thing, can calculate the log of that instead, \log \prod_{i=1}^{m}N_i = \sum_{i=1}^{m} \log(N_i) , especially if the N_i = \exp(...), so the product is converted to summation, and in the end convert it back.

1 Like