The complex inner product is the dot product of two complex numbers. This value is calculated by multiplying the first complex number with the conjugate of the second complex number.
For example, the complex conjugate of 7 + 3i
would be 7 - 3i
. The complex inner product of these two numbers would be:
(7 * 7) + (3i * -3i)
= 49 + (-9 * -1) = 58
.
1. Complex Inner Product (2 vectors)
This program takes two text files, each containing an equal number of newline-separated complex numbers, and outputs a text file containing the sum of the complex inner products between each of the two files.
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <complex>
#define PI 3.14159265359
int main()
{
// Introduction
std::cout << "This program calculates the complex inner product of two vectors given by text files." << std::endl;
std::cout << "======================================================" << std::endl;
// Prompt user for file 1
std::string filename1;
std::cout << "Please enter the name of the text file (with extension .txt) containing the first input: " << std::flush;
std::ifstream in1;
while (true)
{
in1.close();
in1.clear();
std::getline(std::cin, filename1);
in1.open(filename1.c_str());
if (in1)
{
break;
}
std::cout << "Invalid file. Please enter a valid input file name: " << std::flush;
}
std::cout << std::endl;
// Count the number of complex values (lines) in file 1
// Assign to N1
int N1 = 0;
std::string line1;
std::vector<std::complex<double>> vec1;
while (std::getline(in1, line1))
{
++N1;
// Parse the real and imaginary parts of each complex value
std::string re_s, im_s;
double re, im;
std::string::size_type pos = line1.find('+');
std::string::size_type neg = line1.find('-');
pos = std::min(pos, neg);
char sign = line1[pos]; // '+' or '-'
re_s = line1.substr(0, pos);
re = stod(re_s);
std::string::size_type i_pos = line1.find('i');
im_s = line1.substr(pos + 1, i_pos - pos - 1);
im = stod(im_s);
if (sign == '-')
{
im *= -1;
}
std::complex<double> mycomplex(re, im);
// Store them in a vector
vec1.push_back(mycomplex);
}
// Close file 1 stream
in1.close();
in1.clear();
// Prompt user for file 2
std::string filename2;
std::cout << "Please enter the name of the text file (with extension .txt) containing the first input: " << std::flush;
std::ifstream in2;
while (true)
{
in2.close();
in2.clear();
std::getline(std::cin, filename2);
in2.open(filename2.c_str());
if (in2)
{
break;
}
std::cout << "Invalid file. Please enter a valid input file name: " << std::flush;
}
std::cout << std::endl;
// Count the number of complex values (lines) in file 2
// Assign to N2
int N2 = 0;
std::string line2;
std::vector<std::complex<double>> vec2;
while (std::getline(in2, line2))
{
++N2;
// Parse the real and imaginary parts of each complex value
std::string re_s, im_s;
double re, im;
std::string::size_type pos = line2.find('+');
std::string::size_type neg = line2.find('-');
pos = std::min(pos, neg);
char sign = line2[pos]; // '+' or '-'
re_s = line2.substr(0, pos);
re = stod(re_s);
std::string::size_type i_pos = line2.find('i');
im_s = line2.substr(pos + 1, i_pos - pos - 1);
im = stod(im_s);
if (sign == '-')
{
im *= -1;
}
std::complex<double> mycomplex(re, im);
// Store them in a vector
vec2.push_back(mycomplex);
}
// Close file 2 stream
in2.close();
in2.clear();
// Make sure N1 and N2 are equal
if (N1 != N2)
{
std::cout << "The files have different amounts of complex numbers! Try again." << std::endl;
return 0;
}
// Do the math
std::complex<double> sum;
for (int i = 0; i < N1; ++i)
{
// Convert vec2's complex numbers into conjugates
// Multiply it with the number from vec1
sum += vec1[i] * std::conj(vec2[i]);
}
// File output
std::string::size_type dot_pos1 = filename1.find('.');
std::string input1 = filename1.substr(0, dot_pos1);
std::string::size_type dot_pos2 = filename2.find('.');
std::string input2 = filename2.substr(0, dot_pos2);
std::ofstream output_file("out_dot_" + std::to_string(N1) + "_" + input1 + "_" + input2 + ".txt");
output_file << sum.real() << "+" << sum.imag() << "i" << "\n";
std::cout << "==================================================" << std::endl;
std::cout << "Calculation complete. Please check your directory for the output file." << std::endl;
output_file.close();
return 0;
}
Given the following two input files:
1+1i
2-1i
3+1i
1-3i
The following output is generated:
9+7i
2. Complex Inner Product (vector with its complex roots of unity)
This program is similar to the previous one, but instead takes a single input file, generates its complex roots of unity, and outputs the sum of the complex inner products between those two vectors.
Each entry in the vector for complex roots of unity is calculated as the polar coordinate e2*pi*i/N
, where N
is the total number of complex numbers and i
is an index from 1
to N
.
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <complex>
#define PI 3.14159265359
int main()
{
// Introduction
std::cout << "This program calculates the complex inner product of two vectors." << std::endl;
std::cout << "======================================================" << std::endl;
// Prompt user for input file
std::string filename;
std::cout << "Please enter the name of the text file (with extension .txt) containing the input: " << std::flush;
std::ifstream in;
while (true)
{
in.close();
in.clear();
std::getline(std::cin, filename);
in.open(filename.c_str());
if (in)
{
break;
}
std::cout << "Invalid file. Please enter a valid input file name: " << std::flush;
}
std::cout << std::endl;
// Count the number of complex values (lines) in the file
// Assign to N
int N = 0;
std::string line;
std::vector<std::complex<double>> vec1;
while (std::getline(in, line))
{
++N;
// Parse the real and imaginary parts of each complex value
std::string re_s, im_s;
double re, im;
std::string::size_type pos = line.find('+');
std::string::size_type neg = line.find('-');
pos = std::min(pos, neg);
char sign = line[pos]; // '+' or '-'
re_s = line.substr(0, pos);
re = stod(re_s);
std::string::size_type i_pos = line.find('i');
im_s = line.substr(pos + 1, i_pos - pos - 1);
im = stod(im_s);
if (sign == '-')
{
im *= -1;
}
std::complex<double> mycomplex(re, im);
// Store them in a vector
vec1.push_back(mycomplex);
}
std::cout << "There are " << N << " complex numbers in the file." << std::endl;
// Close file stream
in.close();
in.clear();
// Construct the complex vector of roots of unity
std::vector<std::complex<double>> vec2;
std::complex<double> first_val(1,0);
vec2.push_back(first_val);
for (int i = 1; i < N; ++i)
{
vec2.push_back(std::polar(1.0, 2 * PI * i / N));
}
// Then calculate the inner product
std::complex<double> sum;
for (int i = 0; i < N; ++i)
{
// Convert vec2's complex numbers into conjugates
// Multiply it with the number from vec1
sum += vec1[i] * std::conj(vec2[i]);
}
// Output file
std::string::size_type dot_pos = filename.find('.');
std::string input = filename.substr(0, dot_pos);
std::ofstream output_file("out_prod_" + std::to_string(N) + "_" + input + ".txt");
output_file << sum.real() << "+" << sum.imag() << "i" << "\n";
std::cout << "==================================================" << std::endl;
std::cout << "Calculation complete. Please check your directory for the output file." << std::endl;
output_file.close();
return 0;
}
Given the following input:
1+1i
2-1i
The following input is generated:
-1+2i