// Algorithms from "A Course in Computational
// Algebraic Number Theory" by Henri Cohen
// Implemented by James Pate Williams, Jr.
// Copyright (c) 2023 All Rights Reserved
#pragma once
#include "pch.h"
template<class T> class Matrix
{
public:
size_t m, n;
T** data;
Matrix() { m = 0; n = 0; data = NULL; };
Matrix(size_t m, size_t n)
{
this->m = m;
this->n = n;
data = new T*[m];
if (data == NULL)
exit(-300);
for (size_t i = 0; i < m; i++)
{
data[i] = new T[n];
if (data[i] == NULL)
exit(-301);
}
};
void OutputMatrix(
fstream& outs, char fill, int precision, int width)
{
for (size_t i = 0; i < m; i++)
{
for (size_t j = 0; j < n; j++)
{
outs << setfill(fill) << setprecision(precision);
outs << setw(width) << data[i][j] << '\t';
}
outs << endl;
}
};
};
template<class T> class Vector
{
public:
size_t n;
T* data;
Vector() { n = 0; data = NULL; };
Vector(size_t n)
{
this->n = n;
data = new T[n];
};
void OutputVector(
fstream& outs, char fill, int precision, int width)
{
for (size_t i = 0; i < n; i++)
{
outs << setfill(fill) << setprecision(precision);
outs << setw(width) << data[i] << '\t';
}
outs << endl;
};
};
class LinearAlgebra
{
public:
bool initialized;
size_t m, n;
Matrix<double> M;
Vector<double> B;
LinearAlgebra() {
initialized = false;
m = 0; n = 0;
M.data = NULL;
B.data = NULL;
};
LinearAlgebra(size_t m, size_t n) {
initialized = false;
this->m = m;
this->n = n;
this->M.m = m;
this->M.n = n;
this->B.n = n;
this->M.data = new double*[m];
this->B.data = new double[n];
if (M.data != NULL)
{
for (size_t i = 0; i < m; i++)
{
this->M.data[i] = new double[n];
for (size_t j = 0; j < n; j++)
this->M.data[i][j] = 0;
}
}
if (B.data != NULL)
{
this->B.data = new double[n];
for (size_t i = 0; i < n; i++)
this->B.data[i] = 0;
}
initialized = this->B.data != NULL && this->M.data != NULL;
};
LinearAlgebra(
size_t m, size_t n,
double** M,
double* B)
{
this->m = m;
this->n = n;
this->M.m = m;
this->M.n = n;
this->M.data = new double*[m];
if (M != NULL)
{
for (size_t i = 0; i < m; i++)
{
this->M.data[i] = new double[n];
for (size_t j = 0; j < n; j++)
this->M.data[i][j] = M[i][j];
}
}
if (B != NULL)
{
this->B.data = new double[n];
for (size_t i = 0; i < m; i++)
this->B.data[i] = B[i];
}
initialized = this->B.data != NULL && this->M.data != NULL;
}
~LinearAlgebra()
{
M.m = m;
M.n = n;
B.n = n;
if (B.data != NULL)
delete[] B.data;
for (size_t i = 0; i < m; i++)
if (M.data[i] != NULL)
delete[] M.data[i];
if (M.data != NULL)
delete[] M.data;
}
double DblDeterminant(size_t n, bool failure);
Vector<double> DblGaussianElimination(
bool& failure);
// The following three methods are from the
// textbook "Elementary Numerical Analysis
// An Algorithmic Approach" by S. D. Conte
// and Carl de Boor Translated from the
// original FORTRAN by James Pate Williams, Jr.
// Copyright (c) 2023 All Rights Reserved
bool DblGaussianFactor(
size_t n,
Vector<int>& pivot);
bool DblGaussianSolution(
int n,
Vector<double>& x,
Vector<int>& pivot);
bool DblSubstitution(
size_t n,
Vector<double>& x,
Vector<int>& pivot);
bool DblInverse(
size_t n,
Matrix<double>& A,
Vector<int>& pivot);
};
#include "pch.h"
#include "LinearAlgebra.h"
double LinearAlgebra::DblDeterminant(
size_t n, bool failure)
{
double deter = 1;
Vector<int> pivot(n);
if (!initialized || m != n)
{
failure = true;
return 0.0;
}
if (!DblGaussianFactor(n, pivot))
{
failure = true;
return 0.0;
}
for (size_t i = 0; i < n; i++)
deter *= M.data[i][i];
return deter;
}
Vector<double> LinearAlgebra::DblGaussianElimination(
bool& failure)
{
double* C = new double[m];
Vector<double> X(n);
X.data = new double[n];
if (X.data == NULL)
exit(-200);
if (!initialized)
{
failure = true;
delete[] C;
return X;
}
for (size_t i = 0; i < m; i++)
C[i] = -1;
failure = false;
for (size_t j = 0; j < n; j++)
{
bool found = false;
size_t i = j;
while (i < n && !found)
{
if (M.data[i][j] != 0)
found = true;
else
i++;
}
if (!found)
{
failure = true;
break;
}
if (i > j)
{
for (size_t l = j; l < n; l++)
{
double t = M.data[i][l];
M.data[i][l] = M.data[j][l];
M.data[j][l] = t;
t = B.data[i];
B.data[i] = B.data[j];
B.data[j] = t;
}
}
double d = 1.0 / M.data[j][j];
for (size_t k = j + 1; k < n; k++)
C[k] = d * M.data[k][j];
for (size_t k = j + 1; k < n; k++)
{
for (size_t l = j + 1; l < n; l++)
M.data[k][l] = M.data[k][l] - C[k] * M.data[j][l];
B.data[k] = B.data[k] - C[k] * B.data[j];
}
}
for (int i = (int)n - 1; i >= 0; i--)
{
double sum = 0;
for (size_t j = i + 1; j < n; j++)
sum += M.data[i][j] * X.data[j];
X.data[i] = (B.data[i] - sum) / M.data[i][i];
}
delete[] C;
return X;
}
bool LinearAlgebra::DblGaussianFactor(
size_t n,
Vector<int>& pivot)
// returns false if matrix is singular
{
Vector<double> d(n);
double awikod, col_max, ratio, row_max, temp;
int flag = 1;
size_t i_star, itemp;
for (size_t i = 0; i < n; i++)
{
pivot.data[i] = i;
row_max = 0;
for (size_t j = 0; j < n; j++)
row_max = max(row_max, abs(M.data[i][j]));
if (row_max == 0)
{
flag = 0;
row_max = 1;
}
d.data[i] = row_max;
}
if (n <= 1) return flag != 0;
// factorization
for (size_t k = 0; k < n - 1; k++)
{
// determine pivot row the row i_star
col_max = abs(M.data[k][k]) / d.data[k];
i_star = k;
for (size_t i = k + 1; i < n; i++)
{
awikod = abs(M.data[i][k]) / d.data[i];
if (awikod > col_max)
{
col_max = awikod;
i_star = i;
}
}
if (col_max == 0)
flag = 0;
else
{
if (i_star > k)
{
// make k the pivot row by
// interchanging with i_star
flag *= -1;
itemp = pivot.data[i_star];
pivot.data[i_star] = pivot.data[k];
pivot.data[k] = itemp;
temp = d.data[i_star];
d.data[i_star] = d.data[k];
d.data[k] = temp;
for (size_t j = 0; j < n; j++)
{
temp = M.data[i_star][j];
M.data[i_star][j] = M.data[k][j];
M.data[k][j] = temp;
}
}
// eliminate x[k]
for (size_t i = k + 1; i < n; i++)
{
M.data[i][k] /= M.data[k][k];
ratio = M.data[i][k];
for (size_t j = k + 1; j < n; j++)
M.data[i][j] -= ratio * M.data[k][j];
}
}
if (M.data[n - 1][n - 1] == 0) flag = 0;
}
if (flag == 0)
return false;
return true;
}
bool LinearAlgebra::DblGaussianSolution(
int n,
Vector<double>& x,
Vector<int>& pivot)
{
if (!DblGaussianFactor(n, pivot))
return false;
return DblSubstitution(n, x, pivot);
}
bool LinearAlgebra::DblSubstitution(
size_t n, Vector<double>& x,
Vector<int>& pivot)
{
double sum;
size_t j, n1 = n - 1;
if (n == 1)
{
x.data[0] = B.data[0] / M.data[0][0];
return true;
}
// forward substitution
x.data[0] = B.data[pivot.data[0]];
for (int i = 1; i < (int)n; i++)
{
for (j = 0, sum = 0; j < (size_t)i; j++)
sum += M.data[i][j] * x.data[j];
x.data[i] = B.data[pivot.data[i]] - sum;
}
// backward substitution
x.data[n1] /= M.data[n1][n1];
for (int i = n - 2; i >= 0; i--)
{
double sum = 0.0;
for (j = i + 1; j < n; j++)
sum += M.data[i][j] * x.data[j];
x.data[i] = (x.data[i] - sum) / M.data[i][i];
}
return true;
}
bool LinearAlgebra::DblInverse(
size_t n,
Matrix<double>& A,
Vector<int>& pivot)
{
Vector<double> x(n);
if (!DblGaussianFactor(n, pivot))
return false;
for (size_t i = 0; i < n; i++)
{
for (size_t j = 0; j < n; j++)
B.data[j] = 0;
}
for (size_t i = 0; i < n; i++)
{
B.data[i] = 1;
if (!DblSubstitution(n, x, pivot))
return false;
B.data[i] = 0;
for (size_t j = 0; j < n; j++)
A.data[i][j] = x.data[pivot.data[j]];
}
return true;
}
/*
** Cohen's linear algebra test program
** Implemented by James Pate Williams, Jr.
** Copyright (c) 2023 All Rights Reserved
*/
#include "pch.h"
#include "LinearAlgebra.h"
double GetDblNumber(fstream& inps)
{
char ch = inps.get();
string numberStr;
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
ch = inps.get();
while (ch == '+' || ch == '-' || ch == '.' ||
ch >= '0' && ch <= '9')
{
numberStr += ch;
ch = inps.get();
}
double x = atof(numberStr.c_str());
return x;
}
int GetIntNumber(fstream& inps)
{
char ch = inps.get();
string numberStr;
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
ch = inps.get();
while (ch == '+' || ch == '-' || ch >= '0' && ch <= '9')
{
numberStr += ch;
ch = inps.get();
}
int x = atoi(numberStr.c_str());
return x;
}
int main()
{
fstream inps;
inps.open("CLATestFile.txt", fstream::in);
if (inps.fail())
{
cout << "Input file opening error!" << endl;
return -1;
}
fstream outs;
outs.open("CLAResuFile.txt", fstream::out | fstream::ate);
if (outs.fail())
{
cout << "Output file opening error!" << endl;
return -2;
}
size_t m, n;
while (!inps.eof())
{
m = GetIntNumber(inps);
if (inps.eof())
return 0;
if (m < 1)
{
cout << "The number of rows must be >= 1" << endl;
return -100;
}
n = GetIntNumber(inps);
if (n < 1)
{
cout << "The number of rows must be >= 1" << endl;
return -101;
}
LinearAlgebra la(m, n);
Matrix<double> copyM(m, n);
Vector<double> copyB(n);
for (size_t i = 0; i < m; i++)
{
for (size_t j = 0; j < n; j++)
{
double x = GetDblNumber(inps);
la.M.data[i][j] = x;
copyM.data[i][j] = x;
}
}
for (size_t i = 0; i < n; i++)
{
la.B.data[i] = GetDblNumber(inps);
copyB.data[i] = la.B.data[i];
}
bool failure = false;
Vector<double> X = la.DblGaussianElimination(failure);
if (!failure)
X.OutputVector(outs, ' ', 5, 8);
else
{
cout << "Cohen Gaussian elimination failure!" << endl;
exit(-102);
}
for (size_t i = 0; i < m; i++)
{
la.B.data[i] = copyB.data[i];
for (size_t j = 0; j < n; j++)
{
la.M.data[i][j] = copyM.data[i][j];
}
}
Matrix<double> A(n, n);
Vector<int> pivot(n);
if (!la.DblGaussianSolution(n, X, pivot))
exit(-103);
X.OutputVector(outs, ' ', 5, 8);
for (size_t i = 0; i < m; i++)
{
la.B.data[i] = copyB.data[i];
for (size_t j = 0; j < n; j++)
{
la.M.data[i][j] = copyM.data[i][j];
}
}
double deter = la.DblDeterminant(n, failure);
outs << deter << endl;
for (size_t i = 0; i < m; i++)
{
la.B.data[i] = copyB.data[i];
for (size_t j = 0; j < n; j++)
{
la.M.data[i][j] = copyM.data[i][j];
}
}
if (!la.DblInverse(n, A, pivot))
{
cout << "Conte Gaussian inverse matrix failure!" << endl;
exit(-104);
}
else
A.OutputMatrix(outs, ' ', 5, 8);
}
inps.close();
outs.close();
}
We calculate the ground state energies for Helium (Z = 2), Lithium (Z = 3), Beryllium (Z = 4), Boron (Z = 5), and Carbon (Z = 6). Currently, only three of the five atoms are implemented.
/*
Author: Pate Williams (c) January 22, 1995
The following program is a translation of the FORTRAN
subprogram found in Elementary Numerical Analysis by
S. D. Conte and Carl de Boor pages 343-344. The program
uses Romberg extrapolation to find the integral of a
function.
*/
#include "stdafx.h"
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
typedef long double real;
real t[10][10];
real f(real x)
{
return(expl(-x * x));
}
real Li(real x)
{
return(1.0 / logl(x));
}
real romberg(
real a, real b, int start, int row,
real(*f)(real))
{
int i, k, m;
real h, ratio, sum;
m = start;
h = (b - a) / m;
sum = 0.5 * (f(a) + f(b));
if (m > 1)
for (i = 1; i < m; i++)
sum += f(a + i * h);
t[1][1] = h * sum;
if (row < 2) return(t[1][1]);
for (k = 2; k <= row; k++)
{
h = 0.5 * h;
m *= 2;
sum = 0.0;
for (i = 1; i <= m; i += 2)
sum += f(a + h * i);
t[k][1] = 0.5 * t[k - 1][1] + sum * h;
for (i = 1; i < k; i++)
{
t[k - 1][i] = t[k][i] - t[k - 1][i];
t[k][i + 1] = t[k][i] - t[k - 1][i] /
(powl(4.0, (real)i) - 1.0);
}
}
if (row < 3) return(t[2][2]);
for (k = 1; k <= row - 2; k++)
for (i = 1; i <= k; i++)
{
if (t[k + 1][i] == 0.0)
ratio = 0.0;
else
ratio = t[k][i] / t[k + 1][i];
t[k][i] = ratio;
}
return(t[row][row - 1]);
}
int main(void)
{
long double experimental = 0.7468241328124271;
int row = 8;
printf("first test\n");
printf("Romberg integration of f(x) = exp(- x * x)\n");
printf("Internet value = 0.7468241328124271\n");
printf("from website = https://www.integral-calculator.com/\n");
printf("Approximation\t\tPercent Difference\tSteps\tRuntime (s)\n");
for (long steps = 100000; steps <= 900000; steps += 100000)
{
clock_t start = clock();
long double trial = romberg(0.0, 1.0, steps, row, f);
clock_t endTm = clock();
long double runtime = ((long double)endTm - start) /
CLOCKS_PER_SEC;
long double pd = 100.0 * fabsl(experimental - trial) /
(0.5 *(experimental + trial));
printf("%16.15lf\t%16.15le\t%6d\t%4.3lf\n",
trial, pd, steps, runtime);
}
printf("second test\n");
printf("Romberg integration of Li(x) = 1 / ln x between 2 and some n\n");
printf("approximates the number of prime numbers between 2 and n\n");
printf("n\t\tLi(n)\t\tSteps\tTime (s)\n");
for (long n = 10; n <= 1000000000; n *= 10)
{
long steps = 1000000;
clock_t start = clock();
long double trial = romberg(2.0, n, steps, row, Li);
clock_t endTm = clock();
long double runtime = ((long double)endTm - start) /
CLOCKS_PER_SEC;
printf("%12ld\t%12.0lf\t%7ld\t%4.3lf\n",
n, trial, steps, runtime);
}
return(0);
}
/*
Author: Pate Williams (c) January 20, 1995
The following is a translation of the Pascal program
sieve found in Pascalgorithms by Edwin D. Reilly and
Francis D. Federighi page 652. This program uses sets
to represent the sieve (see C Programming Language An
Applied Perspective by Lawrence Miller and Alec Qui-
lici pages 160 - 162).
*/
#include "stdafx.h"
#include <math.h>
#include <stdio.h>
#include <time.h>
#define _WORD_SIZE 32
#define _VECT_SIZE 31250000
#define SET_MIN 0
#define SET_MAX 1000000000
typedef long LONG;
typedef long SET[_VECT_SIZE];
typedef LONG ELEMENT;
SET set;
static LONG get_bit_pos(LONG *long_ptr, LONG *bit_ptr,
ELEMENT element)
{
*long_ptr = element / _WORD_SIZE;
*bit_ptr = element % _WORD_SIZE;
return(element >= SET_MIN && element <= SET_MAX);
}
static void set_bit(ELEMENT element, LONG inset)
{
LONG bit, word;
if (get_bit_pos(&word, &bit, element))
inset ? set[word] |= (01 << bit) :
set[word] &= ~(01 << bit);
}
static int get_bit(ELEMENT element)
{
LONG bit, word;
return(get_bit_pos(&word, &bit, element) ?
(set[word] >> bit) & 01 : 0);
}
void set_Add(ELEMENT element)
{
set_bit(element, 1);
}
void set_Del(ELEMENT element)
{
set_bit(element, 0);
}
int set_Mem(ELEMENT element)
{
return get_bit(element);
}
void primes(LONG n)
{
LONG c, i, inc, k;
double x;
clock_t now = clock();
set_Add(2);
for (i = 3; i <= n; i++)
if ((i + 1) % 2 == 0)
set_Add(i);
else
set_Del(i);
c = 3;
do
{
i = c * c;
inc = c + c;
while (i <= n)
{
set_Del(i);
i = i + inc;
}
c += 2;
while (set_Mem(c) == 0) c += 1;
} while (c * c <= n);
k = 0;
for (i = 2; i <= n; i++)
if (set_Mem(i) == 1) k++;
x = n / log(n) - 5.0;
x = x + exp(1.0 + 0.15 * log(n) * sqrt(log(n)));
clock_t later = clock();
double runtime = (double)(later - now) / CLOCKS_PER_SEC;
printf("%10ld\t%10ld\t%10.0lf\t%6.4lf\n",
n, k, x, runtime);
}
int main(void)
{
LONG n = 10L;
printf("--------------------------------------------------------\n");
printf("n\t\tprimes\t\ttheory\t\ttime (s)\n");
printf("--------------------------------------------------------\n");
do
{
primes(n);
clock_t later = clock();
n = 10L * n;
} while (n < 1000000000);
printf("--------------------------------------------------------\n");
return(0);
}
/*
Author: Pate Williams (c) January 22, 1995
The following program is a translation of the FORTRAN
subprogram found in Elementary Numerical Analysis by
S. D. Conte and Carl de Boor pages 343-344. The program
uses Romberg extrapolation to find the integral of a
function.
*/
#include "stdafx.h"
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
typedef long double real;
real t[10][10];
real f(real x)
{
return(expl(-x * x));
}
real romberg(real a, real b, int start, int row)
{
int i, k, m;
real h, ratio, sum;
m = start;
h = (b - a) / m;
sum = 0.5 * (f(a) + f(b));
if (m > 1)
for (i = 1; i < m; i++)
sum += f(a + i * h);
t[1][1] = h * sum;
if (row < 2) return(t[1][1]);
for (k = 2; k <= row; k++)
{
h = 0.5 * h;
m *= 2;
sum = 0.0;
for (i = 1; i <= m; i += 2)
sum += f(a + h * i);
t[k][1] = 0.5 * t[k - 1][1] + sum * h;
for (i = 1; i < k; i++)
{
t[k - 1][i] = t[k][i] - t[k - 1][i];
t[k][i + 1] = t[k][i] - t[k - 1][i] /
(powl(4.0, (real)i) - 1.0);
}
}
if (row < 3) return(t[2][2]);
for (k = 1; k <= row - 2; k++)
for (i = 1; i <= k; i++)
{
if (t[k + 1][i] == 0.0)
ratio = 0.0;
else
ratio = t[k][i] / t[k + 1][i];
t[k][i] = ratio;
}
return(t[row][row - 1]);
}
int main(void)
{
long double experimental = 0.7468241328124271;
int row = 8;
printf("Romberg integration of f(x) = exp(- x * x)\n");
printf("Internet value = 0.7468241328124271\n");
printf("from website = https://www.integral-calculator.com/\n");
printf("Approximation\t\tPercent Difference\tSteps\tRuntime (s)\n");
for (long steps = 100000; steps <= 900000; steps += 100000)
{
clock_t start = clock();
long double trial = romberg(0.0, 1.0, steps, row);
clock_t endTm = clock();
long double runtime = ((long double)endTm - start) /
CLOCKS_PER_SEC;
long double pd = 100.0 * fabsl(experimental - trial) /
(0.5 *(experimental + trial));
printf("%16.15lf\t%16.15le\t%6d\t%4.3lf\n",
trial, pd, steps, runtime);
}
return(0);
}
We use two numerical analysis algorithms and two artificial intelligent methods. The first two techniques are from the excellent tome “A Numerical Library in C for Scientists and Engineers” by H.T. Lau, PhD. One does not utilize any derivatives and the other requires first partial derivatives. My homegrown algorithms are my implementation of the particle swarm optimization and an evolutionary hill-climber. The output from my C# application is below:
The two numerical algorithms PRAXIS and FLEMIN perform fairly well and do not require that many function evaluations which is better metric than wall-clock time.
The Gibb’s overshoot phenomenon is very well defined by the Fourier series expansion of the Heaviside step function. The following images were produced by a new C/C++ Win32 application that I created in the period February 10, 2023, to February 14, 2023.
The code was adapted from “Fourier Series and Boundary Value Problems” by Ruel V. Churchill and James Ward Brown. The integration algorithm was translated from C source code found in the tome “A Numerical Library in C for Scientists and Engineers” by H.T. Lau, PhD pages 299-303.
I use a very slowly converging infinite series and Fourier series to compute Pi.
// https://en.wikipedia.org/wiki/Rexx#NUMERIC\
// Translated from Rexx code
// by James Pate Williams, Jr.
// Added a lot of functionality
// Copyrighted February 7 - 10, 2023
#include "FourierSeries.h"
#include <stdlib.h>
#include <iomanip>
#include <iostream>
#include <chrono>
using namespace std;
typedef chrono::high_resolution_clock Clock;
void Option3(int digits, int N)
{
long double i = 0;
long double sgn = 1;
long double sum = 0;
long double pi0 = Pi;
long double pi1 = 0.0;
while (i <= N)
{
sum += sgn / (2.0 * i + 1);
sgn *= -1;
i = i + 1.0;
}
pi1 = 4.0 * sum;
cout << setw(static_cast<std::streamsize>((int)digits) + 2);
cout << setprecision(digits) << pi1 << '\t';
cout << setprecision(digits) << (fabsl(pi0 - pi1)) << endl;
}
void Option4(int digits, int N)
{
long double* a = new long double[N + 1];
long double* b = new long double[N + 1];
memset(a, 0, (N + 1) * sizeof(long double));
memset(b, 0, (N + 1) * sizeof(long double));
FourierSeries::CreateCosSeries(N, a);
FourierSeries::CreateSinSeries(N, b);
long double pi = 4.0 * FourierSeries::Series(N, 1.0, a, b);
cout << setw(static_cast<std::streamsize>((int)digits) + 2);
cout << setprecision(digits) << pi << '\t';
cout << setprecision(digits) << (fabsl(pi - Pi)) << endl;
delete[] a;
delete[] b;
}
int main()
{
int choice, digits, N = 0, N1 = 0;
while (1)
{
cout << "==Menu==" << endl;
cout << "1 Compute Sqrt(2)" << endl;
cout << "2 Compute Exp(1)" << endl;
cout << "3 Compute Pi" << endl;
cout << "4 Compute Pi (Fourier Series)" << endl;
cout << "5 Generate Option 3 Table" << endl;
cout << "6 Generate Option 4 Table" << endl;
cout << "7 Exit" << endl;
cin >> choice;
if (choice == 7)
break;
cout << " Digits = ";
cin >> digits;
if (choice >= 3)
{
cout << " Terms = ";
cin >> N;
N1 = N + 1;
}
auto start_time = Clock::now();
if (choice == 1)
{
long double n = 2;
long double r = 1;
while (1)
{
long double rr = (n / r + r) / 2;
if (rr == r)
break;
r = rr;
}
cout << setprecision(digits) << r << endl;
}
else if (choice == 2)
{
long double e = 2.5;
long double f = 0.5;
long double n = 3;
do
{
f /= n;
long double ee = e + f;
if (ee == e)
break;
e = ee;
n += 1;
} while (1);
cout << setprecision(digits) << e << endl;
}
else if (choice == 3)
Option3(digits, N);
else if (choice == 4)
Option4(digits, N);
else if (choice == 5)
{
for (int n = 8; n <= N; n *= 2)
Option3(digits, n);
}
else if (choice == 6)
{
for (int n = 8; n <= N; n *= 2)
Option4(digits, n);
}
auto end_time = Clock::now();
cout << "runtime in milliseconds = ";
cout << std::chrono::duration_cast<std::chrono::milliseconds>
(end_time - start_time).count();
cout << endl;
cout << "runtime in nanoseconds = ";
cout << std::chrono::duration_cast<std::chrono::nanoseconds>
(end_time - start_time).count();
cout << endl;
}
return 0;
}
#pragma once
const long double c = 2.0e9;
const long double Pi = 3.1415926535897932384626433832795;
class FourierSeries
{
private:
static long double f(long double x);
static long double cosTermFunction(int n, long double x);
static long double sinTermFunction(int n, long double x);
public:
static void CreateCosSeries(int N, long double a[]);
static void CreateSinSeries(int N, long double b[]);
static long double Series(int N, long double x,
long double a[], long double b[]);
};
#include <math.h>
#include "FourierSeries.h"
#include "Integral.h"
long double FourierSeries::f(long double x)
{
return atanl(x);
}
long double FourierSeries::cosTermFunction(int n, long double x)
{
return cosl(n * x * Pi / c) * f(x);
}
long double FourierSeries::sinTermFunction(int n, long double x)
{
return sinl(n * x * Pi / c) * f(x);
}
void FourierSeries::CreateCosSeries(int N, long double a[])
{
long double e[7] = { 0 };
e[1] = e[2] = 1.0e-12;
for (int n = 0; n <= N; n++)
a[n] = Integral::integral(
n, -c, c, cosTermFunction, e, 1, 1) / c;
}
void FourierSeries::CreateSinSeries(int N, long double b[])
{
long double e[7] = { 0 };
e[1] = e[2] = 1.0e-12;
for (int n = 1; n <= N; n++)
b[n] = Integral::integral(
n, -c, c, sinTermFunction, e, 1, 1) / c;
}
long double FourierSeries::Series(int N, long double x,
long double a[], long double b[])
{
long double sum = 0.0;
for (int n = 1; n <= N; n++)
sum += a[n] * cosl(2.0 * n * x) + b[n] * sinl(2.0 * n * x);
return a[0] / 2.0 + sum / 2.0;
}
#pragma once
// Translated from C source code found in the tome
// "A Numerical Library in C for Scientists and
// Engineers" by H.T. Lau, PhD
class Integral
{
private:
static long double integralqad(
int n,
int transf, long double (*fx)(int, long double), long double e[],
long double* x0, long double* x1, long double* x2, long double* f0, long double* f1,
long double* f2, long double re, long double ae, long double b1);
static void integralint(
int n,
int transf, long double (*fx)(int, long double), long double e[],
long double* x0, long double* x1, long double* x2, long double* f0, long double* f1,
long double* f2, long double* sum, long double re, long double ae, long double b1,
long double hmin);
public:
static long double integral(int n, long double a, long double b,
long double (*fx)(int, long double), long double e[],
int ua, int ub);
};
#include <math.h>
#include "Integral.h"
long double Integral::integral(
int n,
long double a, long double b,
long double (*fx)(int, long double), long double e[],
int ua, int ub)
{
long double x0, x1, x2, f0, f1, f2, re, ae, b1 = 0, x;
re = e[1];
if (ub)
ae = e[2] * 180.0 / fabsl(b - a);
else
ae = e[2] * 90.0 / fabsl(b - a);
if (ua) {
e[3] = e[4] = 0.0;
x = x0 = a;
f0 = (*fx)(n, x);
}
else {
x = x0 = a = e[5];
f0 = e[6];
}
e[5] = x = x2 = b;
e[6] = f2 = (*fx)(n, x);
e[4] += integralqad(n, 0, fx, e, &x0, &x1, &x2, &f0, &f1, &f2, re, ae, b1);
if (!ub) {
if (a < b) {
b1 = b - 1.0;
x0 = 1.0;
}
else {
b1 = b + 1.0;
x0 = -1.0;
}
f0 = e[6];
e[5] = x2 = 0.0;
e[6] = f2 = 0.0;
ae = e[2] * 90.0;
e[4] -= integralqad(n, 1, fx, e, &x0, &x1, &x2, &f0, &f1, &f2, re, ae, b1);
}
return e[4];
}
long double Integral::integralqad(
int n,
int transf, long double (*fx)(int, long double), long double e[],
long double* x0, long double* x1, long double* x2, long double* f0, long double* f1,
long double* f2, long double re, long double ae, long double b1)
{
/* this function is internally used by INTEGRAL */
long double sum, hmin, x, z;
hmin = fabs((*x0) - (*x2)) * re;
x = (*x1) = ((*x0) + (*x2)) * 0.5;
if (transf) {
z = 1.0 / x;
x = z + b1;
(*f1) = (*fx)(n, x) * z * z;
}
else
(*f1) = (*fx)(n, x);
sum = 0.0;
integralint(n, transf, fx, e, x0, x1, x2, f0, f1, f2, &sum, re, ae, b1, hmin);
return sum / 180.0;
}
void Integral::integralint(
int n,
int transf, long double (*fx)(int, long double), long double e[],
long double* x0, long double* x1, long double* x2, long double* f0, long double* f1,
long double* f2, long double* sum, long double re, long double ae, long double b1,
long double hmin)
{
/* this function is internally used by INTEGRALQAD of INTEGRAL */
int anew;
long double x3, x4, f3, f4, h, x, z, v, t;
x4 = (*x2);
(*x2) = (*x1);
f4 = (*f2);
(*f2) = (*f1);
anew = 1;
while (anew) {
anew = 0;
x = (*x1) = ((*x0) + (*x2)) * 0.5;
if (transf) {
z = 1.0 / x;
x = z + b1;
(*f1) = (*fx)(n, x) * z * z;
}
else
(*f1) = (*fx)(n, x);
x = x3 = ((*x2) + x4) * 0.5;
if (transf) {
z = 1.0 / x;
x = z + b1;
f3 = (*fx)(n, x) * z * z;
}
else
f3 = (*fx)(n, x);
h = x4 - (*x0);
v = (4.0 * ((*f1) + f3) + 2.0 * (*f2) + (*f0) + f4) * 15.0;
t = 6.0 * (*f2) - 4.0 * ((*f1) + f3) + (*f0) + f4;
if (fabsl(t) < fabsl(v) * re + ae)
(*sum) += (v - t) * h;
else if (fabsl(h) < hmin)
e[3] += 1.0;
else {
integralint(n, transf, fx, e, x0, x1, x2, f0, f1, f2, sum,
re, ae, b1, hmin);
*x2 = x3;
*f2 = f3;
anew = 1;
}
if (!anew) {
*x0 = x4;
*f0 = f4;
}
}
}