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
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:
@@ -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} )
|
||||
@@ -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**
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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/Metropolis–Hastings_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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user