Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

imeth

The stupid name "imeth" can be concluded into two translation:

  • I + METH – Because I'm high on math equations like a guy high on meth.
  • IYAN + METH Because Iyan (the original author) is high on math like a guy high on meth.

Even though both still share the same equal meaning.

Imeth is a lightweight C++ math library for exploring computational mathematics while testing the limit of author's C++ skill (and sanity). It's a high modular-designed library, making it very likely to have so many branches and abstractions just to get a method done. Though the author believes that modularity is the key to success. At least in his mind and his dream, it is.

Why imeth?

When asked, "why?", it's not about the matter, "why do I use imeth?". Instead, it's preferable to say that the real question is, "why do I make imeth?". No one, at least a sane being, is stupid enough to use imeth. Not even for fun I'd like to call them, sane, because someone who's sane will never hear the name imeth in their life. Someone who's insane however, will.

Apart from so, imeth is meant to be entirely an experiment that made public. It can be interpreted as a CIA trick to make propaganda so that they can control the world if they haven't. Or as a funny silly project to practice the author's skill while he learns C++ in his young age.

To me, I'm not developing imeth to be productive. It's more of an experiment that I think I'd like to accomplish.

Features

Imeth comes with plenty handy features that I'd like point out:

  • Arithmetic Operations: Basic arithmetic calculations
  • Linear Algebra: Equation solving, matrix operations, and more
  • Factoring Quadratic Equation: Methods to factor quadratic equations
  • Geometric Calculations: 2D and 3D geometric operations
  • Base Conversions and Operations: Convert and operate on numbers between different bases
  • Modular Design: Clean, organized API with namespace separation
  • Simple API: Clean interfaces for complex math

My favorite one is the linear algebra, especially the linear equation with variables. Which I think will be the best and will be the overglazed feature, by me.

Installation

Dependencies

  • C++20 Compatible Compilers
  • CMake V3.15+
  • Git

Clone the Repository

git clone https://github.com/lordpaijo/imeth.cpp imeth
cd imeth

Build and Install with CMake

Linux/MacOS

mkdir build && cd build
cmake ..
make -j
sudo make install

This will install:

  • Library: /usr/local/lib/libimeth.a
  • Headers: /usr/local/include/imeth/
  • CMake config: /usr/local/lib/cmake/imeth/

Windows

Using Visual Studio:

mkdir build
cd build
cmake .. -G "Visual Studio 17 2022"
cmake --build . --config Release
cmake --install . --config Release

Or using MinGW:

mkdir build
cd build
cmake .. -G "MinGW Makefiles"
mingw32-make -j
mingw32-make install

Usage

In your project's CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(MyProject CXX)

set(CMAKE_CXX_STANDARD 20)

# Find the installed imeth library
find_package(imeth REQUIRED)

add_executable(my_app main.cpp)

# Link against imeth
target_link_libraries(my_app PRIVATE imeth::imeth)

Then build:

cmake -B build
cmake --build build

Using with Compiler Directly

After installation, compile your code with:

# Using g++
g++ -std=c++20 your_code.cpp -I/usr/local/include -L/usr/local/lib -limeth -o your_program

# Using clang++
clang++ -std=c++20 your_code.cpp -I/usr/local/include -L/usr/local/lib -limeth -o your_program

Quick Start

You can start building an app using imeth by including a category and its chapter in your code like this:

#include <imeth/linear/algebra.hpp>

Then start using the methods imported from the header like this:

int main() {
    // Solve: 2x + 4 = 0
    // Solution: x = -2
    auto solution = imeth::LinearAlgebra::solve_1v(2, 4);

    if (solution) {
        std::cout << "Solution: x = " << *solution << "\n";
    } else {
        std::cout << "No solution exists\n";
    }

    return 0;
}

Example: Solving a System of Linear Equations

Let's make a program to solve linear equation of two variables using imeth:

#include <imeth/linear/algebra.hpp>
#include <iostream>

int main() {
    // Solve:
    //   2x + 3y = 8
    //   4x - 2y = 0
    // Solution: x = 1, y = 2

    auto solution = imeth::LinearAlgebra::solve_2v(2, 3, 8,    // First equation coefficients
                                                   4, -2, 0);  // Second equation coefficients

    if (solution) {
        std::cout << "Solution: x = " << solution->first
                  << ", y = " << solution->second << "\n";
    } else {
        std::cout << "No unique solution exists\n";
    }

    return 0;
}

Here, I call the library imeth, then the category linear, and then the chapter algebra.hpp.

What I'm really doing is, I'm importing the methods from the algebra chapter (header file, algebra.hpp) from the linear category (linear/) of the imeth library (imeth/).

API Overview

Imeth is a modular library divided into namespaces and classes. I mention the term category and chapter previously, they are simply my way to say a branch and a header. A category can be consisted of many chapters, just like a branch consisting many headers. Thus, imeth is a compilation of mathematical categories and their chapters, which of course include their operations.

Available Categories

CategoryDescription
<imeth/linear>Linear equations and operations
<imeth/operation>Bunch of general mathematical operations
<imeth/geometry>Geometric shape calculations
<imeth/base>Base conversions and operations

Each category has their own chapters. And chapters are the actual APIs that you are going to use.

Operation Category

The operation category contains general mathematical operations including arithmetic and logarithmic functions.

Chapters

  • Arithmetic - Comprehensive arithmetic operations and utilities
  • Logarithm - Logarithmic operations and exponential equation solving

Usage

#include <imeth/operation/arithmetic.hpp>
#include <imeth/operation/logarithm.hpp>

Arithmetic

The arithmetic chapter is the first chapter from the operation category. It provides a comprehensive collection of arithmetic operations and mathematical utilities, ranging from basic operations to statistical functions, number theory, and practical calculations.

#include <imeth/operation/arithmetic.hpp>

Features

Basic Operations

  • add(double a, double b) → double - Standard addition
  • subtract(double a, double b) → double - Standard subtraction
  • multiply(double a, double b) → double - Standard multiplication
  • divide(double a, double b) → double - Standard division

Power and Roots

  • power(double base, int exponent) → double - Raises base to an integer exponent
  • squareRoot(double n) → double - Computes √n
  • cubeRoot(double n) → double - Computes ∛n

Absolute Value and Sign

  • absolute(double n) → double - Returns |n|
  • sign(double n) → int - Returns -1 for negative, 0 for zero, 1 for positive

Remainders and Divisibility

  • remainder(int a, int b) → int - Integer remainder of a ÷ b
  • isDivisible(int a, int b) → bool - Checks if a is divisible by b

Percentages

  • percentOf(double percent, double total) → double - Calculates percent% of total
  • whatPercent(double part, double total) → double - Finds what percent part is of total
  • percentIncrease(double original, double newValue) → double - Calculates percentage increase
  • percentDecrease(double original, double newValue) → double - Calculates percentage decrease

Averages and Statistics

  • average(const std::vector<double>& numbers) → double - Mean of a vector of numbers
  • sum(const std::vector<double>& numbers) → double - Total sum
  • minimum(const std::vector<double>& numbers) → double - Minimum value
  • maximum(const std::vector<double>& numbers) → double - Maximum value
  • range(const std::vector<double>& numbers) → double - Difference between max and min
  • median(std::vector<double> numbers) → double - Middle value (sorts the data)

Fractions

  • addFractions(double num1, double den1, double num2, double den2) → double - Adds two fractions
  • subtractFractions(double num1, double den1, double num2, double den2) → double - Subtracts fractions
  • multiplyFractions(double num1, double den1, double num2, double den2) → double - Multiplies fractions
  • divideFractions(double num1, double den1, double num2, double den2) → double - Divides fractions

Rounding

  • roundToNearest(double n) → double - Rounds to nearest integer
  • roundUp(double n) → double - Ceiling function
  • roundDown(double n) → double - Floor function
  • roundToDecimalPlaces(double n, int places) → double - Rounds to specified decimal places

Number Properties

  • isEven(int n) → bool - Checks if even
  • isOdd(int n) → bool - Checks if odd
  • isPrime(int n) → bool - Tests for primality
  • greatestCommonDivisor(int a, int b) → int - GCD of two integers
  • leastCommonMultiple(int a, int b) → int - LCM of two integers

Geometry

  • distance2D(double x1, double y1, double x2, double y2) → double - Euclidean distance between two points
  • pythagorean(double a, double b) → double - Calculates hypotenuse using Pythagorean theorem

Conversions

  • celsiusToFahrenheit(double celsius) → double - Temperature conversion C → F
  • fahrenheitToCelsius(double fahrenheit) → double - Temperature conversion F → C

Finance

  • simpleInterest(double principal, double rate, double time) → double - Calculates simple interest

Example Usage

#include <imeth/operation/arithmetic.hpp>
#include <iostream>

int main() {
    double a, b;
    char op;

    std::cout << "Simple Calculator\n";
    std::cout << "Enter operation (e.g., 5 + 3): ";
    std::cin >> a >> op >> b;

    double result;
    switch(op) {
        case '+':
            result = imeth::Arithmetic::add(a, b);
            break;
        case '-':
            result = imeth::Arithmetic::subtract(a, b);
            break;
        case '*':
            result = imeth::Arithmetic::multiply(a, b);
            break;
        case '/':
            result = imeth::Arithmetic::divide(a, b);
            break;
        default:
            std::cout << "Invalid operator!\n";
            return 1;
    }

    std::cout << "Result: " << result << "\n";
    return 0;
}

More Examples

// Statistical calculations
std::vector<double> grades = {85.5, 92.0, 78.5, 95.0, 88.0};
double avg = imeth::Arithmetic::average(grades);      // 87.8
double med = imeth::Arithmetic::median(grades);        // 88.0
double minGrade = imeth::Arithmetic::minimum(grades);  // 78.5

// Number theory
int gcd = imeth::Arithmetic::greatestCommonDivisor(48, 18);  // 6
bool prime = imeth::Arithmetic::isPrime(17);                  // true

// Percentage calculations
double discount = imeth::Arithmetic::percentOf(20, 100.0);    // 20.0
double increase = imeth::Arithmetic::percentIncrease(50, 75); // 50.0

// Geometry
double dist = imeth::Arithmetic::distance2D(0, 0, 3, 4);      // 5.0
double hyp = imeth::Arithmetic::pythagorean(3, 4);            // 5.0

// Temperature conversion
double fahrenheit = imeth::Arithmetic::celsiusToFahrenheit(25); // 77.0

Logarithm

Logarithm is the second chapter that can be found from the operation category. It provides methods and functions to operate logarithmic operations, including common logarithms, natural logarithms, exponential equation solving, and base conversions.

#include <imeth/operation/logarithm.hpp>

Features

Logarithm Functions

  • log(double base, double value) → std::optional<double> - Computes log_base(value) with arbitrary base
  • ln(double value) → std::optional<double> - Natural logarithm (base e)
  • log10(double value) → std::optional<double> - Common logarithm (base 10)
  • log2(double value) → std::optional<double> - Binary logarithm (base 2)

Exponential Equations

  • solve_exponential(double base, double value) → std::optional<double> - Solves base^x = value for x

Base Conversion

  • change_base(double value, double old_base, double new_base) → std::optional<double> - Converts logarithm from one base to another using the change of base formula

Return Values

All methods return std::optional<double>:

  • Contains a value if the operation is valid
  • Returns std::nullopt if:
    • value ≤ 0 (logarithm undefined for non-positive numbers)
    • base ≤ 0 (invalid base)
    • base = 1 (division by zero in change of base formula)

Example Usage

#include <imeth/operation/logarithm.hpp>
#include <iostream>

int main() {
    // Basic logarithms
    auto result = imeth::Logarithm::log(2, 8);
    if (result.has_value()) {
        std::cout << "log_2(8) = " << result.value() << "\n";  // 3.0
    }

    // Natural logarithm
    auto ln_result = imeth::Logarithm::ln(2.718281828);
    if (ln_result.has_value()) {
        std::cout << "ln(e) ≈ " << ln_result.value() << "\n";  // ≈ 1.0
    }

    // Common logarithm
    auto log10_result = imeth::Logarithm::log10(1000);
    if (log10_result.has_value()) {
        std::cout << "log_10(1000) = " << log10_result.value() << "\n";  // 3.0
    }

    // Binary logarithm
    auto log2_result = imeth::Logarithm::log2(16);
    if (log2_result.has_value()) {
        std::cout << "log_2(16) = " << log2_result.value() << "\n";  // 4.0
    }

    return 0;
}

More Examples

// Solving exponential equations
// Solve: 2^x = 32
auto x = imeth::Logarithm::solve_exponential(2, 32);
if (x.has_value()) {
    std::cout << "x = " << x.value() << "\n";  // 5.0
}

// Solve: 10^x = 1000
auto x2 = imeth::Logarithm::solve_exponential(10, 1000);
if (x2.has_value()) {
    std::cout << "x = " << x2.value() << "\n";  // 3.0
}

// Change of base
// Convert log_2(8) to base 10
auto converted = imeth::Logarithm::change_base(8, 2, 10);
if (converted.has_value()) {
    std::cout << "log_10(8) = " << converted.value() << "\n";  // ≈ 0.903
}

// Error handling
auto invalid = imeth::Logarithm::log(2, -5);
if (!invalid.has_value()) {
    std::cout << "Cannot compute logarithm of negative number\n";
}

auto invalid_base = imeth::Logarithm::log(1, 10);
if (!invalid_base.has_value()) {
    std::cout << "Base cannot be 1\n";
}

Mathematical Properties

The logarithm functions implement standard mathematical properties:

  • Product rule: log(xy) = log(x) + log(y)
  • Quotient rule: log(x/y) = log(x) - log(y)
  • Power rule: log(x^n) = n·log(x)
  • Change of base: log_b(x) = log_a(x) / log_a(b)

Linear Category

The linear category contains linear algebra operations including equation solving and matrix operations.

Chapters

  • Algebra - Linear equations, systems of equations, and quadratic equations
  • Matrix - Matrix operations, vectors, and linear system solvers

Usage

#include <imeth/linear/algebra.hpp>
#include <imeth/linear/matrix.hpp>

Algebra

Ah, yes, algebra, my favorite subject. This chapter exists in the linear category and provides tools for solving linear equations, systems of linear equations, and quadratic equations.

#include <imeth/linear/algebra.hpp>

Classes

The algebra module contains two main classes:

  • LinearAlgebra - Solves linear equations and systems of linear equations
  • QuadraticEquation - Solves quadratic equations using the quadratic formula

LinearAlgebra

Provides methods for solving linear equations in one or two variables.

Features

Single Variable Linear Equations

  • solve_1v(double a, double b) → std::optional<double> - Solves ax + b = 0 for x
    • Returns std::nullopt if no solution exists (when a = 0 and b ≠ 0)

System of Two Linear Equations

  • solve_2v(double a1, double b1, double c1, double a2, double b2, double c2) → std::optional<std::pair<double, double>> - Solves the system:
    a1·x + b1·y = c1
    a2·x + b2·y = c2
    
    • Returns std::pair<double, double> containing (x, y) if a unique solution exists
    • Returns std::nullopt if the system has no solution or infinitely many solutions

Example Usage

#include <imeth/linear/algebra.hpp>
#include <iostream>

int main() {
    // Solve: 2x + 6 = 0
    auto result = imeth::LinearAlgebra::solve_1v(2, 6);
    if (result.has_value()) {
        std::cout << "x = " << result.value() << "\n";  // x = -3
    }

    // Solve system:
    // 2x + 3y = 8
    // x - y = 1
    auto system = imeth::LinearAlgebra::solve_2v(2, 3, 8, 1, -1, 1);
    if (system.has_value()) {
        auto [x, y] = system.value();
        std::cout << "x = " << x << ", y = " << y << "\n";  // x = 2.2, y = 1.2
    }

    return 0;
}

QuadraticEquation

Solves quadratic equations of the form ax² + bx + c = 0 using the quadratic formula.

Features

Solution Type

using Solution = std::variant<std::monostate, double, std::pair<double, double>>;

The Solution type can represent three possible outcomes:

  • std::monostate - No real solutions (complex roots, discriminant < 0)
  • double - One solution / repeated root (discriminant = 0)
  • std::pair<double, double> - Two distinct real solutions (discriminant > 0), where first ≤ second

Solving Quadratic Equations

  • solve(double a, double b, double c) → Solution - Solves ax² + bx + c = 0
    • Uses the quadratic formula: x = (-b ± √(b² - 4ac)) / 2a
    • Handles degenerate cases (when a = 0, reduces to linear equation)
    • Returns solutions in ascending order when two solutions exist

Example Usage

#include <imeth/linear/algebra.hpp>
#include <iostream>
#include <variant>

int main() {
    // Solve: x² - 5x + 6 = 0
    // Factors as: (x - 2)(x - 3) = 0
    auto result = imeth::QuadraticEquation::solve(1, -5, 6);

    if (std::holds_alternative<std::pair<double, double>>(result)) {
        auto [x1, x2] = std::get<std::pair<double, double>>(result);
        std::cout << "Two solutions: x1 = " << x1 << ", x2 = " << x2 << "\n";
        // Output: x1 = 2, x2 = 3
    }
    else if (std::holds_alternative<double>(result)) {
        double x = std::get<double>(result);
        std::cout << "One solution: x = " << x << "\n";
    }
    else {
        std::cout << "No real solutions (complex roots)\n";
    }

    return 0;
}

More Examples

// Repeated root (discriminant = 0)
// Solve: x² - 4x + 4 = 0  →  (x - 2)² = 0
auto repeated = imeth::QuadraticEquation::solve(1, -4, 4);
if (std::holds_alternative<double>(repeated)) {
    double x = std::get<double>(repeated);
    std::cout << "Repeated root: x = " << x << "\n";  // x = 2
}

// No real solutions (discriminant < 0)
// Solve: x² + x + 1 = 0
auto no_real = imeth::QuadraticEquation::solve(1, 1, 1);
if (std::holds_alternative<std::monostate>(no_real)) {
    std::cout << "No real solutions\n";
}

// Negative leading coefficient
// Solve: -x² + 4x - 3 = 0  →  x² - 4x + 3 = 0
auto negative_a = imeth::QuadraticEquation::solve(-1, 4, -3);
if (std::holds_alternative<std::pair<double, double>>(negative_a)) {
    auto [x1, x2] = std::get<std::pair<double, double>>(negative_a);
    std::cout << "x1 = " << x1 << ", x2 = " << x2 << "\n";  // x1 = 1, x2 = 3
}

// Working with LinearAlgebra and QuadraticEquation together
// Check if a value is a solution
auto solutions = imeth::QuadraticEquation::solve(1, -3, 2);
if (std::holds_alternative<std::pair<double, double>>(solutions)) {
    auto [x1, x2] = std::get<std::pair<double, double>>(solutions);
    // Verify: x² - 3x + 2 = 0 when x = x1
    double check = x1 * x1 - 3 * x1 + 2;
    std::cout << "Verification: " << check << "\n";  // ≈ 0
}

Mathematical Background

Linear Equations (1 variable)

  • Form: ax + b = 0
  • Solution: x = -b/a (when a ≠ 0)

System of Linear Equations (2 variables)

  • Uses elimination or substitution methods
  • Determines if system has unique solution, no solution, or infinite solutions

Quadratic Equations

  • Form: ax² + bx + c = 0
  • Discriminant: Δ = b² - 4ac
    • Δ > 0: Two distinct real roots
    • Δ = 0: One repeated root
    • Δ < 0: Two complex conjugate roots (no real solutions)
  • Quadratic formula: x = (-b ± √Δ) / 2a

Matrix

I genuinely don't know what matrix or vector is (besides them being a dynamic alternative for arrays in C++). I mean, what do you expect from a 9th grader? But, here the chapter matrix.hpp, exists...

#include <imeth/linear/matrix.hpp>

Classes

The matrix module contains three main classes:

  • Matrix - Represents a 2D matrix and provides matrix operations
  • Vector - Represents a mathematical vector (1D array of numbers)
  • Solver - Provides methods for solving systems of linear equations

Matrix

A 2D array of numbers that supports mathematical operations like addition, multiplication, and transposition.

Constructors

  • Matrix(size_t rows, size_t cols) - Creates a matrix with specified dimensions (initialized to zero)
  • Matrix(std::initializer_list<std::vector<double>> data) - Creates a matrix from a list of rows

Element Access

  • operator()(size_t r, size_t c) → double& - Accesses element at row r, column c (modifiable)
  • operator()(size_t r, size_t c) const → double - Accesses element at row r, column c (read-only)

Properties

  • rows() const → size_t - Returns the number of rows
  • cols() const → size_t - Returns the number of columns

Static Methods

  • identity(size_t n) → Matrix - Creates an n×n identity matrix (1s on diagonal, 0s elsewhere)

Operations

  • transpose() const → Matrix - Returns the transpose (rows ↔ columns)
  • operator*(const Matrix& rhs) const → Matrix - Matrix multiplication
  • operator+(const Matrix& rhs) const → Matrix - Matrix addition
  • operator-(const Matrix& rhs) const → Matrix - Matrix subtraction

Example Usage

#include <imeth/linear/matrix.hpp>
#include <iostream>

int main() {
    // Create a 2×3 matrix
    imeth::Matrix A = {
        {1, 2, 3},
        {4, 5, 6}
    };

    std::cout << "Matrix A is " << A.rows() << "×" << A.cols() << "\n";

    // Access elements
    std::cout << "A(0,0) = " << A(0, 0) << "\n";  // 1
    std::cout << "A(1,2) = " << A(1, 2) << "\n";  // 6

    // Modify element
    A(0, 0) = 10;

    // Transpose
    imeth::Matrix A_T = A.transpose();
    std::cout << "Transpose is " << A_T.rows() << "×" << A_T.cols() << "\n";  // 3×2

    // Create identity matrix
    imeth::Matrix I = imeth::Matrix::identity(3);
    // I = [[1, 0, 0],
    //      [0, 1, 0],
    //      [0, 0, 1]]

    return 0;
}

More Examples

// Matrix addition
imeth::Matrix A = {{1, 2}, {3, 4}};
imeth::Matrix B = {{5, 6}, {7, 8}};
imeth::Matrix C = A + B;  // {{6, 8}, {10, 12}}

// Matrix multiplication
imeth::Matrix D = {{1, 2}, {3, 4}};
imeth::Matrix E = {{2, 0}, {1, 2}};
imeth::Matrix F = D * E;  // {{4, 4}, {10, 8}}

// Matrix subtraction
imeth::Matrix G = B - A;  // {{4, 4}, {4, 4}}

Vector

A 1D array of numbers (essentially a column vector in mathematical terms).

Constructors

  • Vector(size_t n) - Creates a vector of size n (initialized to zero)
  • Vector(std::initializer_list<double> data) - Creates a vector from a list of values

Element Access

  • operator[](size_t i) → double& - Accesses element at index i (modifiable)
  • operator[](size_t i) const → double - Accesses element at index i (read-only)

Properties

  • size() const → size_t - Returns the number of elements

Example Usage

#include <imeth/linear/matrix.hpp>
#include <iostream>

int main() {
    // Create a vector
    imeth::Vector v = {1.0, 2.0, 3.0, 4.0};

    std::cout << "Vector size: " << v.size() << "\n";  // 4

    // Access elements
    std::cout << "v[0] = " << v[0] << "\n";  // 1.0
    std::cout << "v[2] = " << v[2] << "\n";  // 3.0

    // Modify element
    v[1] = 5.0;

    // Create empty vector and fill it
    imeth::Vector u(5);
    for (size_t i = 0; i < u.size(); ++i) {
        u[i] = i * 2.0;
    }

    return 0;
}

Solver

Provides numerical methods for solving systems of linear equations Ax = b, where A is a matrix, x is the unknown vector, and b is the result vector.

Methods

  • gaussian_elimination(const Matrix& A, const Vector& b) → Vector - Solves Ax = b using Gaussian elimination with back substitution
  • gauss_jordan(const Matrix& A, const Vector& b) → Vector - Solves Ax = b using Gauss-Jordan elimination (reduced row echelon form)
  • lu_decomposition(const Matrix& A, const Vector& b) → Vector - Solves Ax = b using LU decomposition (factors A = LU)

Example Usage

#include <imeth/linear/matrix.hpp>
#include <iostream>

int main() {
    // Solve the system:
    // 2x + 3y = 8
    // x - y = 1

    imeth::Matrix A = {
        {2, 3},
        {1, -1}
    };

    imeth::Vector b = {8, 1};

    // Method 1: Gaussian elimination
    imeth::Vector x1 = imeth::Solver::gaussian_elimination(A, b);
    std::cout << "Solution (Gaussian): x = " << x1[0] << ", y = " << x1[1] << "\n";

    // Method 2: Gauss-Jordan
    imeth::Vector x2 = imeth::Solver::gauss_jordan(A, b);
    std::cout << "Solution (Gauss-Jordan): x = " << x2[0] << ", y = " << x2[1] << "\n";

    // Method 3: LU decomposition
    imeth::Vector x3 = imeth::Solver::lu_decomposition(A, b);
    std::cout << "Solution (LU): x = " << x3[0] << ", y = " << x3[1] << "\n";

    return 0;
}

More Examples

// Solve a 3×3 system:
// x + 2y + z = 6
// 2x + y + z = 6
// x + y + 2z = 7

imeth::Matrix A = {
    {1, 2, 1},
    {2, 1, 1},
    {1, 1, 2}
};

imeth::Vector b = {6, 6, 7};

imeth::Vector solution = imeth::Solver::gaussian_elimination(A, b);

std::cout << "x = " << solution[0] << "\n";  // x = 1
std::cout << "y = " << solution[1] << "\n";  // y = 2
std::cout << "z = " << solution[2] << "\n";  // z = 2

// Verify solution: A * x = b
for (size_t i = 0; i < A.rows(); ++i) {
    double result = 0;
    for (size_t j = 0; j < A.cols(); ++j) {
        result += A(i, j) * solution[j];
    }
    std::cout << "Row " << i << " check: " << result << " = " << b[i] << "\n";
}

Mathematical Background

Matrix - A rectangular array of numbers arranged in rows and columns. Matrices are used to represent linear transformations and systems of equations.

Vector - A one-dimensional array of numbers. In this context, it represents either the coefficients on the right side of equations (vector b) or the solution values (vector x).

System of Linear Equations - Multiple equations like:

a₁₁x₁ + a₁₂x₂ + ... = b₁
a₂₁x₁ + a₂₂x₂ + ... = b₂
...

Solving Methods:

  • Gaussian Elimination - Transforms the system to upper triangular form, then uses back substitution
  • Gauss-Jordan - Reduces the matrix to reduced row echelon form (identity matrix)
  • LU Decomposition - Factors matrix A into lower (L) and upper (U) triangular matrices

Geometry Category

The geometry category contains geometric shape calculations for 2D and 3D shapes.

Chapters

  • 2D Shapes - Compilation of 2D shapes utilities
  • 3D Shapes - Compilation of 3D shapes utilities

Usage

#include <imeth/geometry/2D.hpp>
#include <imeth/geometry/3D.hpp>

2D Shapes

The Shape2D classes provide an easy way to calculate areas and perimeters of common 2D shapes (flat shapes).

Overview

All 2D shapes inherit from the Shape2D base class and provide two main methods:

  • area() - Calculate the area (space inside the shape)
  • perimeter() - Calculate the perimeter (distance around the shape)

Include

#include <imeth/shape/2D.hpp>

Base Class

class Shape2D {
public:
    virtual double area() const = 0;
    virtual double perimeter() const = 0;
};

Available Shapes

Circle

A round shape with all points equally distant from the center.

Circle(double radius);

Methods:

  • area() - Returns πr²
  • perimeter() - Returns 2πr (also called circumference)

Examples:

Circle circle(5.0);
std::cout << "Area: " << circle.area() << "\n";           // 78.54
std::cout << "Perimeter: " << circle.perimeter() << "\n"; // 31.42

// Pizza with 12 inch diameter (radius = 6)
Circle pizza(6);
std::cout << "Pizza area: " << pizza.area() << " sq in\n"; // 113.1 sq in

Formula:

  • Area = π × r²
  • Perimeter = 2 × π × r

Rectangle

A four-sided shape with opposite sides equal and all angles 90°.

Rectangle(double width, double height);

Methods:

  • area() - Returns width × height
  • perimeter() - Returns 2(width + height)

Examples:

Rectangle rect(10, 5);
std::cout << "Area: " << rect.area() << "\n";           // 50
std::cout << "Perimeter: " << rect.perimeter() << "\n"; // 30

// Phone screen: 6 inches by 3 inches
Rectangle screen(6, 3);
std::cout << "Screen area: " << screen.area() << " sq in\n"; // 18 sq in

Formula:

  • Area = width × height
  • Perimeter = 2 × (width + height)

Square

A special rectangle where all four sides are equal.

Square(double side);

Methods:

  • area() - Returns side²
  • perimeter() - Returns 4 × side

Examples:

Square square(4);
std::cout << "Area: " << square.area() << "\n";           // 16
std::cout << "Perimeter: " << square.perimeter() << "\n"; // 16

// Chess board square (each square is 2 inches)
Square chessSquare(2);
std::cout << "Square area: " << chessSquare.area() << " sq in\n"; // 4 sq in

Formula:

  • Area = side²
  • Perimeter = 4 × side

Triangle

A three-sided shape. This implementation uses base and height (for right triangles or when height is known).

Triangle(double base, double height);

Methods:

  • area() - Returns ½ × base × height
  • perimeter() - Returns base + side1 + side2 (calculated)

Examples:

Triangle triangle(6, 4);
std::cout << "Area: " << triangle.area() << "\n";           // 12
std::cout << "Perimeter: " << triangle.perimeter() << "\n";

// Triangular warning sign
Triangle sign(10, 8.66);
std::cout << "Sign area: " << sign.area() << " sq in\n"; // 43.3 sq in

Formula:

  • Area = ½ × base × height

Pentagon

A five-sided regular polygon (all sides and angles equal).

Pentagon(double side);

Methods:

  • area() - Returns ¼√(25 + 10√5) × side²
  • perimeter() - Returns 5 × side

Examples:

Pentagon pentagon(5);
std::cout << "Area: " << pentagon.area() << "\n";           // 43.01
std::cout << "Perimeter: " << pentagon.perimeter() << "\n"; // 25

// The Pentagon building (simplified, each side ≈ 921 feet)
Pentagon building(921);
std::cout << "Perimeter: " << building.perimeter() << " feet\n"; // 4605 feet

Formula:

  • Area ≈ 1.72048 × side²
  • Perimeter = 5 × side

Hexagon

A six-sided regular polygon (like a honeycomb cell).

Hexagon(double side);

Methods:

  • area() - Returns (3√3/2) × side²
  • perimeter() - Returns 6 × side

Examples:

Hexagon hexagon(4);
std::cout << "Area: " << hexagon.area() << "\n";           // 41.57
std::cout << "Perimeter: " << hexagon.perimeter() << "\n"; // 24

// Honeycomb cell (each side ≈ 2.5mm)
Hexagon honeycomb(2.5);
std::cout << "Cell area: " << honeycomb.area() << " sq mm\n"; // 16.24 sq mm

Formula:

  • Area ≈ 2.598 × side²
  • Perimeter = 6 × side

Fun fact: Hexagons are the most efficient shape for covering an area (that's why bees use them!)


Octagon

An eight-sided regular polygon (like a stop sign).

Octagon(double side);

Methods:

  • area() - Returns 2(1 + √2) × side²
  • perimeter() - Returns 8 × side

Examples:

Octagon octagon(3);
std::cout << "Area: " << octagon.area() << "\n";           // 43.46
std::cout << "Perimeter: " << octagon.perimeter() << "\n"; // 24

// Stop sign (each side ≈ 12 inches)
Octagon stopSign(12);
std::cout << "Sign area: " << stopSign.area() << " sq in\n"; // 695.3 sq in

Formula:

  • Area ≈ 4.828 × side²
  • Perimeter = 8 × side

Polymorphism Example

Since all shapes inherit from Shape2D, you can use them polymorphically:

#include <vector>
#include <memory>

std::vector<std::unique_ptr<Shape2D>> shapes;

shapes.push_back(std::make_unique<Circle>(5));
shapes.push_back(std::make_unique<Square>(4));
shapes.push_back(std::make_unique<Hexagon>(3));

for (const auto& shape : shapes) {
    std::cout << "Area: " << shape->area()
              << ", Perimeter: " << shape->perimeter() << "\n";
}

Comparison Example

Compare different shapes:

Circle circle(5);
Square square(5);

std::cout << "Circle area: " << circle.area() << "\n";     // 78.54
std::cout << "Square area: " << square.area() << "\n";     // 25

// Which has more area?
if (circle.area() > square.area()) {
    std::cout << "Circle has more area!\n";
}

Real-World Applications

1. Calculate Paint Needed

Rectangle wall(10, 8);  // 10 feet wide, 8 feet tall
double paintPerSquareFoot = 0.02;  // gallons per sq ft
double paintNeeded = wall.area() * paintPerSquareFoot;
std::cout << "Paint needed: " << paintNeeded << " gallons\n";

2. Fencing a Garden

Rectangle garden(15, 20);  // 15m × 20m
double fenceCostPerMeter = 25;  // $25 per meter
double totalCost = garden.perimeter() * fenceCostPerMeter;
std::cout << "Fencing cost: $" << totalCost << "\n";  // $1750

3. Pizza Size Comparison

Circle smallPizza(6);   // 6 inch radius
Circle largePizza(9);   // 9 inch radius

double smallArea = smallPizza.area();
double largeArea = largePizza.area();

std::cout << "Small pizza: " << smallArea << " sq in\n";
std::cout << "Large pizza: " << largeArea << " sq in\n";
std::cout << "Large is " << (largeArea / smallArea) << "x bigger!\n";

4. Sports Field

Rectangle soccerField(100, 60);  // 100m × 60m
std::cout << "Field area: " << soccerField.area() << " sq m\n";       // 6000
std::cout << "Running track: " << soccerField.perimeter() << " m\n";  // 320

Circle centerCircle(9.15);  // Center circle radius
std::cout << "Center circle area: " << centerCircle.area() << " sq m\n";

Quick Reference Table

ShapeSidesArea FormulaPerimeter Formula
Circle-πr²2πr
Square44s
Rectangle4w×h2(w+h)
Triangle3½bha+b+c
Pentagon5~1.72s²5s
Hexagon6~2.598s²6s
Octagon8~4.828s²8s

Tips

  • Use circles for round objects (pizza, wheels, clocks)
  • Use rectangles for most everyday objects (rooms, screens, books)
  • Use squares when all sides are equal
  • Regular polygons (pentagon, hexagon, octagon) have all sides and angles equal
  • The more sides a regular polygon has, the more it looks like a circle!

Common Units

  • Area units: square meters (m²), square feet (ft²), square inches (in²)
  • Perimeter units: meters (m), feet (ft), inches (in)

3D Shapes

The Shape3D classes provide an easy way to calculate surface areas and volumes of common 3D shapes (solid objects).

Overview

All 3D shapes inherit from the Shape3D base class and provide two main methods:

  • area() - Calculate the surface area (total area of all outer surfaces)
  • volume() - Calculate the volume (space inside the shape)

Include

#include <imeth/shape/3D.hpp>

Base Class

class Shape3D {
public:
    virtual double area() const = 0;
    virtual double volume() const = 0;
};

Available Shapes

Sphere

A perfectly round 3D object (like a ball or globe).

Sphere(double radius);

Methods:

  • area() - Returns 4πr² (surface area)
  • volume() - Returns (4/3)πr³

Examples:

Sphere sphere(5.0);
std::cout << "Surface area: " << sphere.area() << "\n";   // 314.16
std::cout << "Volume: " << sphere.volume() << "\n";       // 523.6

// Basketball (radius ≈ 12 cm)
Sphere basketball(12);
std::cout << "Surface area: " << basketball.area() << " sq cm\n"; // 1809.6
std::cout << "Volume: " << basketball.volume() << " cu cm\n";     // 7238.2

Formulas:

  • Surface Area = 4 × π × r²
  • Volume = (4/3) × π × r³

Real-world: Balls, planets, bubbles, oranges


Cube

A 3D square - all sides, edges, and angles are equal.

Cube(double side);

Methods:

  • area() - Returns 6 × side² (6 square faces)
  • volume() - Returns side³

Examples:

Cube cube(4);
std::cout << "Surface area: " << cube.area() << "\n";     // 96
std::cout << "Volume: " << cube.volume() << "\n";         // 64

// Rubik's Cube (side ≈ 5.7 cm)
Cube rubiksCube(5.7);
std::cout << "Surface area: " << rubiksCube.area() << " sq cm\n"; // 194.94
std::cout << "Volume: " << rubiksCube.volume() << " cu cm\n";     // 185.19

Formulas:

  • Surface Area = 6 × side²
  • Volume = side³

Real-world: Dice, boxes, Minecraft blocks, ice cubes


Cylinder

A tube shape with circular ends (like a can or pipe).

Cylinder(double radius, double height);

Methods:

  • area() - Returns 2πr² + 2πrh (top + bottom + side)
  • volume() - Returns πr²h

Examples:

Cylinder cylinder(3, 10);
std::cout << "Surface area: " << cylinder.area() << "\n";   // 245.04
std::cout << "Volume: " << cylinder.volume() << "\n";       // 282.74

// Soda can (radius ≈ 3 cm, height ≈ 12 cm)
Cylinder sodaCan(3, 12);
std::cout << "Can surface: " << sodaCan.area() << " sq cm\n";    // 282.74
std::cout << "Can volume: " << sodaCan.volume() << " cu cm\n";   // 339.29
std::cout << "That's " << sodaCan.volume() / 1000 << " liters\n"; // 0.339 L

Formulas:

  • Surface Area = 2πr² + 2πrh = 2πr(r + h)
  • Volume = π × r² × h

Real-world: Cans, pipes, drums, tree trunks, water tanks


Cone

A shape with a circular base that tapers to a point (like an ice cream cone).

Cone(double radius, double height);

Methods:

  • area() - Returns πr² + πr√(h² + r²) (base + curved surface)
  • volume() - Returns (1/3)πr²h

Examples:

Cone cone(4, 9);
std::cout << "Surface area: " << cone.area() << "\n";     // 175.93
std::cout << "Volume: " << cone.volume() << "\n";         // 150.8

// Ice cream cone (radius ≈ 3 cm, height ≈ 10 cm)
Cone iceCream(3, 10);
std::cout << "Cone surface: " << iceCream.area() << " sq cm\n";  // 125.66
std::cout << "Cone volume: " << iceCream.volume() << " cu cm\n"; // 94.25

Formulas:

  • Surface Area = πr² + πr√(h² + r²)
    • Base area: πr²
    • Slant area: πr√(h² + r²)
  • Volume = (1/3) × π × r² × h

Fun fact: A cone's volume is exactly 1/3 of a cylinder with the same base and height!

Real-world: Ice cream cones, traffic cones, party hats, funnels


Torus

A donut shape (a tube bent into a circle).

Torus(double major_radius, double minor_radius);

Parameters:

  • major_radius - Distance from center of torus to center of tube
  • minor_radius - Radius of the tube itself

Methods:

  • area() - Returns 4π²Rr (surface area)
  • volume() - Returns 2π²Rr²

Examples:

Torus torus(10, 3);  // Big radius 10, tube radius 3
std::cout << "Surface area: " << torus.area() << "\n";    // 1184.4
std::cout << "Volume: " << torus.volume() << "\n";        // 1776.6

// Swimming tube (major ≈ 40 cm, minor ≈ 10 cm)
Torus swimmingTube(40, 10);
std::cout << "Tube surface: " << swimmingTube.area() << " sq cm\n";  // 15791.4
std::cout << "Tube volume: " << swimmingTube.volume() << " cu cm\n"; // 78957.1

Formulas:

  • Surface Area = 4π² × R × r
  • Volume = 2π² × R × r²

Where:

  • R = major radius (big circle)
  • r = minor radius (tube)

Real-world: Donuts, swimming tubes, O-rings, bagels, hula hoops


Polymorphism Example

Since all shapes inherit from Shape3D, you can use them polymorphically:

#include <vector>
#include <memory>

std::vector<std::unique_ptr<Shape3D>> shapes;

shapes.push_back(std::make_unique<Sphere>(5));
shapes.push_back(std::make_unique<Cube>(4));
shapes.push_back(std::make_unique<Cylinder>(3, 10));

for (const auto& shape : shapes) {
    std::cout << "Surface area: " << shape->area()
              << ", Volume: " << shape->volume() << "\n";
}

Volume Comparisons

Sphere vs Cube

Sphere sphere(5);
Cube cube(5);

std::cout << "Sphere volume: " << sphere.volume() << "\n";  // 523.6
std::cout << "Cube volume: " << cube.volume() << "\n";      // 125

// A sphere with radius = cube side has ~4.2x more volume!

Cylinder vs Cone

Cylinder cylinder(4, 9);
Cone cone(4, 9);  // Same base and height

std::cout << "Cylinder volume: " << cylinder.volume() << "\n"; // 452.39
std::cout << "Cone volume: " << cone.volume() << "\n";         // 150.8

// Cone is exactly 1/3 of cylinder volume!
std::cout << "Ratio: " << cylinder.volume() / cone.volume() << "\n"; // 3.0

Real-World Applications

1. Water Tank Capacity

Cylinder waterTank(1.5, 3);  // 1.5m radius, 3m height
double liters = waterTank.volume() * 1000;  // 1 m³ = 1000 liters
std::cout << "Tank holds " << liters << " liters\n";  // 21,205 liters

2. Paint for a Sphere

Sphere globe(0.5);  // 0.5m radius globe
double paintPerSqM = 0.1;  // liters per square meter
double paintNeeded = globe.area() * paintPerSqM;
std::cout << "Paint needed: " << paintNeeded << " liters\n";

3. Gift Box Volume

Cube giftBox(20);  // 20cm × 20cm × 20cm
double volumeCm3 = giftBox.volume();  // 8000 cm³
double volumeLiters = volumeCm3 / 1000;
std::cout << "Box can hold " << volumeLiters << " liters\n";  // 8 liters

4. Ice Cream Cone vs Scoop

Cone cone(3, 10);           // Cone: radius 3cm, height 10cm
Sphere scoop(3);            // Scoop: radius 3cm

std::cout << "Cone volume: " << cone.volume() << " cu cm\n";   // 94.25
std::cout << "Scoop volume: " << scoop.volume() << " cu cm\n"; // 113.1

// The scoop has more ice cream than the cone can hold!
if (scoop.volume() > cone.volume()) {
    std::cout << "Better order a bigger cone!\n";
}

5. Swimming Pool

Cylinder pool(5, 1.5);  // 5m radius, 1.5m deep
double volume = pool.volume();
double liters = volume * 1000;

std::cout << "Pool volume: " << volume << " cubic meters\n";
std::cout << "That's " << liters << " liters of water!\n";
std::cout << "Or " << liters * 0.264172 << " gallons\n";

Quick Reference Table

ShapeArea FormulaVolume FormulaExample
Sphere4πr²(4/3)πr³Ball, planet
Cube6s²Dice, box
Cylinder2πr(r+h)πr²hCan, pipe
Coneπr² + πrs(1/3)πr²hIce cream cone
Torus4π²Rr2π²Rr²Donut, tube

Where:

  • r = radius
  • s = side
  • h = height
  • R = major radius (for torus)

Volume Relationships

Interesting Facts:

  • A cone's volume = 1/3 of a cylinder (same base & height)
  • A sphere's volume = 2/3 of a cylinder (if cylinder has radius r and height 2r)
  • A cube with side s has less volume than a sphere with radius s

Common Volume Units

  • Metric: cubic meters (m³), cubic centimeters (cm³), liters (L)
    • 1 m³ = 1,000 liters
    • 1 liter = 1,000 cm³
  • Imperial: cubic feet (ft³), cubic inches (in³), gallons (gal)
    • 1 gallon ≈ 3,785 cm³

Tips

  • Surface area is measured in square units (m², cm²)
  • Volume is measured in cubic units (m³, cm³)
  • Use Cylinder for most containers (cans, tanks, tubes)
  • Use Sphere for balls and planets
  • Use Cube for perfect boxes and dice
  • Torus is rare but fun for donuts and swimming tubes!
  • Remember: Volume tells you how much fits inside, surface area tells you how much material you need to cover it

Base Category

The base category contains base conversions and operations for working with different number bases.

Chapters

  • Base - Comprehensive base conversions and operations utilities.
  • Binary - Binary conversions and operations utilities.
  • Hexadecimal - Hexadecimal conversions and operations utilities.
  • Octal - Octal conversions and operations utilities.

Usage

#include <imeth/base/base.hpp>
#include <imeth/base/binary.hpp>
#include <imeth/base/hexadecimal.hpp>
#include <imeth/base/octal.hpp>

Binary

The Binary class provides specialized functions for working with binary numbers (base 2), including bitwise operations that are essential in computer science.

Overview

Binary is the foundation of computer systems. Every number in a computer is stored as binary (0s and 1s). This class helps you understand and work with binary numbers directly.

Include

#include <imeth/base/binary.hpp>

Conversion Functions

FROM Decimal TO Binary

static std::string fromDecimal(int decimal);

Examples:

Binary::fromDecimal(10);     // "1010"
Binary::fromDecimal(42);     // "101010"
Binary::fromDecimal(255);    // "11111111"
Binary::fromDecimal(0);      // "0"
Binary::fromDecimal(-5);     // "-101"

FROM Binary TO Decimal

static int toDecimal(const std::string& binary);

Examples:

Binary::toDecimal("1010");      // 10
Binary::toDecimal("101010");    // 42
Binary::toDecimal("11111111");  // 255
Binary::toDecimal("-101");      // -5

Arithmetic Operations

static std::string add(const std::string& a, const std::string& b);
static std::string subtract(const std::string& a, const std::string& b);
static std::string multiply(const std::string& a, const std::string& b);

Perform basic math directly in binary.

Examples:

Binary::add("1010", "101");         // "1111" (10 + 5 = 15)
Binary::subtract("1100", "101");    // "111" (12 - 5 = 7)
Binary::multiply("101", "11");      // "1111" (5 × 3 = 15)

Bitwise Operations

These operations work at the bit level and are fundamental to computer programming.

AND Operation

static std::string bitwiseAND(const std::string& a, const std::string& b);

Returns 1 only when both bits are 1.

Examples:

Binary::bitwiseAND("1100", "1010");  // "1000"
//  1100
// &1010
// -----
//  1000

OR Operation

static std::string bitwiseOR(const std::string& a, const std::string& b);

Returns 1 when at least one bit is 1.

Examples:

Binary::bitwiseOR("1100", "1010");   // "1110"
//  1100
// |1010
// -----
//  1110

XOR Operation

static std::string bitwiseXOR(const std::string& a, const std::string& b);

Returns 1 only when bits are different.

Examples:

Binary::bitwiseXOR("1100", "1010");  // "110"
//  1100
// ^1010
// -----
//  0110

NOT Operation

static std::string bitwiseNOT(const std::string& binary);

Flips all bits (0→1, 1→0).

Examples:

Binary::bitwiseNOT("1010");  // "0101"
Binary::bitwiseNOT("1111");  // "0000"

Bit Shifting

static std::string leftShift(const std::string& binary, int positions);
static std::string rightShift(const std::string& binary, int positions);

Shift bits left or right. Left shift multiplies by 2, right shift divides by 2.

Examples:

Binary::leftShift("101", 2);   // "10100" (5 << 2 = 20)
Binary::rightShift("1100", 2); // "11" (12 >> 2 = 3)

Utility Functions

Validation

static bool isValid(const std::string& binary);

Check if a string contains only valid binary digits (0 and 1).

Examples:

Binary::isValid("1010");   // true
Binary::isValid("1012");   // false (contains '2')
Binary::isValid("abc");    // false

Padding

static std::string padLeft(const std::string& binary, size_t length);

Add zeros to the left to reach a specific length.

Examples:

Binary::padLeft("101", 8);     // "00000101"
Binary::padLeft("1111", 8);    // "00001111"
Binary::padLeft("10101010", 4);// "10101010" (already longer)

Counting Bits

static int countOnes(const std::string& binary);
static int countZeros(const std::string& binary);

Count the number of 1s or 0s in a binary number.

Examples:

Binary::countOnes("1010");    // 2
Binary::countZeros("1010");   // 2
Binary::countOnes("1111");    // 4
Binary::countZeros("0000");   // 4

Real-World Examples

Converting Your Age to Binary

int age = 15;
std::string binaryAge = Binary::fromDecimal(age);  // "1111"
std::cout << "I'm " << binaryAge << " years old in binary!\n";

Checking if a Number is Even

std::string num = Binary::fromDecimal(42);  // "101010"
// If last bit is 0, the number is even
bool isEven = (num.back() == '0');  // true

Simple Encryption with XOR

std::string message = "1010";
std::string key = "1100";
std::string encrypted = Binary::bitwiseXOR(message, key);  // "0110"
std::string decrypted = Binary::bitwiseXOR(encrypted, key);// "1010" (back to original!)

Creating Bit Masks

// Create a mask with 4 ones
std::string mask = Binary::fromDecimal(15);  // "1111"

// Use AND to extract bits
std::string data = "10110101";
std::string result = Binary::bitwiseAND(data, Binary::padLeft(mask, 8));
// Gets the last 4 bits: "0101"

Understanding Binary

  • Each digit is called a "bit"
  • 8 bits make a "byte"
  • Right to left: Each position is worth 2^n (1, 2, 4, 8, 16, 32, ...)

Example: 1011 = (1×8) + (0×4) + (1×2) + (1×1) = 8 + 0 + 2 + 1 = 11

Tips

  • Use padLeft() to make binary numbers the same length before comparing
  • Bitwise operations are much faster than regular math in computers
  • Left shift by n is the same as multiplying by 2^n
  • Right shift by n is the same as dividing by 2^n (rounded down)

Hexadecimal

The Hexadecimal class provides functions for working with hexadecimal numbers (base 16). Hex is widely used in computing for colors, memory addresses, and more.

Overview

Hexadecimal (hex) uses 16 digits: 0-9 and A-F (where A=10, B=11, C=12, D=13, E=14, F=15). It's popular because each hex digit represents exactly 4 binary digits (bits).

Include

#include <imeth/base/hexadecimal.hpp>

Conversion Functions

FROM Decimal TO Hexadecimal

static std::string fromDecimal(int decimal);

Examples:

Hexadecimal::fromDecimal(10);      // "A"
Hexadecimal::fromDecimal(15);      // "F"
Hexadecimal::fromDecimal(16);      // "10"
Hexadecimal::fromDecimal(255);     // "FF"
Hexadecimal::fromDecimal(42);      // "2A"
Hexadecimal::fromDecimal(4096);    // "1000"
Hexadecimal::fromDecimal(-10);     // "-A"

FROM Hexadecimal TO Decimal

static int toDecimal(const std::string& hex);

Examples:

Hexadecimal::toDecimal("A");       // 10
Hexadecimal::toDecimal("F");       // 15
Hexadecimal::toDecimal("10");      // 16
Hexadecimal::toDecimal("FF");      // 255
Hexadecimal::toDecimal("2A");      // 42
Hexadecimal::toDecimal("1000");    // 4096
Hexadecimal::toDecimal("ff");      // 255 (case insensitive)

Arithmetic Operations

static std::string add(const std::string& a, const std::string& b);
static std::string subtract(const std::string& a, const std::string& b);
static std::string multiply(const std::string& a, const std::string& b);

Perform basic math directly in hexadecimal.

Examples:

Hexadecimal::add("A", "5");          // "F" (10 + 5 = 15)
Hexadecimal::add("FF", "1");         // "100" (255 + 1 = 256)
Hexadecimal::subtract("20", "A");    // "16" (32 - 10 = 22)
Hexadecimal::multiply("10", "10");   // "100" (16 × 16 = 256)

Utility Functions

Validation

static bool isValid(const std::string& hex);

Check if a string contains only valid hexadecimal digits (0-9, A-F).

Examples:

Hexadecimal::isValid("1234");      // true
Hexadecimal::isValid("ABCDEF");    // true
Hexadecimal::isValid("FF00");      // true
Hexadecimal::isValid("GHI");       // false (G, H, I are not hex digits)
Hexadecimal::isValid("ff");        // true (case insensitive)

Case Conversion

static std::string toUpperCase(const std::string& hex);
static std::string toLowerCase(const std::string& hex);

Convert hex strings between upper and lowercase.

Examples:

Hexadecimal::toUpperCase("2a");    // "2A"
Hexadecimal::toUpperCase("ff");    // "FF"
Hexadecimal::toLowerCase("2A");    // "2a"
Hexadecimal::toLowerCase("FF");    // "ff"

Padding

static std::string padLeft(const std::string& hex, size_t length);

Add zeros to the left to reach a specific length.

Examples:

Hexadecimal::padLeft("FF", 4);     // "00FF"
Hexadecimal::padLeft("A", 2);      // "0A"
Hexadecimal::padLeft("1234", 3);   // "1234" (already longer)

Real-World Examples

RGB Colors

Colors on screens are often represented in hex!

// RGB color: Red=255, Green=128, Blue=64
std::string red = Hexadecimal::fromDecimal(255);    // "FF"
std::string green = Hexadecimal::fromDecimal(128);  // "80"
std::string blue = Hexadecimal::fromDecimal(64);    // "40"

std::string color = red + green + blue;  // "FF8040"
std::cout << "Color code: #" << color << "\n";  // #FF8040

Converting Hex Color Codes

// Parse color #A1B2C3
std::string hexColor = "A1B2C3";

int red = Hexadecimal::toDecimal(hexColor.substr(0, 2));    // 161
int green = Hexadecimal::toDecimal(hexColor.substr(2, 2));  // 178
int blue = Hexadecimal::toDecimal(hexColor.substr(4, 2));   // 195

std::cout << "RGB(" << red << ", " << green << ", " << blue << ")\n";

Memory Addresses

Computer memory addresses are shown in hex:

// A typical memory address
std::string address = "7FFF5C";
int decimal = Hexadecimal::toDecimal(address);  // 8388444
std::cout << "Memory location: 0x" << address << "\n";

Binary to Hex Conversion

Since 4 binary digits = 1 hex digit, hex is a compact way to write binary:

Binary:  1111 1010 0101
Hex:       F    A    5
// If you have binary "111110100101"
// Group into 4s: 1111 1010 0101
// Each group: F, A, 5
// Result: FA5 in hex

int decimal = Binary::toDecimal("111110100101");  // 4005
std::string hex = Hexadecimal::fromDecimal(decimal);  // "FA5"

Common Hex Values

// Powers of 16
Hexadecimal::fromDecimal(16);      // "10"
Hexadecimal::fromDecimal(256);     // "100"
Hexadecimal::fromDecimal(4096);    // "1000"

// Max values
Hexadecimal::fromDecimal(255);     // "FF" (max 8-bit value)
Hexadecimal::fromDecimal(65535);   // "FFFF" (max 16-bit value)

Understanding Hexadecimal

  • 16 digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
  • A through F: A=10, B=11, C=12, D=13, E=14, F=15
  • Right to left: Each position is worth 16^n (1, 16, 256, 4096, ...)

Example: 2A in hex = (2×16) + (10×1) = 32 + 10 = 42 in decimal

Why Use Hexadecimal?

  1. Compact Binary: 4 binary digits = 1 hex digit
  2. Colors: Web colors use hex (#FF0000 = red)
  3. Memory: Addresses and data dumps
  4. File Formats: Image files, network packets
  5. Easier to Read: Than long binary strings

Hex Counting

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12, ..., 1F, 20, ...
// Count from 0 to 20 in hex
for (int i = 0; i <= 20; ++i) {
    std::cout << i << " = " << Hexadecimal::fromDecimal(i) << " (hex)\n";
}
// Output includes:
// 10 = A (hex)
// 15 = F (hex)
// 16 = 10 (hex)
// 20 = 14 (hex)

Hex Addition Example

  2A
+ 1F
----
  49

How it works:

  • A + F = 10 + 15 = 25 (decimal) = 19 (hex), write 9, carry 1
  • 2 + 1 + 1 (carry) = 4
  • Result: 49 (hex) = 73 (decimal)
Hexadecimal::add("2A", "1F");  // "49"

Tips

  • Both uppercase and lowercase work: "FF" and "ff" are the same
  • Use padLeft() to format numbers: padLeft("A", 2) gives "0A"
  • Hex is everywhere in web development (colors!)
  • In C++, you can write hex literals with 0x: int x = 0x2A; (equals 42)
  • Two hex digits = one byte (8 bits)

Common Hex Patterns

// All F's are special
Hexadecimal::toDecimal("F");       // 15 (max 4 bits)
Hexadecimal::toDecimal("FF");      // 255 (max 8 bits / 1 byte)
Hexadecimal::toDecimal("FFF");     // 4095 (max 12 bits)
Hexadecimal::toDecimal("FFFF");    // 65535 (max 16 bits / 2 bytes)

Octal

The Octal class provides functions for working with octal numbers (base 8). Octal is commonly used in computing, especially in Unix/Linux file permissions.

Overview

Octal uses digits 0-7. It's a convenient way to represent binary numbers because each octal digit represents exactly 3 binary digits (bits). For example, octal 7 = binary 111.

Include

#include <imeth/base/octal.hpp>

Conversion Functions

FROM Decimal TO Octal

static std::string fromDecimal(int decimal);

Examples:

Octal::fromDecimal(8);       // "10"
Octal::fromDecimal(64);      // "100"
Octal::fromDecimal(42);      // "52"
Octal::fromDecimal(255);     // "377"
Octal::fromDecimal(0);       // "0"
Octal::fromDecimal(-10);     // "-12"

FROM Octal TO Decimal

static int toDecimal(const std::string& octal);

Examples:

Octal::toDecimal("10");      // 8
Octal::toDecimal("100");     // 64
Octal::toDecimal("52");      // 42
Octal::toDecimal("377");     // 255
Octal::toDecimal("-12");     // -10

Arithmetic Operations

static std::string add(const std::string& a, const std::string& b);
static std::string subtract(const std::string& a, const std::string& b);
static std::string multiply(const std::string& a, const std::string& b);

Perform basic math directly in octal.

Examples:

Octal::add("12", "5");           // "17" (10 + 5 = 15 in decimal)
Octal::subtract("20", "7");      // "11" (16 - 7 = 9 in decimal)
Octal::multiply("7", "7");       // "61" (7 × 7 = 49 in decimal)
Octal::add("77", "1");           // "100" (63 + 1 = 64 in decimal)

Utility Functions

Validation

static bool isValid(const std::string& octal);

Check if a string contains only valid octal digits (0-7).

Examples:

Octal::isValid("1234567");   // true
Octal::isValid("123");       // true
Octal::isValid("789");       // false (8 and 9 are not octal digits)
Octal::isValid("abc");       // false

Padding

static std::string padLeft(const std::string& octal, size_t length);

Add zeros to the left to reach a specific length.

Examples:

Octal::padLeft("12", 4);     // "0012"
Octal::padLeft("777", 4);    // "0777"
Octal::padLeft("1234", 3);   // "1234" (already longer)

Real-World Examples

Unix/Linux File Permissions

File permissions in Unix/Linux are often shown in octal!

// rwxr-xr-x = 755 in octal
// rwx = 111 (binary) = 7 (octal) - owner can read, write, execute
// r-x = 101 (binary) = 5 (octal) - group can read and execute
// r-x = 101 (binary) = 5 (octal) - others can read and execute

std::string permissions = "755";
int decimal = Octal::toDecimal(permissions);  // 493
std::cout << "Decimal value: " << decimal << "\n";

Binary to Octal Conversion

Since 3 binary digits = 1 octal digit, octal is a compact way to write binary:

Binary:  111 101 010
Octal:    7   5   2
// If you have binary "111101010"
// Group into 3s: 111 101 010
// Each group: 7, 5, 2
// Result: 752 in octal

int decimal = Binary::toDecimal("111101010");  // 490
std::string octal = Octal::fromDecimal(decimal);  // "752"

Counting in Octal

// Octal counting: 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, ..., 17, 20
for (int i = 0; i <= 20; ++i) {
    std::cout << i << " = " << Octal::fromDecimal(i) << " (octal)\n";
}
// Output:
// 0 = 0 (octal)
// 1 = 1 (octal)
// ...
// 7 = 7 (octal)
// 8 = 10 (octal)
// 9 = 11 (octal)
// ...

Understanding Octal

  • Each digit can be 0-7 (no 8 or 9!)
  • Right to left: Each position is worth 8^n (1, 8, 64, 512, ...)

Example: 52 in octal = (5×8) + (2×1) = 40 + 2 = 42 in decimal

Why Use Octal?

  1. Compact Binary: 3 binary digits = 1 octal digit
  2. File Permissions: Standard in Unix/Linux systems
  3. Historical: Used in older computer systems
  4. Easier to Read: Than long binary strings

Octal Addition Example

  47
+ 35
----
 104

How it works:

  • 7 + 5 = 12 (decimal) = 14 (octal), write 4, carry 1
  • 4 + 3 + 1 (carry) = 8 (decimal) = 10 (octal), write 0, carry 1
  • Result: 104 (octal)
Octal::add("47", "35");  // "104"

Tips

  • Remember: digits only go up to 7!
  • When you see "10" in octal, it means 8 in decimal
  • Octal is great for grouping binary numbers
  • In C++, you can write octal literals with a leading 0: int x = 052; (equals 42 in decimal)