From 70e80327ef5d9c654c9577ab0c1fcacc0f83db06 Mon Sep 17 00:00:00 2001 From: Michelle Date: Thu, 30 Jul 2026 18:56:27 +0200 Subject: [PATCH] Activation Softmax Forward done --- include/config/omp.hpp | 32 + include/math/div.hpp | 306 +++++++++ include/math/sub.hpp | 286 ++++++++ include/math/sum.hpp | 158 +++++ ...ctivation_ReLU.hpp => activation_relu.hpp} | 8 +- .../activation/activation_softmax.hpp | 94 +++ include/neural_network/model/model.hpp | 20 +- main.cpp | 23 +- src/math/div.cpp | 625 ++++++++++++++++++ src/math/max.cpp | 4 +- src/math/sub.cpp | 582 ++++++++++++++++ src/math/sum.cpp | 327 +++++++++ ...ctivation_ReLU.cpp => activation_relu.cpp} | 31 +- .../activation/activation_softmax.cpp | 144 ++++ src/neural_network/model/model.cpp | 40 +- 15 files changed, 2637 insertions(+), 43 deletions(-) create mode 100644 include/math/div.hpp create mode 100644 include/math/sub.hpp create mode 100644 include/math/sum.hpp rename include/neural_network/activation/{activation_ReLU.hpp => activation_relu.hpp} (95%) create mode 100644 include/neural_network/activation/activation_softmax.hpp create mode 100644 src/math/div.cpp create mode 100644 src/math/sub.cpp create mode 100644 src/math/sum.cpp rename src/neural_network/activation/{activation_ReLU.cpp => activation_relu.cpp} (82%) create mode 100644 src/neural_network/activation/activation_softmax.cpp diff --git a/include/config/omp.hpp b/include/config/omp.hpp index a688522..6c4075d 100644 --- a/include/config/omp.hpp +++ b/include/config/omp.hpp @@ -130,6 +130,23 @@ #define PANIC_OMP_PARALLEL_FOR_IF(condition) \ _Pragma(PANIC_STRINGIFY(omp parallel for if(condition) num_threads(PANIC_OMP_NUM_THREADS))) + + // Expands to: + // #pragma omp parallel for if(condition) + // num_threads(PANIC_OMP_NUM_THREADS) + // schedule(static) + // reduction(operation:variable) + // + // Runs the loop in parallel only when condition is true. + // Each thread receives a private copy of variable. + // Afterward, OpenMP combines those copies using operation. + // schedule(static) assigns fixed groups of iterations to each thread. + #define PANIC_OMP_PARALLEL_FOR_REDUCTION_IF(condition, operation, variable) \ + _Pragma(PANIC_STRINGIFY(omp parallel for if(condition) \ + num_threads(PANIC_OMP_NUM_THREADS) \ + schedule(static) \ + reduction(operation:variable))) + #else // Expands to: @@ -147,6 +164,21 @@ #define PANIC_OMP_PARALLEL_FOR_IF(condition) \ _Pragma(PANIC_STRINGIFY(omp parallel for if(condition))) + // Expands to: + // #pragma omp parallel for if(condition) + // num_threads(PANIC_OMP_NUM_THREADS) + // schedule(static) + // reduction(operation:variable) + // + // Runs the loop in parallel only when condition is true. + // Each thread receives a private copy of variable. + // Afterward, OpenMP combines those copies using operation. + // schedule(static) assigns fixed groups of iterations to each thread. + #define PANIC_OMP_PARALLEL_FOR_REDUCTION_IF(condition, operation, variable) \ + _Pragma(PANIC_STRINGIFY(omp parallel for if(condition) \ + schedule(static) \ + reduction(operation:variable))) + #endif #else diff --git a/include/math/div.hpp b/include/math/div.hpp new file mode 100644 index 0000000..cd969dd --- /dev/null +++ b/include/math/div.hpp @@ -0,0 +1,306 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: math + * File Name: div.hpp + * Revision: 0.1.0 + * Date: 30-07-2026 + * Author: Michelle Bausager + * + * Description: + * Functions to divide panic::tensor + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * @file mul.hpp + * @brief Public API for multiplying operations on PANIC vectors and matrices. + * + * This header contains the declarations that users of the math module should call. + * The comments here describe how each function is used, what dimensions are required, + * and what is returned on failure. + * + * Implementation details, OpenMP thresholds, and explicit template instantiations are + * kept in mul.cpp. + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#pragma once + +#include // for panic::vector +#include // for panic::matrix + +namespace panic{ +namespace math{ + + +/** + * @brief Divides a scalar to every element of a vector. + * + * Computes: + * @code + * c[i] = a[i] / k + * @endcode + * + * @tparam T Numeric element type. + * @param a Input vector. + * @param k Scalar value multiplied to each element of @p a. + * @param c Output vector. Resized to match @p a. + * + * @return true if @p c was resized and filled successfully. + * @return false if resizing @p c failed. + * + * @note This overload writes the result into an existing vector to avoid + * unnecessary temporary allocations. + */ +template +bool div(const panic::tensor::vector& a, const T k, panic::tensor::vector& c); + + +/** + * @brief Returns a new vector containing a scalar divided to every element. + * + * Computes: + * @code + * result[i] = a[i] / k + * @endcode + * + * @tparam T Numeric element type. + * @param a Input vector. + * @param k Scalar value miltiplied to each element of @p a. + * + * @return A new vector containing the result. + * @return An empty vector if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::vector div(const panic::tensor::vector& a, const T k); + + +/** + * @brief Divide a vector elementwise too a vector. + * + * Computes: + * @code + * c[i] = a[i] / b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param a First vector. + * @param b Second vector. Must have size of @p a + * @param c Output vector. Resized to match @p a. + * + * @return true if @p c was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool div(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c); + +/** + * @brief Returns a new vector containing a vector diveded elementwise. + * + * Computes: + * @code + * result[i] = a[i] / b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param a First vector. + * @param b Second vector. Must have size of @p a + * @param k Scalar value multiplied to each element of @p a. + * + * @return A new vector containing the result. + * @return An empty vector if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::vector div(const panic::tensor::vector& a, const panic::tensor::vector& b); + + + +/** + * @brief Divides a scalar to every element of a matix. + * + * Computes: + * @code + * C(i,j) = A(i,j) / k + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param k Scalar value multiplied to each element of @p A. + * @param C Output Matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if resizing @p C failed. + * + * @note This overload writes the result into an existing vector to avoid + * unnecessary temporary allocations. + */ +template +bool div(const panic::tensor::matrix& A, const T k, panic::tensor::matrix& C); + +/** + * @brief Returns a new matrix containing a scalar diveded to every element. + * + * Computes: + * @code + * result(i,j) = A(i,j) / k + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param k Scalar value multiplied to each element of @p A. + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix div(const panic::tensor::matrix& A, const T k); + +/** + * @brief Divides a matrix elementwise too a matrix. + * + * Computes: + * @code + * C(i,j) = A(i,j) / B(i,j) + * @endcode + * + * @tparam T Numeric element type. + * @param A First matrix. + * @param B Second matrix. Must have size of @p A. + * @param C Output matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool div(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C); + +/** + * @brief Returns a new matrix containing a matrix divided elementwise. + * + * Computes: + * @code + * result(i,j) = A(i,j) / B(i,j) + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param B Second matrix. Must have size of @p A. + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::tensor::matrix& B); + + +/** + * @brief Divides a vector rowwise too a matrix. + * + * Computes: + * @code + * C(i,j) = A(i,j) / b[j] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.cols(). + * @param C Output matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C); + +/** + * @brief Divides a vector rowwise too a matrix. + * + * Computes: + * @code + * result(i,j) = A(i,j) / b[j] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.cols(). + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b); + +/** + * @brief Divides a vector colwise too a matrix. + * + * Computes: + * @code + * C(i,j) = A(i,j) / b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.rows(). + * @param C Output matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C); + +/** + * @brief Divides a vector colwise too a matrix. + * + * Computes: + * @code + * result(i,j) = A(i,j) / b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.rows(). + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b); + + + + +} // namespace math +} // namespace panic \ No newline at end of file diff --git a/include/math/sub.hpp b/include/math/sub.hpp new file mode 100644 index 0000000..440e02e --- /dev/null +++ b/include/math/sub.hpp @@ -0,0 +1,286 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: math + * File Name: sub.hpp + * Revision: 0.1.0 + * Date: 25-06-2026 + * Author: Michelle Bausager + * + * Description: + * Functions to subtracts panic::tensor togther; + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#pragma once + +#include // for panic::vector +#include // for panic::matrix + +namespace panic{ +namespace math{ + + +/** + * @brief Subs a scalar to every element of a vector. + * + * Computes: + * @code + * c[i] = a[i] - k + * @endcode + * + * @tparam T Numeric element type. + * @param a Input vector. + * @param k Scalar value added to each element of @p a. + * @param c Output vector. Resized to match @p a. + * + * @return true if @p c was resized and filled successfully. + * @return false if resizing @p c failed. + * + * @note This overload writes the result into an existing vector to avoid + * unnecessary temporary allocations. + */ +template +bool sub(const panic::tensor::vector& a, const T k, panic::tensor::vector& c); + +/** + * @brief Returns a new vector containing a scalar subtraced to every element. + * + * Computes: + * @code + * result[i] = a[i] - k + * @endcode + * + * @tparam T Numeric element type. + * @param a Input vector. + * @param k Scalar value subtracted to each element of @p a. + * + * @return A new vector containing the result. + * @return An empty vector if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::vector sub(const panic::tensor::vector& a, const T k); + +/** + * @brief subtracts a vector elementwise too a vector. + * + * Computes: + * @code + * c[i] = a[i] - b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param a First vector. + * @param b Second vector. Must have size of @p a + * @param c Output vector. Resized to match @p a. + * + * @return true if @p c was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool sub(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c); + +/** + * @brief Returns a new vector containing a vector subtracted elementwise. + * + * Computes: + * @code + * result[i] = a[i] - b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param a First vector. + * @param b Second vector. Must have size of @p a + * @param k Scalar value subtracted to each element of @p a. + * + * @return A new vector containing the result. + * @return An empty vector if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::vector sub(const panic::tensor::vector& a, const panic::tensor::vector& b); + +/** + * @brief subtracts a scalar to every element of a matix. + * + * Computes: + * @code + * C(i,j) = A(i,j) - k + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param k Scalar value added to each element of @p A. + * @param C Output Matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if resizing @p C failed. + * + * @note This overload writes the result into an existing vector to avoid + * unnecessary temporary allocations. + */ +template +bool sub(const panic::tensor::matrix& A, const T k, panic::tensor::matrix& C); + +/** + * @brief Returns a new matrix containing a scalar subtracted to every element. + * + * Computes: + * @code + * result(i,j) = A(i,j) - k + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param k Scalar value subtracted to each element of @p A. + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix sub(const panic::tensor::matrix& A, const T k); + +/** + * @brief subtracts a matrix elementwise too a matrix. + * + * Computes: + * @code + * C(i,j) = A(i,j) - B(i,j) + * @endcode + * + * @tparam T Numeric element type. + * @param A First matrix. + * @param B Second matrix. Must have size of @p A. + * @param C Output matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool sub(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C); + +/** + * @brief Returns a new matrix containing a matrix subtracted elementwise. + * + * Computes: + * @code + * result(i,j) = A(i,j) - B(i,j) + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param B Second matrix. Must have size of @p A. + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix sub(const panic::tensor::matrix& A, const panic::tensor::matrix& B); + +/** + * @brief subtracts a vector rowwise too a matrix. + * + * Computes: + * @code + * C(i,j) = A(i,j) - b[j] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.cols(). + * @param C Output matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool sub_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C); + +/** + * @brief subtracts a vector rowwise too a matrix. + * + * Computes: + * @code + * result(i,j) = A(i,j) - b[j] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.cols(). + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix sub_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b); + +/** + * @brief subtracts a vector colwise too a matrix. + * + * Computes: + * @code + * C(i,j) = A(i,j) - b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.rows(). + * @param C Output matrix. Resized to match @p A. + * + * @return true if @p C was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool sub_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C); + +/** + * @brief subtracts a vector colwise too a matrix. + * + * Computes: + * @code + * result(i,j) = A(i,j) - b[i] + * @endcode + * + * @tparam T Numeric element type. + * @param A Matrix. + * @param b Vector. Must have size of @p A.rows(). + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::matrix sub_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b); + +} // namespace math +} // namespace panic \ No newline at end of file diff --git a/include/math/sum.hpp b/include/math/sum.hpp new file mode 100644 index 0000000..57f541a --- /dev/null +++ b/include/math/sum.hpp @@ -0,0 +1,158 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: math + * File Name: sum.hpp + * Revision: 0.1.0 + * Date: 25-06-2026 + * Author: Michelle Bausager + * + * Description: + * Functions to sum up arrays + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#pragma once + +#include // for panic::vector +#include // for panic::matrix + +namespace panic{ +namespace math{ + + + + +/** + * @brief Returns the sum value of a vector + * + * Computes: + * @code + * result = sum(a) + * @endcode + * + * @tparam T Numeric element type. + * @param a Input vector. + * + * @return A new vector containing the result. + * @return An empty vector if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +T sum(const panic::tensor::vector& a); + +/** + * @brief Returns the sum value of a matrix. + * + * Computes: + * @code + * result = sum(A) + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + */ +template +T sum(const panic::tensor::matrix& A); + +/** + * @brief Find the sum values row-wise of a matrix. + * + * Computes: + * @code + * c(i) = sum(A(i,j)) + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param c Output vector. Resized to match @p A.cols(). + * + * @return true if @p c was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool sum_rowwise(const panic::tensor::matrix& A, panic::tensor::vector& c); + +/** + * @brief Returns a new matrix containing the sum row-wise elementwise. + * + * Computes: + * @code + * result[i] = sum(A(i,j)) + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::vector sum_rowwise(const panic::tensor::matrix& A); + + +/** + * @brief Find the sumation values column-wise of a matrix. + * + * Computes: + * @code + * C(j) = sum(A(i,j)) + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * @param C Output matrix. Resized to match @p A.rows(). + * + * @return true if @p c was resized and filled successfully. + * @return false if vector sizes do not match or resizing @p c failed. + */ +template +bool sum_colwise(const panic::tensor::matrix& A, panic::tensor::vector& c); + +/** + * @brief Returns a new matrix containing the sumation column-wise elementwise. + * + * Computes: + * @code + * result[j] = sum(A(i,j)) + * @endcode + * + * @tparam T Numeric element type. + * @param A Input matrix. + * + * @return A new matrix containing the result. + * @return An empty matrix if the operation fails. + * + * @note This overload is convenient, but may allocate a new vector. + */ +template +panic::tensor::vector sum_colwise(const panic::tensor::matrix& A); + +} // namespace math +} // namespace panic \ No newline at end of file diff --git a/include/neural_network/activation/activation_ReLU.hpp b/include/neural_network/activation/activation_relu.hpp similarity index 95% rename from include/neural_network/activation/activation_ReLU.hpp rename to include/neural_network/activation/activation_relu.hpp index 82d79b2..2063d3c 100644 --- a/include/neural_network/activation/activation_ReLU.hpp +++ b/include/neural_network/activation/activation_relu.hpp @@ -22,7 +22,7 @@ * * Project Name: PANIC * Module Name: neural_network - * File Name: activation_ReLU.hpp + * File Name: activation_relu.hpp * Revision: 0.1.0 * Date: 29-08-2026 * Author: Michelle Bausager @@ -56,19 +56,19 @@ namespace panic{ * * The struct is used in PANIC nural_network library. */ -struct activation_ReLU : public layer{ +struct activation_relu : public layer{ /** * @brief Empthy constructor * */ - activation_ReLU(); + activation_relu(); /** * @brief Default de-constructor * */ - ~activation_ReLU() = default; + ~activation_relu() = default; /** * @brief Forward function for layer diff --git a/include/neural_network/activation/activation_softmax.hpp b/include/neural_network/activation/activation_softmax.hpp new file mode 100644 index 0000000..3e97f7c --- /dev/null +++ b/include/neural_network/activation/activation_softmax.hpp @@ -0,0 +1,94 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: neural_network + * File Name: activation_softmax.hpp + * Revision: 0.1.0 + * Date: 29-08-2026 + * Author: Michelle Bausager + * + * Description: + * Defines the activation layer for Softmax + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#pragma once + +//--------------------------------------------------------------------------------------------------------------------------- +// INCLUDE DESCRIPTION +//--------------------------------------------------------------------------------------------------------------------------- +#include // panic::uint_t, panic::int_t, and panic::real_t +#include // for base layer struct + +#include + + +namespace panic{ + namespace neural_network{ + +/** + * @brief struct for softmax activation layer used in neural networks + * + * Computes: + * @code + * panic::neural_network::activation_softmax myactivation(); + * myactivation.forward(inputMatrix); + * @endcode + * + * The struct is used in PANIC nural_network library. + */ +struct activation_softmax : public layer{ + + /** + * @brief Empthy constructor + * + */ + activation_softmax(); + + /** + * @brief Default de-constructor + * + */ + ~activation_softmax() = default; + + /** + * @brief Forward function for layer + * + * @param inputs Data input for forward pass. + * + * @Note Calculates -> outputs = inputs * weights + biases + */ + bool forward(const panic::tensor::real_matrix& inputs); + + /** + * @brief Backward function for layer + * + * @param inputs Data input for bacward pass. + * + * @Note Calculates derivative of forward function. + */ + bool backward(const panic::tensor::real_matrix& dinpus); +}; + + } // namespace tensor +} // namespace panic + diff --git a/include/neural_network/model/model.hpp b/include/neural_network/model/model.hpp index a47e622..8740c73 100644 --- a/include/neural_network/model/model.hpp +++ b/include/neural_network/model/model.hpp @@ -143,7 +143,7 @@ struct model{ * * Computes: * @code - * model.add_activation_ReLU(3,4); + * model.add_activation_relu(3,4); * @endcode * * @@ -151,7 +151,23 @@ struct model{ * * @note This function is convenient, but it allocates a new layer. */ - bool add_activation_ReLU(); + bool add_activation_relu(); + + /** + * @brief Adds a activation Softmax layer to the model. + * + * Computes: + * @code + * model.add_activation_softmax(3,4); + * @endcode + * + * + * @return true if layer is added + * + * @note This function is convenient, but it allocates a new layer. + */ + bool add_activation_softmax(); + /** * @brief Loops over all layers forward function diff --git a/main.cpp b/main.cpp index d0d0c79..c815c37 100644 --- a/main.cpp +++ b/main.cpp @@ -50,14 +50,14 @@ #include #include -#include +#include #include #include #include #include #include #include - +#include #include @@ -708,24 +708,33 @@ int main(void) { panic::tensor::real_matrix X; panic::tensor::uint_vector y; - panic::types::uint_t samples = 100; + panic::types::uint_t samples = 10; panic::types::uint_t classes = 3; + + // create spiral data panic::neural_network::spiral_data(samples, classes, X, y); + // Initilise my model panic::neural_network::model mymodel; // Create Dense layer with 2 input features and 3 output values mymodel.add_layer_dense(2,3); - mymodel.add_activation_ReLU(); + // Create an activation ReLU layer + mymodel.add_activation_relu(); + + // Create a second dense layer with 3 inputs and 3 outputs + mymodel.add_layer_dense(3, 3); + + // Create activation softmax layer + mymodel.add_activation_softmax(); mymodel.forward(X); - //panic::io::print_matrix(mymodel.outputs); + panic::io::print_matrix(mymodel.outputs); + - std::cout << panic::math::exp(15.5f) << std::endl; - std::cout << std::exp(15.5) << std::endl; return 0; diff --git a/src/math/div.cpp b/src/math/div.cpp new file mode 100644 index 0000000..347c829 --- /dev/null +++ b/src/math/div.cpp @@ -0,0 +1,625 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: math + * File Name: div.cpp + * Revision: 0.1.0 + * Date: 25-06-2026 + * Author: Michelle Bausager + * + * Description: + * Functions to divdes panic::tensor + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +//--------------------------------------------------------------------------------------------------------------------------- +// INCLUDE DESCRIPTION +//----------------------------------------------------------------------------------------------------- + +#include +#include + +#include // for panic::vector +#include // for panic::matrix + +//--------------------------------------------------------------------------------------------------------------------------- +// PRIVATE CONSTANTS +//--------------------------------------------------------------------------------------------------------------------------- +/** + * @brief Minimum number of element operations before using the OpenMP-enabled loop. + * + * Small vectors and matrices are kept serial because the overhead of starting + * worker threads can be larger than the work itself. + */ +static const panic::types::uint_t div_omp_min_work = 500; +//--------------------------------------------------------------------------------------------------------------------------- +// INPLEMENTATION +//--------------------------------------------------------------------------------------------------------------------------- + +namespace panic { + namespace math { + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divedes a constant to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +bool div(const panic::tensor::vector& a, const T k, panic::tensor::vector& c){ + + if (!c.resize(a.size())){ + return false; + } + + if (k == T{0}){ + return false; + } + + PANIC_OMP_PARALLEL_FOR_IF(a.size() > div_omp_min_work) + for (panic::types::uint_t i = 0; i < a.size(); ++i){ + c[i] = a[i] / k; + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool div(const panic::tensor::vector& a, + const panic::types::uint_t k, + panic::tensor::vector& c +); +template bool div(const panic::tensor::vector& a, + const panic::types::int_t k, + panic::tensor::vector& c +); +template bool div(const panic::tensor::vector& a, + const panic::types::real_t k, + panic::tensor::vector& c +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divides a constant to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::vector div(const panic::tensor::vector& a, const T k){ + panic::tensor::vector c(a.size()); + + if (!div(a, k, c)){ + return panic::tensor::vector(); + } + + return c; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::vector + div(const panic::tensor::vector& a, + const panic::types::uint_t k +); +template panic::tensor::vector + div(const panic::tensor::vector& a, + const panic::types::int_t k +); +template panic::tensor::vector + div(const panic::tensor::vector& a, + const panic::types::real_t k +); + + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divides a vector to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +bool div(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c){ + + if (a.size() != b.size()){ + return false; + } + + if (!c.resize(a.size())){ + return false; + } + + bool valid = true; + + // Check all divisors in parallel. + // valid remains true only if every divisor is nonzero. + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( a.size() > div_omp_min_work, &&, valid ) + for (panic::types::uint_t i = 0; i < a.size(); ++i){ + const bool nonzero = b[i] != T{0}; + valid = valid && nonzero; + + if (nonzero){ + c[i] = a[i] / b[i]; + } + } + + return valid; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool div(const panic::tensor::vector& a, + const panic::tensor::vector& b, + panic::tensor::vector& c +); +template bool div(const panic::tensor::vector& a, + const panic::tensor::vector& b, + panic::tensor::vector& c +); +template bool div(const panic::tensor::vector& a, + const panic::tensor::vector& b, + panic::tensor::vector& c +); + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divides a vector to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::vector div(const panic::tensor::vector& a, const panic::tensor::vector& b){ + panic::tensor::vector c(a.size()); + + if (!div(a, b, c)){ + return panic::tensor::vector(); + } + + return c; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::vector + div(const panic::tensor::vector& a, + const panic::tensor::vector& b +); +template panic::tensor::vector + div(const panic::tensor::vector& a, + const panic::tensor::vector& b +); +template panic::tensor::vector + div(const panic::tensor::vector& a, + const panic::tensor::vector& b +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divides a constant to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool div(const panic::tensor::matrix& A, const T k, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( !C.resize(rows, cols) ){ + return false; + } + + if (k == T{0}){ + return false; + } + + + PANIC_OMP_PARALLEL_FOR_IF(work > div_omp_min_work) + for (panic::types::uint_t i = 0; i < rows; ++i){ + for (panic::types::uint_t j = 0; j < cols; ++j){ + C(i,j) = A(i,j) / k; + } + + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool div(const panic::tensor::matrix& A, + const panic::types::uint_t k, + panic::tensor::matrix& C +); +template bool div(const panic::tensor::matrix& A, + const panic::types::int_t k, + panic::tensor::matrix& C +); +template bool div(const panic::tensor::matrix& A, + const panic::types::real_t k, + panic::tensor::matrix& C +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divides a constant to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix div(const panic::tensor::matrix& A, const T k){ + panic::tensor::matrix C; + + if (!div(A, k, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + div(const panic::tensor::matrix& A, + const panic::types::uint_t k +); +template panic::tensor::matrix + div(const panic::tensor::matrix& A, + const panic::types::int_t k +); +template panic::tensor::matrix + div(const panic::tensor::matrix& A, + const panic::types::real_t k +); + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divides a matrix to a matrix elementwise +//-------------------------------------------------------------------------------------------------------------------------- +template +bool div(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( (rows != B.rows()) || (cols != B.cols())){ + return false; + } + + if ( !C.resize(rows, cols) ){ + return false; + } + + bool valid = true; + + // Check all divisors in parallel. + // valid remains true only if every divisor is nonzero. + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( work > div_omp_min_work, &&, valid ) + for (panic::types::uint_t i = 0; i < rows; ++i) { + for (panic::types::uint_t j = 0; j < cols; ++j) { + + const bool nonzero = B(i,j) != T{0}; + valid = valid && nonzero; + + if (nonzero) { + C(i,j) = A(i,j) / B(i,j); + } + } + } + + + return valid; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool div(const panic::tensor::matrix& A, + const panic::tensor::matrix& B, + panic::tensor::matrix& C +); +template bool div(const panic::tensor::matrix& A, + const panic::tensor::matrix& B, + panic::tensor::matrix& C +); +template bool div(const panic::tensor::matrix& A, + const panic::tensor::matrix& B, + panic::tensor::matrix& C +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div +// +// Description: +// Divides a matrix to a matrix elementwise +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::tensor::matrix& B){ + panic::tensor::matrix C; + + if (!div(A, B, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + div(const panic::tensor::matrix& A, + const panic::tensor::matrix& B +); +template panic::tensor::matrix + div(const panic::tensor::matrix& A, + const panic::tensor::matrix& B +); +template panic::tensor::matrix + div(const panic::tensor::matrix& A, + const panic::tensor::matrix& B +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div_rowwise +// +// Description: +// Divides a vector row-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( cols != b.size() ){ + return false; + } + + if ( !C.resize(rows, cols) ){ + return false; + } + + + bool valid = true; + + // Check all divisors in parallel. + // valid remains true only if every divisor is nonzero. + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( work > div_omp_min_work, &&, valid ) + for (panic::types::uint_t i = 0; i < cols; ++i){ + const bool nonzero = b[i] != T{0}; + valid = valid && nonzero; + for (panic::types::uint_t j = 0; j < rows; ++j){ + if (nonzero){ + C(j,i) = A(j,i) / b[i]; + } + } + + } + + return valid; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool div_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool div_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool div_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div_rowwise +// +// Description: +// Divides a vector row-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b){ + panic::tensor::matrix C; + + if (!div_rowwise(A, b, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + div_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + div_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + div_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div_colwise +// +// Description: +// Divides a vector coloumn-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( rows != b.size() ){ + return false; + } + + if ( !C.resize(rows, cols) ){ + return false; + } + + bool valid = true; + + // Check all divisors in parallel. + // valid remains true only if every divisor is nonzero. + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( work > div_omp_min_work, &&, valid ) + for (panic::types::uint_t i = 0; i < rows; ++i){ + const bool nonzero = b[i] != T{0}; + valid = valid && nonzero; + for (panic::types::uint_t j = 0; j < cols; ++j){ + if (nonzero){ + C(i,j) = A(i,j) / b[i]; + } + } + + } + + return valid; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool div_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool div_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool div_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::div_colwise +// +// Description: +// Divides a vector coloumn-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b){ + panic::tensor::matrix C; + + + if (!div_colwise(A, b, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + div_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + div_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + div_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); + + + + } // namespace math +} // namespace panic diff --git a/src/math/max.cpp b/src/math/max.cpp index 108f86b..2317b87 100644 --- a/src/math/max.cpp +++ b/src/math/max.cpp @@ -73,7 +73,7 @@ T max(const panic::tensor::vector& a){ // Find the maximum in parallel for large vectors. // Each thread computes a local maximum, then OpenMP combines them into y. - #pragma omp parallel for if(a.size() > max_omp_min_work) reduction(max:y) + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF(a.size() > max_omp_min_work, max, y) for (panic::types::uint_t i = 1; i < a.size(); ++i) { if (a[i] > y) { y = a[i]; @@ -114,7 +114,7 @@ T max(const panic::tensor::matrix& A){ // Find the maximum in parallel for large vectors. // Each thread computes a local maximum, then OpenMP combines them into y. - #pragma omp parallel for if(work > max_omp_min_work) reduction(max:y) + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF(work > max_omp_min_work, max, y) for (panic::types::uint_t i = 0; i < A.rows(); ++i) { for (panic::types::uint_t j = 0; j < A.cols(); ++j){ if (A(i,j) > y) { diff --git a/src/math/sub.cpp b/src/math/sub.cpp new file mode 100644 index 0000000..c1ab651 --- /dev/null +++ b/src/math/sub.cpp @@ -0,0 +1,582 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: math + * File Name: sub.cpp + * Revision: 0.1.0 + * Date: 25-06-2026 + * Author: Michelle Bausager + * + * Description: + * Functions to subtracts panic::tensors togther; + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +//--------------------------------------------------------------------------------------------------------------------------- +// INCLUDE DESCRIPTION +//----------------------------------------------------------------------------------------------------- + +#include +#include + +#include // for panic::vector +#include // for panic::matrix + +//--------------------------------------------------------------------------------------------------------------------------- +// PRIVATE CONSTANTS +//--------------------------------------------------------------------------------------------------------------------------- +/** + * @brief Minimum number of element operations before using the OpenMP-enabled loop. + * + * Small vectors and matrices are kept serial because the overhead of starting + * worker threads can be larger than the work itself. + */ +static const panic::types::uint_t sub_omp_min_work = 500; +//--------------------------------------------------------------------------------------------------------------------------- +// INPLEMENTATION +//--------------------------------------------------------------------------------------------------------------------------- + +namespace panic { + namespace math { + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a constant to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sub(const panic::tensor::vector& a, const T k, panic::tensor::vector& c){ + + if (!c.resize(a.size())){ + return false; + } + + PANIC_OMP_PARALLEL_FOR_IF(a.size() > sub_omp_min_work) + for (panic::types::uint_t i = 0; i < a.size(); ++i){ + c[i] = a[i] - k; + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sub(const panic::tensor::vector& a, + const panic::types::uint_t k, + panic::tensor::vector& c +); +template bool sub(const panic::tensor::vector& a, + const panic::types::int_t k, + panic::tensor::vector& c +); +template bool sub(const panic::tensor::vector& a, + const panic::types::real_t k, + panic::tensor::vector& c +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a constant to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::vector sub(const panic::tensor::vector& a, const T k){ + panic::tensor::vector c(a.size()); + + if (!sub(a, k, c)){ + return panic::tensor::vector(); + } + + return c; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::vector + sub(const panic::tensor::vector& a, + const panic::types::uint_t k +); +template panic::tensor::vector + sub(const panic::tensor::vector& a, + const panic::types::int_t k +); +template panic::tensor::vector + sub(const panic::tensor::vector& a, + const panic::types::real_t k +); + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a vector to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sub(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c){ + + if (a.size() != b.size()){ + return false; + } + + if (!c.resize(a.size())){ + return false; + } + + PANIC_OMP_PARALLEL_FOR_IF(a.size() > sub_omp_min_work) + for (panic::types::uint_t i = 0; i < a.size(); ++i){ + c[i] = a[i] - b[i]; + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sub(const panic::tensor::vector& a, + const panic::tensor::vector& b, + panic::tensor::vector& c +); +template bool sub(const panic::tensor::vector& a, + const panic::tensor::vector& b, + panic::tensor::vector& c +); +template bool sub(const panic::tensor::vector& a, + const panic::tensor::vector& b, + panic::tensor::vector& c +); + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a vector to a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::vector sub(const panic::tensor::vector& a, const panic::tensor::vector& b){ + panic::tensor::vector c(a.size()); + + if (!sub(a, b, c)){ + return panic::tensor::vector(); + } + + return c; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::vector + sub(const panic::tensor::vector& a, + const panic::tensor::vector& b +); +template panic::tensor::vector + sub(const panic::tensor::vector& a, + const panic::tensor::vector& b +); +template panic::tensor::vector + sub(const panic::tensor::vector& a, + const panic::tensor::vector& b +); + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a constant to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sub(const panic::tensor::matrix& A, const T k, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( !C.resize(rows, cols) ){ + return false; + } + + + PANIC_OMP_PARALLEL_FOR_IF(work > sub_omp_min_work) + for (panic::types::uint_t i = 0; i < rows; ++i){ + for (panic::types::uint_t j = 0; j < cols; ++j){ + C(i,j) = A(i,j) - k; + } + + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sub(const panic::tensor::matrix& A, + const panic::types::uint_t k, + panic::tensor::matrix& C +); +template bool sub(const panic::tensor::matrix& A, + const panic::types::int_t k, + panic::tensor::matrix& C +); +template bool sub(const panic::tensor::matrix& A, + const panic::types::real_t k, + panic::tensor::matrix& C +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a constant to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix sub(const panic::tensor::matrix& A, const T k){ + panic::tensor::matrix C; + + if (!sub(A, k, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + sub(const panic::tensor::matrix& A, + const panic::types::uint_t k +); +template panic::tensor::matrix + sub(const panic::tensor::matrix& A, + const panic::types::int_t k +); +template panic::tensor::matrix + sub(const panic::tensor::matrix& A, + const panic::types::real_t k +); + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a matrix to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sub(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( (rows != B.rows()) || (cols != B.cols())){ + return false; + } + + if ( !C.resize(rows, cols) ){ + return false; + } + + + PANIC_OMP_PARALLEL_FOR_IF(work > sub_omp_min_work) + for (panic::types::uint_t i = 0; i < rows; ++i){ + for (panic::types::uint_t j = 0; j < cols; ++j){ + C(i,j) = A(i,j) - B(i,j); + } + + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sub(const panic::tensor::matrix& A, + const panic::tensor::matrix& B, + panic::tensor::matrix& C +); +template bool sub(const panic::tensor::matrix& A, + const panic::tensor::matrix& B, + panic::tensor::matrix& C +); +template bool sub(const panic::tensor::matrix& A, + const panic::tensor::matrix& B, + panic::tensor::matrix& C +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub +// +// Description: +// subtracts a matrix to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix sub(const panic::tensor::matrix& A, const panic::tensor::matrix& B){ + panic::tensor::matrix C; + + if (!sub(A, B, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + sub(const panic::tensor::matrix& A, + const panic::tensor::matrix& B +); +template panic::tensor::matrix + sub(const panic::tensor::matrix& A, + const panic::tensor::matrix& B +); +template panic::tensor::matrix + sub(const panic::tensor::matrix& A, + const panic::tensor::matrix& B +); + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub_rowwise +// +// Description: +// subtracts a vector row-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sub_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( cols != b.size() ){ + return false; + } + + if ( !C.resize(rows, cols) ){ + return false; + } + + + PANIC_OMP_PARALLEL_FOR_IF(work > sub_omp_min_work) + for (panic::types::uint_t i = 0; i < rows; ++i){ + for (panic::types::uint_t j = 0; j < cols; ++j){ + + C(i,j) = A(i,j) - b[j]; + } + + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sub_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool sub_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool sub_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub_rowwise +// +// Description: +// subtracts a vector row-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix sub_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b){ + panic::tensor::matrix C; + + if (!sub_rowwise(A, b, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + sub_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + sub_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + sub_rowwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub_colwise +// +// Description: +// subtracs a vector coloumn-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sub_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( rows != b.size() ){ + return false; + } + + if ( !C.resize(rows, cols) ){ + return false; + } + + + PANIC_OMP_PARALLEL_FOR_IF(work > sub_omp_min_work) + for (panic::types::uint_t i = 0; i < rows; ++i){ + for (panic::types::uint_t j = 0; j < cols; ++j){ + + C(i,j) = A(i,j) - b[i]; + } + + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sub_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool sub_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); +template bool sub_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b, + panic::tensor::matrix& C +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sub_colwise +// +// Description: +// subtracts a vector coloumn-wise to a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::matrix sub_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b){ + panic::tensor::matrix C; + + + if (!sub_colwise(A, b, C)){ + return panic::tensor::matrix(); + } + + return C; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::matrix + sub_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + sub_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); +template panic::tensor::matrix + sub_colwise(const panic::tensor::matrix& A, + const panic::tensor::vector& b +); + + + + + } // namespace math +} // namespace panic diff --git a/src/math/sum.cpp b/src/math/sum.cpp new file mode 100644 index 0000000..9718517 --- /dev/null +++ b/src/math/sum.cpp @@ -0,0 +1,327 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: math + * File Name: sum.cpp + * Revision: 0.1.0 + * Date: 25-06-2026 + * Author: Michelle Bausager + * + * Description: + * Functions to sum up arrays + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +//--------------------------------------------------------------------------------------------------------------------------- +// INCLUDE DESCRIPTION +//----------------------------------------------------------------------------------------------------- + +#include +#include + +#include // for panic::vector +#include // for panic::matrix + +//--------------------------------------------------------------------------------------------------------------------------- +// PRIVATE CONSTANTS +//--------------------------------------------------------------------------------------------------------------------------- +/** + * @brief Minimum number of element operations before using the OpenMP-enabled loop. + * + * Small vectors and matrices are kept serial because the overhead of starting + * worker threads can be larger than the work itself. + */ +static const panic::types::uint_t sum_omp_min_work = 500; +//--------------------------------------------------------------------------------------------------------------------------- +// INPLEMENTATION +//--------------------------------------------------------------------------------------------------------------------------- + +namespace panic { + namespace math { + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sum +// +// Description: +// Find the sum value for a vector +//-------------------------------------------------------------------------------------------------------------------------- +template +T sum(const panic::tensor::vector& a){ + + T result = T{0}; + + // Find the maximum in parallel for large vectors. + // Each thread computes a partial sum, then OpenMP combines them into result. + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF(a.size() > sum_omp_min_work, +, result) + for (panic::types::uint_t i = 0; i < a.size(); ++i) { + result += a[i]; + } + + return result; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::types::uint_t sum(const panic::tensor::vector& a +); +template panic::types::int_t sum(const panic::tensor::vector& a +); +template panic::types::real_t sum(const panic::tensor::vector& a +); + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sum +// +// Description: +// Find the sum value for a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +T sum(const panic::tensor::matrix& A){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + T result = A(0,0); + + // Find the maximum in parallel for large vectors. + // Each thread computes a partial sum, then OpenMP combines them into result. + PANIC_OMP_PARALLEL_FOR_REDUCTION_IF(work > sum_omp_min_work, +, result) + for (panic::types::uint_t i = 0; i < A.rows(); ++i) { + for (panic::types::uint_t j = 0; j < A.cols(); ++j){ + result += A(i,j); + } + } + return result; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::types::uint_t sum(const panic::tensor::matrix& a +); +template panic::types::int_t sum(const panic::tensor::matrix& a +); +template panic::types::real_t sum(const panic::tensor::matrix& a +); + + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sum_rowwise +// +// Description: +// Find the sum row-wise of a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sum_rowwise(const panic::tensor::matrix& A, panic::tensor::vector& b){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( !b.resize(rows) ){ + return false; + } + + // Each thread handles separate rows and writes to a separate b[i]. + PANIC_OMP_PARALLEL_FOR_IF(work > sum_omp_min_work) + for (panic::types::uint_t i = 0; i < rows; ++i){ + b[i] = T{0}; + for (panic::types::uint_t j = 0; j < cols; ++j){ + b[i] += A(i,j); + } + + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sum_rowwise(const panic::tensor::matrix& A, + panic::tensor::vector& b +); +template bool sum_rowwise(const panic::tensor::matrix& A, + panic::tensor::vector& b +); +template bool sum_rowwise(const panic::tensor::matrix& A, + panic::tensor::vector& b +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sum_rowwise +// +// Description: +// Returns row-wise sum values +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::vector sum_rowwise(const panic::tensor::matrix& A){ + panic::tensor::vector b; + + if (!sum_rowwise(A, b)){ + return panic::tensor::vector(); + } + + return b; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::vector + sum_rowwise(const panic::tensor::matrix& A +); +template panic::tensor::vector + sum_rowwise(const panic::tensor::matrix& A +); +template panic::tensor::vector + sum_rowwise(const panic::tensor::matrix& A +); + + + + + + + + + + + + + + + + + + + + + + + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sum_colwise +// +// Description: +// Find the sum column-wise of a matrix +//-------------------------------------------------------------------------------------------------------------------------- +template +bool sum_colwise(const panic::tensor::matrix& A, panic::tensor::vector& b){ + + panic::types::uint_t rows = A.rows(); + panic::types::uint_t cols = A.cols(); + panic::types::uint_t work = rows*cols; + + if ( !b.resize(cols) ){ + return false; + } + + // Each thread handles separate cols and writes to a separate b[i]. + PANIC_OMP_PARALLEL_FOR_IF(work > sum_omp_min_work) + for (panic::types::uint_t i = 0; i < cols; ++i){ + b[i] = T{0}; + for (panic::types::uint_t j = 0; j < rows; ++j){ + b[i] += A(i,j); + } + + } + + return true; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template bool sum_colwise(const panic::tensor::matrix& A, + panic::tensor::vector& b +); +template bool sum_colwise(const panic::tensor::matrix& A, + panic::tensor::vector& b +); +template bool sum_colwise(const panic::tensor::matrix& A, + panic::tensor::vector& b +); + + + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::math::sum_colwise +// +// Description: +// Returns column-wise sum values +//-------------------------------------------------------------------------------------------------------------------------- +template +panic::tensor::vector sum_colwise(const panic::tensor::matrix& A){ + panic::tensor::vector b; + + if (!sum_colwise(A, b)){ + return panic::tensor::vector(); + } + + return b; +} +//-------------------------------------------------------------------------------------------------------------------------- +// EXPLICIT TEMPLATE INSTANTIATION +// +// The implementation is in this .cpp file. +// Build the overload for the official PANIC numeric types. +//-------------------------------------------------------------------------------------------------------------------------- +template panic::tensor::vector + sum_colwise(const panic::tensor::matrix& A +); +template panic::tensor::vector + sum_colwise(const panic::tensor::matrix& A +); +template panic::tensor::vector + sum_colwise(const panic::tensor::matrix& A +); + + + } // namespace math +} // namespace panic diff --git a/src/neural_network/activation/activation_ReLU.cpp b/src/neural_network/activation/activation_relu.cpp similarity index 82% rename from src/neural_network/activation/activation_ReLU.cpp rename to src/neural_network/activation/activation_relu.cpp index eab0e7e..6a9f093 100644 --- a/src/neural_network/activation/activation_ReLU.cpp +++ b/src/neural_network/activation/activation_relu.cpp @@ -22,7 +22,7 @@ * * Project Name: PANIC * Module Name: neural_network - * File Name: activation_ReLU.cpp + * File Name: activation_relu.cpp * Revision: 0.1.0 * Date: 29-08-2026 * Author: Michelle Bausager @@ -35,7 +35,7 @@ //--------------------------------------------------------------------------------------------------------------------------- // INCLUDE DESCRIPTION //--------------------------------------------------------------------------------------------------------------------------- -#include +#include #include #include @@ -61,53 +61,38 @@ namespace panic{ //-------------------------------------------------------------------------------------------------------------------------- -// Constructor Name : panic::neural_network::activation_ReLU +// Constructor Name : panic::neural_network::activation_relu // // Description: // Creates an empty layer. //-------------------------------------------------------------------------------------------------------------------------- -activation_ReLU::activation_ReLU() { +activation_relu::activation_relu() { } //-------------------------------------------------------------------------------------------------------------------------- -// Function Name : panic::neural_network::activation_ReLU.forward +// Function Name : panic::neural_network::activation_relu.forward // // Description: // Calculated the forward pass: // outputs = max(inputs, 0) //-------------------------------------------------------------------------------------------------------------------------- -bool activation_ReLU::forward(const panic::tensor::real_matrix& inputs){ +bool activation_relu::forward(const panic::tensor::real_matrix& inputs){ panic::math::clip_lower(inputs, 0.0f, outputs); -/* - if (inputs.cols() != weights.rows()){ - return false; - } - if (!outputs.resize(inputs.rows(), weights.cols())){ - return false; - } - if (!panic::math::matmul(inputs, weights, outputs)){ - return false; - } - - if (!panic::math::add_rowwise(outputs, biases, outputs)){ - return false; - } -*/ return true; } //-------------------------------------------------------------------------------------------------------------------------- -// Function Name : panic::neural_network::activation_ReLU.backward +// Function Name : panic::neural_network::activation_relu.backward // // Description: // Calculated the backward pass: // ?? //-------------------------------------------------------------------------------------------------------------------------- -bool activation_ReLU::backward(const panic::tensor::real_matrix& dinputs){ +bool activation_relu::backward(const panic::tensor::real_matrix& dinputs){ return true; diff --git a/src/neural_network/activation/activation_softmax.cpp b/src/neural_network/activation/activation_softmax.cpp new file mode 100644 index 0000000..7c47916 --- /dev/null +++ b/src/neural_network/activation/activation_softmax.cpp @@ -0,0 +1,144 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: neural_network + * File Name: activation_softmax.cpp + * Revision: 0.1.0 + * Date: 29-08-2026 + * Author: Michelle Bausager + * + * Description: + * Defines the activation layer for Softmax + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +//--------------------------------------------------------------------------------------------------------------------------- +// INCLUDE DESCRIPTION +//--------------------------------------------------------------------------------------------------------------------------- +#include +#include + +#include +#include +#include +#include +#include + + + +//--------------------------------------------------------------------------------------------------------------------------- +// PRIVATE CONSTANTS +//--------------------------------------------------------------------------------------------------------------------------- +/** + * @brief Minimum number of element operations before using the OpenMP-enabled loop. + * + * Small vectors and matrices are kept serial because the overhead of starting + * worker threads can be larger than the work itself. + */ +static const panic::types::uint_t activation_softmax_omp_min_size = 500; +//--------------------------------------------------------------------------------------------------------------------------- +// INPLEMENTATION +//--------------------------------------------------------------------------------------------------------------------------- + +namespace panic{ + namespace neural_network{ + + +//-------------------------------------------------------------------------------------------------------------------------- +// Constructor Name : panic::neural_network::activation_softmax +// +// Description: +// Creates an empty layer. +//-------------------------------------------------------------------------------------------------------------------------- +activation_softmax::activation_softmax() { +} + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::neural_network::activation_softmax.forward +// +// Description: +// Calculated the forward pass: +// outputs = max(inputs, 0) +//-------------------------------------------------------------------------------------------------------------------------- +bool activation_softmax::forward(const panic::tensor::real_matrix& inputs){ + + panic::tensor::real_vector row_maximums; + panic::tensor::real_vector row_sums; + + // Each row represents one sample. + // Find the maximum class score in each sample + // + // row_maximums[i] = max(inputs(i, 0), ..., inputs(i, cols - 1)) + if (! panic::math::max_rowwise(inputs, row_maximums)){ + return false; + } + + + // row_maximums contains one value per row, so it behaves + // like a column vector broadcast across all columns: + // + // outputs(i, j) = inputs(i, j) - row_maximums[i] + if (!panic::math::sub_colwise(inputs, row_maximums, outputs)){ + return false; + } + + // Convert the shifted scores into positive exponential values + if (!panic::math::exp(outputs, outputs)){ + return false; + } + + // Sum the exponential values in each sample + // + // row_sums[i] = sum(outputs(i, 0), ..., outputs(i, cols - 1)) + if (!panic::math::sum_rowwise(outputs, row_sums)){ + return false; + } + + // row_sums contains one value per row, so broadcast it + // across all columns and normalize each sample: + // + // outputs(i, j) = outputs(i, j) / row_sums[i] + if (!panic::math::div_colwise(outputs, row_sums, outputs)){ + return false; + } + + return true; +} + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::neural_network::activation_softmax.backward +// +// Description: +// Calculated the backward pass: +// ?? +//-------------------------------------------------------------------------------------------------------------------------- +bool activation_softmax::backward(const panic::tensor::real_matrix& dinputs){ + + + return true; +} + + + } // namespace tensor +} // namespace panic diff --git a/src/neural_network/model/model.cpp b/src/neural_network/model/model.cpp index fb767df..ae403f1 100644 --- a/src/neural_network/model/model.cpp +++ b/src/neural_network/model/model.cpp @@ -42,7 +42,8 @@ #include -#include +#include +#include //--------------------------------------------------------------------------------------------------------------------------- // IMPLEMENTATION @@ -171,18 +172,47 @@ bool model::add_layer_dense( return true; } //-------------------------------------------------------------------------------------------------------------------------- -// Function Name : panic::neural_network::model::add_activation_ReLU +// Function Name : panic::neural_network::model::add_activation_relu // // Description: // Creates a activation ReLU layer and adds it to the model. // // Example: -// model.add_activation_ReLU(); +// model.activation_relu(); //-------------------------------------------------------------------------------------------------------------------------- -bool model::add_activation_ReLU(){ +bool model::add_activation_relu(){ // Create the ReLU layer. - activation_ReLU* new_layer = new activation_ReLU(); + activation_relu* new_layer = new activation_relu(); + + if (new_layer == 0){ + return false; + } + + // Add it to the model. + // + // If add() fails, delete the layer so we do not leak memory. + if (!add(new_layer)){ + delete new_layer; + return false; + } + + return true; +} + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::neural_network::model::add_activation_softmax +// +// Description: +// Creates a activation Softmax layer and adds it to the model. +// +// Example: +// model.activation_softmax(); +//-------------------------------------------------------------------------------------------------------------------------- +bool model::add_activation_softmax(){ + + // Create the ReLU layer. + activation_softmax* new_layer = new activation_softmax(); if (new_layer == 0){ return false;