How to Calculate Dot Product of Two Vectors in C++

Jinku Hu Feb 02, 2024
  1. Use std::inner_product to Calculate the Dot Product of Two Vectors in C++
  2. Use std::transform_reduce to Calculate the Dot Product of Two Vectors in C++
  3. Use Parallelized Computing With std::transform_reduce to Calculate the Dot Product of Two Vectors in C++
  4. Use Raw Arrays to Calculate Dot Product of Two Vectors in C++
  5. Conclusion
How to Calculate Dot Product of Two Vectors in C++

This article explores various methods for calculating the dot product of two vectors in C++. The dot product, a fundamental operation in linear algebra, involves summing the products of corresponding elements in two vectors.

We will delve into the use of C++ Standard Template Library (STL) functions, such as std::inner_product and std::transform_reduce, to streamline these computations efficiently.

Additionally, we’ll discuss parallelized computing with std::transform_reduce for improved performance and explore a manual approach using raw arrays.

Each method will be illustrated with practical examples to provide a comprehensive understanding of dot product calculations in C++.

Use std::inner_product to Calculate the Dot Product of Two Vectors in C++

The dot product of two vectors is a fundamental operation in linear algebra, and in C++, we can efficiently compute it using the std::inner_product function from the numeric algorithms library.

The std::inner_product function is part of the C++ Standard Template Library (STL) and is declared in the <numeric> header. It calculates the dot product of two ranges by computing the sum of the products of their corresponding elements.

The syntax of std::inner_product is as follows:

template <class InputIt1, class InputIt2, class T>
T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init);
  • InputIt1 and InputIt2: Iterator types defining the range of the two input vectors.
  • T: The type of the accumulator and the result of the dot product.
  • first1, last1: Iterator range for the first vector.
  • first2: Iterator pointing to the beginning of the second vector.
  • init: Initial value for the accumulator.

Here is a practical example demonstrating the use of std::inner_product to calculate the dot product of two vectors:

#include <iostream>
#include <numeric>
#include <vector>

int main() {
  std::vector<int> vector1 = {1, 2, 3, 4, 5};
  std::vector<int> vector2 = {2, 4, 6, 8, 10};

  int result =
      std::inner_product(vector1.begin(), vector1.end(), vector2.begin(), 0);

  std::cout << "Dot Product: " << result << std::endl;

  return 0;
}

Output:

Dot Product: 110

In this example, we begin by including the necessary headers for input and output operations (<iostream>), the numeric algorithms library (<numeric>), and the vector container (<vector>).

We then define two vectors, vector1 and vector2, with integer values. The main focus is on the usage of std::inner_product to calculate the dot product.

As we can see, the function takes four parameters:

std::inner_product(vector1.begin(), vector1.end(), vector2.begin(), 0);
  • vector1.begin() and vector1.end(): The iterators specifying the range of the first vector.
  • vector2.begin(): The iterator pointing to the beginning of the second vector.
  • 0: The initial value of the accumulator.

The result is stored in the variable result, which is then printed to the console using std::cout. The output provides the calculated dot product of the two vectors.

Use std::transform_reduce to Calculate the Dot Product of Two Vectors in C++

In addition to std::inner_product, C++ provides another powerful tool for calculating the dot product of two vectors: std::transform_reduce. This function offers the advantage of potentially improved performance by allowing operations on ranges to be performed out of order.

std::transform_reduce is part of the C++ Standard Template Library (STL) and is also declared in the <numeric> header. It is essentially the parallelized version of std::inner_product, which is particularly advantageous when dealing with large datasets.

The syntax of std::transform_reduce is as follows:

template <class InputIt1, class InputIt2, class T>
T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init);
  • InputIt1 and InputIt2: Iterator types defining the range of the two input vectors.
  • T: The type of the accumulator and the result of the dot product.
  • first1, last1: Iterator range for the first vector.
  • first2: Iterator pointing to the beginning of the second vector.
  • init: Initial value for the accumulator.

Below is an example showing the use of std::transform_reduce to calculate the dot product of two vectors:

#include <iostream>
#include <numeric>
#include <vector>

int main() {
  std::vector<int> vector1 = {1, 2, 3, 4, 5};
  std::vector<int> vector2 = {2, 4, 6, 8, 10};

  int result =
      std::transform_reduce(vector1.begin(), vector1.end(), vector2.begin(), 0);

  std::cout << "Dot Product: " << result << std::endl;

  return 0;
}

Here, we employ std::transform_reduce to calculate the dot product of two vectors.

Similar to std::inner_product, the function takes four parameters:

  • The iterators specifying the range of the first vector (vector1.begin() and vector1.end()),
  • The iterator pointing to the beginning of the second vector (vector2.begin()), and
  • The initial value of the accumulator (0).

The result is stored in the variable result, and we print it to the console using std::cout. The output provides the calculated dot product of the two vectors.

Output:

Dot Product: 110

Now, let’s consider a practical scenario where you have two vectors representing quantities and prices of items in an online store. The dot product of these vectors can be used to calculate the total revenue generated from the sale of each item.

Here’s an example:

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

struct Item {
  double quantity;
  double price;

  Item(double q, double p) : quantity(q), price(p) {}
};

int main() {
  std::vector<Item> items = {
      {10, 15.99},  // 10 units at $15.99 each
      {5, 25.49},   // 5 units at $25.49 each
      {8, 10.99}    // 8 units at $10.99 each
  };

  std::vector<double> quantities;
  std::vector<double> prices;

  for (const auto& item : items) {
    quantities.push_back(item.quantity);
    prices.push_back(item.price);
  }

  std::vector<double> revenue;
  revenue.resize(quantities.size());
  std::transform(quantities.begin(), quantities.end(), prices.begin(),
                 revenue.begin(), std::multiplies<double>());

  double totalRevenue = std::reduce(revenue.begin(), revenue.end(), 0.0);

  std::cout << "Total Revenue: $" << totalRevenue << std::endl;

  return 0;
}

Output:

Total Revenue: $375.27

In this scenario, each Item structure in the items vector represents a product with a specific quantity and price.

We then use std::transform to calculate the revenue for each item (quantity * price), and std::reduce is employed to sum up these revenues, providing the total revenue generated from the sale of all items.

Use Parallelized Computing With std::transform_reduce to Calculate the Dot Product of Two Vectors in C++

Alternatively, C++ offers the capability to parallelize vector computations using std::transform_reduce with a parallel execution policy. This can significantly enhance performance when dealing with large datasets.

std::transform_reduce with a parallel execution policy introduces the concept of parallelism, allowing for concurrent computation on multi-core systems. The syntax is as follows:

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T>
T transform_reduce(ExecutionPolicy&& policy, ForwardIt1 first1,
                   ForwardIt1 last1, ForwardIt2 first2, T init);

Where:

  • ExecutionPolicy: The policy that determines the parallelization strategy.
  • ForwardIt1 and ForwardIt2: Iterator types defining the range of the two input vectors.
  • T: The type of the accumulator and the result of the dot product.
  • first1, last1: Iterator range for the first vector.
  • first2: Iterator pointing to the beginning of the second vector.
  • init: Initial value for the accumulator.

Building upon our physics simulation scenario, let’s parallelize the computation of work done using std::transform_reduce with a parallel execution policy:

#include <algorithm>
#include <execution>
#include <iostream>
#include <numeric>
#include <vector>

int main() {
  std::vector<double> force = {50.0, 30.0, 40.0};      // Force vector
  std::vector<double> displacement = {2.0, 3.0, 4.0};  // Displacement vector

  if (force.size() != displacement.size()) {
    std::cerr << "Error: Vectors must be of the same size." << std::endl;
    return 1;  // Exit with an error code
  }

  double totalWork = std::transform_reduce(
      std::execution::par, force.begin(), force.end(), displacement.begin(),
      0.0, std::plus<double>(), [](double f, double d) { return f * d; });

  std::cout << "Total Work (Parallel): " << totalWork << " Joules" << std::endl;

  return 0;
}

Output:

Total Work (Parallel): 350 Joules

In this example, we start with the familiar scenario of force and displacement vectors representing a physics simulation. The vectors are then used in conjunction with std::transform_reduce to calculate the total work done in parallel.

The key addition is the introduction of the parallel execution policy std::execution::par when invoking std::transform_reduce. This policy guides the implementation to leverage parallelism when computing the dot product of the vectors.

The lambda function [](double f, double d) { return f * d; } serves as the binary operation applied to each pair of elements during the computation. In this case, it multiplies the corresponding elements of the force and displacement vectors.

The result is a total work calculation performed in parallel, showcasing the power of std::transform_reduce with a parallel execution policy.

Use Raw Arrays to Calculate Dot Product of Two Vectors in C++

While C++ provides versatile tools in the Standard Template Library (STL) for vector calculations, there are scenarios where using raw arrays is desirable. In this case, we can perform dot product calculations with a straightforward approach.

The syntax involves manual iteration through the arrays, multiplying corresponding elements, and summing the results.

template <typename T, size_t N>
T dotProduct(const T (&arr1)[N], const T (&arr2)[N]) {
  T result = 0;
  for (size_t i = 0; i < N; ++i) {
    result += arr1[i] * arr2[i];
  }
  return result;
}

Where:

  • T: The type of the elements in the arrays.
  • N: The size of the arrays.

Let’s consider an example where we have two arrays representing quantities and prices of items in an online store. The dot product of these arrays can be used to calculate the total revenue generated from the sale of each item.

#include <iostream>

int main() {
  double quantities[] = {10, 5, 8};         // Quantities array
  double prices[] = {15.99, 25.49, 10.99};  // Prices array

  size_t size = sizeof(quantities) / sizeof(quantities[0]);
  if (size != sizeof(prices) / sizeof(prices[0])) {
    std::cerr << "Error: Arrays must be of the same size." << std::endl;
    return 1;  // Exit with an error code
  }

  double dotProduct = 0.0;
  for (size_t i = 0; i < size; ++i) {
    dotProduct += quantities[i] * prices[i];
  }

  std::cout << "Total Revenue: $" << dotProduct << std::endl;

  return 0;
}

Output:

Total Revenue: $375.27

Similar to the example above, we have two arrays, quantities and prices, representing the quantities and prices of items in an online store. The size of the arrays is determined using sizeof to ensure they are of the same size.

We then perform a manual dot product calculation by iterating through the arrays and multiplying corresponding elements. The result is accumulated in the variable dotProduct.

While raw arrays offer a straightforward and memory-efficient solution, it’s essential to consider their limitations, such as fixed size and lack of built-in safety checks. Raw arrays can provide a performant and simple alternative for dot product calculations in C++, depending on the specific use case.

Conclusion

This article has demonstrated multiple approaches for calculating the dot product of two vectors in C++. We explored the convenience and efficiency of utilizing STL functions like std::inner_product and std::transform_reduce to streamline the computation process.

The introduction of parallelized computing with std::transform_reduce highlighted the potential performance gains, especially when dealing with substantial datasets. Additionally, we discussed a manual approach using raw arrays for scenarios where simplicity and memory efficiency are paramount.

By providing practical examples for each method, this article equips readers with a versatile toolkit for dot product calculations, catering to different preferences and requirements in C++.

Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Related Article - C++ Vector