chore: import upstream snapshot with attribution
Awesome CI Workflow / Code Formatter (push) Has been cancelled
Awesome CI Workflow / Compile checks (macOS-latest) (push) Has been cancelled
Awesome CI Workflow / Compile checks (ubuntu-latest) (push) Has been cancelled
Awesome CI Workflow / Compile checks (windows-latest) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:37:28 +08:00
commit 29cfe479ab
432 changed files with 68491 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
# If necessary, use the RELATIVE flag, otherwise each source file may be listed
# with full pathname. RELATIVE may makes it easier to extract an executable name
# automatically.
file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp )
# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c )
# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES)
foreach( testsourcefile ${APP_SOURCES} )
# I used a simple string replace, to cut off .cpp.
string( REPLACE ".cpp" "" testname ${testsourcefile} )
add_executable( ${testname} ${testsourcefile} )
set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX)
if(OpenMP_CXX_FOUND)
target_link_libraries(${testname} OpenMP::OpenMP_CXX)
endif()
install(TARGETS ${testname} DESTINATION "bin/math")
endforeach( testsourcefile ${APP_SOURCES} )
+13
View File
@@ -0,0 +1,13 @@
# Prime factorization # {#section}
Prime Factorization is a very important and useful technique to factorize any number into its prime factors. It has various applications in the field of number theory.
The method of prime factorization involves two function calls.
First: Calculating all the prime number up till a certain range using the standard
Sieve of Eratosthenes.
Second: Using the prime numbers to reduce the the given number and thus find all its prime factors.
The complexity of the solution involves approx. O(n logn) in calculating sieve of eratosthenes
O(log n) in calculating the prime factors of the number. So in total approx. O(n logn).
**Requirements: For compile you need the compiler flag for C++ 11**
+77
View File
@@ -0,0 +1,77 @@
/**
* @file
* @brief Program to return the [Aliquot
* Sum](https://en.wikipedia.org/wiki/Aliquot_sum) of a number
*
* @details
* The Aliquot sum \f$s(n)\f$ of a non-negative integer n is the sum of all
* proper divisors of n, that is, all the divisors of n, other than itself.
*
* Formula:
*
* \f[
* s(n) = \sum_{d|n, d\neq n}d.
* \f]
*
* For example;
* \f$s(18) = 1 + 2 + 3 + 6 + 9 = 21 \f$
*
* @author [SpiderMath](https://github.com/SpiderMath)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for IO operations
/**
* @brief Mathematical algorithms
* @namespace math
*/
namespace math {
/**
* @brief to return the aliquot sum of a number
* @param num The input number
*/
uint64_t aliquot_sum(const uint64_t num) {
if (num == 0 || num == 1) {
return 0; // The aliquot sum for 0 and 1 is 0
}
uint64_t sum = 0;
for (uint64_t i = 1; i <= num / 2; i++) {
if (num % i == 0) {
sum += i;
}
}
return sum;
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// Aliquot sum of 10 is 1 + 2 + 5 = 8
assert(math::aliquot_sum(10) == 8);
// Aliquot sum of 15 is 1 + 3 + 5 = 9
assert(math::aliquot_sum(15) == 9);
// Aliquot sum of 1 is 0
assert(math::aliquot_sum(1) == 0);
// Aliquot sum of 97 is 1 (the aliquot sum of a prime number is 1)
assert(math::aliquot_sum(97) == 1);
std::cout << "All the tests have successfully passed!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run the self-test implementations
return 0;
}
+83
View File
@@ -0,0 +1,83 @@
/**
* @file
* @brief
* Implementation to calculate an estimate of the [number π
* (Pi)](https://en.wikipedia.org/wiki/File:Pi_30K.gif).
*
* @details
* We take a random point P with coordinates (x, y) such that 0 ≤ x ≤ 1 and 0 ≤
* y ≤ 1. If x² + y² ≤ 1, then the point is inside the quarter disk of radius 1,
* else the point is outside. We know that the probability of the point being
* inside the quarter disk is equal to π/4 double approx(vector<Point> &pts)
* which will use the points pts (drawn at random) to return an estimate of the
* number π
* @note This implementation is better than naive recursive or iterative
* approach.
*
* @author [Qannaf AL-SAHMI](https://github.com/Qannaf)
*/
#include <cassert> /// for assert
#include <cstdlib> /// for std::rand
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief structure of points containing two numbers, x and y, such that 0 ≤ x ≤
* 1 and 0 ≤ y ≤ 1.
*/
using Point = struct {
double x;
double y;
};
/**
* @brief This function uses the points in a given vector 'pts' (drawn at
* random) to return an approximation of the number π.
* @param pts Each item of pts contains a point. A point is represented by the
* point structure (coded above).
* @return an estimate of the number π.
*/
double approximate_pi(const std::vector<Point> &pts) {
double count = 0; // Points in circle
for (Point p : pts) {
if ((p.x * p.x) + (p.y * p.y) <= 1) {
count++;
}
}
return 4.0 * count / static_cast<double>(pts.size());
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void tests() {
std::vector<math::Point> rands;
for (std::size_t i = 0; i < 100000; i++) {
math::Point p;
p.x = rand() / static_cast<double>(RAND_MAX); // 0 <= x <= 1
p.y = rand() / static_cast<double>(RAND_MAX); // 0 <= y <= 1
rands.push_back(p);
}
assert(math::approximate_pi(rands) > 3.135);
assert(math::approximate_pi(rands) < 3.145);
std::cout << "All tests have successfully passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // run self-test implementations
return 0;
}
+303
View File
@@ -0,0 +1,303 @@
/**
* @file
* @brief Implementations for the [area](https://en.wikipedia.org/wiki/Area) of
* various shapes
* @details The area of a shape is the amount of 2D space it takes up.
* All shapes have a formula to get the area of any given shape.
* These implementations support multiple return types.
*
* @author [Focusucof](https://github.com/Focusucof)
*/
#define _USE_MATH_DEFINES
#include <cassert> /// for assert
#include <cmath> /// for M_PI definition and pow()
#include <cmath>
#include <cstdint> /// for uint16_t datatype
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief area of a [square](https://en.wikipedia.org/wiki/Square) (l * l)
* @param length is the length of the square
* @returns area of square
*/
template <typename T>
T square_area(T length) {
return length * length;
}
/**
* @brief area of a [rectangle](https://en.wikipedia.org/wiki/Rectangle) (l * w)
* @param length is the length of the rectangle
* @param width is the width of the rectangle
* @returns area of the rectangle
*/
template <typename T>
T rect_area(T length, T width) {
return length * width;
}
/**
* @brief area of a [triangle](https://en.wikipedia.org/wiki/Triangle) (b * h /
* 2)
* @param base is the length of the bottom side of the triangle
* @param height is the length of the tallest point in the triangle
* @returns area of the triangle
*/
template <typename T>
T triangle_area(T base, T height) {
return base * height / 2;
}
/**
* @brief area of a [circle](https://en.wikipedia.org/wiki/Area_of_a_circle) (pi
* * r^2)
* @param radius is the radius of the circle
* @returns area of the circle
*/
template <typename T>
T circle_area(T radius) {
return M_PI * pow(radius, 2);
}
/**
* @brief area of a [parallelogram](https://en.wikipedia.org/wiki/Parallelogram)
* (b * h)
* @param base is the length of the bottom side of the parallelogram
* @param height is the length of the tallest point in the parallelogram
* @returns area of the parallelogram
*/
template <typename T>
T parallelogram_area(T base, T height) {
return base * height;
}
/**
* @brief surface area of a [cube](https://en.wikipedia.org/wiki/Cube) ( 6 * (l
* * l))
* @param length is the length of the cube
* @returns surface area of the cube
*/
template <typename T>
T cube_surface_area(T length) {
return 6 * length * length;
}
/**
* @brief surface area of a [sphere](https://en.wikipedia.org/wiki/Sphere) ( 4 *
* pi * r^2)
* @param radius is the radius of the sphere
* @returns surface area of the sphere
*/
template <typename T>
T sphere_surface_area(T radius) {
return 4 * M_PI * pow(radius, 2);
}
/**
* @brief surface area of a [cylinder](https://en.wikipedia.org/wiki/Cylinder)
* (2 * pi * r * h + 2 * pi * r^2)
* @param radius is the radius of the cylinder
* @param height is the height of the cylinder
* @returns surface area of the cylinder
*/
template <typename T>
T cylinder_surface_area(T radius, T height) {
return 2 * M_PI * radius * height + 2 * M_PI * pow(radius, 2);
}
/**
* @brief surface area of a [hemi-sphere](https://en.wikipedia.org/wiki/Surface_area) ( 3 *
* pi * r^2)
* @param radius is the radius of the hemi-sphere
* @tparam T datatype of radius
* @returns surface area of the hemi-sphere
*/
template <typename T>
T hemi_sphere_surface_area(T radius) {
return 3 * M_PI * pow(radius, 2);
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// I/O variables for testing
uint16_t int_length = 0; // 16 bit integer length input
uint16_t int_width = 0; // 16 bit integer width input
uint16_t int_base = 0; // 16 bit integer base input
uint16_t int_height = 0; // 16 bit integer height input
uint16_t int_expected = 0; // 16 bit integer expected output
uint16_t int_area = 0; // 16 bit integer output
float float_length = NAN; // float length input
float float_expected = NAN; // float expected output
float float_area = NAN; // float output
double double_length = NAN; // double length input
double double_width = NAN; // double width input
double double_radius = NAN; // double radius input
double double_height = NAN; // double height input
double double_expected = NAN; // double expected output
double double_area = NAN; // double output
// 1st test
int_length = 5;
int_expected = 25;
int_area = math::square_area(int_length);
std::cout << "AREA OF A SQUARE (int)" << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_area << std::endl;
assert(int_area == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 2nd test
float_length = 2.5;
float_expected = 6.25;
float_area = math::square_area(float_length);
std::cout << "AREA OF A SQUARE (float)" << std::endl;
std::cout << "Input Length: " << float_length << std::endl;
std::cout << "Expected Output: " << float_expected << std::endl;
std::cout << "Output: " << float_area << std::endl;
assert(float_area == float_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 3rd test
int_length = 4;
int_width = 7;
int_expected = 28;
int_area = math::rect_area(int_length, int_width);
std::cout << "AREA OF A RECTANGLE (int)" << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Input Width: " << int_width << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_area << std::endl;
assert(int_area == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 4th test
double_length = 2.5;
double_width = 5.7;
double_expected = 14.25;
double_area = math::rect_area(double_length, double_width);
std::cout << "AREA OF A RECTANGLE (double)" << std::endl;
std::cout << "Input Length: " << double_length << std::endl;
std::cout << "Input Width: " << double_width << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_area << std::endl;
assert(double_area == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 5th test
int_base = 10;
int_height = 3;
int_expected = 15;
int_area = math::triangle_area(int_base, int_height);
std::cout << "AREA OF A TRIANGLE" << std::endl;
std::cout << "Input Base: " << int_base << std::endl;
std::cout << "Input Height: " << int_height << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_area << std::endl;
assert(int_area == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 6th test
double_radius = 6;
double_expected =
113.09733552923255; // rounded down because the double datatype
// truncates after 14 decimal places
double_area = math::circle_area(double_radius);
std::cout << "AREA OF A CIRCLE" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_area << std::endl;
assert(double_area == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 7th test
int_base = 6;
int_height = 7;
int_expected = 42;
int_area = math::parallelogram_area(int_base, int_height);
std::cout << "AREA OF A PARALLELOGRAM" << std::endl;
std::cout << "Input Base: " << int_base << std::endl;
std::cout << "Input Height: " << int_height << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_area << std::endl;
assert(int_area == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 8th test
double_length = 5.5;
double_expected = 181.5;
double_area = math::cube_surface_area(double_length);
std::cout << "SURFACE AREA OF A CUBE" << std::endl;
std::cout << "Input Length: " << double_length << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_area << std::endl;
assert(double_area == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 9th test
double_radius = 10.0;
double_expected = 1256.6370614359172; // rounded down because the whole
// value gets truncated
double_area = math::sphere_surface_area(double_radius);
std::cout << "SURFACE AREA OF A SPHERE" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_area << std::endl;
assert(double_area == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 10th test
double_radius = 4.0;
double_height = 7.0;
double_expected = 276.46015351590177;
double_area = math::cylinder_surface_area(double_radius, double_height);
std::cout << "SURFACE AREA OF A CYLINDER" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Input Height: " << double_height << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_area << std::endl;
assert(double_area == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 11th test
double_radius = 10.0;
double_expected = 942.4777960769379;
double_area = math::hemi_sphere_surface_area(double_radius);
std::cout << "SURFACE AREA OF A HEMI-SPHERE" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_area << std::endl;
assert(double_area == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+91
View File
@@ -0,0 +1,91 @@
/**
* @file
* @brief Program to check if a number is an [Armstrong/Narcissistic
* number](https://en.wikipedia.org/wiki/Narcissistic_number) in decimal system.
*
* @details
* Armstrong number or [Narcissistic
* number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that
* is the sum of its own digits raised to the power of the number of digits.
*
* let n be the narcissistic number,
* \f[F_b(n) = \sum_{i=0}^{k-1}d_{i}^{k}\f] for
* \f$ b > 1 F_b : \N \to \N \f$ where
* \f$ k = \lfloor log_b n\rfloor is the number of digits in the number in base
* \f$b\f$, and \f$ d_i = \frac{n mod b^{i+1} - n mod b^{i}}{b^{i}} \f$
*
* @author [Neeraj Cherkara](https://github.com/iamnambiar)
*/
#include <cassert> /// for assert
#include <cmath> /// for std::pow
#include <iostream> /// for IO operations
/**
* @brief Function to calculate the total number of digits in the number.
* @param num Number
* @return Total number of digits.
*/
int number_of_digits(int num) {
int total_digits = 0;
while (num > 0) {
num = num / 10;
++total_digits;
}
return total_digits;
}
/**
* @brief Function to check whether the number is armstrong number or not.
* @param number to be checked
* @return `true` if the number is armstrong.
* @return `false` if the number is not armstrong.
*/
bool is_armstrong(int number) {
// If the number is less than 0, then it is not an armstrong number.
if (number < 0) {
return false;
}
int sum = 0;
int temp = number;
// Finding the total number of digits in the number
int total_digits = number_of_digits(number);
while (temp > 0) {
int rem = temp % 10;
// Finding each digit raised to the power total digit and add it to the
// total sum
sum += static_cast<int>(std::pow(rem, total_digits));
temp = temp / 10;
}
return number == sum;
}
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// is_armstrong(370) returns true.
assert(is_armstrong(370) == true);
// is_armstrong(225) returns false.
assert(is_armstrong(225) == false);
// is_armstrong(-23) returns false.
assert(is_armstrong(-23) == false);
// is_armstrong(153) returns true.
assert(is_armstrong(153) == true);
// is_armstrong(0) returns true.
assert(is_armstrong(0) == true);
// is_armstrong(12) returns false.
assert(is_armstrong(12) == false);
std::cout << "All tests have successfully passed!\n";
}
/**
* @brief Main Function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
/**
* @file
* @brief C++ Program to find Binary Exponent Iteratively and Recursively.
*
* Calculate \f$a^b\f$ in \f$O(\log(b))\f$ by converting \f$b\f$ to a
* binary number. Binary exponentiation is also known as exponentiation by
* squaring.
* @note This is a far better approach compared to naive method which
* provide \f$O(b)\f$ operations.
*
* Example:
* </br>10 in base 2 is 1010.
* \f{eqnarray*}{
* 2^{10_d} &=& 2^{1010_b} = 2^8 * 2^2\\
* 2^1 &=& 2\\
* 2^2 &=& (2^1)^2 = 2^2 = 4\\
* 2^4 &=& (2^2)^2 = 4^2 = 16\\
* 2^8 &=& (2^4)^2 = 16^2 = 256\\
* \f}
* Hence to calculate 2^10 we only need to multiply \f$2^8\f$ and \f$2^2\f$
* skipping \f$2^1\f$ and \f$2^4\f$.
*/
#include <iostream>
/// Recursive function to calculate exponent in \f$O(\log(n))\f$ using binary
/// exponent.
int binExpo(int a, int b) {
if (b == 0) {
return 1;
}
int res = binExpo(a, b / 2);
if (b % 2) {
return res * res * a;
} else {
return res * res;
}
}
/// Iterative function to calculate exponent in \f$O(\log(n))\f$ using binary
/// exponent.
int binExpo_alt(int a, int b) {
int res = 1;
while (b > 0) {
if (b % 2) {
res = res * a;
}
a = a * a;
b /= 2;
}
return res;
}
/// Main function
int main() {
int a, b;
/// Give two numbers a, b
std::cin >> a >> b;
if (a == 0 && b == 0) {
std::cout << "Math error" << std::endl;
} else if (b < 0) {
std::cout << "Exponent must be positive !!" << std::endl;
} else {
int resRecurse = binExpo(a, b);
/// int resIterate = binExpo_alt(a, b);
/// Result of a^b (where '^' denotes exponentiation)
std::cout << resRecurse << std::endl;
/// std::cout << resIterate << std::endl;
}
}
+92
View File
@@ -0,0 +1,92 @@
/**
* @file
* @brief Program to calculate [Binomial
* coefficients](https://en.wikipedia.org/wiki/Binomial_coefficient)
*
* @author [astronmax](https://github.com/astronmax)
*/
#include <cassert> /// for assert
#include <cstdint> /// for int32_t type
#include <cstdlib> /// for atoi
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace binomial
* @brief Functions for [Binomial
* coefficients](https://en.wikipedia.org/wiki/Binomial_coefficient)
* implementation
*/
namespace binomial {
/**
* @brief Function to calculate binomial coefficients
* @param n first value
* @param k second value
* @return binomial coefficient for n and k
*/
size_t calculate(int32_t n, int32_t k) {
// basic cases
if (k > (n / 2))
k = n - k;
if (k == 1)
return n;
if (k == 0)
return 1;
size_t result = 1;
for (int32_t i = 1; i <= k; ++i) {
result *= n - k + i;
result /= i;
}
return result;
}
} // namespace binomial
} // namespace math
/**
* @brief Test implementations
* @returns void
*/
static void tests() {
// tests for calculate function
assert(math::binomial::calculate(1, 1) == 1);
assert(math::binomial::calculate(57, 57) == 1);
assert(math::binomial::calculate(6, 3) == 20);
assert(math::binomial::calculate(10, 5) == 252);
assert(math::binomial::calculate(20, 10) == 184756);
assert(math::binomial::calculate(30, 15) == 155117520);
assert(math::binomial::calculate(40, 20) == 137846528820);
assert(math::binomial::calculate(50, 25) == 126410606437752);
assert(math::binomial::calculate(60, 30) == 118264581564861424);
assert(math::binomial::calculate(62, 31) == 465428353255261088);
std::cout << "[+] Binomial coefficients calculate test completed"
<< std::endl;
}
/**
* @brief Main function
* @param argc commandline argument count
* @param argv commandline array of arguments
* @returns 0 on exit
*/
int main(int argc, const char* argv[]) {
tests(); // run self-test implementations
if (argc < 3) {
std::cout << "Usage ./binomial_calculate {n} {k}" << std::endl;
return 0;
}
int32_t n = atoi(argv[1]);
int32_t k = atoi(argv[2]);
std::cout << math::binomial::calculate(n, k) << std::endl;
return 0;
}
+84
View File
@@ -0,0 +1,84 @@
/**
* @file
* @brief A C++ Program to check whether a pair of numbers is an [amicable
* pair](https://en.wikipedia.org/wiki/Amicable_numbers) or not.
*
* @details
* An Amicable Pair is two positive integers such that the sum of the proper
* divisor for each number is equal to the other number.
*
* @note Remember that a proper divisor is any positive whole number that
* divides into a selected number, apart from the selected number itself, and
* returns a positive integer. for example 1, 2 and 5 are all proper divisors
* of 10.
*
* @author [iamnambiar](https://github.com/iamnambiar)
*/
#include <cassert> /// for assert
#include <iostream> /// for IO operations
/**
* @brief Mathematical algorithms
* @namespace
*/
namespace math {
/**
* @brief Function to calculate the sum of all the proper divisor
* of an integer.
* @param num selected number.
* @return Sum of the proper divisor of the number.
*/
int sum_of_divisor(int num) {
// Variable to store the sum of all proper divisors.
int sum = 1;
// Below loop condition helps to reduce Time complexity by a factor of
// square root of the number.
for (int div = 2; div * div <= num; ++div) {
// Check 'div' is divisor of 'num'.
if (num % div == 0) {
// If both divisor are same, add once to 'sum'
if (div == (num / div)) {
sum += div;
} else {
// If both divisor are not the same, add both to 'sum'.
sum += (div + (num / div));
}
}
}
return sum;
}
/**
* @brief Function to check whether the pair is amicable or not.
* @param x First number.
* @param y Second number.
* @return `true` if the pair is amicable
* @return `false` if the pair is not amicable
*/
bool are_amicable(int x, int y) {
return (sum_of_divisor(x) == y) && (sum_of_divisor(y) == x);
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void tests() {
assert(math::are_amicable(220, 284) == true);
assert(math::are_amicable(6368, 6232) == true);
assert(math::are_amicable(458, 232) == false);
assert(math::are_amicable(17296, 18416) == true);
assert(math::are_amicable(18416, 17296) == true);
std::cout << "All tests have successfully passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // perform self-tests implementations
return 0;
}
+74
View File
@@ -0,0 +1,74 @@
/**
* @file
* @brief A simple program to check if the given number is a
* [factorial](https://en.wikipedia.org/wiki/Factorial) of some number or not.
*
* @details A factorial number is the sum of k! where any value of k is a
* positive integer. https://www.mathsisfun.com/numbers/factorial.html
*
* @author [Divyajyoti Ukirde](https://github.com/divyajyotiuk)
* @author [ewd00010](https://github.com/ewd00010)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for cout
/**
* @namespace
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief Function to check if the given number is factorial of some number or
* not.
* @param n number to be checked.
* @return true if number is a factorial returns true
* @return false if number is not a factorial
*/
bool is_factorial(uint64_t n) {
if (n <= 0) { // factorial numbers are only ever positive Integers
return false;
}
/*!
* this loop is basically a reverse factorial calculation, where instead
* of multiplying we are dividing. We start at i = 2 since i = 1 has
* no impact division wise
*/
int i = 2;
while (n % i == 0) {
n = n / i;
i++;
}
/*!
* if n was the sum of a factorial then it should be divided until it
* becomes 1
*/
return (n == 1);
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void tests() {
assert(math::is_factorial(50) == false);
assert(math::is_factorial(720) == true);
assert(math::is_factorial(0) == false);
assert(math::is_factorial(1) == true);
assert(math::is_factorial(479001600) == true);
assert(math::is_factorial(-24) == false);
std::cout << "All tests have successfully passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // run self-test implementations
return 0;
}
+84
View File
@@ -0,0 +1,84 @@
/**
* @file
* @brief
* A simple program to check if the given number is
* [Prime](https://en.wikipedia.org/wiki/Primality_test) or not.
* @details
* A prime number is any number that can be divided only by itself and 1. It
* must be positive and a whole number, therefore any prime number is part of
* the set of natural numbers. The majority of prime numbers are even numbers,
* with the exception of 2. This algorithm finds prime numbers using this
* information. additional ways to solve the prime check problem:
* https://cp-algorithms.com/algebra/primality_tests.html#practice-problems
* @author [Omkar Langhe](https://github.com/omkarlanghe)
* @author [ewd00010](https://github.com/ewd00010)
*/
#include <cassert> /// for assert
#include <iostream> /// for IO operations
/**
* @brief Mathematical algorithms
* @namespace
*/
namespace math {
/**
* @brief Function to check if the given number is prime or not.
* @param num number to be checked.
* @return true if number is a prime
* @return false if number is not a prime.
*/
bool is_prime(int64_t num) {
/*!
* Reduce all possibilities of a number which cannot be prime with the first
* 3 if, else if conditionals. Example: Since no even number, except 2 can
* be a prime number and the next prime we find after our checks is 5,
* we will start the for loop with i = 5. then for each loop we increment
* i by +6 and check if i or i+2 is a factor of the number; if it's a factor
* then we will return false. otherwise, true will be returned after the
* loop terminates at the terminating condition which is i*i <= num
*/
if (num <= 1) {
return false;
} else if (num == 2 || num == 3) {
return true;
} else if (num % 2 == 0 || num % 3 == 0) {
return false;
} else {
for (int64_t i = 5; i * i <= num; i = i + 6) {
if (num % i == 0 || num % (i + 2) == 0) {
return false;
}
}
}
return true;
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void tests() {
assert(math::is_prime(1) == false);
assert(math::is_prime(2) == true);
assert(math::is_prime(3) == true);
assert(math::is_prime(4) == false);
assert(math::is_prime(-4) == false);
assert(math::is_prime(7) == true);
assert(math::is_prime(-7) == false);
assert(math::is_prime(19) == true);
assert(math::is_prime(50) == false);
assert(math::is_prime(115249) == true);
std::cout << "All tests have successfully passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // perform self-tests implementations
return 0;
}
+271
View File
@@ -0,0 +1,271 @@
/**
* @author tjgurwara99
* @file
*
* \brief An implementation of Complex Number as Objects
* \details A basic implementation of Complex Number field as a class with
* operators overloaded to accommodate (mathematical) field operations.
*/
#include <cassert>
#include <cmath>
#include <complex>
#include <ctime>
#include <iostream>
#include <stdexcept>
/**
* \brief Class Complex to represent complex numbers as a field.
*/
class Complex {
// The real value of the complex number
double re;
// The imaginary value of the complex number
double im;
public:
/**
* \brief Complex Constructor which initialises our complex number.
* \details
* Complex Constructor which initialises the complex number which takes
* three arguments.
* @param x If the third parameter is 'true' then this x is the absolute
* value of the complex number, if the third parameter is 'false' then this
* x is the real value of the complex number (optional).
* @param y If the third parameter is 'true' then this y is the argument of
* the complex number, if the third parameter is 'false' then this y is the
* imaginary value of the complex number (optional).
* @param is_polar 'false' by default. If we want to initialise our complex
* number using polar form then set this to true, otherwise set it to false
* to use initialiser which initialises real and imaginary values using the
* first two parameters (optional).
*/
explicit Complex(double x = 0.f, double y = 0.f, bool is_polar = false) {
if (!is_polar) {
re = x;
im = y;
return;
}
re = x * std::cos(y);
im = x * std::sin(y);
}
/**
* \brief Copy Constructor
* @param other The other number to equate our number to.
*/
Complex(const Complex &other) : re(other.real()), im(other.imag()) {}
/**
* \brief Member function to get real value of our complex number.
* Member function (getter) to access the class' re value.
*/
double real() const { return this->re; }
/**
* \brief Member function to get imaginary value of our complex number.
* Member function (getter) to access the class' im value.
*/
double imag() const { return this->im; }
/**
* \brief Member function to give the modulus of our complex number.
* Member function to which gives the absolute value (modulus) of our
* complex number
* @return \f$ \sqrt{z \bar{z}} \f$ where \f$ z \f$ is our complex
* number.
*/
double abs() const {
return std::sqrt(this->re * this->re + this->im * this->im);
}
/**
* \brief Member function to give the argument of our complex number.
* @return Argument of our Complex number in radians.
*/
double arg() const { return std::atan2(this->im, this->re); }
/**
* \brief Operator overload of '+' on Complex class.
* Operator overload to be able to add two complex numbers.
* @param other The other number that is added to the current number.
* @return result current number plus other number
*/
Complex operator+(const Complex &other) {
Complex result(this->re + other.re, this->im + other.im);
return result;
}
/**
* \brief Operator overload of '-' on Complex class.
* Operator overload to be able to subtract two complex numbers.
* @param other The other number being subtracted from the current number.
* @return result current number subtract other number
*/
Complex operator-(const Complex &other) {
Complex result(this->re - other.re, this->im - other.im);
return result;
}
/**
* \brief Operator overload of '*' on Complex class.
* Operator overload to be able to multiple two complex numbers.
* @param other The other number to multiply the current number to.
* @return result current number times other number.
*/
Complex operator*(const Complex &other) {
Complex result(this->re * other.re - this->im * other.im,
this->re * other.im + this->im * other.re);
return result;
}
/**
* \brief Operator overload of '~' on Complex class.
* Operator overload of the BITWISE NOT which gives us the conjugate of our
* complex number. NOTE: This is overloading the BITWISE operator but its
* not a BITWISE operation in this definition.
* @return result The conjugate of our complex number.
*/
Complex operator~() const {
Complex result(this->re, -(this->im));
return result;
}
/**
* \brief Operator overload of '/' on Complex class.
* Operator overload to be able to divide two complex numbers. This function
* would throw an exception if the other number is zero.
* @param other The other number we divide our number by.
* @return result Current number divided by other number.
*/
Complex operator/(const Complex &other) {
Complex result = *this * ~other;
double denominator =
other.real() * other.real() + other.imag() * other.imag();
if (denominator != 0) {
result = Complex(result.real() / denominator,
result.imag() / denominator);
return result;
} else {
throw std::invalid_argument("Undefined Value");
}
}
/**
* \brief Operator overload of '=' on Complex class.
* Operator overload to be able to copy RHS instance of Complex to LHS
* instance of Complex
*/
const Complex &operator=(const Complex &other) {
this->re = other.real();
this->im = other.imag();
return *this;
}
};
/**
* \brief Operator overload of '==' on Complex class.
* Logical Equal overload for our Complex class.
* @param a Left hand side of our expression
* @param b Right hand side of our expression
* @return 'True' If real and imaginary parts of a and b are same
* @return 'False' Otherwise.
*/
bool operator==(const Complex &a, const Complex &b) {
return a.real() == b.real() && a.imag() == b.imag();
}
/**
* \brief Operator overload of '<<' of ostream for Complex class.
* Overloaded insersion operator to accommodate the printing of our complex
* number in their standard form.
* @param os The console stream
* @param num The complex number.
*/
std::ostream &operator<<(std::ostream &os, const Complex &num) {
os << "(" << num.real();
if (num.imag() < 0) {
os << " - " << -num.imag();
} else {
os << " + " << num.imag();
}
os << "i)";
return os;
}
/**
* \brief Function to get random numbers to generate our complex numbers for
* test
*/
double get_rand() { return (std::rand() % 100 - 50) / 100.f; }
/**
* Tests Function
*/
void tests() {
std::srand(std::time(nullptr));
double x1 = get_rand(), y1 = get_rand(), x2 = get_rand(), y2 = get_rand();
Complex num1(x1, y1), num2(x2, y2);
std::complex<double> cnum1(x1, y1), cnum2(x2, y2);
Complex result;
std::complex<double> expected;
// Test for addition
result = num1 + num2;
expected = cnum1 + cnum2;
assert(((void)"1 + 1i + 1 + 1i is equal to 2 + 2i but the addition doesn't "
"add up \n",
(result.real() == expected.real() &&
result.imag() == expected.imag())));
std::cout << "First test passes." << std::endl;
// Test for subtraction
result = num1 - num2;
expected = cnum1 - cnum2;
assert(((void)"1 + 1i - 1 - 1i is equal to 0 but the program says "
"otherwise. \n",
(result.real() == expected.real() &&
result.imag() == expected.imag())));
std::cout << "Second test passes." << std::endl;
// Test for multiplication
result = num1 * num2;
expected = cnum1 * cnum2;
assert(((void)"(1 + 1i) * (1 + 1i) is equal to 2i but the program says "
"otherwise. \n",
(result.real() == expected.real() &&
result.imag() == expected.imag())));
std::cout << "Third test passes." << std::endl;
// Test for division
result = num1 / num2;
expected = cnum1 / cnum2;
assert(((void)"(1 + 1i) / (1 + 1i) is equal to 1 but the program says "
"otherwise.\n",
(result.real() == expected.real() &&
result.imag() == expected.imag())));
std::cout << "Fourth test passes." << std::endl;
// Test for conjugates
result = ~num1;
expected = std::conj(cnum1);
assert(((void)"(1 + 1i) has a conjugate which is equal to (1 - 1i) but the "
"program says otherwise.\n",
(result.real() == expected.real() &&
result.imag() == expected.imag())));
std::cout << "Fifth test passes.\n";
// Test for Argument of our complex number
assert(((void)"(1 + 1i) has argument PI / 4 but the program differs from "
"the std::complex result.\n",
(num1.arg() == std::arg(cnum1))));
std::cout << "Sixth test passes.\n";
// Test for absolute value of our complex number
assert(((void)"(1 + 1i) has absolute value sqrt(2) but the program differs "
"from the std::complex result. \n",
(num1.abs() == std::abs(cnum1))));
std::cout << "Seventh test passes.\n";
}
/**
* Main function
*/
int main() {
tests();
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
/**
* @file
* @brief Compute [double
* factorial](https://en.wikipedia.org/wiki/Double_factorial): \f$n!!\f$
*
* Double factorial of a non-negative integer `n`, is defined as the product of
* all the integers from 1 to n that have the same parity (odd or even) as n.
* <br/>It is also called as semifactorial of a number and is denoted by
* \f$n!!\f$
*/
#include <cassert>
#include <cstdint>
#include <iostream>
/** Compute double factorial using iterative method
*/
uint64_t double_factorial_iterative(uint64_t n) {
uint64_t res = 1;
for (uint64_t i = n;; i -= 2) {
if (i == 0 || i == 1)
return res;
res *= i;
}
return res;
}
/** Compute double factorial using resursive method.
* <br/>Recursion can be costly for large numbers.
*/
uint64_t double_factorial_recursive(uint64_t n) {
if (n <= 1)
return 1;
return n * double_factorial_recursive(n - 2);
}
/** Wrapper to run tests using both recursive and iterative implementations.
* The checks are only valid in debug builds due to the use of `assert()`
* statements.
* \param [in] n number to check double factorial for
* \param [in] expected expected result
*/
void test(uint64_t n, uint64_t expected) {
assert(double_factorial_iterative(n) == expected);
assert(double_factorial_recursive(n) == expected);
}
/**
* Test implementations
*/
void tests() {
std::cout << "Test 1:\t n=5\t...";
test(5, 15);
std::cout << "passed\n";
std::cout << "Test 2:\t n=15\t...";
test(15, 2027025);
std::cout << "passed\n";
std::cout << "Test 3:\t n=0\t...";
test(0, 1);
std::cout << "passed\n";
}
/**
* Main function
*/
int main() {
tests();
return 0;
}
+118
View File
@@ -0,0 +1,118 @@
/**
* @file
* @brief [The Sieve of
* Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
* @details
* Store an array of booleans where a true value indicates that it's index is
* prime. For all the values in the array starting from 2 which we know is
* prime, we walk the array in multiples of the current outer value setting them
* to not prime. If we remove all multiples of a value as we see it, we'll be
* left with just primes.
*
* Pass "print" as a command line arg to see the generated list of primes
* @author [Keval Kapdee](https://github.com/thechubbypanda)
*/
#include <cassert> /// For assert
#include <chrono> /// For timing the sieve
#include <iostream> /// For IO operations
#include <string> /// For string handling
#include <vector> /// For std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief Performs the sieve
* @param vec Array of bools, all initialised to true, where the number of
* elements is the highest number we wish to check for primeness
* @returns void
*/
void sieve(std::vector<bool> *vec) {
(*vec)[0] = false;
(*vec)[1] = false;
// The sieve sets values to false as they are found not prime
for (uint64_t n = 2; n < vec->size(); n++) {
for (uint64_t multiple = n << 1; multiple < vec->size();
multiple += n) {
(*vec)[multiple] = false;
}
}
}
/**
* @brief Prints all the indexes of true values in the passed std::vector
* @param primes The vector that has been passed through `sieve(...)`
* @returns void
*/
void print_primes(std::vector<bool> const &primes) {
for (uint64_t i = 0; i < primes.size(); i++) {
if (primes[i]) {
std::cout << i << std::endl;
}
}
}
} // namespace math
/**
* @brief Self-tests the sieve function for major inconsistencies
* @returns void
*/
static void test() {
auto primes = std::vector<bool>(10, true);
math::sieve(&primes);
assert(primes[0] == false);
assert(primes[1] == false);
assert(primes[2] == true);
assert(primes[3] == true);
assert(primes[4] == false);
assert(primes[5] == true);
assert(primes[6] == false);
assert(primes[7] == true);
assert(primes[8] == false);
assert(primes[9] == false);
std::cout << "All tests have successfully passed!\n";
}
/**
* @brief Main function
* @param argc commandline argument count
* @param argv commandline array of arguments
* @returns 0 on exit
*/
int main(int argc, char *argv[]) {
test(); // run self-test implementations
// The largest prime we will check for
auto max = 10000;
// Store a boolean for every number which states if that index is prime or
// not
auto primes = std::vector<bool>(max, true);
// Store the algorithm start time
auto start = std::chrono::high_resolution_clock::now();
// Run the sieve
math::sieve(&primes);
// Time difference calculation
auto time = std::chrono::duration_cast<
std::chrono::duration<double, std::ratio<1>>>(
std::chrono::high_resolution_clock::now() - start)
.count();
// Print the primes if we see that "print" was passed as an arg
if (argc > 1 && argv[1] == std::string("print")) {
math::print_primes(primes);
}
// Print the time taken we found earlier
std::cout << "Time taken: " << time << " seconds" << std::endl;
return 0;
}
+80
View File
@@ -0,0 +1,80 @@
/**
* @file
* @brief Implementation of [Euler's
* Totient](https://en.wikipedia.org/wiki/Euler%27s_totient_function)
* @description
* Euler Totient Function is also known as phi function.
* \f[\phi(n) =
* \phi\left({p_1}^{a_1}\right)\cdot\phi\left({p_2}^{a_2}\right)\ldots\f] where
* \f$p_1\f$, \f$p_2\f$, \f$\ldots\f$ are prime factors of n.
* <br/>3 Euler's properties:
* 1. \f$\phi(n) = n-1\f$
* 2. \f$\phi(n^k) = n^k - n^{k-1}\f$
* 3. \f$\phi(a,b) = \phi(a)\cdot\phi(b)\f$ where a and b are relative primes.
*
* Applying this 3 properties on the first equation.
* \f[\phi(n) =
* n\cdot\left(1-\frac{1}{p_1}\right)\cdot\left(1-\frac{1}{p_2}\right)\cdots\f]
* where \f$p_1\f$,\f$p_2\f$... are prime factors.
* Hence Implementation in \f$O\left(\sqrt{n}\right)\f$.
* <br/>Some known values are:
* * \f$\phi(100) = 40\f$
* * \f$\phi(1) = 1\f$
* * \f$\phi(17501) = 15120\f$
* * \f$\phi(1420) = 560\f$
* @author [Mann Mehta](https://github.com/mann2108)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for IO operations
/**
* @brief Mathematical algorithms
* @namespace
*/
namespace math {
/**
* @brief Function to calculate Euler's Totient
* @param n the number to find the Euler's Totient of
*/
uint64_t phiFunction(uint64_t n) {
uint64_t result = n;
for (uint64_t i = 2; i * i <= n; i++) {
if (n % i != 0)
continue;
while (n % i == 0) n /= i;
result -= result / i;
}
if (n > 1)
result -= result / n;
return result;
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
assert(math::phiFunction(1) == 1);
assert(math::phiFunction(2) == 1);
assert(math::phiFunction(10) == 4);
assert(math::phiFunction(123456) == 41088);
assert(math::phiFunction(808017424794) == 263582333856);
assert(math::phiFunction(3141592) == 1570792);
assert(math::phiFunction(27182818) == 12545904);
std::cout << "All tests have successfully passed!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test();
return 0;
}
+97
View File
@@ -0,0 +1,97 @@
/**
* @file
* @brief GCD using [extended Euclid's algorithm]
* (https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm)
*
* Finding coefficients of a and b ie x and y in Bézout's identity
* \f[\text{gcd}(a, b) = a \times x + b \times y \f]
* This is also used in finding Modular
* multiplicative inverse of a number. (A * B)%M == 1 Here B is the MMI of A for
* given M, so extendedEuclid (A, M) gives B.
*/
#include <algorithm> // for swap function
#include <iostream>
#include <cstdint>
/**
* function to update the coefficients per iteration
* \f[r_0,\,r = r,\, r_0 - \text{quotient}\times r\f]
*
* @param[in,out] r signed or unsigned
* @param[in,out] r0 signed or unsigned
* @param[in] quotient unsigned
*/
template <typename T, typename T2>
inline void update_step(T *r, T *r0, const T2 quotient) {
T temp = *r;
*r = *r0 - (quotient * temp);
*r0 = temp;
}
/**
* Implementation using iterative algorithm from
* [Wikipedia](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Pseudocode)
*
* @param[in] A unsigned
* @param[in] B unsigned
* @param[out] GCD unsigned
* @param[out] x signed
* @param[out] y signed
*/
template <typename T1, typename T2>
void extendedEuclid_1(T1 A, T1 B, T1 *GCD, T2 *x, T2 *y) {
if (B > A)
std::swap(A, B); // Ensure that A >= B
T2 s = 0, s0 = 1;
T2 t = 1, t0 = 0;
T1 r = B, r0 = A;
while (r != 0) {
T1 quotient = r0 / r;
update_step(&r, &r0, quotient);
update_step(&s, &s0, quotient);
update_step(&t, &t0, quotient);
}
*GCD = r0;
*x = s0;
*y = t0;
}
/**
* Implementation using recursive algorithm
*
* @param[in] A unsigned
* @param[in] B unsigned
* @param[out] GCD unsigned
* @param[in,out] x signed
* @param[in,out] y signed
*/
template <typename T, typename T2>
void extendedEuclid(T A, T B, T *GCD, T2 *x, T2 *y) {
if (B > A)
std::swap(A, B); // Ensure that A >= B
if (B == 0) {
*GCD = A;
*x = 1;
*y = 0;
} else {
extendedEuclid(B, A % B, GCD, x, y);
T2 temp = *x;
*x = *y;
*y = temp - (A / B) * (*y);
}
}
/// Main function
int main() {
uint32_t a, b, gcd;
int32_t x, y;
std::cin >> a >> b;
extendedEuclid(a, b, &gcd, &x, &y);
std::cout << gcd << " " << x << " " << y << std::endl;
extendedEuclid_1(a, b, &gcd, &x, &y);
std::cout << gcd << " " << x << " " << y << std::endl;
return 0;
}
+60
View File
@@ -0,0 +1,60 @@
/**
* @file
* @brief Find the [factorial](https://en.wikipedia.org/wiki/Factorial) of a
* given number
* @details Calculate factorial via recursion
* \f[n! = n\times(n-1)\times(n-2)\times(n-3)\times\ldots\times3\times2\times1
* = n\times(n-1)!\f]
* for example:
* \f$5! = 5\times4! = 5\times4\times3\times2\times1 = 120\f$
*
* @author [Akshay Gupta](https://github.com/Akshay1910)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for I/O operations
/**
* @namespace
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief function to find factorial of given number
* @param n is the number which is to be factorialized
* @warning Maximum value for the parameter is 20 as 21!
* cannot be represented in 64 bit unsigned int
*/
uint64_t factorial(uint8_t n) {
if (n > 20) {
throw std::invalid_argument("maximum value is 20\n");
}
if (n == 0) {
return 1;
}
return n * factorial(n - 1);
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void tests() {
assert(math::factorial(1) == 1);
assert(math::factorial(0) == 1);
assert(math::factorial(5) == 120);
assert(math::factorial(10) == 3628800);
assert(math::factorial(20) == 2432902008176640000);
std::cout << "All tests have passed successfully!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // run self-test implementations
return 0;
}
+65
View File
@@ -0,0 +1,65 @@
/**
* @file
* @brief [Factorial](https://en.wikipedia.org/wiki/Factorial) calculation using
* recursion and [memoization](https://en.wikipedia.org/wiki/Memoization)
* @details
* This program computes the factorial of a non-negative integer using recursion
* with memoization (top-down dynamic programming). It stores intermediate
* results to avoid redundant calculations for improved efficiency.
*
* Memoization is a form of caching where the result to an expensive function
* call is stored and returned. Example: Input: n = 5 Output: 120
*
* Explanation: 5! = 5 × 4 × 3 × 2 × 1 = 120
*
* The program uses a recursive function which caches computed
* results in a memo array to avoid recalculating factorials for the same
* numbers.
*
* Time Complexity: O(n)
* Space Complexity: O(n)
*/
#include <cassert> // For test cases
#include <cstdint> // For uint64_t
#include <vector> // For std::vector
class MemorisedFactorial {
std::vector<std::uint64_t> known_values = {1};
public:
/**
* @note This function was intentionally written as recursive
* and it does not handle overflows.
* @returns factorial of n
*/
std::uint64_t operator()(std::uint64_t n) {
if (n >= this->known_values.size()) {
this->known_values.push_back(n * this->operator()(n - 1));
}
return this->known_values.at(n);
}
};
void test_MemorisedFactorial_in_order() {
auto factorial = MemorisedFactorial();
assert(factorial(0) == 1);
assert(factorial(1) == 1);
assert(factorial(5) == 120);
assert(factorial(10) == 3628800);
}
void test_MemorisedFactorial_no_order() {
auto factorial = MemorisedFactorial();
assert(factorial(10) == 3628800);
}
/**
* @brief Main function to run tests
* @returns 0 on program success
*/
int main() {
test_MemorisedFactorial_in_order();
test_MemorisedFactorial_no_order();
return 0;
}
+93
View File
@@ -0,0 +1,93 @@
/**
* @file
* @brief Faster computation for \f$a^b\f$
*
* Program that computes \f$a^b\f$ in \f$O(logN)\f$ time.
* It is based on formula that:
* 1. if \f$b\f$ is even:
* \f$a^b = a^\frac{b}{2} \cdot a^\frac{b}{2} = {a^\frac{b}{2}}^2\f$
* 2. if \f$b\f$ is odd: \f$a^b = a^\frac{b-1}{2}
* \cdot a^\frac{b-1}{2} \cdot a = {a^\frac{b-1}{2}}^2 \cdot a\f$
*
* We can compute \f$a^b\f$ recursively using above algorithm.
*/
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <ctime>
#include <iostream>
/**
* algorithm implementation for \f$a^b\f$
*/
template <typename T>
double fast_power_recursive(T a, T b) {
// negative power. a^b = 1 / (a^-b)
if (b < 0)
return 1.0 / fast_power_recursive(a, -b);
if (b == 0)
return 1;
T bottom = fast_power_recursive(a, b >> 1);
// Since it is integer division b/2 = (b-1)/2 where b is odd.
// Therefore, case2 is easily solved by integer division.
double result;
if ((b & 1) == 0) // case1
result = bottom * bottom;
else // case2
result = bottom * bottom * a;
return result;
}
/**
Same algorithm with little different formula.
It still calculates in \f$O(\log N)\f$
*/
template <typename T>
double fast_power_linear(T a, T b) {
// negative power. a^b = 1 / (a^-b)
if (b < 0)
return 1.0 / fast_power_linear(a, -b);
double result = 1;
while (b) {
if (b & 1)
result = result * a;
a = a * a;
b = b >> 1;
}
return result;
}
/**
* Main function
*/
int main() {
std::srand(std::time(nullptr));
std::ios_base::sync_with_stdio(false);
std::cout << "Testing..." << std::endl;
for (int i = 0; i < 20; i++) {
int a = std::rand() % 20 - 10;
int b = std::rand() % 20 - 10;
std::cout << std::endl << "Calculating " << a << "^" << b << std::endl;
assert(fast_power_recursive(a, b) == std::pow(a, b));
assert(fast_power_linear(a, b) == std::pow(a, b));
std::cout << "------ " << a << "^" << b << " = "
<< fast_power_recursive(a, b) << std::endl;
}
int64_t a, b;
std::cin >> a >> b;
std::cout << a << "^" << b << " = " << fast_power_recursive(a, b)
<< std::endl;
std::cout << a << "^" << b << " = " << fast_power_linear(a, b) << std::endl;
return 0;
}
+67
View File
@@ -0,0 +1,67 @@
/**
* @file
* @brief n-th [Fibonacci
* number](https://en.wikipedia.org/wiki/Fibonacci_sequence).
*
* @details
* Naive recursive implementation to calculate the n-th Fibonacci number.
* \f[\text{fib}(n) = \text{fib}(n-1) + \text{fib}(n-2)\f]
*
* @see fibonacci_large.cpp, fibonacci_fast.cpp, string_fibonacci.cpp
*/
#include <cstdint>
#include <cassert> /// for assert
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Math algorithms
*/
namespace math {
/**
* @namespace fibonacci
* @brief Functions for Fibonacci sequence
*/
namespace fibonacci {
/**
* @brief Function to compute the n-th Fibonacci number
* @param n the index of the Fibonacci number
* @returns n-th element of the Fibonacci's sequence
*/
uint64_t fibonacci(uint64_t n) {
// If the input is 0 or 1 just return the same (Base Case)
// This will set the first 2 values of the sequence
if (n <= 1) {
return n;
}
// Add the preceding 2 values of the sequence to get next
return fibonacci(n - 1) + fibonacci(n - 2);
}
} // namespace fibonacci
} // namespace math
/**
* @brief Self-test implementation
* @returns `void`
*/
static void test() {
assert(math::fibonacci::fibonacci(0) == 0);
assert(math::fibonacci::fibonacci(1) == 1);
assert(math::fibonacci::fibonacci(2) == 1);
assert(math::fibonacci::fibonacci(3) == 2);
assert(math::fibonacci::fibonacci(4) == 3);
assert(math::fibonacci::fibonacci(15) == 610);
assert(math::fibonacci::fibonacci(20) == 6765);
std::cout << "All tests have passed successfully!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+178
View File
@@ -0,0 +1,178 @@
/**
* @file
* @brief Faster computation of Fibonacci series.
*
* @details
* An efficient way to calculate nth fibonacci number faster and simpler than
* \f$O(n\log n)\f$ method of matrix exponentiation. This works by using both
* recursion and dynamic programming. As 93rd fibonacci exceeds 19 digits, which
* cannot be stored in a single long long variable, we can only use it till 92nd
* fibonacci we can use it for 10000th fibonacci etc, if we implement
* bigintegers. This algorithm works with the fact that nth fibonacci can easily
* found if we have already found \f$n/2\f$th or \f$(n+1)/2\f$th fibonacci. It is a property
* of fibonacci similar to matrix exponentiation.
*
* @author [Krishna Vedala](https://github.com/kvedala)
* @see fibonacci_large.cpp, fibonacci.cpp, string_fibonacci.cpp
*/
#include <cinttypes> /// for uint64_t
#include <cstdio> /// for standard IO
#include <iostream> /// for IO operations
#include <cassert> /// for assert
#include <string> /// for std::to_string
#include <stdexcept> /// for std::invalid_argument
/**
* @brief Maximum Fibonacci number that can be computed
*
* @details
* The result after 93 cannot be stored in a `uint64_t` data type.
*/
constexpr uint64_t MAX = 93;
/**
* @brief Function to compute the nth Fibonacci number
* @param n The index of the Fibonacci number to compute
* @return uint64_t The nth Fibonacci number
*/
uint64_t fib(uint64_t n) {
// Using static keyword will retain the values of
// f1 and f2 for the next function call.
static uint64_t f1 = 1, f2 = 1;
if (n <= 2) {
return f2;
} if (n >= MAX) {
throw std::invalid_argument("Cannot compute for n>=" + std::to_string(MAX) +
" due to limit of 64-bit integers");
return 0;
}
// We do not need temp to be static.
uint64_t temp = f2;
f2 += f1;
f1 = temp;
return f2;
}
/**
* @brief Function to test the Fibonacci computation
* @returns void
*/
static void test() {
// Test for valid Fibonacci numbers
assert(fib(1) == 1);
assert(fib(2) == 1);
assert(fib(3) == 2);
assert(fib(4) == 3);
assert(fib(5) == 5);
assert(fib(6) == 8);
assert(fib(7) == 13);
assert(fib(8) == 21);
assert(fib(9) == 34);
assert(fib(10) == 55);
assert(fib(11) == 89);
assert(fib(12) == 144);
assert(fib(13) == 233);
assert(fib(14) == 377);
assert(fib(15) == 610);
assert(fib(16) == 987);
assert(fib(17) == 1597);
assert(fib(18) == 2584);
assert(fib(19) == 4181);
assert(fib(20) == 6765);
assert(fib(21) == 10946);
assert(fib(22) == 17711);
assert(fib(23) == 28657);
assert(fib(24) == 46368);
assert(fib(25) == 75025);
assert(fib(26) == 121393);
assert(fib(27) == 196418);
assert(fib(28) == 317811);
assert(fib(29) == 514229);
assert(fib(30) == 832040);
assert(fib(31) == 1346269);
assert(fib(32) == 2178309);
assert(fib(33) == 3524578);
assert(fib(34) == 5702887);
assert(fib(35) == 9227465);
assert(fib(36) == 14930352);
assert(fib(37) == 24157817);
assert(fib(38) == 39088169);
assert(fib(39) == 63245986);
assert(fib(40) == 102334155);
assert(fib(41) == 165580141);
assert(fib(42) == 267914296);
assert(fib(43) == 433494437);
assert(fib(44) == 701408733);
assert(fib(45) == 1134903170);
assert(fib(46) == 1836311903);
assert(fib(47) == 2971215073);
assert(fib(48) == 4807526976);
assert(fib(49) == 7778742049);
assert(fib(50) == 12586269025);
assert(fib(51) == 20365011074);
assert(fib(52) == 32951280099);
assert(fib(53) == 53316291173);
assert(fib(54) == 86267571272);
assert(fib(55) == 139583862445);
assert(fib(56) == 225851433717);
assert(fib(57) == 365435296162);
assert(fib(58) == 591286729879);
assert(fib(59) == 956722026041);
assert(fib(60) == 1548008755920);
assert(fib(61) == 2504730781961);
assert(fib(62) == 4052739537881);
assert(fib(63) == 6557470319842);
assert(fib(64) == 10610209857723);
assert(fib(65) == 17167680177565);
assert(fib(66) == 27777890035288);
assert(fib(67) == 44945570212853);
assert(fib(68) == 72723460248141);
assert(fib(69) == 117669030460994);
assert(fib(70) == 190392490709135);
assert(fib(71) == 308061521170129);
assert(fib(72) == 498454011879264);
assert(fib(73) == 806515533049393);
assert(fib(74) == 1304969544928657);
assert(fib(75) == 2111485077978050);
assert(fib(76) == 3416454622906707);
assert(fib(77) == 5527939700884757);
assert(fib(78) == 8944394323791464);
assert(fib(79) == 14472334024676221);
assert(fib(80) == 23416728348467685);
assert(fib(81) == 37889062373143906);
assert(fib(82) == 61305790721611591);
assert(fib(83) == 99194853094755497);
assert(fib(84) == 160500643816367088);
assert(fib(85) == 259695496911122585);
assert(fib(86) == 420196140727489673);
assert(fib(87) == 679891637638612258);
assert(fib(88) == 1100087778366101931);
assert(fib(89) == 1779979416004714189);
assert(fib(90) == 2880067194370816120);
assert(fib(91) == 4660046610375530309);
assert(fib(92) == 7540113804746346429);
// Test for invalid Fibonacci numbers
try {
fib(MAX + 1);
assert(false && "Expected an invalid_argument exception to be thrown");
} catch (const std::invalid_argument& e) {
const std::string expected_message = "Cannot compute for n>=" + std::to_string(MAX) +
" due to limit of 64-bit integers";
assert(e.what() == expected_message);
}
std::cout << "All Fibonacci tests have successfully passed!\n";
}
/**
* @brief Main Function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+85
View File
@@ -0,0 +1,85 @@
/**
* @file
* @brief Computes N^th Fibonacci number given as
* input argument. Uses custom build arbitrary integers library
* to perform additions and other operations.
*
* Took 0.608246 seconds to compute 50,000^th Fibonacci
* number that contains 10450 digits!
*
* \author [Krishna Vedala](https://github.com/kvedala)
* @see fibonacci.cpp, fibonacci_fast.cpp, string_fibonacci.cpp
*/
#include <cinttypes>
#include <ctime>
#include <iostream>
#include "./large_number.h"
/** Compute fibonacci numbers using the relation
* \f[f(n)=f(n-1)+f(n-2)\f]
* and returns the result as a large_number type.
*/
large_number fib(uint64_t n) {
large_number f0(1);
large_number f1(1);
do {
large_number f2 = f1;
f1 += f0;
f0 = f2;
n--;
} while (n > 2); // since we start from 2
return f1;
}
int main(int argc, char *argv[]) {
uint64_t N;
if (argc == 2) {
N = strtoull(argv[1], NULL, 10);
} else {
std::cout << "Enter N: ";
std::cin >> N;
}
clock_t start_time = std::clock();
large_number result = fib(N);
clock_t end_time = std::clock();
double time_taken = static_cast<double>(end_time - start_time) /
static_cast<double>(CLOCKS_PER_SEC);
std::cout << std::endl
<< N << "^th Fibonacci number: " << result << std::endl
<< "Number of digits: " << result.num_digits() << std::endl
<< "Time taken: " << std::scientific << time_taken << " s"
<< std::endl;
N = 5000;
if (fib(N) ==
large_number(
"387896845438832563370191630832590531208212771464624510616059721489"
"555013904403709701082291646221066947929345285888297381348310200895"
"498294036143015691147893836421656394410691021450563413370655865623"
"825465670071252592990385493381392883637834751890876297071203333705"
"292310769300851809384980180384781399674888176555465378829164426891"
"298038461377896902150229308247566634622492307188332480328037503913"
"035290330450584270114763524227021093463769910400671417488329842289"
"149127310405432875329804427367682297724498774987455569190770388063"
"704683279481135897373999311010621930814901857081539785437919530561"
"751076105307568878376603366735544525884488624161921055345749367589"
"784902798823435102359984466393485325641195222185956306047536464547"
"076033090242080638258492915645287629157575914234380914230291749108"
"898415520985443248659407979357131684169286803954530954538869811466"
"508206686289742063932343848846524098874239587380197699382031717420"
"893226546887936400263079778005875912967138963421425257911687275560"
"0360311370547754724604639987588046985178408674382863125"))
std::cout << "Test for " << N << "^th Fibonacci number passed!"
<< std::endl;
else
std::cerr << "Test for " << N << "^th Fibonacci number failed!"
<< std::endl;
return 0;
}
+116
View File
@@ -0,0 +1,116 @@
/**
* @file
* @brief This program computes the N^th Fibonacci number in modulo mod
* input argument .
*
* Takes O(logn) time to compute nth Fibonacci number
*
*
* \author [villayatali123](https://github.com/villayatali123)
* \author [unknown author]()
* @see fibonacci.cpp, fibonacci_fast.cpp, string_fibonacci.cpp,
* fibonacci_large.cpp
*/
#include <cassert>
#include <cstdint>
#include <iostream>
#include <vector>
/**
* This function finds nth fibonacci number in a given modulus
* @param n nth fibonacci number
* @param mod modulo number
*/
uint64_t fibo(uint64_t n, uint64_t mod) {
std::vector<uint64_t> result(2, 0);
std::vector<std::vector<uint64_t>> transition(2,
std::vector<uint64_t>(2, 0));
std::vector<std::vector<uint64_t>> Identity(2, std::vector<uint64_t>(2, 0));
n--;
result[0] = 1, result[1] = 1;
Identity[0][0] = 1;
Identity[0][1] = 0;
Identity[1][0] = 0;
Identity[1][1] = 1;
transition[0][0] = 0;
transition[1][0] = transition[1][1] = transition[0][1] = 1;
while (n) {
if (n % 2) {
std::vector<std::vector<uint64_t>> res(2,
std::vector<uint64_t>(2, 0));
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
res[i][j] =
(res[i][j] % mod +
((Identity[i][k] % mod * transition[k][j] % mod)) %
mod) %
mod;
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
Identity[i][j] = res[i][j];
}
}
n--;
} else {
std::vector<std::vector<uint64_t>> res1(
2, std::vector<uint64_t>(2, 0));
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
res1[i][j] =
(res1[i][j] % mod + ((transition[i][k] % mod *
transition[k][j] % mod)) %
mod) %
mod;
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
transition[i][j] = res1[i][j];
}
}
n = n / 2;
}
}
return ((result[0] % mod * Identity[0][0] % mod) % mod +
(result[1] % mod * Identity[1][0] % mod) % mod) %
mod;
}
/**
* Function to test above algorithm
*/
static void test() {
assert(fibo(6, 1000000007) == 8);
std::cout << "test case:1 passed\n";
assert(fibo(5, 1000000007) == 5);
std::cout << "test case:2 passed\n";
assert(fibo(10, 1000000007) == 55);
std::cout << "test case:3 passed\n";
assert(fibo(500, 100) == 25);
std::cout << "test case:3 passed\n";
assert(fibo(500, 10000) == 4125);
std::cout << "test case:3 passed\n";
std::cout << "--All tests passed--\n";
}
/**
* Main function
*/
int main() {
test();
uint64_t mod = 1000000007;
std::cout << "Enter the value of N: ";
uint64_t n = 0;
std::cin >> n;
std::cout << n << "th Fibonacci number in modulo " << mod << ": "
<< fibo(n, mod) << std::endl;
}
+140
View File
@@ -0,0 +1,140 @@
/**
* @file
* @brief An algorithm to calculate the sum of [Fibonacci
* Sequence](https://en.wikipedia.org/wiki/Fibonacci_number): \f$\mathrm{F}(n) +
* \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$
* @details An algorithm to calculate the sum of Fibonacci Sequence:
* \f$\mathrm{F}(n) + \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$ where
* \f$\mathrm{F}(i)\f$ denotes the i-th Fibonacci Number . Note that F(0) = 0
* and F(1) = 1. The value of the sum is calculated using matrix exponentiation.
* Reference source:
* https://stackoverflow.com/questions/4357223/finding-the-sum-of-fibonacci-numbers
* @author [Sarthak Sahu](https://github.com/SarthakSahu1009)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::cin and std::cout
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace fibonacci_sum
* @brief Functions for the sum of the Fibonacci Sequence: \f$\mathrm{F}(n) +
* \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$
*/
namespace fibonacci_sum {
using matrix = std::vector<std::vector<uint64_t> >;
/**
* Function to multiply two matrices
* @param T matrix 1
* @param A martix 2
* @returns resultant matrix
*/
math::fibonacci_sum::matrix multiply(const math::fibonacci_sum::matrix &T,
const math::fibonacci_sum::matrix &A) {
math::fibonacci_sum::matrix result(2, std::vector<uint64_t>(2, 0));
// multiplying matrices
result[0][0] = T[0][0] * A[0][0] + T[0][1] * A[1][0];
result[0][1] = T[0][0] * A[0][1] + T[0][1] * A[1][1];
result[1][0] = T[1][0] * A[0][0] + T[1][1] * A[1][0];
result[1][1] = T[1][0] * A[0][1] + T[1][1] * A[1][1];
return result;
}
/**
* Function to compute A^n where A is a matrix.
* @param T matrix
* @param ex power
* @returns resultant matrix
*/
math::fibonacci_sum::matrix power(math::fibonacci_sum::matrix T, uint64_t ex) {
math::fibonacci_sum::matrix A{{1, 1}, {1, 0}};
if (ex == 0 || ex == 1) {
return T;
}
T = power(T, ex / 2);
T = multiply(T, T);
if (ex & 1) {
T = multiply(T, A);
}
return T;
}
/**
* Function to compute sum of fibonacci sequence from 0 to n.
* @param n number
* @returns uint64_t ans, the sum of sequence
*/
uint64_t result(uint64_t n) {
math::fibonacci_sum::matrix T{{1, 1}, {1, 0}};
T = power(T, n);
uint64_t ans = T[0][1];
ans = (ans - 1);
return ans;
}
/**
* Function to compute sum of fibonacci sequence from n to m.
* @param n start of sequence
* @param m end of sequence
* @returns uint64_t the sum of sequence
*/
uint64_t fiboSum(uint64_t n, uint64_t m) {
return (result(m + 2) - result(n + 1));
}
} // namespace fibonacci_sum
} // namespace math
/**
* Function for testing fiboSum function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint64_t n = 0, m = 3;
uint64_t test_1 = math::fibonacci_sum::fiboSum(n, m);
assert(test_1 == 4);
std::cout << "Passed Test 1!" << std::endl;
n = 3;
m = 5;
uint64_t test_2 = math::fibonacci_sum::fiboSum(n, m);
assert(test_2 == 10);
std::cout << "Passed Test 2!" << std::endl;
n = 5;
m = 7;
uint64_t test_3 = math::fibonacci_sum::fiboSum(n, m);
assert(test_3 == 26);
std::cout << "Passed Test 3!" << std::endl;
n = 7;
m = 10;
uint64_t test_4 = math::fibonacci_sum::fiboSum(n, m);
assert(test_4 == 123);
std::cout << "Passed Test 4!" << std::endl;
n = 9;
m = 12;
uint64_t test_5 = math::fibonacci_sum::fiboSum(n, m);
assert(test_5 == 322);
std::cout << "Passed Test 5!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}
@@ -0,0 +1,103 @@
/**
* @author [aminos 🇮🇳](https://github.com/amino19)
* @file
*
* @brief [Program to count digits
* in an
* integer](https://www.geeksforgeeks.org/program-count-digits-integer-3-different-methods)
* @details It is a very basic math of finding number of digits in a given
* number i.e, we can use it by inputting values whether it can be a
* positive/negative value, let's say: an integer. There is also a second
* method: by using "K = floor(log10(N) + 1)", but it's only applicable for
* numbers (not integers). The code for that is also included
* (finding_number_of_digits_in_a_number_using_log). For more details, refer to
* the
* [Algorithms-Explanation](https://github.com/TheAlgorithms/Algorithms-Explanation/blob/master/en/Basic%20Math/Finding
* the number of digits in a number.md) repository.
*/
#include <cassert> /// for assert
#include <cmath> /// for log calculation
#include <cstdint>
#include <iostream> /// for IO operations
/**
* @brief The main function that checks
* the number of digits in a number.
* TC : O(number of digits)
* @param n the number to check its digits
* @returns the digits count
*/
uint64_t finding_number_of_digits_in_a_number(uint64_t n) {
uint64_t count = 0; ///< the variable used for the digits count
// iterate until `n` becomes 0
// remove last digit from `n` in each iteration
// increase `count` by 1 in each iteration
while (n != 0) {
// we can also use `n = n / 10`
n /= 10;
// each time the loop is running, `count` will be incremented by 1.
++count;
}
return count;
}
/**
* @brief This function finds the number of digits
* in constant time using logarithmic function
* TC: O(1)
* @param n the number to check its digits
* @returns the digits count
*/
double finding_number_of_digits_in_a_number_using_log(double n) {
// log(0) is undefined
if (n == 0) {
return 0;
}
// to handle the negative numbers
if (n < 0) {
n = -n;
}
double count = floor(log10(n) + 1);
return count;
}
/**
* @brief Self-test implementations
* @returns void
*/
static void first_test() {
assert(finding_number_of_digits_in_a_number(5492) == 4);
assert(finding_number_of_digits_in_a_number(-0) == 0);
assert(finding_number_of_digits_in_a_number(10000) == 5);
assert(finding_number_of_digits_in_a_number(9) == 1);
assert(finding_number_of_digits_in_a_number(100000) == 6);
assert(finding_number_of_digits_in_a_number(13) == 2);
assert(finding_number_of_digits_in_a_number(564) == 3);
}
static void second_test() {
assert(finding_number_of_digits_in_a_number_using_log(5492) == 4);
assert(finding_number_of_digits_in_a_number_using_log(-0) == 0);
assert(finding_number_of_digits_in_a_number_using_log(10000) == 5);
assert(finding_number_of_digits_in_a_number_using_log(9) == 1);
assert(finding_number_of_digits_in_a_number_using_log(100000) == 6);
assert(finding_number_of_digits_in_a_number_using_log(13) == 2);
assert(finding_number_of_digits_in_a_number_using_log(564) == 3);
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
// run self-test implementations
first_test();
second_test();
std::cout << "All tests have successfully passed!\n";
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
/**
* @file
* @brief Compute the greatest common denominator of two integers using
* *iterative form* of
* [Euclidean algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm)
*
* @see gcd_recursive_euclidean.cpp, gcd_of_n_numbers.cpp
*/
#include <iostream>
#include <stdexcept>
/**
* algorithm
*/
int gcd(int num1, int num2) {
if (num1 <= 0 | num2 <= 0) {
throw std::domain_error("Euclidean algorithm domain is for ints > 0");
}
if (num1 == num2) {
return num1;
}
int base_num = 0;
int previous_remainder = 1;
if (num1 > num2) {
base_num = num1;
previous_remainder = num2;
} else {
base_num = num2;
previous_remainder = num1;
}
while ((base_num % previous_remainder) != 0) {
int old_base = base_num;
base_num = previous_remainder;
previous_remainder = old_base % previous_remainder;
}
return previous_remainder;
}
/**
* Main function
*/
int main() {
std::cout << "gcd of 120,7 is " << (gcd(120, 7)) << std::endl;
try {
std::cout << "gcd of -120,10 is " << gcd(-120, 10) << std::endl;
} catch (const std::domain_error &e) {
std::cout << "Error handling was successful" << std::endl;
}
std::cout << "gcd of 312,221 is " << (gcd(312, 221)) << std::endl;
std::cout << "gcd of 289,204 is " << (gcd(289, 204)) << std::endl;
return 0;
}
+114
View File
@@ -0,0 +1,114 @@
/**
* @file
* @brief This program aims at calculating the GCD of n numbers
*
* @details
* The GCD of n numbers can be calculated by
* repeatedly calculating the GCDs of pairs of numbers
* i.e. \f$\gcd(a, b, c)\f$ = \f$\gcd(\gcd(a, b), c)\f$
* Euclidean algorithm helps calculate the GCD of each pair of numbers
* efficiently
*
* @see gcd_iterative_euclidean.cpp, gcd_recursive_euclidean.cpp
*/
#include <algorithm> /// for std::abs
#include <array> /// for std::array
#include <cassert> /// for assert
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Maths algorithms
*/
namespace math {
/**
* @namespace gcd_of_n_numbers
* @brief Compute GCD of numbers in an array
*/
namespace gcd_of_n_numbers {
/**
* @brief Function to compute GCD of 2 numbers x and y
* @param x First number
* @param y Second number
* @return GCD of x and y via recursion
*/
int gcd_two(int x, int y) {
// base cases
if (y == 0) {
return x;
}
if (x == 0) {
return y;
}
return gcd_two(y, x % y); // Euclidean method
}
/**
* @brief Function to check if all elements in the array are 0
* @param a Array of numbers
* @return 'True' if all elements are 0
* @return 'False' if not all elements are 0
*/
template <std::size_t n>
bool check_all_zeros(const std::array<int, n> &a) {
// Use std::all_of to simplify zero-checking
return std::all_of(a.begin(), a.end(), [](int x) { return x == 0; });
}
/**
* @brief Main program to compute GCD using the Euclidean algorithm
* @param a Array of integers to compute GCD for
* @return GCD of the numbers in the array or std::nullopt if undefined
*/
template <std::size_t n>
int gcd(const std::array<int, n> &a) {
// GCD is undefined if all elements in the array are 0
if (check_all_zeros(a)) {
return -1; // Use std::optional to represent undefined GCD
}
// divisors can be negative, we only want the positive value
int result = std::abs(a[0]);
for (std::size_t i = 1; i < n; ++i) {
result = gcd_two(result, std::abs(a[i]));
if (result == 1) {
break; // Further computations still result in gcd of 1
}
}
return result;
}
} // namespace gcd_of_n_numbers
} // namespace math
/**
* @brief Self-test implementation
* @return void
*/
static void test() {
std::array<int, 1> array_1 = {0};
std::array<int, 1> array_2 = {1};
std::array<int, 2> array_3 = {0, 2};
std::array<int, 3> array_4 = {-60, 24, 18};
std::array<int, 4> array_5 = {100, -100, -100, 200};
std::array<int, 5> array_6 = {0, 0, 0, 0, 0};
std::array<int, 7> array_7 = {10350, -24150, 0, 17250, 37950, -127650, 51750};
std::array<int, 7> array_8 = {9500000, -12121200, 0, 4444, 0, 0, 123456789};
assert(math::gcd_of_n_numbers::gcd(array_1) == -1);
assert(math::gcd_of_n_numbers::gcd(array_2) == 1);
assert(math::gcd_of_n_numbers::gcd(array_3) == 2);
assert(math::gcd_of_n_numbers::gcd(array_4) == 6);
assert(math::gcd_of_n_numbers::gcd(array_5) == 100);
assert(math::gcd_of_n_numbers::gcd(array_6) == -1);
assert(math::gcd_of_n_numbers::gcd(array_7) == 3450);
assert(math::gcd_of_n_numbers::gcd(array_8) == 1);
}
/**
* @brief Main function
* @return 0 on exit
*/
int main() {
test(); // run self-test implementation
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
/**
* @file
* @brief Compute the greatest common denominator of two integers using
* *recursive form* of
* [Euclidean algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm)
*
* @see gcd_iterative_euclidean.cpp, gcd_of_n_numbers.cpp
*/
#include <iostream>
/**
* algorithm
*/
int gcd(int num1, int num2) {
if (num1 <= 0 | num2 <= 0) {
throw std::domain_error("Euclidean algorithm domain is for ints > 0");
}
if (num1 == num2) {
return num1;
}
// Everything divides 0
if (num1 == 0)
return num2;
if (num2 == 0)
return num1;
// base case
if (num1 == num2)
return num1;
// a is greater
if (num1 > num2)
return gcd(num1 - num2, num2);
return gcd(num1, num2 - num1);
}
/**
* Main function
*/
int main() {
std::cout << "gcd of 120,7 is " << (gcd(120, 7)) << std::endl;
try {
std::cout << "gcd of -120,10 is " << gcd(-120, 10) << std::endl;
} catch (const std::domain_error &e) {
std::cout << "Error handling was successful" << std::endl;
}
std::cout << "gcd of 312,221 is " << (gcd(312, 221)) << std::endl;
std::cout << "gcd of 289,204 is " << (gcd(289, 204)) << std::endl;
return 0;
}
+136
View File
@@ -0,0 +1,136 @@
/**
* @file
* @brief Compute integral approximation of the function using [Riemann
* sum](https://en.wikipedia.org/wiki/Riemann_sum)
* @details In mathematics, a Riemann sum is a certain kind of approximation of
* an integral by a finite sum. It is named after nineteenth-century German
* mathematician Bernhard Riemann. One very common application is approximating
* the area of functions or lines on a graph and the length of curves and other
* approximations. The sum is calculated by partitioning the region into shapes
* (rectangles, trapezoids, parabolas, or cubics) that form a region similar to
* the region being measured, then calculating the area for each of these
* shapes, and finally adding all of these small areas together. This approach
* can be used to find a numerical approximation for a definite integral even if
* the fundamental theorem of calculus does not make it easy to find a
* closed-form solution. Because the region filled by the small shapes is
* usually not the same shape as the region being measured, the Riemann sum will
* differ from the area being measured. This error can be reduced by dividing up
* the region more finely, using smaller and smaller shapes. As the shapes get
* smaller and smaller, the sum approaches the Riemann integral. \author
* [Benjamin Walton](https://github.com/bwalton24) \author [Shiqi
* Sheng](https://github.com/shiqisheng00)
*/
#include <cassert> /// for assert
#include <cmath> /// for mathematical functions
#include <cstdint>
#include <functional> /// for passing in functions
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Mathematical functions
*/
namespace math {
/**
* @brief Computes integral approximation
* @param lb lower bound
* @param ub upper bound
* @param func function passed in
* @param delta
* @returns integral approximation of function from [lb, ub]
*/
double integral_approx(double lb, double ub,
const std::function<double(double)>& func,
double delta = .0001) {
double result = 0;
uint64_t numDeltas = static_cast<uint64_t>((ub - lb) / delta);
for (int i = 0; i < numDeltas; i++) {
double begin = lb + i * delta;
double end = lb + (i + 1) * delta;
result += delta * (func(begin) + func(end)) / 2;
}
return result;
}
/**
* @brief Wrapper to evaluate if the approximated
* value is within `.XX%` threshold of the exact value.
* @param approx aprroximate value
* @param exact expected value
* @param threshold values from [0, 1)
*/
void test_eval(double approx, double expected, double threshold) {
assert(approx >= expected * (1 - threshold));
assert(approx <= expected * (1 + threshold));
}
/**
* @brief Self-test implementations to
* test the `integral_approx` function.
*
* @returns `void`
*/
} // namespace math
static void test() {
double test_1 = math::integral_approx(
3.24, 7.56, [](const double x) { return log(x) + exp(x) + x; });
std::cout << "Test Case 1" << std::endl;
std::cout << "function: log(x) + e^x + x" << std::endl;
std::cout << "range: [3.24, 7.56]" << std::endl;
std::cout << "value: " << test_1 << std::endl;
math::test_eval(test_1, 1924.80384023549, .001);
std::cout << "Test 1 Passed!" << std::endl;
std::cout << "=====================" << std::endl;
double test_2 = math::integral_approx(0.023, 3.69, [](const double x) {
return x * x + cos(x) + exp(x) + log(x) * log(x);
});
std::cout << "Test Case 2" << std::endl;
std::cout << "function: x^2 + cos(x) + e^x + log^2(x)" << std::endl;
std::cout << "range: [.023, 3.69]" << std::endl;
std::cout << "value: " << test_2 << std::endl;
math::test_eval(test_2, 58.71291345202729, .001);
std::cout << "Test 2 Passed!" << std::endl;
std::cout << "=====================" << std::endl;
double test_3 = math::integral_approx(
10.78, 24.899, [](const double x) { return x * x * x - x * x + 378; });
std::cout << "Test Case 3" << std::endl;
std::cout << "function: x^3 - x^2 + 378" << std::endl;
std::cout << "range: [10.78, 24.899]" << std::endl;
std::cout << "value: " << test_3 << std::endl;
math::test_eval(test_3, 93320.65915078377, .001);
std::cout << "Test 3 Passed!" << std::endl;
std::cout << "=====================" << std::endl;
double test_4 = math::integral_approx(
.101, .505,
[](const double x) { return cos(x) * tan(x) * x * x + exp(x); },
.00001);
std::cout << "Test Case 4" << std::endl;
std::cout << "function: cos(x)*tan(x)*x^2 + e^x" << std::endl;
std::cout << "range: [.101, .505]" << std::endl;
std::cout << "value: " << test_4 << std::endl;
math::test_eval(test_4, 0.566485986311631, .001);
std::cout << "Test 4 Passed!" << std::endl;
std::cout << "=====================" << std::endl;
double test_5 = math::integral_approx(
-1, 1, [](const double x) { return exp(-1 / (x * x)); });
std::cout << "Test Case 5" << std::endl;
std::cout << "function: e^(-1/x^2)" << std::endl;
std::cout << "range: [-1, 1]" << std::endl;
std::cout << "value: " << test_5 << std::endl;
math::test_eval(test_5, 0.1781477117815607, .001);
std::cout << "Test 5 Passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+218
View File
@@ -0,0 +1,218 @@
/**
* @file
* @brief [Monte Carlo
* Integration](https://en.wikipedia.org/wiki/Monte_Carlo_integration)
*
* @details
* In mathematics, Monte Carlo integration is a technique for numerical
* integration using random numbers. It is a particular Monte Carlo method that
* numerically computes a definite integral. While other algorithms usually
* evaluate the integrand at a regular grid, Monte Carlo randomly chooses points
* at which the integrand is evaluated. This method is particularly useful for
* higher-dimensional integrals.
*
* This implementation supports arbitrary pdfs.
* These pdfs are sampled using the [Metropolis-Hastings
* algorithm](https://en.wikipedia.org/wiki/MetropolisHastings_algorithm). This
* can be swapped out by every other sampling techniques for example the inverse
* method. Metropolis-Hastings was chosen because it is the most general and can
* also be extended for a higher dimensional sampling space.
*
* @author [Domenic Zingsheim](https://github.com/DerAndereDomenic)
*/
#define _USE_MATH_DEFINES /// for M_PI on windows
#include <cmath> /// for math functions
#include <cstdint> /// for fixed size data types
#include <ctime> /// for time to initialize rng
#include <functional> /// for function pointers
#include <iostream> /// for std::cout
#include <random> /// for random number generation
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Math algorithms
*/
namespace math {
/**
* @namespace monte_carlo
* @brief Functions for the [Monte Carlo
* Integration](https://en.wikipedia.org/wiki/Monte_Carlo_integration)
* implementation
*/
namespace monte_carlo {
using Function = std::function<double(
double&)>; /// short-hand for std::functions used in this implementation
/**
* @brief Generate samples according to some pdf
* @details This function uses Metropolis-Hastings to generate random numbers.
* It generates a sequence of random numbers by using a markov chain. Therefore,
* we need to define a start_point and the number of samples we want to
* generate. Because the first samples generated by the markov chain may not be
* distributed according to the given pdf, one can specify how many samples
* should be discarded before storing samples.
* @param start_point The starting point of the markov chain
* @param pdf The pdf to sample
* @param num_samples The number of samples to generate
* @param discard How many samples should be discarded at the start
* @returns A vector of size num_samples with samples distributed according to
* the pdf
*/
std::vector<double> generate_samples(const double& start_point,
const Function& pdf,
const uint32_t& num_samples,
const uint32_t& discard = 100000) {
std::vector<double> samples;
samples.reserve(num_samples);
double x_t = start_point;
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform(0.0, 1.0);
std::normal_distribution<double> normal(0.0, 1.0);
generator.seed(time(nullptr));
for (uint32_t t = 0; t < num_samples + discard; ++t) {
// Generate a new proposal according to some mutation strategy.
// This is arbitrary and can be swapped.
double x_dash = normal(generator) + x_t;
double acceptance_probability = std::min(pdf(x_dash) / pdf(x_t), 1.0);
double u = uniform(generator);
// Accept "new state" according to the acceptance_probability
if (u <= acceptance_probability) {
x_t = x_dash;
}
if (t >= discard) {
samples.push_back(x_t);
}
}
return samples;
}
/**
* @brief Compute an approximation of an integral using Monte Carlo integration
* @details The integration domain [a,b] is given by the pdf.
* The pdf has to fulfill the following conditions:
* 1) for all x \in [a,b] : p(x) > 0
* 2) for all x \not\in [a,b] : p(x) = 0
* 3) \int_a^b p(x) dx = 1
* @param start_point The start point of the Markov Chain (see generate_samples)
* @param function The function to integrate
* @param pdf The pdf to sample
* @param num_samples The number of samples used to approximate the integral
* @returns The approximation of the integral according to 1/N \sum_{i}^N f(x_i)
* / p(x_i)
*/
double integral_monte_carlo(const double& start_point, const Function& function,
const Function& pdf,
const uint32_t& num_samples = 1000000) {
double integral = 0.0;
std::vector<double> samples =
generate_samples(start_point, pdf, num_samples);
for (double sample : samples) {
integral += function(sample) / pdf(sample);
}
return integral / static_cast<double>(samples.size());
}
} // namespace monte_carlo
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
std::cout << "Disclaimer: Because this is a randomized algorithm,"
<< std::endl;
std::cout
<< "it may happen that singular samples deviate from the true result."
<< std::endl
<< std::endl;
;
math::monte_carlo::Function f;
math::monte_carlo::Function pdf;
double integral = 0;
double lower_bound = 0, upper_bound = 0;
/* \int_{-2}^{2} -x^2 + 4 dx */
f = [&](double& x) { return -x * x + 4.0; };
lower_bound = -2.0;
upper_bound = 2.0;
pdf = [&](double& x) {
if (x >= lower_bound && x <= -1.0) {
return 0.1;
}
if (x <= upper_bound && x >= 1.0) {
return 0.1;
}
if (x > -1.0 && x < 1.0) {
return 0.4;
}
return 0.0;
};
integral = math::monte_carlo::integral_monte_carlo(
(upper_bound - lower_bound) / 2.0, f, pdf);
std::cout << "This number should be close to 10.666666: " << integral
<< std::endl;
/* \int_{0}^{1} e^x dx */
f = [&](double& x) { return std::exp(x); };
lower_bound = 0.0;
upper_bound = 1.0;
pdf = [&](double& x) {
if (x >= lower_bound && x <= 0.2) {
return 0.1;
}
if (x > 0.2 && x <= 0.4) {
return 0.4;
}
if (x > 0.4 && x < upper_bound) {
return 1.5;
}
return 0.0;
};
integral = math::monte_carlo::integral_monte_carlo(
(upper_bound - lower_bound) / 2.0, f, pdf);
std::cout << "This number should be close to 1.7182818: " << integral
<< std::endl;
/* \int_{-\infty}^{\infty} sinc(x) dx, sinc(x) = sin(pi * x) / (pi * x)
This is a difficult integral because of its infinite domain.
Therefore, it may deviate largely from the expected result.
*/
f = [&](double& x) { return std::sin(M_PI * x) / (M_PI * x); };
pdf = [&](double& x) {
return 1.0 / std::sqrt(2.0 * M_PI) * std::exp(-x * x / 2.0);
};
integral = math::monte_carlo::integral_monte_carlo(0.0, f, pdf, 10000000);
std::cout << "This number should be close to 1.0: " << integral
<< std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+103
View File
@@ -0,0 +1,103 @@
/**
* @file
* @brief Implementation of [the inverse square root
* Root](https://medium.com/hard-mode/the-legendary-fast-inverse-square-root-e51fee3b49d9).
* @details
* Two implementation to calculate inverse inverse root,
* from Quake III Arena (C++ version) and with a standard library (`cmath`).
* This algorithm is used to calculate shadows in Quake III Arena.
*/
#include <cassert> /// for assert
#include <cmath> /// for `std::sqrt`
#include <cstdint>
#include <iostream> /// for IO operations
#include <limits> /// for numeric_limits
/**
* @brief This is the function that calculates the fast inverse square root.
* The following code is the fast inverse square root implementation from
* Quake III Arena (Adapted for C++). More information can be found at
* [Wikipedia](https://en.wikipedia.org/wiki/Fast_inverse_square_root)
* @tparam T floating type
* @tparam iterations inverse square root, the greater the number of
* iterations, the more exact the result will be (1 or 2).
* @param x value to calculate
* @return the inverse square root
*/
template <typename T = double, char iterations = 2>
inline T Fast_InvSqrt(T x) {
using Tint = typename std::conditional<sizeof(T) == 8, std::int64_t,
std::int32_t>::type;
T y = x;
T x2 = y * 0.5;
Tint i =
*reinterpret_cast<Tint *>(&y); // Store floating-point bits in integer
i = (sizeof(T) == 8 ? 0x5fe6eb50c7b537a9 : 0x5f3759df) -
(i >> 1); // Initial guess for Newton's method
y = *reinterpret_cast<T *>(&i); // Convert new bits into float
y = y * (1.5 - (x2 * y * y)); // 1st iteration Newton's method
if (iterations == 2) {
y = y * (1.5 - (x2 * y * y)); // 2nd iteration, the more exact result
}
return y;
}
/**
* @brief This is the function that calculates the fast inverse square root.
* The following code is the fast inverse square root with standard lib (cmath)
* More information can be found at
* [LinkedIn](https://www.linkedin.com/pulse/fast-inverse-square-root-still-armin-kassemi-langroodi)
* @tparam T floating type
* @param number value to calculate
* @return the inverse square root
*/
template <typename T = double>
T Standard_InvSqrt(T number) {
T squareRoot = sqrt(number);
return 1.0f / squareRoot;
}
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
const float epsilon = 1e-3f;
/* Tests with multiple values */
assert(std::fabs(Standard_InvSqrt<float>(100.0f) - 0.0998449f) < epsilon);
assert(std::fabs(Standard_InvSqrt<double>(36.0f) - 0.166667f) < epsilon);
assert(std::fabs(Standard_InvSqrt(12.0f) - 0.288423f) < epsilon);
assert(std::fabs(Standard_InvSqrt<double>(5.0f) - 0.447141f) < epsilon);
assert(std::fabs(Fast_InvSqrt<float, 1>(100.0f) - 0.0998449f) < epsilon);
assert(std::fabs(Fast_InvSqrt<double, 1>(36.0f) - 0.166667f) < epsilon);
assert(std::fabs(Fast_InvSqrt(12.0f) - 0.288423) < epsilon);
assert(std::fabs(Fast_InvSqrt<double>(5.0f) - 0.447141) < epsilon);
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
std::cout << "The Fast inverse square root of 36 is: "
<< Fast_InvSqrt<float, 1>(36.0f) << std::endl;
std::cout << "The Fast inverse square root of 36 is: "
<< Fast_InvSqrt<double, 2>(36.0f) << " (2 iterations)"
<< std::endl;
std::cout << "The Fast inverse square root of 100 is: "
<< Fast_InvSqrt(100.0f)
<< " (With default template type and iterations: double, 2)"
<< std::endl;
std::cout << "The Standard inverse square root of 36 is: "
<< Standard_InvSqrt<float>(36.0f) << std::endl;
std::cout << "The Standard inverse square root of 100 is: "
<< Standard_InvSqrt(100.0f)
<< " (With default template type: double)" << std::endl;
}
+123
View File
@@ -0,0 +1,123 @@
/**
* @file
* @brief Iterative implementation of
* [Factorial](https://en.wikipedia.org/wiki/Factorial)
*
* @author [Renjian-buchai](https://github.com/Renjian-buchai)
*
* @details Calculates factorial iteratively.
* \f[n! = n\times(n-1)\times(n-2)\times(n-3)\times\ldots\times3\times2\times1
* = n\times(n-1)!\f]
* for example:
* \f$4! = 4\times3! = 4\times3\times2\times1 = 24\f$
*
* @example
*
* 5! = 5 * 4 * 3 * 2 * 1
*
* Recursive implementation of factorial pseudocode:
*
* function factorial(n):
* if n == 1:
* return 1
* else:
* return factorial(n-1)
*
*/
#include <cassert> /// for assert
#include <cstdint> /// for integral types
#include <exception> /// for std::invalid_argument
#include <iostream> /// for std::cout
/**
* @namespace
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief Calculates the factorial iteratively.
* @param n Nth factorial.
* @return Factorial.
* @note 0! = 1.
* @warning Maximum=20 because there are no 128-bit integers in C++. 21!
* returns 1.419e+19, which is not 21! but (21! % UINT64_MAX).
*/
uint64_t iterativeFactorial(uint8_t n) {
if (n > 20) {
throw std::invalid_argument("Maximum n value is 20");
}
// 1 because it is the identity number of multiplication.
uint64_t accumulator = 1;
while (n > 1) {
accumulator *= n;
--n;
}
return accumulator;
}
} // namespace math
/**
* @brief Self-test implementations to test iterativeFactorial function.
* @note There is 1 special case: 0! = 1.
*/
static void test() {
// Special case test
std::cout << "Exception case test \n"
"Input: 0 \n"
"Expected output: 1 \n\n";
assert(math::iterativeFactorial(0) == 1);
// Base case
std::cout << "Base case test \n"
"Input: 1 \n"
"Expected output: 1 \n\n";
assert(math::iterativeFactorial(1) == 1);
// Small case
std::cout << "Small number case test \n"
"Input: 5 \n"
"Expected output: 120 \n\n";
assert(math::iterativeFactorial(5) == 120);
// Medium case
std::cout << "Medium number case test \n"
"Input: 10 \n"
"Expected output: 3628800 \n\n";
assert(math::iterativeFactorial(10) == 3628800);
// Maximum case
std::cout << "Maximum case test \n"
"Input: 20 \n"
"Expected output: 2432902008176640000\n\n";
assert(math::iterativeFactorial(20) == 2432902008176640000);
// Exception test
std::cout << "Exception test \n"
"Input: 21 \n"
"Expected output: Exception thrown \n";
bool wasExceptionThrown = false;
try {
math::iterativeFactorial(21);
} catch (const std::invalid_argument&) {
wasExceptionThrown = true;
}
assert(wasExceptionThrown);
std::cout << "All tests have passed successfully.\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // Run self-test implementation
return 0;
}
+118
View File
@@ -0,0 +1,118 @@
/**
* @file
* @brief Compute factorial of any arbitratily large number/
*
* \author [Krishna Vedala](https://github.com/kvedala)
* @see factorial.cpp
*/
#include <cstring>
#include <ctime>
#include <iostream>
#include "./large_number.h"
/** Test implementation for 10! Result must be 3628800.
* @returns True if test pass else False
*/
bool test1() {
std::cout << "---- Check 1\t";
unsigned int i, number = 10;
large_number result;
for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */
result *= i;
const char *known_reslt = "3628800";
/* check 1 */
if (strlen(known_reslt) != result.num_digits()) {
std::cerr << "Result lengths dont match! " << strlen(known_reslt)
<< " != " << result.num_digits() << std::endl;
return false;
}
const size_t N = result.num_digits();
for (i = 0; i < N; i++) {
if (known_reslt[i] != result.digit_char(i)) {
std::cerr << i << "^th digit mismatch! " << known_reslt[i]
<< " != " << result.digit_char(i) << std::endl;
return false;
}
}
std::cout << "Passed!" << std::endl;
return true;
}
/** Test implementation for 100! The result is the 156 digit number:
* ```
* 9332621544394415268169923885626670049071596826438162146859296389521759
* 9993229915608941463976156518286253697920827223758251185210916864000000
* 000000000000000000
* ```
* @returns True if test pass else False
*/
bool test2() {
std::cout << "---- Check 2\t";
unsigned int i, number = 100;
large_number result;
for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */
result *= i;
const char *known_reslt =
"9332621544394415268169923885626670049071596826438162146859296389521759"
"9993229915608941463976156518286253697920827223758251185210916864000000"
"000000000000000000";
/* check 1 */
if (strlen(known_reslt) != result.num_digits()) {
std::cerr << "Result lengths dont match! " << strlen(known_reslt)
<< " != " << result.num_digits() << std::endl;
return false;
}
const size_t N = result.num_digits();
for (i = 0; i < N; i++) {
if (known_reslt[i] != result.digit_char(i)) {
std::cerr << i << "^th digit mismatch! " << known_reslt[i]
<< " != " << result.digit_char(i) << std::endl;
return false;
}
}
std::cout << "Passed!" << std::endl;
return true;
}
/**
* Main program
**/
int main(int argc, char *argv[]) {
int number, i;
if (argc == 2) {
number = atoi(argv[1]);
} else {
std::cout << "Enter the value of n(n starts from 0 ): ";
std::cin >> number;
}
large_number result;
std::clock_t start_time = std::clock();
for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */
result *= i;
std::clock_t end_time = std::clock();
double time_taken =
static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC;
std::cout << number << "! = " << result << std::endl
<< "Number of digits: " << result.num_digits() << std::endl
<< "Time taken: " << std::scientific << time_taken << " s"
<< std::endl;
test1();
test2();
result.test();
return 0;
}
+288
View File
@@ -0,0 +1,288 @@
/**
* @file
* @brief Library to perform arithmatic operations on arbitrarily large
* numbers.
* \author [Krishna Vedala](https://github.com/kvedala)
*/
#ifndef MATH_LARGE_NUMBER_H_
#define MATH_LARGE_NUMBER_H_
#include <algorithm>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <iostream>
#include <type_traits>
#include <vector>
/**
* Store large unsigned numbers as a C++ vector
* The class provides convenience functions to add a
* digit to the number, perform multiplication of
* large number with long unsigned integers.
**/
class large_number {
public:
/**< initializer with value = 1 */
large_number() { _digits.push_back(1); }
// /**< initializer from an integer */
// explicit large_number(uint64_t n) {
// uint64_t carry = n;
// do {
// add_digit(carry % 10);
// carry /= 10;
// } while (carry != 0);
// }
/**< initializer from an integer */
explicit large_number(int n) {
int carry = n;
do {
add_digit(carry % 10);
carry /= 10;
} while (carry != 0);
}
/**< initializer from another large_number */
large_number(const large_number &a) : _digits(a._digits) {}
/**< initializer from a vector */
explicit large_number(std::vector<unsigned char> &vec) : _digits(vec) {}
/**< initializer from a string */
explicit large_number(char const *number_str) {
for (size_t i = strlen(number_str); i > 0; i--) {
char a = number_str[i - 1] - '0';
if (a >= 0 && a <= 9)
_digits.push_back(a);
}
}
/**
* Function to check implementation
**/
static bool test() {
std::cout << "------ Checking `large_number` class implementations\t"
<< std::endl;
large_number a(40);
// 1. test multiplication
a *= 10;
if (a != large_number(400)) {
std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl;
return false;
}
std::cout << "\tPassed 1/6...";
// 2. test compound addition with integer
a += 120;
if (a != large_number(520)) {
std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl;
return false;
}
std::cout << "\tPassed 2/6...";
// 3. test compound multiplication again
a *= 10;
if (a != large_number(5200)) {
std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl;
return false;
}
std::cout << "\tPassed 3/6...";
// 4. test increment (prefix)
++a;
if (a != large_number(5201)) {
std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl;
return false;
}
std::cout << "\tPassed 4/6...";
// 5. test increment (postfix)
a++;
if (a != large_number(5202)) {
std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl;
return false;
}
std::cout << "\tPassed 5/6...";
// 6. test addition with another large number
a = a + large_number("7000000000000000000000000000000");
if (a != large_number("7000000000000000000000000005202")) {
std::cerr << "\tFailed 6/6 (" << a
<< "!=7000000000000000000000000005202)" << std::endl;
return false;
}
std::cout << "\tPassed 6/6..." << std::endl;
return true;
}
/**
* add a digit at MSB to the large number
**/
void add_digit(unsigned int value) {
if (value > 9) {
std::cerr << "digit > 9!!\n";
exit(EXIT_FAILURE);
}
_digits.push_back(value);
}
/**
* Get number of digits in the number
**/
size_t num_digits() const { return _digits.size(); }
/**
* operator over load to access the
* i^th digit conveniently and also
* assign value to it
**/
inline unsigned char &operator[](size_t n) { return this->_digits[n]; }
inline const unsigned char &operator[](size_t n) const {
return this->_digits[n];
}
/**
* operator overload to compare two numbers
**/
friend std::ostream &operator<<(std::ostream &out, const large_number &a) {
for (size_t i = a.num_digits(); i > 0; i--)
out << static_cast<int>(a[i - 1]);
return out;
}
/**
* operator overload to compare two numbers
**/
friend bool operator==(large_number const &a, large_number const &b) {
size_t N = a.num_digits();
if (N != b.num_digits())
return false;
for (size_t i = 0; i < N; i++)
if (a[i] != b[i])
return false;
return true;
}
/**
* operator overload to compare two numbers
**/
friend bool operator!=(large_number const &a, large_number const &b) {
return !(a == b);
}
/**
* operator overload to increment (prefix)
**/
large_number &operator++() {
(*this) += 1;
return *this;
}
/**
* operator overload to increment (postfix)
**/
large_number &operator++(int) {
static large_number tmp(_digits);
++(*this);
return tmp;
}
/**
* operator overload to add
**/
large_number &operator+=(large_number n) {
// if adding with another large_number
large_number *b = reinterpret_cast<large_number *>(&n);
const size_t max_L = std::max(this->num_digits(), b->num_digits());
unsigned int carry = 0;
size_t i;
for (i = 0; i < max_L || carry != 0; i++) {
if (i < b->num_digits())
carry += (*b)[i];
if (i < this->num_digits())
carry += (*this)[i];
if (i < this->num_digits())
(*this)[i] = carry % 10;
else
this->add_digit(carry % 10);
carry /= 10;
}
return *this;
}
large_number &operator+=(int n) { return (*this) += large_number(n); }
// large_number &operator+=(uint64_t n) { return (*this) += large_number(n);
// }
/**
* operator overload to perform addition
**/
template <class T>
friend large_number &operator+(const large_number &a, const T &b) {
static large_number c = a;
c += b;
return c;
}
/**
* assignment operator
**/
large_number &operator=(const large_number &b) {
this->_digits = b._digits;
return *this;
}
/**
* operator overload to increment
**/
template <class T>
large_number &operator*=(const T n) {
static_assert(std::is_integral<T>::value,
"Must be integer addition unsigned integer types.");
this->multiply(n);
return *this;
}
/**
* returns i^th digit as an ASCII character
**/
char digit_char(size_t i) const {
return _digits[num_digits() - i - 1] + '0';
}
private:
/**
* multiply large number with another integer and
* store the result in the same large number
**/
template <class T>
void multiply(const T n) {
static_assert(std::is_integral<T>::value,
"Can only have integer types.");
// assert(!(std::is_signed<T>::value)); //, "Implemented only for
// unsigned integer types.");
size_t i;
uint64_t carry = 0, temp;
for (i = 0; i < this->num_digits(); i++) {
temp = static_cast<uint64_t>((*this)[i]) * n;
temp += carry;
if (temp < 10) {
carry = 0;
} else {
carry = temp / 10;
temp = temp % 10;
}
(*this)[i] = temp;
}
while (carry != 0) {
this->add_digit(carry % 10);
carry /= 10;
}
}
std::vector<unsigned char>
_digits; /**< where individual digits are stored */
};
#endif // MATH_LARGE_NUMBER_H_
+77
View File
@@ -0,0 +1,77 @@
/**
* @file
* @brief Algorithm to find largest x such that p^x divides n! (factorial) using
* Legendre's Formula.
* @details Given an integer n and a prime number p, the task is to find the
* largest x such that p^x (p raised to power x) divides n! (factorial). This
* will be done using Legendre's formula: x = [n/(p^1)] + [n/(p^2)] + [n/(p^3)]
* + \ldots + 1
* @see more on
* https://math.stackexchange.com/questions/141196/highest-power-of-a-prime-p-dividing-n
* @author [uday6670](https://github.com/uday6670)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::cin and std::cout
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief Function to calculate largest power
* @param n number
* @param p prime number
* @returns largest power
*/
uint64_t largestPower(uint32_t n, const uint16_t& p) {
// Initialize result
int x = 0;
// Calculate result
while (n) {
n /= p;
x += n;
}
return x;
}
} // namespace math
/**
* @brief Function for testing largestPower function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint8_t test_case_1 = math::largestPower(5, 2);
assert(test_case_1 == 3);
std::cout << "Test 1 Passed!" << std::endl;
uint16_t test_case_2 = math::largestPower(10, 3);
assert(test_case_2 == 4);
std::cout << "Test 2 Passed!" << std::endl;
uint32_t test_case_3 = math::largestPower(25, 5);
assert(test_case_3 == 6);
std::cout << "Test 3 Passed!" << std::endl;
uint32_t test_case_4 = math::largestPower(27, 2);
assert(test_case_4 == 23);
std::cout << "Test 4 Passed!" << std::endl;
uint16_t test_case_5 = math::largestPower(7, 3);
assert(test_case_5 == 2);
std::cout << "Test 5 Passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}
+100
View File
@@ -0,0 +1,100 @@
/**
* @file
* @brief An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) +
* \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$
* @details An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) +
* \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ where
* \f$\mathrm{LCM}(i,n)\f$ denotes the Least Common Multiple of the integers i
* and n. For n greater than or equal to 1. The value of the sum is calculated
* by formula: \f[ \sum\mathrm{LCM}(i, n) = \frac{1}{2} \left[\left(\sum (d *
* \mathrm{ETF}(d)) + 1\right) * n\right] \f] where \mathrm{ETF}(i) represents
* Euler totient function of i.
* @author [Chesta Mittal](https://github.com/chestamittal)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::cin and std::cout
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* Function to compute sum of euler totients in sumOfEulerTotient vector
* @param num input number
* @returns int Sum of LCMs, i.e. ∑LCM(i, num) from i = 1 to num
*/
uint64_t lcmSum(const uint16_t& num) {
uint64_t i = 0, j = 0;
std::vector<uint64_t> eulerTotient(num + 1);
std::vector<uint64_t> sumOfEulerTotient(num + 1);
// storing initial values in eulerTotient vector
for (i = 1; i <= num; i++) {
eulerTotient[i] = i;
}
// applying totient sieve
for (i = 2; i <= num; i++) {
if (eulerTotient[i] == i) {
for (j = i; j <= num; j += i) {
eulerTotient[j] = eulerTotient[j] / i;
eulerTotient[j] = eulerTotient[j] * (i - 1);
}
}
}
// computing sum of euler totients
for (i = 1; i <= num; i++) {
for (j = i; j <= num; j += i) {
sumOfEulerTotient[j] += eulerTotient[i] * i;
}
}
return ((sumOfEulerTotient[num] + 1) * num) / 2;
}
} // namespace math
/**
* Function for testing lcmSum function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint64_t n = 2;
uint64_t test_1 = math::lcmSum(n);
assert(test_1 == 4);
std::cout << "Passed Test 1!" << std::endl;
n = 5;
uint64_t test_2 = math::lcmSum(n);
assert(test_2 == 55);
std::cout << "Passed Test 2!" << std::endl;
n = 10;
uint64_t test_3 = math::lcmSum(n);
assert(test_3 == 320);
std::cout << "Passed Test 3!" << std::endl;
n = 11;
uint64_t test_4 = math::lcmSum(n);
assert(test_4 == 616);
std::cout << "Passed Test 4!" << std::endl;
n = 15;
uint64_t test_5 = math::lcmSum(n);
assert(test_5 == 1110);
std::cout << "Passed Test 5!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}
+81
View File
@@ -0,0 +1,81 @@
/**
* Copyright 2020 @author tjgurwara99
* @file
*
* A basic implementation of LCM function
*/
#include <cassert>
#include <iostream>
/**
* Function for finding greatest common divisor of two numbers.
* @params two integers x and y whose gcd we want to find.
* @return greatest common divisor of x and y.
*/
unsigned int gcd(unsigned int x, unsigned int y) {
if (x == 0) {
return y;
}
if (y == 0) {
return x;
}
if (x == y) {
return x;
}
if (x > y) {
// The following is valid because we have checked whether y == 0
unsigned int temp = x / y;
return gcd(y, x - temp * y);
}
// Again the following is valid because we have checked whether x == 0
unsigned int temp = y / x;
return gcd(x, y - temp * x);
}
/**
* Function for finding the least common multiple of two numbers.
* @params integer x and y whose lcm we want to find.
* @return lcm of x and y using the relation x * y = gcd(x, y) * lcm(x, y)
*/
unsigned int lcm(unsigned int x, unsigned int y) {
return x / gcd(x, y) * y;
}
/**
* Function for testing the lcm() functions with some assert statements.
*/
void tests() {
// First test on lcm(5,10) == 10
assert(((void)"LCM of 5 and 10 is 10 but lcm function gives a different "
"result.\n",
lcm(5, 10) == 10));
std::cout << "First assertion passes: LCM of 5 and 10 is " << lcm(5, 10)
<< std::endl;
// Second test on lcm(2,3) == 6 as 2 and 3 are coprime (prime in fact)
assert(((void)"LCM of 2 and 3 is 6 but lcm function gives a different "
"result.\n",
lcm(2, 3) == 6));
std::cout << "Second assertion passes: LCM of 2 and 3 is " << lcm(2, 3)
<< std::endl;
// Testing an integer overflow.
// The algorithm should work as long as the result fits into integer.
assert(((void)"LCM of 987654321 and 987654321 is 987654321 but lcm function"
" gives a different result.\n",
lcm(987654321, 987654321) == 987654321));
std::cout << "Third assertion passes: LCM of 987654321 and 987654321 is "
<< lcm(987654321, 987654321)
<< std::endl;
}
/**
* Main function
*/
int main() {
tests();
return 0;
}
+373
View File
@@ -0,0 +1,373 @@
/**
* @brief Evaluate recurrence relation using [matrix
* exponentiation](https://www.hackerearth.com/practice/notes/matrix-exponentiation-1/).
* @details
* Given a recurrence relation; evaluate the value of nth term.
* For e.g., For fibonacci series, recurrence series is `f(n) = f(n-1) + f(n-2)`
* where `f(0) = 0` and `f(1) = 1`.
* Note that the method used only demonstrates
* recurrence relation with one variable (n), unlike `nCr` problem, since it has
* two (n, r)
*
* ### Algorithm
* This problem can be solved using matrix exponentiation method.
* @see here for simple [number exponentiation
* algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_exponentiation.cpp)
* or [explaination
* here](https://en.wikipedia.org/wiki/Exponentiation_by_squaring).
* @author [Ashish Daulatabad](https://github.com/AshishYUO)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for IO operations
#include <vector> /// for std::vector STL
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace linear_recurrence_matrix
* @brief Functions for [Linear Recurrence
* Matrix](https://www.hackerearth.com/practice/notes/matrix-exponentiation-1/)
* implementation.
*/
namespace linear_recurrence_matrix {
/**
* @brief Implementation of matrix multiplication
* @details Multiplies matrix A and B, given total columns in A are equal to
* total given rows in column B
* @tparam T template type for integer as well as floating values, default is
* long long int
* @param _mat_a first matrix of size n * m
* @param _mat_b second matrix of size m * k
* @returns `_mat_c` resultant matrix of size n * k
* Complexity: `O(n*m*k)`
* @note The complexity in this case will be O(n^3) due to the nature of the
* problem. We'll be multiplying the matrix with itself most of the time.
*/
template <typename T = int64_t>
std::vector<std::vector<T>> matrix_multiplication(
const std::vector<std::vector<T>>& _mat_a,
const std::vector<std::vector<T>>& _mat_b, const int64_t mod = 1000000007) {
// assert that columns in `_mat_a` and rows in `_mat_b` are equal
assert(_mat_a[0].size() == _mat_b.size());
std::vector<std::vector<T>> _mat_c(_mat_a.size(),
std::vector<T>(_mat_b[0].size(), 0));
/**
* Actual matrix multiplication.
*/
for (uint32_t i = 0; i < _mat_a.size(); ++i) {
for (uint32_t j = 0; j < _mat_b[0].size(); ++j) {
for (uint32_t k = 0; k < _mat_b.size(); ++k) {
_mat_c[i][j] =
(_mat_c[i][j] % mod +
(_mat_a[i][k] % mod * _mat_b[k][j] % mod) % mod) %
mod;
}
}
}
return _mat_c;
}
/**
* @brief Returns whether matrix `mat` is a [zero
* matrix.](https://en.wikipedia.org/wiki/Zero_matrix)
* @tparam T template type for integer as well as floating values, default is
* long long int
* @param _mat A matrix
* @returns true if it is a zero matrix else false
*/
template <typename T = int64_t>
bool is_zero_matrix(const std::vector<std::vector<T>>& _mat) {
for (uint32_t i = 0; i < _mat.size(); ++i) {
for (uint32_t j = 0; j < _mat[i].size(); ++j) {
if (_mat[i][j] != 0) {
return false;
}
}
}
return true;
}
/**
* @brief Implementation of Matrix exponentiation
* @details returns the matrix exponentiation `(B^n)` in `k^3 * O(log2(power))`
* time, where `k` is the size of matrix (k by k).
* @tparam T template type for integer as well as floating values, default is
* long long int
* @param _mat matrix for exponentiation
* @param power the exponent value
* @returns the matrix _mat to the power `power (_mat^power)`
*/
template <typename T = int64_t>
std::vector<std::vector<T>> matrix_exponentiation(
std::vector<std::vector<T>> _mat, uint64_t power,
const int64_t mod = 1000000007) {
/**
* Initializing answer as identity matrix. For simple binary
* exponentiation reference, [see
* here](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_exponentiation.cpp)
*/
if (is_zero_matrix(_mat)) {
return _mat;
}
std::vector<std::vector<T>> _mat_answer(_mat.size(),
std::vector<T>(_mat.size(), 0));
for (uint32_t i = 0; i < _mat.size(); ++i) {
_mat_answer[i][i] = 1;
}
// exponentiation algorithm here.
while (power > 0) {
if (power & 1) {
_mat_answer = matrix_multiplication(_mat_answer, _mat, mod);
}
power >>= 1;
_mat = matrix_multiplication(_mat, _mat, mod);
}
return _mat_answer;
}
/**
* @brief Implementation of nth recurrence series.
* @details Returns the nth term in the recurrence series.
* Note that the function assumes definition of base cases from `n = 0`
* (e.g., for fibonacci, `f(0)` has a defined value `0`)
* @tparam T template type for integer as well as floating values, default is
* long long int
* @param _mat [square matrix](https://en.m.wikipedia.org/wiki/Square_matrix)
* that evaluates the nth term using exponentiation
* @param _base_cases 2D array of dimension `1*n` containing values which are
* defined for some n (e.g., for fibonacci, `f(0)` and `f(1)` are defined, and
* `f(n)` where `n > 1` is evaluated on previous two values)
* @param nth_term the nth term of recurrence relation
* @param constant_or_sum_included whether the recurrence relation has a
* constant value or is evaluating sum of first n terms of the recurrence.
* @returns the nth term of the recurrence relation in `O(k^3. log(n))`, where k
* is number of rows and columns in `_mat` and `n` is the value of `nth_term`
* If constant_or_sum_included is true, returns the sum of first n terms in
* recurrence series
*/
template <typename T = int64_t>
T get_nth_term_of_recurrence_series(
const std::vector<std::vector<T>>& _mat,
const std::vector<std::vector<T>>& _base_cases, uint64_t nth_term,
bool constant_or_sum_included = false) {
assert(_mat.size() == _base_cases.back().size());
/**
* If nth term is a base case, then return base case directly.
*/
if (nth_term < _base_cases.back().size() - constant_or_sum_included) {
return _base_cases.back()[nth_term - constant_or_sum_included];
} else {
/**
* Else evaluate the expression, so multiplying _mat to itself (n -
* base_cases.length + 1 + constant_or_sum_included) times.
*/
std::vector<std::vector<T>> _res_matrix =
matrix_exponentiation(_mat, nth_term - _base_cases.back().size() +
1 + constant_or_sum_included);
/**
* After matrix exponentiation, multiply with the base case to evaluate
* the answer. The answer is always at the end of the array.
*/
std::vector<std::vector<T>> _res =
matrix_multiplication(_base_cases, _res_matrix);
return _res.back().back();
}
}
} // namespace linear_recurrence_matrix
} // namespace math
/**
* @brief Self test-implementations
* @returns void
*/
static void test() {
/*
* Example 1: [Fibonacci
* series](https://en.wikipedia.org/wiki/Fibonacci_number);
*
* [fn-2 fn-1] [0 1] == [fn-1 (fn-2 + fn-1)] => [fn-1 fn]
* [1 1]
*
* Let A = [fn-2 fn-1], and B = [0 1]
* [1 1],
*
* Since, A.B....(n-1 times) = [fn-1 fn]
* we can multiply B with itself n-1 times to obtain the required value
*/
std::vector<std::vector<int64_t>> fibonacci_matrix = {{0, 1}, {1, 1}},
fib_base_case = {{0, 1}};
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
fibonacci_matrix, fib_base_case, 11) == 89LL);
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
fibonacci_matrix, fib_base_case, 39) == 63245986LL);
/*
* Example 2: [Tribonacci series](https://oeis.org/A000073)
* [0 0 1]
* [fn-3 fn-2 fn-1] [1 0 1] = [(fn-2) (fn-1) (fn-3 + fn-2 + fn-1)]
* [0 1 1]
* => [fn-2 fn-1 fn]
*
* [0 0 1]
* Let A = [fn-3 fn-2 fn-1], and B = [1 0 1]
* [0 1 1]
*
* Since, A.B....(n-2 times) = [fn-2 fn-1 fn]
* we will have multiply B with itself n-2 times to obtain the required
* value ()
*/
std::vector<std::vector<int64_t>> tribonacci = {{0, 0, 1},
{1, 0, 1},
{0, 1, 1}},
trib_base_case = {
{0, 0, 1}}; // f0 = 0, f1 = 0, f2 = 1
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
tribonacci, trib_base_case, 11) == 149LL);
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
tribonacci, trib_base_case, 36) == 615693474LL);
/*
* Example 3: [Pell numbers](https://oeis.org/A000129)
* `f(n) = 2* f(n-1) + f(n-2); f(0) = f(1) = 2`
*
* [fn-2 fn-1] [0 1] = [(fn-1) fn-2 + 2*fn-1)]
* [1 2]
* => [fn-1 fn]
*
* Let A = [fn-2 fn-1], and B = [0 1]
* [1 2]
*/
std::vector<std::vector<int64_t>> pell_recurrence = {{0, 1}, {1, 2}},
pell_base_case = {
{2, 2}}; // `f0 = 2, f1 = 2`
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
pell_recurrence, pell_base_case, 15) == 551614LL);
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
pell_recurrence, pell_base_case, 23) == 636562078LL);
/*
* Example 4: Custom recurrence relation:
* Now the recurrence is of the form `a*f(n-1) + b*(fn-2) + ... + c`
* where `c` is the constant
* `f(n) = 2* f(n-1) + f(n-2) + 7; f(0) = f(1) = 2, c = 7`
*
* [1 0 1]
* [7, fn-2, fn-1] [0 0 1]
* [0 1 2]
* = [7, (fn-1), fn-2 + 2*fn-1) + 7]
*
* => [7, fn-1, fn]
* :: Series will be 2, 2, 13, 35, 90, 222, 541, 1311, 3170, 7658, 18493,
* 44651, 107802, 260262, 628333, 1516935, 362210, 8841362, 21344941,
* 51531251
*
* Let A = [7, fn-2, fn-1], and B = [1 0 1]
* [0 0 1]
* [0 1 2]
*/
std::vector<std::vector<int64_t>>
custom_recurrence = {{1, 0, 1}, {0, 0, 1}, {0, 1, 2}},
custom_base_case = {{7, 2, 2}}; // `c = 7, f0 = 2, f1 = 2`
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
custom_recurrence, custom_base_case, 10, 1) == 18493LL);
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
custom_recurrence, custom_base_case, 19, 1) == 51531251LL);
/*
* Example 5: Sum fibonacci sequence
* The following matrix evaluates the sum of first n fibonacci terms in
* O(27. log2(n)) time.
* `f(n) = f(n-1) + f(n-2); f(0) = 0, f(1) = 1`
*
* [1 0 0]
* [s(f, n-1), fn-2, fn-1] [1 0 1]
* [1 1 1]
* => [(s(f, n-1)+f(n-2)+f(n-1)), (fn-1), f(n-2)+f(n-1)]
*
* => [s(f, n-1)+f(n), fn-1, fn]
*
* => [s(f, n), fn-1, fn]
*
* Sum of first 20 fibonacci series:
* 0, 1, 2, 4, 7, 12, 20, 33, 54, 88, 143, 232, 376, 609, 986, 1596, 2583,
* 4180, 6764
* f0 f1 s(f,1)
* Let A = [0 1 1], and B = [0 1 1]
* [1 1 1]
* [0 0 1]
*/
std::vector<std::vector<int64_t>> sum_fibo_recurrence = {{0, 1, 1},
{1, 1, 1},
{0, 0, 1}},
sum_fibo_base_case = {
{0, 1, 1}}; // `f0 = 0, f1 = 1`
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
sum_fibo_recurrence, sum_fibo_base_case, 13, 1) == 609LL);
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
sum_fibo_recurrence, sum_fibo_base_case, 16, 1) == 2583LL);
/*
* Example 6: [Tribonacci sum series](https://oeis.org/A000073)
* [0 0 1 1]
* [fn-3 fn-2 fn-1 s(f, n-1)] [1 0 1 1]
* [0 1 1 1]
* [0 0 0 1]
*
* = [fn-2, fn-1, fn-3 + fn-2 + fn-1, (fn-3 + fn-2 + fn-1 + s(f, n-1))]
*
* => [fn-2, fn-1, fn, fn + s(f, n-1)]
*
* => [fn-2, fn-1, fn, s(f, n)]
*
* Sum of the series is: 0, 0, 1, 2, 4, 8, 15, 28, 52, 96, 177, 326, 600,
* 1104, 2031, 3736, 6872, 12640, 23249, 42762
*
* Let A = [fn-3 fn-2 fn-1 s(f, n-1)], and
* [0 0 1 1]
* B = [1 0 1 1]
* [0 1 1 1]
* [0 0 0 1]
*
* Since, A.B....(n-2 times) = [fn-2 fn-1 fn]
* we will have multiply B with itself n-2 times to obtain the required
* value
*/
std::vector<std::vector<int64_t>> tribonacci_sum = {{0, 0, 1, 1},
{1, 0, 1, 1},
{0, 1, 1, 1},
{0, 0, 0, 1}},
trib_sum_base_case = {{0, 0, 1, 1}};
// `f0 = 0, f1 = 0, f2 = 1, s = 1`
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
tribonacci_sum, trib_sum_base_case, 18, 1) == 23249LL);
assert(math::linear_recurrence_matrix::get_nth_term_of_recurrence_series(
tribonacci_sum, trib_sum_base_case, 19, 1) == 42762LL);
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+81
View File
@@ -0,0 +1,81 @@
/**
* @file
* @brief A simple program to check if the given number is a magic number or
* not. A number is said to be a magic number, if the sum of its digits are
* calculated till a single digit recursively by adding the sum of the digits
* after every addition. If the single digit comes out to be 1,then the number
* is a magic number.
*
* This is a shortcut method to verify Magic Number.
* On dividing the input by 9, if the remainder is 1 then the number is a magic
* number else not. The divisibility rule of 9 says that a number is divisible
* by 9 if the sum of its digits are also divisible by 9. Therefore, if a number
* is divisible by 9, then, recursively, all the digit sums are also divisible
* by 9. The final digit sum is always 9. An increase of 1 in the original
* number will increase the ultimate value by 1, making it 10 and the ultimate
* sum will be 1, thus verifying that it is a magic number.
* @author [Neha Hasija](https://github.com/neha-hasija17)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for io operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* Function to check if the given number is magic number or not.
* @param n number to be checked.
* @return if number is a magic number, returns true, else false.
*/
bool magic_number(const uint64_t &n) {
if (n <= 0) {
return false;
}
// result stores the modulus of @param n with 9
uint64_t result = n % 9;
// if result is 1 then the number is a magic number else not
if (result == 1) {
return true;
} else {
return false;
}
}
} // namespace math
/**
* @brief Test function
* @returns void
*/
static void tests() {
std::cout << "Test 1:\t n=60\n";
assert(math::magic_number(60) == false);
std::cout << "passed\n";
std::cout << "Test 2:\t n=730\n";
assert(math::magic_number(730) == true);
std::cout << "passed\n";
std::cout << "Test 3:\t n=0\n";
assert(math::magic_number(0) == false);
std::cout << "passed\n";
std::cout << "Test 4:\t n=479001600\n";
assert(math::magic_number(479001600) == false);
std::cout << "passed\n";
std::cout << "Test 5:\t n=-35\n";
assert(math::magic_number(-35) == false);
std::cout << "passed\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // execute the tests
return 0;
}
+186
View File
@@ -0,0 +1,186 @@
/**
* Copyright 2020 @author tjgurwara99
* @file
*
* A basic implementation of Miller-Rabin primality test.
*/
#include <cassert>
#include <iostream>
#include <random>
#include <vector>
/**
* Function to give a binary representation of a number in reverse order
* @param num integer number that we want to convert
* @return result vector of the number input in reverse binary
*/
template <typename T>
std::vector<T> reverse_binary(T num) {
std::vector<T> result;
T temp = num;
while (temp > 0) {
result.push_back(temp % 2);
temp = temp / 2;
}
return result;
}
/**
* Function for modular exponentiation.
* This function is an efficient modular exponentiation function.
* It can be used with any big integer library such as Boost multiprecision
* to give result any modular exponentiation problem relatively quickly.
* @param base number being raised to a power as integer
* @param rev_binary_exponent reverse binary of the power the base is being
* raised to
* @param mod modulo
* @return r the modular exponentiation of \f$a^{n} \equiv r \mod{m}\f$ where
* \f$n\f$ is the base 10 representation of rev_binary_exponent and \f$m = mod
* \f$ parameter.
*/
template <typename T>
T modular_exponentiation(T base, const std::vector<T> &rev_binary_exponent,
T mod) {
if (mod == 1)
return 0;
T b = 1;
if (rev_binary_exponent.size() == 0)
return b;
T A = base;
if (rev_binary_exponent[0] == 1)
b = base;
for (typename std::vector<T>::const_iterator it =
rev_binary_exponent.cbegin() + 1;
it != rev_binary_exponent.cend(); ++it) {
A = A * A % mod;
if (*it == 1)
b = A * b % mod;
}
return b;
}
/** Function for testing the conditions that are satisfied when a number is
* prime.
* @param d number such that \f$d \cdot 2^r = n - 1\f$ where \f$n = num\f$
* parameter and \f$r \geq 1\f$
* @param num number being tested for primality.
* @return 'false' if n is composite
* @return 'true' if n is (probably) prime.
*/
template <typename T>
bool miller_test(T d, T num) {
// random number seed
std::random_device rd_seed;
// random number generator
std::mt19937 gen(rd_seed());
// Uniformly distributed range [2, num - 2] for random numbers
std::uniform_int_distribution<> distribution(2, num - 2);
// Random number generated in the range [2, num -2].
T random = distribution(gen);
// vector for reverse binary of the power
std::vector<T> power = reverse_binary(d);
// x = random ^ d % num
T x = modular_exponentiation(random, power, num);
// miller conditions
if (x == 1 || x == num - 1) {
return true;
}
while (d != num - 1) {
x = (x * x) % num;
d *= 2;
if (x == 1) {
return false;
}
if (x == num - 1) {
return true;
}
}
return false;
}
/**
* Function that test (probabilistically) whether a given number is a prime
* based on the Miller-Rabin Primality Test.
* @param num number to be tested for primality.
* @param repeats number of repetitions for the test to increase probability of
* correct result.
* @return 'false' if num is composite
* @return 'true' if num is (probably) prime
*
* \detail
* First we check whether the num input is less than 4, if so we can determine
* whether this is a prime or composite by checking for 2 and 3.
* Next we check whether this num is odd (as all primes greater than 2 are odd).
* Next we write our num in the following format \f$num = 2^r \cdot d + 1\f$.
* After finding r and d for our input num, we use for loop repeat number of
* times inside which we check the miller conditions using the function
* miller_test. If miller_test returns false then the number is composite After
* the loop finishes completely without issuing a false return call, we can
* conclude that this number is probably prime.
*/
template <typename T>
bool miller_rabin_primality_test(T num, T repeats) {
if (num <= 4) {
// If num == 2 or num == 3 then prime
if (num == 2 || num == 3) {
return true;
} else {
return false;
}
}
// If num is even then not prime
if (num % 2 == 0) {
return false;
}
// Finding d and r in num = 2^r * d + 1
T d = num - 1, r = 0;
while (d % 2 == 0) {
d = d / 2;
r++;
}
for (T i = 0; i < repeats; ++i) {
if (!miller_test(d, num)) {
return false;
}
}
return true;
}
/**
* Functions for testing the miller_rabin_primality_test() function with some
* assert statements.
*/
void tests() {
// First test on 2
assert(((void)"2 is prime but function says otherwise.\n",
miller_rabin_primality_test(2, 1) == true));
std::cout << "First test passes." << std::endl;
// Second test on 5
assert(((void)"5 should be prime but the function says otherwise.\n",
miller_rabin_primality_test(5, 3) == true));
std::cout << "Second test passes." << std::endl;
// Third test on 23
assert(((void)"23 should be prime but the function says otherwise.\n",
miller_rabin_primality_test(23, 3) == true));
std::cout << "Third test passes." << std::endl;
// Fourth test on 16
assert(((void)"16 is not a prime but the function says otherwise.\n",
miller_rabin_primality_test(16, 3) == false));
std::cout << "Fourth test passes." << std::endl;
// Fifth test on 27
assert(((void)"27 is not a prime but the function says otherwise.\n",
miller_rabin_primality_test(27, 3) == false));
std::cout << "Fifth test passes." << std::endl;
}
/**
* Main function
*/
int main() {
tests();
return 0;
}
+114
View File
@@ -0,0 +1,114 @@
/**
* @file
* @brief An algorithm to divide two numbers under modulo p [Modular
* Division](https://www.geeksforgeeks.org/modular-division)
* @details To calculate division of two numbers under modulo p
* Modulo operator is not distributive under division, therefore
* we first have to calculate the inverse of divisor using
* [Fermat's little
theorem](https://en.wikipedia.org/wiki/Fermat%27s_little_theorem)
* Now, we can multiply the dividend with the inverse of divisor
* and modulo is distributive over multiplication operation.
* Let,
* We have 3 numbers a, b, p
* To compute (a/b)%p
* (a/b)%p ≡ (a*(inverse(b)))%p ≡ ((a%p)*inverse(b)%p)%p
* NOTE: For the existence of inverse of 'b', 'b' and 'p' must be coprime
* For simplicity we take p as prime
* Time Complexity: O(log(b))
* Example: ( 24 / 3 ) % 5 => 8 % 5 = 3 --- (i)
Now the inverse of 3 is 2
(24 * 2) % 5 = (24 % 5) * (2 % 5) = (4 * 2) % 5 = 3 --- (ii)
(i) and (ii) are equal hence the answer is correct.
* @see modular_inverse_fermat_little_theorem.cpp, modular_exponentiation.cpp
* @author [Shubham Yadav](https://github.com/shubhamamsa)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace modular_division
* @brief Functions for [Modular
* Division](https://www.geeksforgeeks.org/modular-division) implementation
*/
namespace modular_division {
/**
* @brief This function calculates a raised to exponent b under modulo c using
* modular exponentiation.
* @param a integer base
* @param b unsigned integer exponent
* @param c integer modulo
* @return a raised to power b modulo c
*/
uint64_t power(uint64_t a, uint64_t b, uint64_t c) {
uint64_t ans = 1; /// Initialize the answer to be returned
a = a % c; /// Update a if it is more than or equal to c
if (a == 0) {
return 0; /// In case a is divisible by c;
}
while (b > 0) {
/// If b is odd, multiply a with answer
if (b & 1) {
ans = ((ans % c) * (a % c)) % c;
}
/// b must be even now
b = b >> 1; /// b = b/2
a = ((a % c) * (a % c)) % c;
}
return ans;
}
/**
* @brief This function calculates modular division
* @param a integer dividend
* @param b integer divisor
* @param p integer modulo
* @return a/b modulo c
*/
uint64_t mod_division(uint64_t a, uint64_t b, uint64_t p) {
uint64_t inverse = power(b, p - 2, p) % p; /// Calculate the inverse of b
uint64_t result =
((a % p) * (inverse % p)) % p; /// Calculate the final result
return result;
}
} // namespace modular_division
} // namespace math
/**
* Function for testing power function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint64_t test_case_1 = math::modular_division::mod_division(8, 2, 2);
assert(test_case_1 == 0);
std::cout << "Test 1 Passed!" << std::endl;
uint64_t test_case_2 = math::modular_division::mod_division(15, 3, 7);
assert(test_case_2 == 5);
std::cout << "Test 2 Passed!" << std::endl;
uint64_t test_case_3 = math::modular_division::mod_division(10, 5, 2);
assert(test_case_3 == 0);
std::cout << "Test 3 Passed!" << std::endl;
uint64_t test_case_4 = math::modular_division::mod_division(81, 3, 5);
assert(test_case_4 == 2);
std::cout << "Test 4 Passed!" << std::endl;
uint64_t test_case_5 = math::modular_division::mod_division(12848, 73, 29);
assert(test_case_5 == 2);
std::cout << "Test 5 Passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}
+89
View File
@@ -0,0 +1,89 @@
/**
* @file
* @brief C++ Program for Modular Exponentiation Iteratively.
* @details The task is to calculate the value of an integer a raised to an
* integer exponent b under modulo c.
* @note The time complexity of this approach is O(log b).
*
* Example:
* (4^3) % 5 (where ^ stands for exponentiation and % for modulo)
* (4*4*4) % 5
* (4 % 5) * ( (4*4) % 5 )
* 4 * (16 % 5)
* 4 * 1
* 4
* We can also verify the result as 4^3 is 64 and 64 modulo 5 is 4
*
* @author [Shri2206](https://github.com/Shri2206)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for io operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief This function calculates a raised to exponent b under modulo c using
* modular exponentiation.
* @param a integer base
* @param b unsigned integer exponent
* @param c integer modulo
* @return a raised to power b modulo c
*/
uint64_t power(uint64_t a, uint64_t b, uint64_t c) {
uint64_t ans = 1; /// Initialize the answer to be returned
a = a % c; /// Update a if it is more than or equal to c
if (a == 0) {
return 0; /// In case a is divisible by c;
}
while (b > 0) {
/// If b is odd, multiply a with answer
if (b & 1) {
ans = ((ans % c) * (a % c)) % c;
}
/// b must be even now
b = b >> 1; /// b = b/2
a = ((a % c) * (a % c)) % c;
}
return ans;
}
} // namespace math
/**
* Function for testing power function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint32_t test_case_1 = math::power(2, 5, 13);
assert(test_case_1 == 6);
std::cout << "Test 1 Passed!" << std::endl;
uint32_t test_case_2 = math::power(14, 7, 15);
assert(test_case_2 == 14);
std::cout << "Test 2 Passed!" << std::endl;
uint64_t test_case_3 = math::power(8, 15, 41);
assert(test_case_3 == 32);
std::cout << "Test 3 Passed!" << std::endl;
uint64_t test_case_4 = math::power(27, 2, 5);
assert(test_case_4 == 4);
std::cout << "Test 4 Passed!" << std::endl;
uint16_t test_case_5 = math::power(7, 3, 6);
assert(test_case_5 == 1);
std::cout << "Test 5 Passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}
@@ -0,0 +1,140 @@
/**
* @file
* @brief C++ Program to find the modular inverse using [Fermat's Little
* Theorem](https://en.wikipedia.org/wiki/Fermat%27s_little_theorem)
*
* Fermat's Little Theorem state that \f[ϕ(m) = m-1\f]
* where \f$m\f$ is a prime number.
* \f{eqnarray*}{
* a \cdot x &≡& 1 \;\text{mod}\; m\\
* x &≡& a^{-1} \;\text{mod}\; m
* \f}
* Using Euler's theorem we can modify the equation.
*\f[
* a^{ϕ(m)} ≡ 1 \;\text{mod}\; m
* \f]
* (Where '^' denotes the exponent operator)
*
* Here 'ϕ' is Euler's Totient Function. For modular inverse existence 'a' and
* 'm' must be relatively primes numbers. To apply Fermat's Little Theorem is
* necessary that 'm' must be a prime number. Generally in many competitive
* programming competitions 'm' is either 1000000007 (1e9+7) or 998244353.
*
* We considered m as large prime (1e9+7).
* \f$a^{ϕ(m)} ≡ 1 \;\text{mod}\; m\f$ (Using Euler's Theorem)
* \f$ϕ(m) = m-1\f$ using Fermat's Little Theorem.
* \f$a^{m-1} ≡ 1 \;\text{mod}\; m\f$
* Now multiplying both side by \f$a^{-1}\f$.
* \f{eqnarray*}{
* a^{m-1} \cdot a^{-1} &≡& a^{-1} \;\text{mod}\; m\\
* a^{m-2} &≡& a^{-1} \;\text{mod}\; m
* \f}
*
* We will find the exponent using binary exponentiation such that the
* algorithm works in \f$O(\log n)\f$ time.
*
* Examples: -
* * a = 3 and m = 7
* * \f$a^{-1} \;\text{mod}\; m\f$ is equivalent to
* \f$a^{m-2} \;\text{mod}\; m\f$
* * \f$3^5 \;\text{mod}\; 7 = 243 \;\text{mod}\; 7 = 5\f$
* <br/>Hence, \f$3^{-1} \;\text{mod}\; 7 = 5\f$
* or \f$3 \times 5 \;\text{mod}\; 7 = 1 \;\text{mod}\; 7\f$
* (as \f$a\times a^{-1} = 1\f$)
*/
#include <cassert> /// for assert
#include <cstdint> /// for std::int64_t
#include <iostream> /// for IO implementations
/**
* @namespace math
* @brief Maths algorithms.
*/
namespace math {
/**
* @namespace modular_inverse_fermat
* @brief Calculate modular inverse using Fermat's Little Theorem.
*/
namespace modular_inverse_fermat {
/**
* @brief Calculate exponent with modulo using binary exponentiation in \f$O(\log b)\f$ time.
* @param a The base
* @param b The exponent
* @param m The modulo
* @return The result of \f$a^{b} % m\f$
*/
std::int64_t binExpo(std::int64_t a, std::int64_t b, std::int64_t m) {
a %= m;
std::int64_t res = 1;
while (b > 0) {
if (b % 2 != 0) {
res = res * a % m;
}
a = a * a % m;
// Dividing b by 2 is similar to right shift by 1 bit
b >>= 1;
}
return res;
}
/**
* @brief Check if an integer is a prime number in \f$O(\sqrt{m})\f$ time.
* @param m An intger to check for primality
* @return true if the number is prime
* @return false if the number is not prime
*/
bool isPrime(std::int64_t m) {
if (m <= 1) {
return false;
}
for (std::int64_t i = 2; i * i <= m; i++) {
if (m % i == 0) {
return false;
}
}
return true;
}
/**
* @brief calculates the modular inverse.
* @param a Integer value for the base
* @param m Integer value for modulo
* @return The result that is the modular inverse of a modulo m
*/
std::int64_t modular_inverse(std::int64_t a, std::int64_t m) {
while (a < 0) {
a += m;
}
// Check for invalid cases
if (!isPrime(m) || a == 0) {
return -1; // Invalid input
}
return binExpo(a, m - 2, m); // Fermat's Little Theorem
}
} // namespace modular_inverse_fermat
} // namespace math
/**
* @brief Self-test implementation
* @return void
*/
static void test() {
assert(math::modular_inverse_fermat::modular_inverse(0, 97) == -1);
assert(math::modular_inverse_fermat::modular_inverse(15, -2) == -1);
assert(math::modular_inverse_fermat::modular_inverse(3, 10) == -1);
assert(math::modular_inverse_fermat::modular_inverse(3, 7) == 5);
assert(math::modular_inverse_fermat::modular_inverse(1, 101) == 1);
assert(math::modular_inverse_fermat::modular_inverse(-1337, 285179) == 165519);
assert(math::modular_inverse_fermat::modular_inverse(123456789, 998244353) == 25170271);
assert(math::modular_inverse_fermat::modular_inverse(-9876543210, 1000000007) == 784794281);
}
/**
* @brief Main function
* @return 0 on exit
*/
int main() {
test(); // run self-test implementation
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
/**
* @file
* @brief Simple implementation of [modular multiplicative
* inverse](https://en.wikipedia.org/wiki/Modular_multiplicative_inverse)
*
* @details
* this algorithm calculates the modular inverse x^{-1} \mod y iteratively
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for IO operations
/**
* @brief Function imod
* Calculates the modular inverse of x with respect to y, x^{-1} \mod y
* @param x number
* @param y number
* @returns the modular inverse
*/
uint64_t imod(uint64_t x, uint64_t y) {
uint64_t aux = 0; // auxiliary variable
uint64_t itr = 0; // iteration counter
do { // run the algorithm while not find the inverse
aux = y * itr + 1;
itr++;
} while (aux % x); // while module aux % x non-zero
return aux / x;
}
/**
* @brief self-test implementations
* @returns void
*/
static void test() {
std::cout << "First case testing... \n";
// for a = 3 and b = 11 return 4
assert(imod(3, 11) == 4);
std::cout << "\nPassed!\n";
std::cout << "Second case testing... \n";
// for a = 3 and b = 26 return 9
assert(imod(3, 26) == 9);
std::cout << "\nPassed!\n";
std::cout << "Third case testing... \n";
// for a = 7 and b = 26 return 15
assert(imod(7, 26) == 15);
std::cout << "\nPassed!\n";
std::cout << "\nAll test cases have successfully passed!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
};
+107
View File
@@ -0,0 +1,107 @@
/**
* @file
* @brief Implementation of the
* [N-bonacci](http://oeis.org/wiki/N-bonacci_numbers) series
*
* @details
* In general, in N-bonacci sequence,
* we generate sum of preceding N numbers from the next term.
*
* For example, a 3-bonacci sequence is the following:
* 0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81
* In this code we take N and M as input where M is the number of terms
* to be printed of the N-bonacci series
*
* @author [Swastika Gupta](https://github.com/Swastyy)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::cout
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace n_bonacci
* @brief Functions for the [N-bonacci](http://oeis.org/wiki/N-bonacci_numbers)
* implementation
*/
namespace n_bonacci {
/**
* @brief Finds the N-Bonacci series for the `n` parameter value and `m`
* parameter terms
* @param n is in the N-Bonacci series
* @param m is the number of terms in the N-Bonacci sequence
* @returns the n-bonacci sequence as vector array
*/
std::vector<uint64_t> N_bonacci(const uint64_t &n, const uint64_t &m) {
std::vector<uint64_t> a(
m, 0); // we create an array of size m filled with zeros
if (m < n || n == 0) {
return a;
}
a[n - 1] = 1; /// we initialise the (n-1)th term as 1 which is the sum of
/// preceding N zeros
if (n == m) {
return a;
}
a[n] = 1; /// similarily the sum of preceding N zeros and the (N+1)th 1 is
/// also 1
for (uint64_t i = n + 1; i < m; i++) {
// this is an optimized solution that works in O(M) time and takes O(M)
// extra space here we use the concept of the sliding window the current
// term can be computed using the given formula
a[i] = 2 * a[i - 1] - a[i - 1 - n];
}
return a;
}
} // namespace n_bonacci
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
struct TestCase {
const uint64_t n;
const uint64_t m;
const std::vector<uint64_t> expected;
TestCase(const uint64_t in_n, const uint64_t in_m,
std::initializer_list<uint64_t> data)
: n(in_n), m(in_m), expected(data) {
assert(data.size() == m);
}
};
const std::vector<TestCase> test_cases = {
TestCase(0, 0, {}),
TestCase(0, 1, {0}),
TestCase(0, 2, {0, 0}),
TestCase(1, 0, {}),
TestCase(1, 1, {1}),
TestCase(1, 2, {1, 1}),
TestCase(1, 3, {1, 1, 1}),
TestCase(5, 15, {0, 0, 0, 0, 1, 1, 2, 4, 8, 16, 31, 61, 120, 236, 464}),
TestCase(
6, 17,
{0, 0, 0, 0, 0, 1, 1, 2, 4, 8, 16, 32, 63, 125, 248, 492, 976}),
TestCase(56, 15, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})};
for (const auto &tc : test_cases) {
assert(math::n_bonacci::N_bonacci(tc.n, tc.m) == tc.expected);
}
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+81
View File
@@ -0,0 +1,81 @@
/**
* @file
* @brief [Combinations](https://en.wikipedia.org/wiki/Combination) n choose r
* function implementation
* @details
* A very basic and efficient method of calculating
* choosing r from n different choices.
* \f$ \binom{n}{r} = \frac{n!}{r! (n-r)!} \f$
*
* @author [Tajmeet Singh](https://github.com/tjgurwara99)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for io operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief This is the function implementation of \f$ \binom{n}{r} \f$
* @details
* We are calculating the ans with iterations
* instead of calculating three different factorials.
* Also, we are using the fact that
* \f$ \frac{n!}{r! (n-r)!} = \frac{(n - r + 1) \times \cdots \times n}{1 \times
* \cdots \times r} \f$
* @tparam T Only for integer types such as long, int_64 etc
* @param n \f$ n \f$ in \f$ \binom{n}{r} \f$
* @param r \f$ r \f$ in \f$ \binom{n}{r} \f$
* @returns ans \f$ \binom{n}{r} \f$
*/
template <class T>
T n_choose_r(T n, T r) {
if (r > n / 2) {
r = n - r; // Because of the fact that nCr(n, r) == nCr(n, n - r)
}
T ans = 1;
for (int i = 1; i <= r; i++) {
ans *= n - r + i;
ans /= i;
}
return ans;
}
} // namespace math
/**
* @brief Test implementations
* @returns void
*/
static void test() {
// First test on 5 choose 2
uint8_t t = math::n_choose_r(5, 2);
assert(((void)"10 is the answer but function says otherwise.\n", t == 10));
std::cout << "First test passes." << std::endl;
// Second test on 5 choose 3
t = math::n_choose_r(5, 3);
assert(
((void)"10 is the answer but the function says otherwise.\n", t == 10));
std::cout << "Second test passes." << std::endl;
// Third test on 3 choose 2
t = math::n_choose_r(3, 2);
assert(
((void)"3 is the answer but the function says otherwise.\n", t == 3));
std::cout << "Third test passes." << std::endl;
// Fourth test on 10 choose 4
t = math::n_choose_r(10, 4);
assert(((void)"210 is the answer but the function says otherwise.\n",
t == 210));
std::cout << "Fourth test passes." << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // executing tests
return 0;
}
+195
View File
@@ -0,0 +1,195 @@
/**
* @file
* @brief This program aims at calculating [nCr modulo
* p](https://cp-algorithms.com/combinatorics/binomial-coefficients.html).
* @details nCr is defined as n! / (r! * (n-r)!) where n! represents factorial
* of n. In many cases, the value of nCr is too large to fit in a 64 bit
* integer. Hence, in competitive programming, there are many problems or
* subproblems to compute nCr modulo p where p is a given number.
* @author [Kaustubh Damania](https://github.com/KaustubhDamania)
*/
#include <cassert> /// for assert
#include <iostream> /// for std::cout
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace ncr_modulo_p
* @brief Functions for [nCr modulo
* p](https://cp-algorithms.com/combinatorics/binomial-coefficients.html)
* implementation.
*/
namespace ncr_modulo_p {
/**
* @namespace utils
* @brief this namespace contains the definitions of the functions called from
* the class math::ncr_modulo_p::NCRModuloP
*/
namespace utils {
/**
* @brief finds the values x and y such that a*x + b*y = gcd(a,b)
*
* @param[in] a the first input of the gcd
* @param[in] a the second input of the gcd
* @param[out] x the Bézout coefficient of a
* @param[out] y the Bézout coefficient of b
* @return the gcd of a and b
*/
int64_t gcdExtended(const int64_t& a, const int64_t& b, int64_t& x,
int64_t& y) {
if (a == 0) {
x = 0;
y = 1;
return b;
}
int64_t x1 = 0, y1 = 0;
const int64_t gcd = gcdExtended(b % a, a, x1, y1);
x = y1 - (b / a) * x1;
y = x1;
return gcd;
}
/** Find modular inverse of a modulo m i.e. a number x such that (a*x)%m = 1
*
* @param[in] a the number for which the modular inverse is queried
* @param[in] m the modulus
* @return the inverce of a modulo m, if it exists, -1 otherwise
*/
int64_t modInverse(const int64_t& a, const int64_t& m) {
int64_t x = 0, y = 0;
const int64_t g = gcdExtended(a, m, x, y);
if (g != 1) { // modular inverse doesn't exist
return -1;
} else {
return ((x + m) % m);
}
}
} // namespace utils
/**
* @brief Class which contains all methods required for calculating nCr mod p
*/
class NCRModuloP {
private:
const int64_t p = 0; /// the p from (nCr % p)
const std::vector<int64_t>
fac; /// stores precomputed factorial(i) % p value
/**
* @brief computes the array of values of factorials reduced modulo mod
* @param max_arg_val argument of the last factorial stored in the result
* @param mod value of the divisor used to reduce factorials
* @return vector storing factorials of the numbers 0, ..., max_arg_val
* reduced modulo mod
*/
static std::vector<int64_t> computeFactorialsMod(const int64_t& max_arg_val,
const int64_t& mod) {
auto res = std::vector<int64_t>(max_arg_val + 1);
res[0] = 1;
for (int64_t i = 1; i <= max_arg_val; i++) {
res[i] = (res[i - 1] * i) % mod;
}
return res;
}
public:
/**
* @brief constructs an NCRModuloP object allowing to compute (nCr)%p for
* inputs from 0 to size
*/
NCRModuloP(const int64_t& size, const int64_t& p)
: p(p), fac(computeFactorialsMod(size, p)) {}
/**
* @brief computes nCr % p
* @param[in] n the number of objects to be chosen
* @param[in] r the number of objects to choose from
* @return the value nCr % p
*/
int64_t ncr(const int64_t& n, const int64_t& r) const {
// Base cases
if (r > n) {
return 0;
}
if (r == 1) {
return n % p;
}
if (r == 0 || r == n) {
return 1;
}
// fac is a global array with fac[r] = (r! % p)
const auto denominator = (fac[r] * fac[n - r]) % p;
const auto denominator_inv = utils::modInverse(denominator, p);
if (denominator_inv < 0) { // modular inverse doesn't exist
return -1;
}
return (fac[n] * denominator_inv) % p;
}
};
} // namespace ncr_modulo_p
} // namespace math
/**
* @brief tests math::ncr_modulo_p::NCRModuloP
*/
static void tests() {
struct TestCase {
const int64_t size;
const int64_t p;
const int64_t n;
const int64_t r;
const int64_t expected;
TestCase(const int64_t size, const int64_t p, const int64_t n,
const int64_t r, const int64_t expected)
: size(size), p(p), n(n), r(r), expected(expected) {}
};
const std::vector<TestCase> test_cases = {
TestCase(60000, 1000000007, 52323, 26161, 224944353),
TestCase(20, 5, 6, 2, 30 % 5),
TestCase(100, 29, 7, 3, 35 % 29),
TestCase(1000, 13, 10, 3, 120 % 13),
TestCase(20, 17, 1, 10, 0),
TestCase(45, 19, 23, 1, 23 % 19),
TestCase(45, 19, 23, 0, 1),
TestCase(45, 19, 23, 23, 1),
TestCase(20, 9, 10, 2, -1)};
for (const auto& tc : test_cases) {
assert(math::ncr_modulo_p::NCRModuloP(tc.size, tc.p).ncr(tc.n, tc.r) ==
tc.expected);
}
std::cout << "\n\nAll tests have successfully passed!\n";
}
/**
* @brief example showing the usage of the math::ncr_modulo_p::NCRModuloP class
*/
void example() {
const int64_t size = 1e6 + 1;
const int64_t p = 1e9 + 7;
// the ncrObj contains the precomputed values of factorials modulo p for
// values from 0 to size
const auto ncrObj = math::ncr_modulo_p::NCRModuloP(size, p);
// having the ncrObj we can efficiently query the values of (n C r)%p
// note that time of the computation does not depend on size
for (int i = 0; i <= 7; i++) {
std::cout << 6 << "C" << i << " mod " << p << " = " << ncrObj.ncr(6, i)
<< "\n";
}
}
int main() {
tests();
example();
return 0;
}
+83
View File
@@ -0,0 +1,83 @@
/**
* @file
* @brief C++ Program to calculate the number of positive divisors
*
* This algorithm uses the prime factorization approach.
* Any positive integer can be written as a product of its prime factors.
* <br/>Let \f$N = p_1^{e_1} \times p_2^{e_2} \times\cdots\times p_k^{e_k}\f$
* where \f$p_1,\, p_2,\, \dots,\, p_k\f$ are distinct prime factors of \f$N\f$ and
* \f$e_1,\, e_2,\, \dots,\, e_k\f$ are respective positive integer exponents.
* <br/>Each positive divisor of \f$N\f$ is in the form
* \f$p_1^{g_1}\times p_2^{g_2}\times\cdots\times p_k^{g_k}\f$
* where \f$0\le g_i\le e_i\f$ are integers for all \f$1\le i\le k\f$.
* <br/>Finally, there are \f$(e_1+1) \times (e_2+1)\times\cdots\times (e_k+1)\f$
* positive divisors of \f$N\f$ since we can choose every \f$g_i\f$
* independently.
*
* Example:
* <br/>\f$N = 36 = (3^2 \cdot 2^2)\f$
* <br/>\f$\mbox{number_of_positive_divisors}(36) = (2+1) \cdot (2+1) = 9\f$.
* <br/>list of positive divisors of 36 = 1, 2, 3, 4, 6, 9, 12, 18, 36.
*
* Similarly, for N = -36 the number of positive divisors remain same.
**/
#include <cassert>
/**
* Function to compute the number of positive divisors.
* @param n number to compute divisors for
* @returns number of positive divisors of n (or 1 if n = 0)
*/
int number_of_positive_divisors(int n) {
if (n < 0) {
n = -n; // take the absolute value of n
}
int number_of_divisors = 1;
for (int i = 2; i * i <= n; i++) {
// This part is doing the prime factorization.
// Note that we cannot find a composite divisor of n unless we would
// already previously find the corresponding prime divisor and dvided
// n by that prime. Therefore, all the divisors found here will
// actually be primes.
// The loop terminates early when it is left with a number n which
// does not have a divisor smaller or equal to sqrt(n) - that means
// the remaining number is a prime itself.
int prime_exponent = 0;
while (n % i == 0) {
// Repeatedly divide n by the prime divisor n to compute
// the exponent (e_i in the algorithm description).
prime_exponent++;
n /= i;
}
number_of_divisors *= prime_exponent + 1;
}
if (n > 1) {
// In case the remaining number n is a prime number itself
// (essentially p_k^1) the final answer is also multiplied by (e_k+1).
number_of_divisors *= 2;
}
return number_of_divisors;
}
/**
* Test implementations
*/
void tests() {
assert(number_of_positive_divisors(36) == 9);
assert(number_of_positive_divisors(-36) == 9);
assert(number_of_positive_divisors(1) == 1);
assert(number_of_positive_divisors(2011) == 2); // 2011 is a prime
assert(number_of_positive_divisors(756) == 24); // 756 = 2^2 * 3^3 * 7
}
/**
* Main function
*/
int main() {
tests();
return 0;
}
+287
View File
@@ -0,0 +1,287 @@
/**
* @file
* @brief Implementations for the
* [perimeter](https://en.wikipedia.org/wiki/Perimeter) of various shapes
* @details The of a shape is the amount of 2D space it takes up.
* All shapes have a formula for their perimeter.
* These implementations support multiple return types.
*
* @author [OGscorpion](https://github.com/OGscorpion)
*/
#define _USE_MATH_DEFINES
#include <cassert> /// for assert
#include <cmath> /// for M_PI definition and pow()
#include <cstdint> /// for uint16_t datatype
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief perimeter of a [square](https://en.wikipedia.org/wiki/Square) (4 * l)
* @param length is the length of the square
* @returns perimeter of square
*/
template <typename T>
T square_perimeter(T length) {
return 4 * length;
}
/**
* @brief perimeter of a [rectangle](https://en.wikipedia.org/wiki/Rectangle) (
* 2(l + w) )
* @param length is the length of the rectangle
* @param width is the width of the rectangle
* @returns perimeter of the rectangle
*/
template <typename T>
T rect_perimeter(T length, T width) {
return 2 * (length + width);
}
/**
* @brief perimeter of a [triangle](https://en.wikipedia.org/wiki/Triangle) (a +
* b + c)
* @param base is the length of the bottom side of the triangle
* @param height is the length of the tallest point in the triangle
* @returns perimeter of the triangle
*/
template <typename T>
T triangle_perimeter(T base, T height, T hypotenuse) {
return base + height + hypotenuse;
}
/**
* @brief perimeter of a
* [circle](https://en.wikipedia.org/wiki/perimeter_of_a_circle) (2 * pi * r)
* @param radius is the radius of the circle
* @returns perimeter of the circle
*/
template <typename T>
T circle_perimeter(T radius) {
return 2 * M_PI * radius;
}
/**
* @brief perimeter of a
* [parallelogram](https://en.wikipedia.org/wiki/Parallelogram) 2(b + h)
* @param base is the length of the bottom side of the parallelogram
* @param height is the length of the tallest point in the parallelogram
* @returns perimeter of the parallelogram
*/
template <typename T>
T parallelogram_perimeter(T base, T height) {
return 2 * (base + height);
}
/**
* @brief surface perimeter of a [cube](https://en.wikipedia.org/wiki/Cube) ( 12
* * l)
* @param length is the length of the cube
* @returns surface perimeter of the cube
*/
template <typename T>
T cube_surface_perimeter(T length) {
return 12 * length;
}
/**
* @brief surface perimeter of a
* [n-polygon](https://www.cuemath.com/measurement/perimeter-of-polygon/) ( n *
* l)
* @param length is the length of the polygon
* @param sides is the number of sides of the polygon
* @returns surface perimeter of the polygon
*/
template <typename T>
T n_polygon_surface_perimeter(T sides, T length) {
return sides * length;
}
/**
* @brief surface perimeter of a
* [cylinder](https://en.wikipedia.org/wiki/Cylinder) (2 * radius + 2 * height)
* @param radius is the radius of the cylinder
* @param height is the height of the cylinder
* @returns surface perimeter of the cylinder
*/
template <typename T>
T cylinder_surface_perimeter(T radius, T height) {
return (2 * radius) + (2 * height);
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// I/O variables for testing
uint16_t int_length = 0; // 16 bit integer length input
uint16_t int_width = 0; // 16 bit integer width input
uint16_t int_base = 0; // 16 bit integer base input
uint16_t int_height = 0; // 16 bit integer height input
uint16_t int_hypotenuse = 0; // 16 bit integer hypotenuse input
uint16_t int_sides = 0; // 16 bit integer sides input
uint16_t int_expected = 0; // 16 bit integer expected output
uint16_t int_perimeter = 0; // 16 bit integer output
float float_length = NAN; // float length input
float float_expected = NAN; // float expected output
float float_perimeter = NAN; // float output
double double_length = NAN; // double length input
double double_width = NAN; // double width input
double double_radius = NAN; // double radius input
double double_height = NAN; // double height input
double double_expected = NAN; // double expected output
double double_perimeter = NAN; // double output
// 1st test
int_length = 5;
int_expected = 20;
int_perimeter = math::square_perimeter(int_length);
std::cout << "perimeter OF A SQUARE (int)" << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_perimeter << std::endl;
assert(int_perimeter == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 2nd test
float_length = 2.5;
float_expected = 10;
float_perimeter = math::square_perimeter(float_length);
std::cout << "perimeter OF A SQUARE (float)" << std::endl;
std::cout << "Input Length: " << float_length << std::endl;
std::cout << "Expected Output: " << float_expected << std::endl;
std::cout << "Output: " << float_perimeter << std::endl;
assert(float_perimeter == float_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 3rd test
int_length = 4;
int_width = 7;
int_expected = 22;
int_perimeter = math::rect_perimeter(int_length, int_width);
std::cout << "perimeter OF A RECTANGLE (int)" << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Input Width: " << int_width << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_perimeter << std::endl;
assert(int_perimeter == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 4th test
double_length = 2.5;
double_width = 5.7;
double_expected = 16.4;
double_perimeter = math::rect_perimeter(double_length, double_width);
std::cout << "perimeter OF A RECTANGLE (double)" << std::endl;
std::cout << "Input Length: " << double_length << std::endl;
std::cout << "Input Width: " << double_width << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_perimeter << std::endl;
assert(double_perimeter == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 5th test
int_base = 10;
int_height = 3;
int_hypotenuse = 5;
int_expected = 18;
int_perimeter =
math::triangle_perimeter(int_base, int_height, int_hypotenuse);
std::cout << "perimeter OF A TRIANGLE" << std::endl;
std::cout << "Input Base: " << int_base << std::endl;
std::cout << "Input Height: " << int_height << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_perimeter << std::endl;
assert(int_perimeter == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 6th test
double_radius = 6;
double_expected =
37.69911184307752; // rounded down because the double datatype
// truncates after 14 decimal places
double_perimeter = math::circle_perimeter(double_radius);
std::cout << "perimeter OF A CIRCLE" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_perimeter << std::endl;
assert(double_perimeter == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 7th test
int_base = 6;
int_height = 7;
int_expected = 26;
int_perimeter = math::parallelogram_perimeter(int_base, int_height);
std::cout << "perimeter OF A PARALLELOGRAM" << std::endl;
std::cout << "Input Base: " << int_base << std::endl;
std::cout << "Input Height: " << int_height << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_perimeter << std::endl;
assert(int_perimeter == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 8th test
double_length = 5.5;
double_expected = 66.0;
double_perimeter = math::cube_surface_perimeter(double_length);
std::cout << "SURFACE perimeter OF A CUBE" << std::endl;
std::cout << "Input Length: " << double_length << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_perimeter << std::endl;
assert(double_perimeter == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 9th test
int_sides = 7;
int_length = 10;
int_expected = 70;
int_perimeter = math::n_polygon_surface_perimeter(int_sides, int_length);
std::cout << "SURFACE perimeter OF A N-POLYGON" << std::endl;
std::cout << "Input Sides: " << int_sides << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_perimeter << std::endl;
assert(int_perimeter == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 10th test
double_radius = 4.0;
double_height = 7.0;
double_expected = 22.0;
double_perimeter =
math::cylinder_surface_perimeter(double_radius, double_height);
std::cout << "SURFACE perimeter OF A CYLINDER" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Input Height: " << double_height << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_perimeter << std::endl;
assert(double_perimeter == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+90
View File
@@ -0,0 +1,90 @@
/**
* @file
* @brief Compute powers of large numbers
*/
#include <iostream>
/** Maximum number of digits in output
* \f$x^n\f$ where \f$1 <= x,\; n <= 10000\f$ and overflow may happen
*/
#define MAX 100000
/** This function multiplies x
* with the number represented by res[].
* res_size is size of res[] or
* number of digits in the number
* represented by res[]. This function
* uses simple school mathematics
* for multiplication.
* This function may value of res_size
* and returns the new value of res_size
* @param x multiplicand
* @param res large number representation using array
* @param res_size number of digits in `res`
*/
int multiply(int x, int res[], int res_size) {
// Initialize carry
int carry = 0;
// One by one multiply n with
// individual digits of res[]
for (int i = 0; i < res_size; i++) {
int prod = res[i] * x + carry;
// Store last digit of
// 'prod' in res[]
res[i] = prod % 10;
// Put rest in carry
carry = prod / 10;
}
// Put carry in res and
// increase result size
while (carry) {
res[res_size] = carry % 10;
carry = carry / 10;
res_size++;
}
return res_size;
}
/** This function finds power of a number x and print \f$x^n\f$
* @param x base
* @param n exponent
*/
void power(int x, int n) {
// printing value "1" for power = 0
if (n == 0) {
std::cout << "1";
return;
}
int res[MAX];
int res_size = 0;
int temp = x;
// Initialize result
while (temp != 0) {
res[res_size++] = temp % 10;
temp = temp / 10;
}
// Multiply x n times
// (x^n = x*x*x....n times)
for (int i = 2; i <= n; i++) res_size = multiply(x, res, res_size);
std::cout << x << "^" << n << " = ";
for (int i = res_size - 1; i >= 0; i--) std::cout << res[i];
}
/** Main function */
int main() {
int exponent, base;
std::cout << "Enter base ";
std::cin >> base;
std::cout << "Enter exponent ";
std::cin >> exponent;
power(base, exponent);
return 0;
}
+106
View File
@@ -0,0 +1,106 @@
/**
* @file
* @brief Implementation to check whether a number is a power of 2 or not.
*
* @details
* This algorithm uses bit manipulation to check if a number is a power of 2 or
* not.
*
* ### Algorithm
* Let the input number be n, then the bitwise and between n and n-1 will let us
* know whether the number is power of 2 or not
*
* For Example,
* If N= 32 then N-1 is 31, if we perform bitwise and of these two numbers then
* the result will be zero, which indicates that it is the power of 2
* If N=23 then N-1 is 22, if we perform bitwise and of these two numbers then
* the result will not be zero , which indicates that it is not the power of 2
* \note This implementation is better than naive recursive or iterative
* approach.
*
* @author [Neha Hasija](https://github.com/neha-hasija17)
* @author [Rijul.S](https://github.com/Rijul24)
*/
#include <iostream> /// for IO operations
#include <cassert> /// for assert
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief This function finds whether a number is power of 2 or not
* @param n value for which we want to check
* prints the result, as "Yes, the number n is a power of 2" or
* "No, the number is not a power of 2" without quotes
* @returns 1 if `n` IS the power of 2
* @returns 0 if n is NOT a power of 2
*/
int power_of_two(int n) {
/// result stores the
/// bitwise and of n and n-1
int result = n & (n - 1);
if (result == 0) {
return 1;
}
return 0;
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
std::cout << "First case testing... \n"; // for n = 32 return 1
assert(math::power_of_two(32) == 1);
std::cout << "\nPassed!\n";
std::cout << "Second case testing... \n"; // for n = 5 return 0
assert(math::power_of_two(5) == 0);
std::cout << "\nPassed!\n";
std::cout << "Third case testing... \n"; // for n = 232 return 0
assert(math::power_of_two(232) == 0);
std::cout << "\nPassed!\n";
std::cout << "\nAll test cases have successfully passed!\n";
}
/**
* @brief Take user input in the test cases (optional; currently commented)
* @returns void
*/
void user_input_test() {
int n = 0; // input from user
std::cout << "Enter a number " << std::endl;
std::cin >> n;
/// function call with @param n
int result = math::power_of_two(n);
if (result == 1) {
std::cout << "Yes, the number " << n << " is a power of 2\n";
}
else {
std::cout << "No, the number " << n << " is not a power of 2\n";
}
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
// uncomment the line below to take user inputs
//user_input_test();
return 0;
}
+78
View File
@@ -0,0 +1,78 @@
/**
* @file
* @brief Prime factorization of positive integers
*/
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
/** Declaring variables for maintaing prime numbers and to check whether a
* number is prime or not
*/
bool isprime[1000006];
/** list of prime numbers */
std::vector<int> prime_numbers;
/** list of prime factor-pairs */
std::vector<std::pair<int, int>> factors;
/** Calculating prime number upto a given range
*/
void SieveOfEratosthenes(int N) {
// initializes the array isprime
memset(isprime, true, sizeof isprime);
for (int i = 2; i <= N; i++) {
if (isprime[i]) {
for (int j = 2 * i; j <= N; j += i) isprime[j] = false;
}
}
for (int i = 2; i <= N; i++) {
if (isprime[i])
prime_numbers.push_back(i);
}
}
/** Prime factorization of a number */
void prime_factorization(int num) {
int number = num;
for (int i = 0; prime_numbers[i] <= num; i++) {
int count = 0;
// termination condition
if (number == 1) {
break;
}
while (number % prime_numbers[i] == 0) {
count++;
number = number / prime_numbers[i];
}
if (count)
factors.push_back(std::make_pair(prime_numbers[i], count));
}
}
/** Main program */
int main() {
int num;
std::cout << "\t\tComputes the prime factorization\n\n";
std::cout << "Type in a number: ";
std::cin >> num;
SieveOfEratosthenes(num);
prime_factorization(num);
// Prime factors with their powers in the given number in new line
for (auto it : factors) {
std::cout << it.first << " " << it.second << std::endl;
}
return 0;
}
+41
View File
@@ -0,0 +1,41 @@
/**
* @file
* @brief Get list of prime numbers
* @see primes_up_to_billion.cpp sieve_of_eratosthenes.cpp
*/
#include <iostream>
#include <vector>
/** Generate an increasingly large number of primes
* and store in a list
*/
std::vector<int> primes(size_t max) {
std::vector<int> res;
std::vector<bool> is_not_prime(max + 1, false);
for (size_t i = 2; i <= max; i++) {
if (!is_not_prime[i]) {
res.emplace_back(i);
}
for (int p : res) {
size_t k = i * p;
if (k > max) {
break;
}
is_not_prime[k] = true;
if (i % p == 0) {
break;
}
}
}
return res;
}
/** main function */
int main() {
std::cout << "Calculate primes up to:\n>> ";
int n = 0;
std::cin >> n;
std::vector<int> ans = primes(n);
for (int p : ans) std::cout << p << ' ';
std::cout << std::endl;
}
+36
View File
@@ -0,0 +1,36 @@
/**
* @file
* @brief Compute prime numbers upto 1 billion
* @see prime_numbers.cpp sieve_of_eratosthenes.cpp
*/
#include <cstring>
#include <iostream>
/** array to store the primes */
char prime[100000000];
/** Perform Sieve algorithm */
void Sieve(int64_t n) {
memset(prime, '1', sizeof(prime)); // intitize '1' to every index
prime[0] = '0'; // 0 is not prime
prime[1] = '0'; // 1 is not prime
for (int64_t p = 2; p * p <= n; p++) {
if (prime[p] == '1') {
for (int64_t i = p * p; i <= n; i += p)
prime[i] = '0'; // set all multiples of p to false
}
}
}
/** Main function */
int main() {
Sieve(100000000);
int64_t n;
std::cin >> n; // 10006187
if (prime[n] == '1')
std::cout << "YES\n";
else
std::cout << "NO\n";
return 0;
}
@@ -0,0 +1,189 @@
/**
* @file
* @brief Calculate quadratic equation with complex roots, i.e. b^2 - 4ac < 0.
*
* @author [Renjian-buchai](https://github.com/Renjian-buchai)
*
* @description Calculates any quadratic equation in form ax^2 + bx + c.
*
* Quadratic equation:
* x = (-b +/- sqrt(b^2 - 4ac)) / 2a
*
* @example
* int main() {
* using std::array;
* using std::complex;
* using std::cout;
*
* array<complex<long double, 2> solutions = quadraticEquation(1, 2, 1);
* cout << solutions[0] << " " << solutions[1] << "\n";
*
* solutions = quadraticEquation(1, 1, 1); // Reusing solutions.
* cout << solutions[0] << " " << solutions[1] << "\n";
* return 0;
* }
*
* Output:
* (-1, 0) (-1, 0)
* (-0.5,0.866025) (-0.5,0.866025)
*/
#include <array> /// std::array
#include <cassert> /// assert
#include <cmath> /// std::sqrt, std::trunc, std::pow
#include <complex> /// std::complex
#include <exception> /// std::invalid_argument
#include <iomanip> /// std::setprecision
#include <iostream> /// std::cout
/**
* @namespace
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief Quadratic equation calculator.
* @param a quadratic coefficient.
* @param b linear coefficient.
* @param c constant
* @return Array containing the roots of quadratic equation, incl. complex
* root.
*/
std::array<std::complex<long double>, 2> quadraticEquation(long double a,
long double b,
long double c) {
if (a == 0) {
throw std::invalid_argument("quadratic coefficient cannot be 0");
}
long double discriminant = b * b - 4 * a * c;
std::array<std::complex<long double>, 2> solutions{0, 0};
if (discriminant == 0) {
solutions[0] = -b * 0.5 / a;
solutions[1] = -b * 0.5 / a;
return solutions;
}
// Complex root (discriminant < 0)
// Note that the left term (-b / 2a) is always real. The imaginary part
// appears when b^2 - 4ac < 0, so sqrt(b^2 - 4ac) has no real roots. So,
// the imaginary component is i * (+/-)sqrt(abs(b^2 - 4ac)) / 2a.
if (discriminant > 0) {
// Since discriminant > 0, there are only real roots. Therefore,
// imaginary component = 0.
solutions[0] = std::complex<long double>{
(-b - std::sqrt(discriminant)) * 0.5 / a, 0};
solutions[1] = std::complex<long double>{
(-b + std::sqrt(discriminant)) * 0.5 / a, 0};
return solutions;
}
// Since b^2 - 4ac is < 0, for faster computation, -discriminant is
// enough to make it positive.
solutions[0] = std::complex<long double>{
-b * 0.5 / a, -std::sqrt(-discriminant) * 0.5 / a};
solutions[1] = std::complex<long double>{
-b * 0.5 / a, std::sqrt(-discriminant) * 0.5 / a};
return solutions;
}
} // namespace math
/**
* @brief Asserts an array of complex numbers.
* @param input Input array of complex numbers. .
* @param expected Expected array of complex numbers.
* @param precision Precision to be asserted. Default=10
*/
void assertArray(std::array<std::complex<long double>, 2> input,
std::array<std::complex<long double>, 2> expected,
size_t precision = 10) {
long double exponent = std::pow(10, precision);
input[0].real(std::round(input[0].real() * exponent));
input[1].real(std::round(input[1].real() * exponent));
input[0].imag(std::round(input[0].imag() * exponent));
input[1].imag(std::round(input[1].imag() * exponent));
expected[0].real(std::round(expected[0].real() * exponent));
expected[1].real(std::round(expected[1].real() * exponent));
expected[0].imag(std::round(expected[0].imag() * exponent));
expected[1].imag(std::round(expected[1].imag() * exponent));
assert(input == expected);
}
/**
* @brief Self-test implementations to test quadraticEquation function.
* @note There are 4 different types of solutions: Real and equal, real,
* complex, complex and equal.
*/
static void test() {
// Values are equal and real.
std::cout << "Input: \n"
"a=1 \n"
"b=-2 \n"
"c=1 \n"
"Expected output: \n"
"(1, 0), (1, 0)\n\n";
std::array<std::complex<long double>, 2> equalCase{
std::complex<long double>{1, 0}, std::complex<long double>{1, 0}};
assert(math::quadraticEquation(1, -2, 1) == equalCase);
// Values are equal and complex.
std::cout << "Input: \n"
"a=1 \n"
"b=4 \n"
"c=5 \n"
"Expected output: \n"
"(-2, -1), (-2, 1)\n\n";
std::array<std::complex<long double>, 2> complexCase{
std::complex<long double>{-2, -1}, std::complex<long double>{-2, 1}};
assert(math::quadraticEquation(1, 4, 5) == complexCase);
// Values are real.
std::cout << "Input: \n"
"a=1 \n"
"b=5 \n"
"c=1 \n"
"Expected output: \n"
"(-4.7912878475, 0), (-0.2087121525, 0)\n\n";
std::array<std::complex<long double>, 2> floatCase{
std::complex<long double>{-4.7912878475, 0},
std::complex<long double>{-0.2087121525, 0}};
assertArray(math::quadraticEquation(1, 5, 1), floatCase);
// Values are complex.
std::cout << "Input: \n"
"a=1 \n"
"b=1 \n"
"c=1 \n"
"Expected output: \n"
"(-0.5, -0.8660254038), (-0.5, 0.8660254038)\n\n";
std::array<std::complex<long double>, 2> ifloatCase{
std::complex<long double>{-0.5, -0.8660254038},
std::complex<long double>{-0.5, 0.8660254038}};
assertArray(math::quadraticEquation(1, 1, 1), ifloatCase);
std::cout << "Exception test: \n"
"Input: \n"
"a=0 \n"
"b=0 \n"
"c=0\n"
"Expected output: Exception thrown \n";
try {
math::quadraticEquation(0, 0, 0);
} catch (std::invalid_argument& e) {
std::cout << "Exception thrown successfully \n";
}
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // Run self-test implementation.
return 0;
}
+193
View File
@@ -0,0 +1,193 @@
/**
* \file
* \brief Compute statistics for data entered in rreal-time
*
* This algorithm is really beneficial to compute statistics on data read in
* realtime. For example, devices reading biometrics data. The algorithm is
* simple enough to be easily implemented in an embedded system.
* \author [Krishna Vedala](https://github.com/kvedala)
*/
#include <cassert>
#include <cmath>
#include <iostream>
/**
* \namespace statistics
* \brief Statistical algorithms
*/
namespace statistics {
/**
* continuous mean and variance computance using
* first value as an approximation for the mean.
* If the first number is much far form the mean, the algorithm becomes very
* inaccurate to compute variance and standard deviation.
*/
template <typename T>
class stats_computer1 {
public:
/** Constructor
* \param[in] x new data sample
*/
void new_val(T x) {
if (n == 0)
K = x;
n++;
T tmp = x - K;
Ex += tmp;
Ex2 += static_cast<double>(tmp) * tmp;
}
/** return sample mean computed till last sample */
double mean() const { return K + Ex / n; }
/** return data variance computed till last sample */
double variance() const { return (Ex2 - (Ex * Ex) / n) / (n - 1); }
/** return sample standard deviation computed till last sample */
double std() const { return std::sqrt(this->variance()); }
/** short-hand operator to read new sample from input stream
* \n e.g.: `std::cin >> stats1;`
*/
friend std::istream &operator>>(std::istream &input,
stats_computer1 &stat) {
T val;
input >> val;
stat.new_val(val);
return input;
}
private:
unsigned int n = 0;
double Ex, Ex2;
T K;
};
/**
* continuous mean and variance computance using
* Welford's algorithm (very accurate)
*/
template <typename T>
class stats_computer2 {
public:
/** Constructor
* \param[in] x new data sample
*/
void new_val(T x) {
n++;
double delta = x - mu;
mu += delta / n;
double delta2 = x - mu;
M += delta * delta2;
}
/** return sample mean computed till last sample */
double mean() const { return mu; }
/** return data variance computed till last sample */
double variance() const { return M / n; }
/** return sample standard deviation computed till last sample */
double std() const { return std::sqrt(this->variance()); }
/** short-hand operator to read new sample from input stream
* \n e.g.: `std::cin >> stats1;`
*/
friend std::istream &operator>>(std::istream &input,
stats_computer2 &stat) {
T val;
input >> val;
stat.new_val(val);
return input;
}
private:
unsigned int n = 0;
double mu = 0, var = 0, M = 0;
};
} // namespace statistics
using statistics::stats_computer1;
using statistics::stats_computer2;
/** Test the algorithm implementation
* \param[in] test_data array of data to test the algorithms
*/
void test_function(const float *test_data, const int number_of_samples) {
float mean = 0.f, variance = 0.f;
stats_computer1<float> stats01;
stats_computer2<float> stats02;
for (int i = 0; i < number_of_samples; i++) {
stats01.new_val(test_data[i]);
stats02.new_val(test_data[i]);
mean += test_data[i];
}
mean /= number_of_samples;
for (int i = 0; i < number_of_samples; i++) {
float temp = test_data[i] - mean;
variance += temp * temp;
}
variance /= number_of_samples;
std::cout << "<<<<<<<< Test Function >>>>>>>>" << std::endl
<< "Expected: Mean: " << mean << "\t Variance: " << variance
<< std::endl;
std::cout << "\tMethod 1:"
<< "\tMean: " << stats01.mean()
<< "\t Variance: " << stats01.variance()
<< "\t Std: " << stats01.std() << std::endl;
std::cout << "\tMethod 2:"
<< "\tMean: " << stats02.mean()
<< "\t Variance: " << stats02.variance()
<< "\t Std: " << stats02.std() << std::endl;
assert(std::abs(stats01.mean() - mean) < 0.01);
assert(std::abs(stats02.mean() - mean) < 0.01);
assert(std::abs(stats02.variance() - variance) < 0.01);
std::cout << "(Tests passed)" << std::endl;
}
/** Main function */
int main() {
const float test_data1[] = {3, 4, 5, -1.4, -3.6, 1.9, 1.};
test_function(test_data1, sizeof(test_data1) / sizeof(test_data1[0]));
std::cout
<< "Enter data. Any non-numeric data will terminate the data input."
<< std::endl;
stats_computer1<float> stats1;
stats_computer2<float> stats2;
while (1) {
double val;
std::cout << "Enter number: ";
std::cin >> val;
// check for failure to read input. Happens for
// non-numeric data
if (std::cin.fail())
break;
stats1.new_val(val);
stats2.new_val(val);
std::cout << "\tMethod 1:"
<< "\tMean: " << stats1.mean()
<< "\t Variance: " << stats1.variance()
<< "\t Std: " << stats1.std() << std::endl;
std::cout << "\tMethod 2:"
<< "\tMean: " << stats2.mean()
<< "\t Variance: " << stats2.variance()
<< "\t Std: " << stats2.std() << std::endl;
}
return 0;
}
+122
View File
@@ -0,0 +1,122 @@
/**
* @file
* @brief Prime Numbers using [Sieve of
* Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
* @details
* Sieve of Eratosthenes is an algorithm that finds all the primes
* between 2 and N.
*
* Time Complexity : \f$O(N \cdot\log \log N)\f$
* <br/>Space Complexity : \f$O(N)\f$
*
* @see primes_up_to_billion.cpp prime_numbers.cpp
*/
#include <cstdint>
#include <cassert> /// for assert
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace sieve_of_eratosthenes
* @brief Functions for finding Prime Numbers using Sieve of Eratosthenes
*/
namespace sieve_of_eratosthenes {
/**
* @brief Function to sieve out the primes
* @details
* This function finds all the primes between 2 and N using the Sieve of
* Eratosthenes algorithm. It starts by assuming all numbers (except zero and
* one) are prime and then iteratively marks the multiples of each prime as
* non-prime.
*
* Contains a common optimization to start eliminating multiples of
* a prime p starting from p * p since all of the lower multiples
* have been already eliminated.
* @param N number till which primes are to be found
* @return is_prime a vector of `N + 1` booleans identifying if `i`^th number is
* a prime or not
*/
std::vector<bool> sieve(uint32_t N) {
std::vector<bool> is_prime(N + 1, true); // Initialize all as prime numbers
is_prime[0] = is_prime[1] = false; // 0 and 1 are not prime numbers
for (uint32_t i = 2; i * i <= N; i++) {
if (is_prime[i]) {
for (uint32_t j = i * i; j <= N; j += i) {
is_prime[j] = false;
}
}
}
return is_prime;
}
/**
* @brief Function to print the prime numbers
* @param N number till which primes are to be found
* @param is_prime a vector of `N + 1` booleans identifying if `i`^th number is
* a prime or not
*/
void print(uint32_t N, const std::vector<bool> &is_prime) {
for (uint32_t i = 2; i <= N; i++) {
if (is_prime[i]) {
std::cout << i << ' ';
}
}
std::cout << std::endl;
}
} // namespace sieve_of_eratosthenes
} // namespace math
/**
* @brief Self-test implementations
* @return void
*/
static void tests() {
std::vector<bool> is_prime_1 =
math::sieve_of_eratosthenes::sieve(static_cast<uint32_t>(10));
std::vector<bool> is_prime_2 =
math::sieve_of_eratosthenes::sieve(static_cast<uint32_t>(20));
std::vector<bool> is_prime_3 =
math::sieve_of_eratosthenes::sieve(static_cast<uint32_t>(100));
std::vector<bool> expected_1{false, false, true, true, false, true,
false, true, false, false, false};
assert(is_prime_1 == expected_1);
std::vector<bool> expected_2{false, false, true, true, false, true,
false, true, false, false, false, true,
false, true, false, false, false, true,
false, true, false};
assert(is_prime_2 == expected_2);
std::vector<bool> expected_3{
false, false, true, true, false, true, false, true, false, false,
false, true, false, true, false, false, false, true, false, true,
false, false, false, true, false, false, false, false, false, true,
false, true, false, false, false, false, false, true, false, false,
false, true, false, true, false, false, false, true, false, false,
false, false, false, true, false, false, false, false, false, true,
false, true, false, false, false, false, false, true, false, false,
false, true, false, true, false, false, false, false, false, true,
false, false, false, true, false, false, false, false, false, true,
false, false, false, false, false, false, false, true, false, false,
false};
assert(is_prime_3 == expected_3);
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests();
return 0;
}
+49
View File
@@ -0,0 +1,49 @@
/**
* @file
* @brief Calculate the square root of any positive real number in \f$O(\log
* N)\f$ time, with precision fixed using [bisection
* method](https://en.wikipedia.org/wiki/Bisection_method) of root-finding.
*
* @see Can be implemented using faster and better algorithms like
* newton_raphson_method.cpp and false_position.cpp
*/
#include <cassert>
#include <iostream>
/** Bisection method implemented for the function \f$x^2-a=0\f$
* whose roots are \f$\pm\sqrt{a}\f$ and only the positive root is returned.
*/
double Sqrt(double a) {
if (a > 0 && a < 1) {
return 1 / Sqrt(1 / a);
}
double l = 0, r = a;
/* Epsilon is the precision.
A great precision is
between 1e-7 and 1e-12.
double epsilon = 1e-12;
*/
double epsilon = 1e-12;
while (l <= r) {
double mid = (l + r) / 2;
if (mid * mid > a) {
r = mid;
} else {
if (a - mid * mid < epsilon) {
return mid;
}
l = mid;
}
}
return -1;
}
/** main function */
int main() {
double n{};
std::cin >> n;
assert(n >= 0);
// Change this line for a better precision
std::cout.precision(12);
std::cout << std::fixed << Sqrt(n);
}
+90
View File
@@ -0,0 +1,90 @@
/**
* @file
* @brief This Programme returns the Nth fibonacci as a string.
*
* The method used is manual addition with carry and placing it in a string
* which is called string addition This makes it have no bounds or limits
*
* @see fibonacci_large.cpp, fibonacci_fast.cpp, fibonacci.cpp
*/
#include <cstdint>
#include <iostream>
#ifdef _MSC_VER
#include <string> // use this for MS Visual C
#else
#include <cstring> // otherwise
#endif
/**
* function to add two string numbers
* \param [in] a first number in string to add
* \param [in] b second number in string to add
* \returns sum as a std::string
*/
std::string add(std::string a, std::string b) {
std::string temp = "";
// carry flag
int carry = 0;
// fills up with zeros
while (a.length() < b.length()) {
a = "0" + a;
}
// fills up with zeros
while (b.length() < a.length()) {
b = "0" + b;
}
// adds the numbers a and b
for (int i = a.length() - 1; i >= 0; i--) {
char val = static_cast<char>(((a[i] - 48) + (b[i] - 48)) + 48 + carry);
if (val > 57) {
carry = 1;
val -= 10;
} else {
carry = 0;
}
temp = val + temp;
}
// processes the carry flag
if (carry == 1) {
temp = "1" + temp;
}
// removes leading zeros.
while (temp[0] == '0' && temp.length() > 1) {
temp = temp.substr(1);
}
return temp;
}
/** Fibonacci iterator
* \param [in] n n^th Fibonacci number
*/
void fib_Accurate(uint64_t n) {
std::string tmp = "";
std::string fibMinus1 = "1";
std::string fibMinus2 = "0";
for (uint64_t i = 0; i < n; i++) {
tmp = add(fibMinus1, fibMinus2);
fibMinus2 = fibMinus1;
fibMinus1 = tmp;
}
std::cout << fibMinus2;
}
/** main function */
int main() {
int n;
std::cout << "Enter whatever number N you want to find the fibonacci of\n";
std::cin >> n;
std::cout << n << " th Fibonacci is \n";
fib_Accurate(n);
return 0;
}
+67
View File
@@ -0,0 +1,67 @@
/**
* @file
* @brief Algorithm to find sum of binomial coefficients of a given positive
* integer.
* @details Given a positive integer n, the task is to find the sum of binomial
* coefficient i.e nC0 + nC1 + nC2 + ... + nCn-1 + nCn By induction, we can
* prove that the sum is equal to 2^n
* @see more on
* https://en.wikipedia.org/wiki/Binomial_coefficient#Sums_of_the_binomial_coefficients
* @author [muskan0719](https://github.com/muskan0719)
*/
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::cin and std::cout
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* Function to calculate sum of binomial coefficients
* @param n number
* @return Sum of binomial coefficients of number
*/
uint64_t binomialCoeffSum(uint64_t n) {
// Calculating 2^n
return (1 << n);
}
} // namespace math
/**
* Function for testing binomialCoeffSum function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
int test_case_1 = math::binomialCoeffSum(2);
assert(test_case_1 == 4);
std::cout << "Test_case_1 Passed!" << std::endl;
int test_case_2 = math::binomialCoeffSum(3);
assert(test_case_2 == 8);
std::cout << "Test_case_2 Passed!" << std::endl;
int test_case_3 = math::binomialCoeffSum(4);
assert(test_case_3 == 16);
std::cout << "Test_case_3 Passed!" << std::endl;
int test_case_4 = math::binomialCoeffSum(5);
assert(test_case_4 == 32);
std::cout << "Test_case_4 Passed!" << std::endl;
int test_case_5 = math::binomialCoeffSum(7);
assert(test_case_5 == 128);
std::cout << "Test_case_5 Passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}
+72
View File
@@ -0,0 +1,72 @@
/**
* Copyright 2020 @author iamnambiar
*
* @file
* \brief A C++ Program to find the Sum of Digits of input integer.
*/
#include <cassert>
#include <iostream>
/**
* Function to find the sum of the digits of an integer.
* @param num The integer.
* @return Sum of the digits of the integer.
*
* \detail
* First the algorithm check whether the num is negative or positive,
* if it is negative, then we neglect the negative sign.
* Next, the algorithm extract the last digit of num by dividing by 10
* and extracting the remainder and this is added to the sum.
* The number is then divided by 10 to remove the last digit.
* This loop continues until num becomes 0.
*/
int sum_of_digits(int num) {
// If num is negative then negative sign is neglected.
if (num < 0) {
num = -1 * num;
}
int sum = 0;
while (num > 0) {
sum = sum + (num % 10);
num = num / 10;
}
return sum;
}
/**
* Function for testing the sum_of_digits() function with a
* first test case of 119765 and assert statement.
*/
void test1() {
int test_case_1 = sum_of_digits(119765);
assert(test_case_1 == 29);
}
/**
* Function for testing the sum_of_digits() function with a
* second test case of -12256 and assert statement.
*/
void test2() {
int test_case_2 = sum_of_digits(-12256);
assert(test_case_2 == 16);
}
/**
* Function for testing the sum_of_digits() with
* all the test cases.
*/
void test() {
// First test.
test1();
// Second test.
test2();
}
/**
* Main Function
*/
int main() {
test();
std::cout << "Success." << std::endl;
return 0;
}
+132
View File
@@ -0,0 +1,132 @@
/**
* @file
*
* @brief Calculates the [Cross
*Product](https://en.wikipedia.org/wiki/Cross_product) and the magnitude of two
*mathematical 3D vectors.
*
*
* @details Cross Product of two vectors gives a vector.
* Direction Ratios of a vector are the numeric parts of the given vector. They
*are the tree parts of the vector which determine the magnitude (value) of the
*vector. The method of finding a cross product is the same as finding the
*determinant of an order 3 matrix consisting of the first row with unit vectors
*of magnitude 1, the second row with the direction ratios of the first vector
*and the third row with the direction ratios of the second vector. The
*magnitude of a vector is it's value expressed as a number. Let the direction
*ratios of the first vector, P be: a, b, c Let the direction ratios of the
*second vector, Q be: x, y, z Therefore the calculation for the cross product
*can be arranged as:
*
* ```
* P x Q:
* 1 1 1
* a b c
* x y z
* ```
*
* The direction ratios (DR) are calculated as follows:
* 1st DR, J: (b * z) - (c * y)
* 2nd DR, A: -((a * z) - (c * x))
* 3rd DR, N: (a * y) - (b * x)
*
* Therefore, the direction ratios of the cross product are: J, A, N
* The following C++ Program calculates the direction ratios of the cross
*products of two vector. The program uses a function, cross() for doing so. The
*direction ratios for the first and the second vector has to be passed one by
*one seperated by a space character.
*
* Magnitude of a vector is the square root of the sum of the squares of the
*direction ratios.
*
* ### Example:
* An example of a running instance of the executable program:
*
* Pass the first Vector: 1 2 3
* Pass the second Vector: 4 5 6
* The cross product is: -3 6 -3
* Magnitude: 7.34847
*
* @author [Shreyas Sable](https://github.com/Shreyas-OwO)
*/
#include <array>
#include <cassert>
#include <cmath>
/**
* @namespace math
* @brief Math algorithms
*/
namespace math {
/**
* @namespace vector_cross
* @brief Functions for Vector Cross Product algorithms
*/
namespace vector_cross {
/**
* @brief Function to calculate the cross product of the passed arrays
* containing the direction ratios of the two mathematical vectors.
* @param A contains the direction ratios of the first mathematical vector.
* @param B contains the direction ration of the second mathematical vector.
* @returns the direction ratios of the cross product.
*/
std::array<double, 3> cross(const std::array<double, 3> &A,
const std::array<double, 3> &B) {
std::array<double, 3> product;
/// Performs the cross product as shown in @algorithm.
product[0] = (A[1] * B[2]) - (A[2] * B[1]);
product[1] = -((A[0] * B[2]) - (A[2] * B[0]));
product[2] = (A[0] * B[1]) - (A[1] * B[0]);
return product;
}
/**
* @brief Calculates the magnitude of the mathematical vector from it's
* direction ratios.
* @param vec an array containing the direction ratios of a mathematical vector.
* @returns type: double description: the magnitude of the mathematical vector
* from the given direction ratios.
*/
double mag(const std::array<double, 3> &vec) {
double magnitude =
sqrt((vec[0] * vec[0]) + (vec[1] * vec[1]) + (vec[2] * vec[2]));
return magnitude;
}
} // namespace vector_cross
} // namespace math
/**
* @brief test function.
* @details test the cross() and the mag() functions.
*/
static void test() {
/// Tests the cross() function.
std::array<double, 3> t_vec =
math::vector_cross::cross({1, 2, 3}, {4, 5, 6});
assert(t_vec[0] == -3 && t_vec[1] == 6 && t_vec[2] == -3);
/// Tests the mag() function.
double t_mag = math::vector_cross::mag({6, 8, 0});
assert(t_mag == 10);
/// Tests A A = 0
std::array<double, 3> t_vec2 =
math::vector_cross::cross({1, 2, 3}, {1, 2, 3});
assert(t_vec2[0] == 0 && t_vec2[1] == 0 &&
t_vec2[2] == 0); // checking each element
assert(math::vector_cross::mag(t_vec2) ==
0); // checking the magnitude is also zero
}
/**
* @brief Main Function
* @details Asks the user to enter the direction ratios for each of the two
* mathematical vectors using std::cin
* @returns 0 on exit
*/
int main() {
/// Tests the functions with sample input before asking for user input.
test();
return 0;
}
+238
View File
@@ -0,0 +1,238 @@
/**
* @file
* @brief Implmentations for the [volume](https://en.wikipedia.org/wiki/Volume)
* of various 3D shapes.
* @details The volume of a 3D shape is the amount of 3D space that the shape
* takes up. All shapes have a formula to get the volume of any given shape.
* These implementations support multiple return types.
*
* @author [Focusucof](https://github.com/Focusucof)
*/
#include <cassert> /// for assert
#include <cmath> /// for std::pow
#include <cstdint> /// for std::uint32_t
#include <iostream> /// for IO operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief The volume of a [cube](https://en.wikipedia.org/wiki/Cube)
* @param length The length of the cube
* @returns The volume of the cube
*/
template <typename T>
T cube_volume(T length) {
return std::pow(length, 3);
}
/**
* @brief The volume of a
* [rectangular](https://en.wikipedia.org/wiki/Cuboid) prism
* @param length The length of the base rectangle
* @param width The width of the base rectangle
* @param height The height of the rectangular prism
* @returns The volume of the rectangular prism
*/
template <typename T>
T rect_prism_volume(T length, T width, T height) {
return length * width * height;
}
/**
* @brief The volume of a [cone](https://en.wikipedia.org/wiki/Cone)
* @param radius The radius of the base circle
* @param height The height of the cone
* @param PI The definition of the constant PI
* @returns The volume of the cone
*/
template <typename T>
T cone_volume(T radius, T height, double PI = 3.14) {
return std::pow(radius, 2) * PI * height / 3;
}
/**
* @brief The volume of a
* [triangular](https://en.wikipedia.org/wiki/Triangular_prism) prism
* @param base The length of the base triangle
* @param height The height of the base triangles
* @param depth The depth of the triangular prism (the height of the whole
* prism)
* @returns The volume of the triangular prism
*/
template <typename T>
T triangle_prism_volume(T base, T height, T depth) {
return base * height * depth / 2;
}
/**
* @brief The volume of a
* [pyramid](https://en.wikipedia.org/wiki/Pyramid_(geometry))
* @param length The length of the base shape (or base for triangles)
* @param width The width of the base shape (or height for triangles)
* @param height The height of the pyramid
* @returns The volume of the pyramid
*/
template <typename T>
T pyramid_volume(T length, T width, T height) {
return length * width * height / 3;
}
/**
* @brief The volume of a [sphere](https://en.wikipedia.org/wiki/Sphere)
* @param radius The radius of the sphere
* @param PI The definition of the constant PI
* @returns The volume of the sphere
*/
template <typename T>
T sphere_volume(T radius, double PI = 3.14) {
return PI * std::pow(radius, 3) * 4 / 3;
}
/**
* @brief The volume of a [cylinder](https://en.wikipedia.org/wiki/Cylinder)
* @param radius The radius of the base circle
* @param height The height of the cylinder
* @param PI The definition of the constant PI
* @returns The volume of the cylinder
*/
template <typename T>
T cylinder_volume(T radius, T height, double PI = 3.14) {
return PI * std::pow(radius, 2) * height;
}
} // namespace math
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// Input variables
uint32_t int_length = 0; // 32 bit integer length input
uint32_t int_width = 0; // 32 bit integer width input
uint32_t int_base = 0; // 32 bit integer base input
uint32_t int_height = 0; // 32 bit integer height input
uint32_t int_depth = 0; // 32 bit integer depth input
double double_radius = NAN; // double radius input
double double_height = NAN; // double height input
// Output variables
uint32_t int_expected = 0; // 32 bit integer expected output
uint32_t int_volume = 0; // 32 bit integer output
double double_expected = NAN; // double expected output
double double_volume = NAN; // double output
// 1st test
int_length = 5;
int_expected = 125;
int_volume = math::cube_volume(int_length);
std::cout << "VOLUME OF A CUBE" << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_volume << std::endl;
assert(int_volume == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 2nd test
int_length = 4;
int_width = 3;
int_height = 5;
int_expected = 60;
int_volume = math::rect_prism_volume(int_length, int_width, int_height);
std::cout << "VOLUME OF A RECTANGULAR PRISM" << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Input Width: " << int_width << std::endl;
std::cout << "Input Height: " << int_height << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_volume << std::endl;
assert(int_volume == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 3rd test
double_radius = 5;
double_height = 7;
double_expected = 183.16666666666666; // truncated to 14 decimal places
double_volume = math::cone_volume(double_radius, double_height);
std::cout << "VOLUME OF A CONE" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Input Height: " << double_height << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_volume << std::endl;
assert(double_volume == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 4th test
int_base = 3;
int_height = 4;
int_depth = 5;
int_expected = 30;
int_volume = math::triangle_prism_volume(int_base, int_height, int_depth);
std::cout << "VOLUME OF A TRIANGULAR PRISM" << std::endl;
std::cout << "Input Base: " << int_base << std::endl;
std::cout << "Input Height: " << int_height << std::endl;
std::cout << "Input Depth: " << int_depth << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_volume << std::endl;
assert(int_volume == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 5th test
int_length = 10;
int_width = 3;
int_height = 5;
int_expected = 50;
int_volume = math::pyramid_volume(int_length, int_width, int_height);
std::cout << "VOLUME OF A PYRAMID" << std::endl;
std::cout << "Input Length: " << int_length << std::endl;
std::cout << "Input Width: " << int_width << std::endl;
std::cout << "Input Height: " << int_height << std::endl;
std::cout << "Expected Output: " << int_expected << std::endl;
std::cout << "Output: " << int_volume << std::endl;
assert(int_volume == int_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 6th test
double_radius = 3;
double_expected = 113.04;
double_volume = math::sphere_volume(double_radius);
std::cout << "VOLUME OF A SPHERE" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_volume << std::endl;
assert(double_volume == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
// 7th test
double_radius = 5;
double_height = 2;
double_expected = 157;
double_volume = math::cylinder_volume(double_radius, double_height);
std::cout << "VOLUME OF A CYLINDER" << std::endl;
std::cout << "Input Radius: " << double_radius << std::endl;
std::cout << "Input Height: " << double_height << std::endl;
std::cout << "Expected Output: " << double_expected << std::endl;
std::cout << "Output: " << double_volume << std::endl;
assert(double_volume == double_expected);
std::cout << "TEST PASSED" << std::endl << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}