perldot-product

Using perl's reduce to compute dot-product


Suppose I have the following two equal-sized arrays in my perl program:

my @arr1 = 1..5;
my @arr2 = 6..10;

I'm trying to get their dot-product using the reduce function defined in the List::Util core module but the following is not working for me:

my $dot_prod = reduce { $arr1[$a] * $arr2[$a] + $arr1[$b] * $arr2[$b] }0..$#arr1;

I get 50 as my output instead of the expected 130.


Solution

  • The documentation describes the behavior of reduce as follows:

    The first call will be with $a and $b set to the first two elements of the list, subsequent calls will be done by setting $a to the result of the previous call and $b to the next element in the list.

    Thus, in this case, on the first iteration reduce will set $a = 0 and $b = 1, and hence, execute

    $arr1[0] * $arr2[0] + $arr1[1] * $arr2[1] 
    

    This temporary result happens to be 20.

    Now, for the second iteration, $a is set to the result of the previous iteratrion and so $a = 20 and $b = 2. Thus, the following will be executed

    $arr1[20] * $arr2[20] + $arr1[2] * $arr2[2]
    

    which is not what we want.

    A possible workaround:

    prepend an initial 0 to the list provided as input to reduce as follows:

    my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1;       
    

    This gives us the desired result since on the first iteration $a = $b = 0 and we'll compute

    0 + $arr[0] * $arr[0]
    

    whose result will be 6.

    Then in the second iteration, we'll have $a = 6 $b = 1 and so we'll compute

    6 + $arr1[1] * $arr2[1]
    

    etc.