Done with activation softmax backwards

This commit is contained in:
2026-07-31 19:08:57 +02:00
parent d7b74ab40f
commit 11da534fd6
30 changed files with 3029 additions and 184 deletions
+176
View File
@@ -0,0 +1,176 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
*
* 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: argmax.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to find the index of the maximum value;
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#pragma once
#include <config/types.hpp>
#include <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // for panic::matrix
namespace panic{
namespace math{
/**
* @brief Returns the index of maximum value of a vector
*
* Computes:
* @code
* @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 <typename T>
panic::types::uint_t argmax(const panic::tensor::vector<T>& a);
/**
* @brief Calculates the index of the maximum value of a matrix.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param A Input matrix.
* @param b Output vector for index
*
* @return A new matrix containing the result.
* @return An empty matrix if the operation fails.
*
*/
template <typename T>
bool argmax(const panic::tensor::matrix<T>& A, panic::tensor::uint_vector& b);
/**
* @brief Returns the index of the maximum value of a matrix.
*
* Computes:
* @code
* @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 <typename T>
panic::types::uint_t argmax(const panic::tensor::matrix<T>& A);
/**
* @brief Find the index of the maximum values row-wise of a matrix.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param A Input matrix.
* @param C Output vector with indexes. 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 <typename T>
bool argmax_rowwise(const panic::tensor::matrix<T>& A, panic::tensor::uint_vector& c);
/**
* @brief Returns a new matrix containing the index of the maiximum row-wise elementwise.
*
* Computes:
* @code
* @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 <typename T>
panic::tensor::uint_vector argmax_rowwise(const panic::tensor::matrix<T>& A);
/**
* @brief Find the index of the maximum values column-wise of a matrix.
*
* Computes:
* @code
* @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 <typename T>
bool argmax_colwise(const panic::tensor::matrix<T>& A, panic::tensor::uint_vector& c);
/**
* @brief Returns a new matrix containing the index of the maiximum column-wise elementwise.
*
* Computes:
* @code
* @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 <typename T>
panic::tensor::uint_vector argmax_colwise(const panic::tensor::matrix<T>& A);
} // namespace math
} // namespace panic
+102
View File
@@ -0,0 +1,102 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* 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: dot.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to calculate dot product of tensors;
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#pragma once
//---------------------------------------------------------------------------------------------------------------------------
// INCLUDE DESCRIPTION
//-----------------------------------------------------------------------------------------------------
#include <tensor/vector.hpp>
#include <tensor/matrix.hpp> // for panic::real_matrix
namespace panic{
namespace math{
/**
* @brief Returns dor product of vector and vector.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param a First vector.
* @param b Second vector for dot product. Need to be @p a.size()
*
*/
template <typename T>
T dot(const panic::tensor::vector<T>& a, const panic::tensor::vector<T>& b);
/**
* @brief Returns a new vector of dot product of a matrix and vector.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param A Input matrix.
* @param b Input vector. @ p b.size needs to be the size of @p A.cols.
* @param c Output vector with result.
*
* @return true if success
* @return false if resizeing fails or dimention mismatch
*
*/
template <typename T>
bool dot(const panic::tensor::matrix<T>& A, const panic::tensor::matrix<T>& b, panic::tensor::vector<T>& c);
/**
* @brief Returns a new vector of dot product of a matrix and vector.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param A Input matrix.
* @param b Input vector. @ p b.size needs to be the size of @p A.cols.
*
* @return A new matrix containing the result.
* @return An empty vector if the operation fails.
*
* @note This overload is convenient, but may allocate a new matrix.
*/
template <typename T>
panic::tensor::vector<T> dot(const panic::tensor::matrix<T>& A, const panic::tensor::matrix<T>& b);
} // namespace math
} // namespace panic
+294
View File
@@ -0,0 +1,294 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
*
* 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: equal.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to find the equal in 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 <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // for panic::matrix
namespace panic{
namespace math{
/**
* @brief Find the equal for a scalar to every element of a vector.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param a Input vector.
* @param k Scalar value compared 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 <typename T>
bool equal(const panic::tensor::vector<T>& a, const T k, panic::tensor::vector<T>& c);
/**
* @brief Returns a new vector containing a scalar equaled to every element.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param a Input vector.
* @param k Scalar value compared 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 <typename T>
panic::tensor::vector<T> equal(const panic::tensor::vector<T>& a, const T k);
/**
* @brief Equal a vector elementwise too a vector.
*
* Computes:
* @code
* @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 <typename T>
bool equal(const panic::tensor::vector<T>& a, const panic::tensor::vector<T>& b, panic::tensor::vector<T>& c);
/**
* @brief Returns a new vector containing a vector with equals elementwise.
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param a First vector.
* @param b Second vector. Must have size of @p a
* @param k Scalar value compared 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 <typename T>
panic::tensor::vector<T> equal(const panic::tensor::vector<T>& a, const panic::tensor::vector<T>& b);
/**
* @brief Equal compared a scalar to every element of a matix.
*
* Computes:
* @code
* @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 <typename T>
bool equal(const panic::tensor::matrix<T>& A, const T k, panic::tensor::matrix<T>& C);
/**
* @brief Returns a new matrix containing a scalar equal compared to every element.
*
* Computes:
* @code
* @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 <typename T>
panic::tensor::matrix<T> equal(const panic::tensor::matrix<T>& A, const T k);
/**
* @brief Equal compared a matrix elementwise too a matrix.
*
* Computes:
* @code
* @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 <typename T>
bool equal(const panic::tensor::matrix<T>& A, const panic::tensor::matrix<T>& B, panic::tensor::matrix<T>& C);
/**
* @brief Returns a new matrix containing a matrix equal compaed elementwise.
*
* Computes:
* @code
* @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 <typename T>
panic::tensor::matrix<T> equal(const panic::tensor::matrix<T>& A, const panic::tensor::matrix<T>& B);
/**
* @brief Equal compared a vector rowwise too a matrix.
*
* Computes:
* @code
* @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 <typename T>
bool equal_rowwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b, panic::tensor::matrix<T>& C);
/**
* @brief Equal compared a vector rowwise too a matrix.
*
* Computes:
* @code
* @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 <typename T>
panic::tensor::matrix<T> equal_rowwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b);
/**
* @brief Equal compared a vector colwise too a matrix.
*
* Computes:
* @code
* @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 <typename T>
bool equal_colwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b, panic::tensor::matrix<T>& C);
/**
* @brief Equal compared a vector colwise too a matrix.
*
* Computes:
* @code
* @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 <typename T>
panic::tensor::matrix<T> equal_colwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b);
} // namespace math
} // namespace panic
+1 -1
View File
@@ -99,7 +99,7 @@ bool exp(const panic::tensor::vector<T>& a, panic::tensor::vector<T>& c);
* @note This overload is convenient, but may allocate a new vector.
*/
template <typename T>
panic::tensor::vector<T> add(const panic::tensor::vector<T>& a);
panic::tensor::vector<T> exp(const panic::tensor::vector<T>& a);
/**
* @brief Calculates the expnential elementwise of a matrix
+18 -18
View File
@@ -24,11 +24,11 @@
* Module Name: math
* File Name: log.cpp
* Revision: 0.1.0
* Date: 29-07-2026
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to calculate the logorithem of numbers
* Functions to calculate the natural logorithem of numbers
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#pragma once
@@ -42,30 +42,30 @@ namespace math{
/**
* @brief calculates the exponential of a value.
* @brief calculates the log of a value.
*
* Computes:
* @code
* result = exp(k)
* result = log(k)
* @endcode
*
* @tparam T Numeric element type.
* @param k Value to take the exp of.
* @param x Value to take the log of.
*
* @return The calculated value
*
* @note This function is omp-friendly.
*/
template <typename T>
T exp(const T x);
T log(const T x);
/**
* @brief Calculates the exponential elementwise in a vector
* @brief Calculates the natrual logorithmic elementwise in a vector
*
* Computes:
* @code
* c[i] = exp(a[i])
* c[i] = log(a[i])
* @endcode
*
* @tparam T Numeric element type.
@@ -79,14 +79,14 @@ T exp(const T x);
* unnecessary temporary allocations.
*/
template <typename T>
bool exp(const panic::tensor::vector<T>& a, panic::tensor::vector<T>& c);
bool log(const panic::tensor::vector<T>& a, panic::tensor::vector<T>& c);
/**
* @brief Calculates the exponential elementwise in a vector
* @brief Calculates the natrual log elementwise in a vector
*
* Computes:
* @code
* result[i] = exp(a[i])
* result[i] = log(a[i])
* @endcode
*
* @tparam T Numeric element type.
@@ -98,14 +98,14 @@ bool exp(const panic::tensor::vector<T>& a, panic::tensor::vector<T>& c);
* @note This overload is convenient, but may allocate a new vector.
*/
template <typename T>
panic::tensor::vector<T> add(const panic::tensor::vector<T>& a);
panic::tensor::vector<T> log(const panic::tensor::vector<T>& a);
/**
* @brief Calculates the expnential elementwise of a matrix
* @brief Calculates the natrual log elementwise of a matrix
*
* Computes:
* @code
* C(i,j) = exp(A(i,j))
* C(i,j) = log(A(i,j))
* @endcode
*
* @tparam T Numeric element type.
@@ -119,14 +119,14 @@ panic::tensor::vector<T> add(const panic::tensor::vector<T>& a);
* unnecessary temporary allocations.
*/
template <typename T>
bool exp(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& C);
bool log(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& C);
/**
* @brief Returns the calculated ecponential elementwise of the matrix
* @brief Returns the calculated natrual log elementwise of the matrix
*
* Computes:
* @code
* result(i,j) = exp(A(i,j))
* result(i,j) = log(A(i,j))
* @endcode
*
* @tparam T Numeric element type.
@@ -138,7 +138,7 @@ bool exp(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& C);
* @note This overload is convenient, but may allocate a new vector.
*/
template <typename T>
panic::tensor::matrix<T> exp(const panic::tensor::matrix<T>& A);
panic::tensor::matrix<T> log(const panic::tensor::matrix<T>& A);
} // namespace math
} // namespace panic
+7 -6
View File
@@ -33,6 +33,7 @@
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#pragma once
#include <config/types.hpp>
#include <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // for panic::matrix
@@ -60,7 +61,7 @@ namespace math{
* @note This overload is convenient, but may allocate a new vector.
*/
template <typename T>
T mean(const panic::tensor::vector<T>& a);
panic::types::real_t mean(const panic::tensor::vector<T>& a);
/**
* @brief Returns the mean value of a matrix.
@@ -78,7 +79,7 @@ T mean(const panic::tensor::vector<T>& a);
*
*/
template <typename T>
T mean(const panic::tensor::matrix<T>& A);
panic::types::real_t mean(const panic::tensor::matrix<T>& A);
/**
* @brief Find the mean values row-wise of a matrix.
@@ -96,7 +97,7 @@ T mean(const panic::tensor::matrix<T>& A);
* @return false if vector sizes do not match or resizing @p c failed.
*/
template <typename T>
bool mean_rowwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& c);
bool mean_rowwise(const panic::tensor::real_matrix& A, panic::tensor::real_vector& c);
/**
* @brief Returns a new matrix containing the mean row-wise elementwise.
@@ -115,7 +116,7 @@ bool mean_rowwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& c
* @note This overload is convenient, but may allocate a new vector.
*/
template <typename T>
panic::tensor::vector<T> mean_rowwise(const panic::tensor::matrix<T>& A);
panic::tensor::real_vector mean_rowwise(const panic::tensor::real_matrix& A);
/**
@@ -134,7 +135,7 @@ panic::tensor::vector<T> mean_rowwise(const panic::tensor::matrix<T>& A);
* @return false if vector sizes do not match or resizing @p c failed.
*/
template <typename T>
bool mean_colwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& c);
bool mean_colwise(const panic::tensor::real_matrix& A, panic::tensor::real_vector& c);
/**
* @brief Returns a new matrix containing the mean column-wise elementwise.
@@ -153,7 +154,7 @@ bool mean_colwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& c
* @note This overload is convenient, but may allocate a new vector.
*/
template <typename T>
panic::tensor::vector<T> mean_colwise(const panic::tensor::matrix<T>& A);
panic::tensor::real_vector mean_colwise(const panic::tensor::real_matrix& A);
} // namespace math
} // namespace panic
+86
View File
@@ -0,0 +1,86 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* 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: transpose.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to transpose a matrix;
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#pragma once
//---------------------------------------------------------------------------------------------------------------------------
// INCLUDE DESCRIPTION
//-----------------------------------------------------------------------------------------------------
#include <tensor/matrix.hpp> // for panic::real_matrix
namespace panic{
namespace math{
/**
* @brief Transposes a matrix.
*
* Computes:
* @code
* B = transpose(A)
* @endcode
*
* @tparam T Numeric element type.
* @param A Input matrix.
* @param B Output matrix with result.
*
* @return true if success
* @return false if resizeing fails or dimention mismatch
*
*/
template <typename T>
bool transpose(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& B);
/**
* @brief Returns a new matrix of the transposed A.
*
* Computes:
* @code
* result = transpose(A)
* @endcode
*
* @tparam T Numeric element type.
* @param A Input matrix.
*
* @return A new matrix containing the result.
* @return An empty vector if the operation fails.
*
* @note This overload is convenient, but may allocate a new matrix.
*/
template <typename T>
panic::tensor::matrix<T> transpose(const panic::tensor::matrix<T>& A);
} // namespace math
} // namespace panic
@@ -77,7 +77,7 @@ struct activation_relu : public layer{
*
* @Note Calculates -> outputs = inputs * weights + biases
*/
bool forward(const panic::tensor::real_matrix& inputs);
bool forward(const panic::tensor::real_matrix& input_data);
/**
* @brief Backward function for layer
@@ -86,7 +86,7 @@ struct activation_relu : public layer{
*
* @Note Calculates derivative of forward function.
*/
bool backward(const panic::tensor::real_matrix& dinpus);
bool backward(const panic::tensor::real_matrix& dvalues);
};
} // namespace tensor
@@ -77,7 +77,7 @@ struct activation_softmax : public layer{
*
* @Note Calculates -> outputs = inputs * weights + biases
*/
bool forward(const panic::tensor::real_matrix& inputs);
bool forward(const panic::tensor::real_matrix& input_data);
/**
* @brief Backward function for layer
@@ -86,7 +86,7 @@ struct activation_softmax : public layer{
*
* @Note Calculates derivative of forward function.
*/
bool backward(const panic::tensor::real_matrix& dinpus);
bool backward(const panic::tensor::real_matrix& dvalues);
};
} // namespace tensor
+14
View File
@@ -56,6 +56,14 @@ namespace panic{
*/
struct layer{
/**
* @brief Emphty output matrix to store layer input
*
* Output shape:
* samples x neuron_count
*/
panic::tensor::real_matrix inputs;
/**
* @brief Emphty output matrix to store layer output
*
@@ -64,6 +72,12 @@ struct layer{
*/
panic::tensor::real_matrix outputs;
/**
* @brief Emphty matrix to store output for backward pass
*
*/
panic::tensor::real_matrix dinputs;
/**
* @brief Default de-constructor
*
+10 -2
View File
@@ -58,6 +58,12 @@ namespace panic{
*/
struct layer_dense : public layer{
/**
* @brief Emphty matrix to store input data
*
*/
panic::tensor::real_matrix ipnuts;
/**
* @brief Emphty weight matrix to store layer weights
*
@@ -65,6 +71,7 @@ struct layer_dense : public layer{
* input_size x neuron_count
*/
panic::tensor::real_matrix weights;
panic::tensor::real_matrix dweights;
/**
* @brief Emphty bias vector to store layer bias
@@ -73,6 +80,7 @@ struct layer_dense : public layer{
* 1 x neuron_count
*/
panic::tensor::real_vector biases;
panic::tensor::real_vector dbiases;
/**
* @brief Empthy constructor
@@ -102,7 +110,7 @@ struct layer_dense : public layer{
*
* @Note Calculates -> outputs = inputs * weights + biases
*/
bool forward(const panic::tensor::real_matrix& inputs);
bool forward(const panic::tensor::real_matrix& input_data);
/**
* @brief Backward function for layer
@@ -111,7 +119,7 @@ struct layer_dense : public layer{
*
* @Note Calculates derivative of forward function.
*/
bool backward(const panic::tensor::real_matrix& dinpus);
bool backward(const panic::tensor::real_matrix& dvalues);
};
} // namespace tensor
+6
View File
@@ -68,6 +68,12 @@ struct loss{
*/
panic::types::real_t data_loss;
/**
* @brief Matrix for backwards pass
*/
panic::tensor::real_matrix dinputs;
/**
* @brief Default de-constructor
*
@@ -82,9 +82,35 @@ struct loss_categorical_crossentropy: loss{
const panic::tensor::real_matrix& y_pred,
const panic::tensor::real_matrix& y_true);
};
/**
* @brief backward function to calculate from losses
*
* @param y_pred Matrix of model predection.
* @param y_true Vector of true label of data.
*
*/
bool backward(
const panic::tensor::real_matrix& dvalues,
const panic::tensor::uint_vector& y_true);
/**
* @brief backward function to calculate from losses
*
* @param y_pred Matrix of model predection.
* @param y_true Vector of true label of data.
*
* @Note Overloaded if one-shot endcoded
* is used.
*/
bool backward(
const panic::tensor::real_matrix& dvalues,
const panic::tensor::real_matrix& y_true);
};
} // namespace neural_network
} // namespace panic
+93
View File
@@ -0,0 +1,93 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
*
* 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: tensor
* File Name: eye.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to generate eye matrices
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#pragma once
#include <tensor/matrix.hpp> // for panic::vector
#include <config/types.hpp>
namespace panic{
namespace tensor{
/**
* @brief Outputs an eye matrix
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param size Number or rows and columns.
* @param A Output matrix
*
* @return true if @p A was resized and filled successfully.
* @return false if resizing @p A failed.
*
* @note This overload writes the result into an existing vector to avoid
* unnecessary temporary allocations.
*/
template <typename T>
bool eye(const panic::types::uint_t size, panic::tensor::matrix<T> A);
/**
* @brief Returns a eye matrix
*
* Computes:
* @code
* @endcode
*
* @param T Numeric element type.
* @param size Number of rows and columns.
*
* @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 <typename T>
//panic::tensor::matrix<T> eye(const T size);
} // namespace tensor
} // namespace panic
+91
View File
@@ -0,0 +1,91 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
*
* 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: tensor
* File Name: one_hot.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to one_hot matrices
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#pragma once
#include <tensor/vector.hpp>
#include <tensor/matrix.hpp> // for panic::vector
#include <config/types.hpp>
namespace panic{
namespace tensor{
/**
* @brief Outputs an one_hot matrix
*
* Computes:
* @code
* @endcode
*
* @tparam T Numeric element type.
* @param size Number of columns.
* @param a Input vector that contains here 1 should be
* @param B Output matrix
*
* @return true if @p B was resized and filled successfully.
* @return false if resizing @p B failed.
*
* @note This overload writes the result into an existing vector to avoid
* unnecessary temporary allocations.
*/
template <typename T>
bool one_hot(const panic::types::uint_t size, const panic::tensor::uint_vector& a, panic::tensor::matrix<T>& B);
/**
* @brief Returns a one_hot matrix
*
* Computes:
* @code
* @endcode
*
* @param T Numeric element type.
* @param size Number of columns.
* @param a Input vector that contains here 1 should be
*
* @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 <typename T>
//panic::tensor::matrix<T> one_hot(const panic::types::uint_t size, const panic::tensor::vector<T>& a);
} // namespace tensor
} // namespace panic
+28 -1
View File
@@ -59,6 +59,10 @@
#include <math/exp.hpp>
#include <math/sub.hpp>
#include <neural_network/loss/loss_categorical_crossentropy.hpp>
#include <math/log.hpp>
#include <math/argmax.hpp>
#include <math/equal.hpp>
#include <math/mean.hpp>
#include <math.h>
@@ -731,9 +735,32 @@ int main(void) {
// Create activation softmax layer
mymodel.add_activation_softmax();
// create loss function
panic::neural_network::loss_categorical_crossentropy loss_function;
mymodel.forward(X);
panic::io::print_matrix(mymodel.outputs);
loss_function.calculate(mymodel.outputs, y);
panic::tensor::uint_vector prediction;
prediction = panic::math::argmax_rowwise(mymodel.outputs);
panic::types::real_t accuracy;
panic::tensor::uint_vector comparisons;
comparisons = panic::math::equal(prediction, y);
accuracy = panic::math::mean(comparisons);
std::cout << "loss: " << loss_function.data_loss << std::endl;
std::cout << "acc: " << accuracy << std::endl;
+387
View File
@@ -0,0 +1,387 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* 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: argmax.cpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to find the index of the maximum value;
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
//---------------------------------------------------------------------------------------------------------------------------
// INCLUDE DESCRIPTION
//-----------------------------------------------------------------------------------------------------
#include <math/argmax.hpp>
#include <config/types.hpp>
#include <config/omp.hpp>
#include <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // 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 argmax_omp_min_work = 500;
//---------------------------------------------------------------------------------------------------------------------------
// INPLEMENTATION
//---------------------------------------------------------------------------------------------------------------------------
namespace panic {
namespace math {
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::argmax
//
// Description:
// Find the argmax index for a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::types::uint_t argmax(const panic::tensor::vector<T>& a){
panic::types::uint_t idx = 0;
if (a.size() == 0){
return idx;
}
for (panic::types::uint_t i = 0; i < a.size(); ++i){
if (a[idx] < a[i]){
idx = i;
}
}
return idx;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::types::uint_t argmax(const panic::tensor::vector<panic::types::uint_t>& a
);
template panic::types::uint_t argmax(const panic::tensor::vector<panic::types::int_t>& a
);
template panic::types::uint_t argmax(const panic::tensor::vector<panic::types::real_t>& a
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::argmax
//
// Description:
// Find the argmax value for a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool argmax(const panic::tensor::matrix<T>& A, panic::tensor::uint_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(2)){
return false;
}
b.fill(0);
for (panic::types::uint_t i = 0; i < A.rows(); ++i) {
for (panic::types::uint_t j = 0; j < A.cols(); ++j){
if (A(b[0], b[1]) < A(i,j)) {
b[0] = i;
b[1] = j;
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool argmax<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& a,
panic::tensor::uint_vector& b
);
template bool argmax<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& a,
panic::tensor::uint_vector& b
);
template bool argmax<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& a,
panic::tensor::uint_vector& b
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::argmax
//
// Description:
// Find the argmax value for a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::uint_vector argmax(const panic::tensor::matrix<T>& A){
panic::tensor::uint_vector b;
if (! argmax(A, b)){
return panic::tensor::uint_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::uint_vector argmax<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& A
);
template panic::tensor::uint_vector argmax<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& A
);
template panic::tensor::uint_vector argmax<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::argmax_rowwise
//
// Description:
// Find the index value of maximum row-wise of a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool argmax_rowwise(const panic::tensor::matrix<T>& A, panic::tensor::uint_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;
}
b.fill(0);
PANIC_OMP_PARALLEL_FOR_IF(work > argmax_omp_min_work)
for (panic::types::uint_t i = 0; i < rows; ++i){
for (panic::types::uint_t j = 0; j < cols; ++j){
if (A(i, b[i]) < 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 argmax_rowwise<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& A,
panic::tensor::uint_vector& b
);
template bool argmax_rowwise<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& A,
panic::tensor::uint_vector& b
);
template bool argmax_rowwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A,
panic::tensor::uint_vector& b
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::argmax_rowwise
//
// Description:
// Returns index row-wise max values
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::uint_vector argmax_rowwise(const panic::tensor::matrix<T>& A){
panic::tensor::uint_vector b;
if (!argmax_rowwise(A, b)){
return panic::tensor::uint_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::uint_vector
argmax_rowwise<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& A
);
template panic::tensor::uint_vector
argmax_rowwise<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& A
);
template panic::tensor::uint_vector
argmax_rowwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::argmax_colwise
//
// Description:
// Find the index of the maximum column-wise of a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool argmax_colwise(const panic::tensor::matrix<T>& A, panic::tensor::uint_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;
}
b.fill(0);
PANIC_OMP_PARALLEL_FOR_IF(work > argmax_omp_min_work)
for (panic::types::uint_t i = 0; i < cols; ++i){
for (panic::types::uint_t j = 0; j < rows; ++j){
if(A(j, b[i]) < A(j,i)){
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 argmax_colwise<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& A,
panic::tensor::uint_vector& b
);
template bool argmax_colwise<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& A,
panic::tensor::uint_vector& b
);
template bool argmax_colwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A,
panic::tensor::uint_vector& b
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::argmax_colwise
//
// Description:
// Returns column-wise max index values
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::uint_vector argmax_colwise(const panic::tensor::matrix<T>& A){
panic::tensor::uint_vector b;
if (!argmax_colwise(A, b)){
return panic::tensor::uint_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::uint_vector
argmax_colwise<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& A
);
template panic::tensor::uint_vector
argmax_colwise<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& A
);
template panic::tensor::uint_vector
argmax_colwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A
);
} // namespace math
} // namespace panic
+199
View File
@@ -0,0 +1,199 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* 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: dot.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to calculate dot product of tensors;
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
//---------------------------------------------------------------------------------------------------------------------------
// INCLUDE DESCRIPTION
//-----------------------------------------------------------------------------------------------------
#include <math/dot.hpp>
#include <config/omp.hpp>
#include <tensor/vector.hpp>
#include <tensor/matrix.hpp> // for panic::tensor::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 dot_omp_min_work = 500;
//---------------------------------------------------------------------------------------------------------------------------
// INPLEMENTATION
//---------------------------------------------------------------------------------------------------------------------------
namespace panic {
namespace math {
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::dot
//
// Description:
// Multiply sum two vector.
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
T dot(const panic::tensor::vector<T>& a, const panic::tensor::vector<T>& b){
T result = T{0};
if (a.size() != b.size()){
return result;
}
// 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() > dot_omp_min_work, +, result)
for (panic::types::uint_t i = 0; i < a.size(); ++i){
result += a[i]*b[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 dot(const panic::tensor::vector<panic::types::uint_t>& a,
const panic::tensor::vector<panic::types::uint_t>& b
);
template panic::types::int_t dot(const panic::tensor::vector<panic::types::int_t>& a,
const panic::tensor::vector<panic::types::int_t>& b
);
template panic::types::real_t dot(const panic::tensor::vector<panic::types::real_t>& a,
const panic::tensor::vector<panic::types::real_t>& b
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::dot
//
// Description:
// Multiply sum a matrix and vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool dot(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b, panic::tensor::vector<T>& c){
if (b.size() != A.rows()){
return false;
}
c.fill(0);
PANIC_OMP_PARALLEL_FOR_IF(A.rows()*A.cols() > dot_omp_min_work)
for (panic::types::uint_t i = 0; i < A.rows(); ++i){
for (panic::types::uint_t j = 0; j < A.cols(); ++j){
c[i] += 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 dot(
const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::vector<panic::types::uint_t>& b,
panic::tensor::vector<panic::types::uint_t>& c
);
template bool dot(
const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::vector<panic::types::int_t>& b,
panic::tensor::vector<panic::types::int_t>& c
);
template bool dot(
const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::vector<panic::types::real_t>& b,
panic::tensor::vector<panic::types::real_t>& c
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::dot
//
// Description:
// Multiply sum a matrix and vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::vector<T> dot(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b){
panic::tensor::vector<T> c;
if (! dot(A,b,c)){
return panic::tensor::vector<T>();
}
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<panic::types::uint_t> dot(
const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::vector<panic::types::uint_t>& b
);
template panic::tensor::vector<panic::types::int_t> dot(
const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::vector<panic::types::int_t>& b
);
template panic::tensor::vector<panic::types::real_t> dot(
const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::vector<panic::types::real_t>& b
);
} // namespace math
} // namespace panic
+614
View File
@@ -0,0 +1,614 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* 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: equal.cpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to find the equal in panic::tensor
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
//---------------------------------------------------------------------------------------------------------------------------
// INCLUDE DESCRIPTION
//-----------------------------------------------------------------------------------------------------
#include <math/equal.hpp>
#include <config/omp.hpp>
#include <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // 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 equal_omp_min_work = 500;
//---------------------------------------------------------------------------------------------------------------------------
// INPLEMENTATION
//---------------------------------------------------------------------------------------------------------------------------
namespace panic {
namespace math {
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// Equal compares a constant to a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool equal(const panic::tensor::vector<T>& a, const T k, panic::tensor::vector<T>& c){
if (!c.resize(a.size())){
return false;
}
PANIC_OMP_PARALLEL_FOR_IF(a.size() > equal_omp_min_work)
for (panic::types::uint_t i = 0; i < a.size(); ++i){
if (a[i] == k){
c[i] = T{1};
}
else{
c[i] = T{0};
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool equal<panic::types::uint_t>(const panic::tensor::vector<panic::types::uint_t>& a,
const panic::types::uint_t k,
panic::tensor::vector<panic::types::uint_t>& c
);
template bool equal<panic::types::int_t>(const panic::tensor::vector<panic::types::int_t>& a,
const panic::types::int_t k,
panic::tensor::vector<panic::types::int_t>& c
);
template bool equal<panic::types::real_t>(const panic::tensor::vector<panic::types::real_t>& a,
const panic::types::real_t k,
panic::tensor::vector<panic::types::real_t>& c
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// Equal compared a constant to a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::vector<T> equal(const panic::tensor::vector<T>& a, const T k){
panic::tensor::vector<T> c(a.size());
if (!equal(a, k, c)){
return panic::tensor::vector<T>();
}
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<panic::types::uint_t>
equal(const panic::tensor::vector<panic::types::uint_t>& a,
const panic::types::uint_t k
);
template panic::tensor::vector<panic::types::int_t>
equal(const panic::tensor::vector<panic::types::int_t>& a,
const panic::types::int_t k
);
template panic::tensor::vector<panic::types::real_t>
equal(const panic::tensor::vector<panic::types::real_t>& a,
const panic::types::real_t k
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// Equal compared a vector to a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool equal(const panic::tensor::vector<T>& a, const panic::tensor::vector<T>& b, panic::tensor::vector<T>& c){
if (a.size() != b.size()){
return false;
}
if (!c.resize(a.size())){
return false;
}
PANIC_OMP_PARALLEL_FOR_IF(a.size() > equal_omp_min_work)
for (panic::types::uint_t i = 0; i < a.size(); ++i){
if (a[i] == b[i]){
c[i] = T{1};
}
else{
c[i] = T{0};
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool equal(const panic::tensor::vector<panic::types::uint_t>& a,
const panic::tensor::vector<panic::types::uint_t>& b,
panic::tensor::vector<panic::types::uint_t>& c
);
template bool equal(const panic::tensor::vector<panic::types::int_t>& a,
const panic::tensor::vector<panic::types::int_t>& b,
panic::tensor::vector<panic::types::int_t>& c
);
template bool equal(const panic::tensor::vector<panic::types::real_t>& a,
const panic::tensor::vector<panic::types::real_t>& b,
panic::tensor::vector<panic::types::real_t>& c
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// equal compared a vector to a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::vector<T> equal(const panic::tensor::vector<T>& a, const panic::tensor::vector<T>& b){
panic::tensor::vector<T> c(a.size());
if (!equal(a, b, c)){
return panic::tensor::vector<T>();
}
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<panic::types::uint_t>
equal(const panic::tensor::vector<panic::types::uint_t>& a,
const panic::tensor::vector<panic::types::uint_t>& b
);
template panic::tensor::vector<panic::types::int_t>
equal(const panic::tensor::vector<panic::types::int_t>& a,
const panic::tensor::vector<panic::types::int_t>& b
);
template panic::tensor::vector<panic::types::real_t>
equal(const panic::tensor::vector<panic::types::real_t>& a,
const panic::tensor::vector<panic::types::real_t>& b
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// equal compared a constant to a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool equal(const panic::tensor::matrix<T>& A, const T k, panic::tensor::matrix<T>& 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 > equal_omp_min_work)
for (panic::types::uint_t i = 0; i < rows; ++i){
for (panic::types::uint_t j = 0; j < cols; ++j){
if (A(i,j) == k){
C(i,j) = T{1};
}
else{
C(i,j) = T{0};
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool equal(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::types::uint_t k,
panic::tensor::matrix<panic::types::uint_t>& C
);
template bool equal(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::types::int_t k,
panic::tensor::matrix<panic::types::int_t>& C
);
template bool equal(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::types::real_t k,
panic::tensor::matrix<panic::types::real_t>& C
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// equal compared a constant to a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> equal(const panic::tensor::matrix<T>& A, const T k){
panic::tensor::matrix<T> C;
if (!equal(A, k, C)){
return panic::tensor::matrix<T>();
}
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<panic::types::uint_t>
equal(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::types::uint_t k
);
template panic::tensor::matrix<panic::types::int_t>
equal(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::types::int_t k
);
template panic::tensor::matrix<panic::types::real_t>
equal(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::types::real_t k
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// equal compared a matrix to a matrix elementwise
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool equal(const panic::tensor::matrix<T>& A, const panic::tensor::matrix<T>& B, panic::tensor::matrix<T>& 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 > equal_omp_min_work)
for (panic::types::uint_t i = 0; i < rows; ++i){
for (panic::types::uint_t j = 0; j < cols; ++j){
if ( A(i,j) == B(i,j)){
C(i,j) = T{1};
}
else{
C(i,j) = T{0};
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool equal(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::matrix<panic::types::uint_t>& B,
panic::tensor::matrix<panic::types::uint_t>& C
);
template bool equal(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::matrix<panic::types::int_t>& B,
panic::tensor::matrix<panic::types::int_t>& C
);
template bool equal(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::matrix<panic::types::real_t>& B,
panic::tensor::matrix<panic::types::real_t>& C
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal
//
// Description:
// equal compared a matrix to a matrix elementwise
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> equal(const panic::tensor::matrix<T>& A, const panic::tensor::matrix<T>& B){
panic::tensor::matrix<T> C;
if (!equal(A, B, C)){
return panic::tensor::matrix<T>();
}
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<panic::types::uint_t>
equal(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::matrix<panic::types::uint_t>& B
);
template panic::tensor::matrix<panic::types::int_t>
equal(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::matrix<panic::types::int_t>& B
);
template panic::tensor::matrix<panic::types::real_t>
equal(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::matrix<panic::types::real_t>& B
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal_rowwise
//
// Description:
// equal compared a vector row-wise to a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool equal_rowwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b, panic::tensor::matrix<T>& 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 > equal_omp_min_work)
for (panic::types::uint_t i = 0; i < rows; ++i){
for (panic::types::uint_t j = 0; j < cols; ++j){
if (A(i,j) == b[j]){
C(i,j) = T{1};
}
else{
C(i,j) = T{0};
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool equal_rowwise(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::vector<panic::types::uint_t>& b,
panic::tensor::matrix<panic::types::uint_t>& C
);
template bool equal_rowwise(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::vector<panic::types::int_t>& b,
panic::tensor::matrix<panic::types::int_t>& C
);
template bool equal_rowwise(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::vector<panic::types::real_t>& b,
panic::tensor::matrix<panic::types::real_t>& C
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal_rowwise
//
// Description:
// equal_rowwise a vector row-wise to a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> equal_rowwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b){
panic::tensor::matrix<T> C;
if (!equal_rowwise(A, b, C)){
return panic::tensor::matrix<T>();
}
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<panic::types::uint_t>
equal_rowwise(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::vector<panic::types::uint_t>& b
);
template panic::tensor::matrix<panic::types::int_t>
equal_rowwise(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::vector<panic::types::int_t>& b
);
template panic::tensor::matrix<panic::types::real_t>
equal_rowwise(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::vector<panic::types::real_t>& b
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal_colwise
//
// Description:
// equal_colwise a vector coloumn-wise to a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool equal_colwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b, panic::tensor::matrix<T>& 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 > equal_omp_min_work)
for (panic::types::uint_t i = 0; i < cols; ++i){
for (panic::types::uint_t j = 0; j < rows; ++j){
if (A(j,i) == b[i]){
C(j,i) == T{1};
}
else{
C(j,i) = T{0};
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool equal_colwise(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::vector<panic::types::uint_t>& b,
panic::tensor::matrix<panic::types::uint_t>& C
);
template bool equal_colwise(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::vector<panic::types::int_t>& b,
panic::tensor::matrix<panic::types::int_t>& C
);
template bool equal_colwise(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::vector<panic::types::real_t>& b,
panic::tensor::matrix<panic::types::real_t>& C
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::equal_colwise
//
// Description:
// equal_colwise a vector coloumn-wise to a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> equal_colwise(const panic::tensor::matrix<T>& A, const panic::tensor::vector<T>& b){
panic::tensor::matrix<T> C;
if (!equal_colwise(A, b, C)){
return panic::tensor::matrix<T>();
}
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<panic::types::uint_t>
equal_colwise(const panic::tensor::matrix<panic::types::uint_t>& A,
const panic::tensor::vector<panic::types::uint_t>& b
);
template panic::tensor::matrix<panic::types::int_t>
equal_colwise(const panic::tensor::matrix<panic::types::int_t>& A,
const panic::tensor::vector<panic::types::int_t>& b
);
template panic::tensor::matrix<panic::types::real_t>
equal_colwise(const panic::tensor::matrix<panic::types::real_t>& A,
const panic::tensor::vector<panic::types::real_t>& b
);
} // namespace math
} // namespace panic
+193 -103
View File
@@ -24,11 +24,11 @@
* Module Name: math
* File Name: log.cpp
* Revision: 0.1.0
* Date: 29-07-2026
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to calculate the logorithem of numbers
* Functions to calculate the natrual logorithem of numbers
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
@@ -52,7 +52,7 @@
* 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 exp_omp_min_work = 500;
static const panic::types::uint_t log_omp_min_work = 250;
//---------------------------------------------------------------------------------------------------------------------------
// INPLEMENTATION
//---------------------------------------------------------------------------------------------------------------------------
@@ -64,94 +64,184 @@ namespace panic {
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::exp
// Function Name : panic::math::log
//
// Description:
// Calculates the exponential
// Calculates the natural log
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
T exp(const T x){
T log(const T x){
// The identity:
//
// e^(-x) = 1 / e^x
//
// lets the rest of the function work only with positive values.
if (x < static_cast<T>(0)) {
return static_cast<T>(1) / exp(-x);
T result = T{0};
const T zero = T{0};
const T one = T{1};
const T two = T{2};
/*
* The real natural logarithm is only defined for
* positive numbers.
*
* log(0) approaches negative infinity, while negative
* x would require complex numbers.
*/
if (x <= zero){
return result;
}
// Natural logarithm of 2.
//
// This is useful because:
//
// e^(ln(2)) = 2
//
const T ln2 = static_cast<T>(0.69314718055994530942);
// Split x into:
//
// x = k * ln(2) + r
//
// For example, when x = 2:
//
// k = floor(2 / ln(2)) = 2
// r = 2 - 2 * ln(2) ≈ 0.6137
//
// This makes r small, which makes the Taylor series
// converge much faster.
const panic::types::uint_t k = static_cast<panic::types::uint_t>(x / ln2);
const T r = x - static_cast<T>(k) * ln2;
// Taylor series:
//
// r² r³ r⁴
// e^r = 1 + r + ---- + ---- + ---- + ...
// 2! 3! 4!
//
// result starts with the first term: 1.
T result = static_cast<T>(1);
// term also starts at 1, representing:
//
// r^0 / 0! = 1
T term = static_cast<T>(1);
for (panic::types::uint_t n = 1; n <= 15; ++n){
// Produce the next Taylor term from the previous one.
//
// For example:
//
// n = 1: term = 1 * r / 1 = r
// n = 2: term = r * r / 2 = r² / 2!
// n = 3: term = r²/2 * r/3 = r³ / 3!
//
// This avoids separately calculating powers and factorials.
term *= r / static_cast<T>(n);
// Add the new term to the approximation.
result += term;
/*
* NaN is the only floating-point value that is not
* equal to itself.
*/
if (x != x){
return result;
}
// We currently have e^r.
//
// From:
//
// x = k * ln(2) + r
//
// we get:
//
// e^x = e^(k * ln(2)) * e^r
// = 2^k * e^r
//
// Therefore, multiply the result by 2 exactly k times.
for (panic::types::uint_t i = 0; i < k; ++i) {
result *= static_cast<T>(2);
/*
* This is ln(2).
*
* We need it later because we rewrite the input as:
*
* input = value * 2^exponent
*
* Therefore:
*
* ln(input) = ln(value) + exponent * ln(2)
*/
static const T ln_2 = static_cast<T>(0.69314718055994530942);
/*
* value will be reduced to the interval [1, 2).
*
* exponent records how many powers of two were removed
* or added.
*/
T value = x;
panic::types::int_t exponent = 0;
/*
* Example:
*
* x = 20
*
* 20 / 2 = 10
* 10 / 2 = 5
* 5 / 2 = 2.5
* 2.5 / 2 = 1.25
*
* Therefore:
*
* 20 = 1.25 * 2^4
*
* So value becomes 1.25 and exponent becomes 4.
*/
while (value >= two){
value *= T{0.5};
++exponent;
}
/*
* For an input smaller than 1, multiply by two until it
* reaches [1, 2).
*
* Example:
*
* 0.25 * 2 = 0.5
* 0.5 * 2 = 1
*
* Therefore:
*
* 0.25 = 1 * 2^-2
*/
while (value < one){
value *= two;
--exponent;
}
/*
* Transform value into a smaller number near zero:
*
* y = (value - 1) / (value + 1)
*
* Since value is in [1, 2), y is in [0, 1/3).
*
* Small y values are useful because powers such as
* y^3, y^5 and y^7 become small very quickly.
*/
const T y = (value - one) / (value + one);
/*
* The series uses only odd powers:
*
* y, y^3, y^5, y^7, ...
*
* Multiplying by y^2 moves from one odd power to the next:
*
* y * y^2 = y^3
* y^3 * y^2 = y^5
*/
const T y_squared = y * y;
/*
* term begins as y^1.
*/
T term = y;
/*
* Accumulates:
*
* y + y^3/3 + y^5/5 + ...
*/
T sum = zero;
/*
* Twenty terms are more than enough for float
* after the range reduction above.
*
* A fixed number of iterations also makes the runtime
* predictable.
*/
for (panic::types::uint_t i = 0; i < 20; ++i){
/*
* The denominators are:
*
* 1, 3, 5, 7, ...
*
* which are generated by 2*i + 1.
*/
const panic::types::uint_t denominator =
2 * i + 1;
sum += term / static_cast<T>(denominator);
/*
* Advance:
*
* y -> y^3 -> y^5 -> y^7
*/
term *= y_squared;
}
/*
* The series calculates:
*
* ln(value) =
* 2 * (y + y^3/3 + y^5/5 + ...)
*
* Then restore the power of two removed during range
* reduction:
*
* ln(input) =
* ln(value) + exponent * ln(2)
*/
result = two * sum + static_cast<T>(exponent) * ln_2;
return result;
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -160,28 +250,28 @@ T exp(const T x){
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::types::real_t exp<panic::types::real_t>(const panic::types::real_t x
template panic::types::real_t log<panic::types::real_t>(const panic::types::real_t x
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::exp
// Function Name : panic::math::log
//
// Description:
// Calculates the exponential elementwise of a vector
// Calculates the natrual log elementwise of a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool exp(const panic::tensor::vector<T>& a, panic::tensor::vector<T>& c){
bool log(const panic::tensor::vector<T>& a, panic::tensor::vector<T>& c){
if (!c.resize(a.size())){
return false;
}
PANIC_OMP_PARALLEL_FOR_IF(a.size() > exp_omp_min_work)
PANIC_OMP_PARALLEL_FOR_IF(a.size() > log_omp_min_work)
for (panic::types::uint_t i = 0; i < a.size(); ++i){
c[i] = exp(a[i]);
c[i] = log(a[i]);
}
return true;
@@ -193,23 +283,23 @@ bool exp(const panic::tensor::vector<T>& a, panic::tensor::vector<T>& c){
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool exp<panic::types::real_t>(const panic::tensor::vector<panic::types::real_t>& a,
template bool log<panic::types::real_t>(const panic::tensor::vector<panic::types::real_t>& a,
panic::tensor::vector<panic::types::real_t>& c
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::exp
// Function Name : panic::math::log
//
// Description:
// Calculates the exponential elementwise for a vector
// Calculates the natrual log elementwise for a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::vector<T> exp(const panic::tensor::vector<T>& a){
panic::tensor::vector<T> log(const panic::tensor::vector<T>& a){
panic::tensor::vector<T> c(a.size());
if (!exp(a, c)){
if (!log(a, c)){
return panic::tensor::vector<T>();
}
@@ -222,18 +312,18 @@ panic::tensor::vector<T> exp(const panic::tensor::vector<T>& a){
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::tensor::vector<panic::types::real_t>
exp(const panic::tensor::vector<panic::types::real_t>& a
log(const panic::tensor::vector<panic::types::real_t>& a
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::exp
// Function Name : panic::math::log
//
// Description:
// calculates the exponential elementwise of a matrix
// calculates the natrual log elementwise of a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool exp(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& C){
bool log(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& C){
panic::types::uint_t rows = A.rows();
panic::types::uint_t cols = A.cols();
@@ -244,10 +334,10 @@ bool exp(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& C){
}
PANIC_OMP_PARALLEL_FOR_IF(work > exp_omp_min_work)
PANIC_OMP_PARALLEL_FOR_IF(work > log_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) = exp(A(i,j));
C(i,j) = log(A(i,j));
}
}
@@ -260,7 +350,7 @@ bool exp(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& C){
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool exp(const panic::tensor::matrix<panic::types::real_t>& A,
template bool log(const panic::tensor::matrix<panic::types::real_t>& A,
panic::tensor::matrix<panic::types::real_t>& C
);
@@ -268,16 +358,16 @@ template bool exp(const panic::tensor::matrix<panic::types::real_t>& A,
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::exp
// Function Name : panic::math::log
//
// Description:
// Calculates the exponential element-wise of a matrix
// Calculates the natrual log element-wise of a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> exp(const panic::tensor::matrix<T>& A){
panic::tensor::matrix<T> log(const panic::tensor::matrix<T>& A){
panic::tensor::matrix<T> C;
if (!exp(A, C)){
if (!log(A, C)){
return panic::tensor::matrix<T>();
}
@@ -290,7 +380,7 @@ panic::tensor::matrix<T> exp(const panic::tensor::matrix<T>& A){
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::tensor::matrix<panic::types::real_t>
exp(const panic::tensor::matrix<panic::types::real_t>& A
log(const panic::tensor::matrix<panic::types::real_t>& A
);
+1 -1
View File
@@ -36,7 +36,7 @@
// INCLUDE DESCRIPTION
//-----------------------------------------------------------------------------------------------------
#include <math/add.hpp>
#include <math/max.hpp>
#include <config/omp.hpp>
#include <tensor/vector.hpp> // for panic::vector
+31 -30
View File
@@ -38,6 +38,7 @@
#include <math/mean.hpp>
#include <config/omp.hpp>
#include <config/types.hpp>
#include <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // for panic::matrix
@@ -69,11 +70,11 @@ namespace panic {
// Find the mean value for a vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
T mean(const panic::tensor::vector<T>& a){
panic::types::real_t mean(const panic::tensor::vector<T>& a){
T sum = panic::math::sum(a);
const panic::types::real_t sum = static_cast<panic::types::real_t>(panic::math::sum(a));
return sum / static_cast<T>(a.size());
return sum / static_cast<panic::types::real_t>(a.size());
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
@@ -81,9 +82,9 @@ T mean(const panic::tensor::vector<T>& a){
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::types::uint_t mean<panic::types::uint_t>(const panic::tensor::vector<panic::types::uint_t>& a
template panic::types::real_t mean<panic::types::uint_t>(const panic::tensor::vector<panic::types::uint_t>& a
);
template panic::types::int_t mean<panic::types::int_t>(const panic::tensor::vector<panic::types::int_t>& a
template panic::types::real_t mean<panic::types::int_t>(const panic::tensor::vector<panic::types::int_t>& a
);
template panic::types::real_t mean<panic::types::real_t>(const panic::tensor::vector<panic::types::real_t>& a
);
@@ -97,15 +98,15 @@ template panic::types::real_t mean<panic::types::real_t>(const panic::tensor::ve
// Find the mean value for a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
T mean(const panic::tensor::matrix<T>& A){
panic::types::real_t mean(const panic::tensor::matrix<T>& A){
panic::types::uint_t rows = A.rows();
panic::types::uint_t cols = A.cols();
panic::types::uint_t work = rows*cols;
T sum = panic::math::sum(A);
panic::types::real_t sum = static_cast<panic::types::real_t> (panic::math::sum(A));
return sum / static_cast<T>(work);
return sum / static_cast<panic::types::real_t>(work);
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
@@ -113,9 +114,9 @@ T mean(const panic::tensor::matrix<T>& A){
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::types::uint_t mean<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& a
template panic::types::real_t mean<panic::types::uint_t>(const panic::tensor::matrix<panic::types::uint_t>& a
);
template panic::types::int_t mean<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& a
template panic::types::real_t mean<panic::types::int_t>(const panic::tensor::matrix<panic::types::int_t>& a
);
template panic::types::real_t mean<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& a
);
@@ -130,8 +131,8 @@ template panic::types::real_t mean<panic::types::real_t>(const panic::tensor::ma
// Description:
// Find the mean row-wise of a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool mean_rowwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& b){
//template <typename T>
bool mean_rowwise(const panic::tensor::real_matrix& A, panic::tensor::real_vector& b){
panic::types::uint_t rows = A.rows();
panic::types::uint_t cols = A.cols();
@@ -154,7 +155,7 @@ bool mean_rowwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& b
}
return true;
}
}/*
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
@@ -170,7 +171,7 @@ template bool mean_rowwise<panic::types::int_t>(const panic::tensor::matrix<pani
template bool mean_rowwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A,
panic::tensor::vector<panic::types::real_t>& b
);
*/
@@ -180,16 +181,16 @@ template bool mean_rowwise<panic::types::real_t>(const panic::tensor::matrix<pan
// Description:
// Returns row-wise sum values
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::vector<T> mean_rowwise(const panic::tensor::matrix<T>& A){
panic::tensor::vector<T> b;
//template <typename T>
panic::tensor::real_vector mean_rowwise(const panic::tensor::real_matrix& A){
panic::tensor::real_vector b;
if (!mean_rowwise(A, b)){
return panic::tensor::vector<T>();
return panic::tensor::real_vector();
}
return b;
}
}/*
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
@@ -204,7 +205,7 @@ template panic::tensor::vector<panic::types::int_t>
);
template panic::tensor::vector<panic::types::real_t>
mean_rowwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A
);
);*/
@@ -237,8 +238,8 @@ template panic::tensor::vector<panic::types::real_t>
// Description:
// Find the mean column-wise of a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool mean_colwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& b){
//template <typename T>
bool mean_colwise(const panic::tensor::real_matrix& A, panic::tensor::real_vector& b){
panic::types::uint_t rows = A.rows();
panic::types::uint_t cols = A.cols();
@@ -259,7 +260,7 @@ bool mean_colwise(const panic::tensor::matrix<T>& A, panic::tensor::vector<T>& b
}
return true;
}
}/*
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
@@ -274,7 +275,7 @@ template bool mean_colwise<panic::types::int_t>(const panic::tensor::matrix<pani
);
template bool mean_colwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A,
panic::tensor::vector<panic::types::real_t>& b
);
);*/
@@ -285,16 +286,16 @@ template bool mean_colwise<panic::types::real_t>(const panic::tensor::matrix<pan
// Description:
// Returns column-wise mean values
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::vector<T> mean_colwise(const panic::tensor::matrix<T>& A){
panic::tensor::vector<T> b;
//template <typename T>
panic::tensor::real_vector mean_colwise(const panic::tensor::real_matrix& A){
panic::tensor::real_vector b;
if (!mean_colwise(A, b)){
return panic::tensor::vector<T>();
return panic::tensor::real_vector();
}
return b;
}
}/*
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
@@ -309,7 +310,7 @@ template panic::tensor::vector<panic::types::int_t>
);
template panic::tensor::vector<panic::types::real_t>
mean_colwise<panic::types::real_t>(const panic::tensor::matrix<panic::types::real_t>& A
);
);*/
} // namespace math
+146
View File
@@ -0,0 +1,146 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* 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: transpose.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to transpose a matrix;
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
//---------------------------------------------------------------------------------------------------------------------------
// INCLUDE DESCRIPTION
//-----------------------------------------------------------------------------------------------------
#include <math/transpose.hpp>
#include <config/omp.hpp>
#include <tensor/matrix.hpp> // for panic::tensor::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 transpose_omp_min_work = 500;
//---------------------------------------------------------------------------------------------------------------------------
// INPLEMENTATION
//---------------------------------------------------------------------------------------------------------------------------
namespace panic {
namespace math {
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::transpose
//
// Description:
// Transposes a matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool transpose(const panic::tensor::matrix<T>& A, panic::tensor::matrix<T>& 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, rows) ){
return false;
}
PANIC_OMP_PARALLEL_FOR_IF(work > transpose_omp_min_work)
for (panic::types::uint_t i = 0; i < rows; ++i){
for (panic::types::uint_t j = 0; j < cols; ++j){
B(j,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 transpose(const panic::tensor::matrix<panic::types::uint_t>& A,
panic::tensor::matrix<panic::types::uint_t>& B
);
template bool transpose(const panic::tensor::matrix<panic::types::int_t>& A,
panic::tensor::matrix<panic::types::int_t>& B
);
template bool transpose(const panic::tensor::matrix<panic::types::real_t>& A,
panic::tensor::matrix<panic::types::real_t>& B
);
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::dot
//
// Description:
// Multiply sum a matrix and vector
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> transpose(const panic::tensor::matrix<T>& A){
panic::tensor::matrix<T> B;
if (! transpose(A,B)){
return panic::tensor::matrix<T>();
}
return B;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::tensor::matrix<panic::types::uint_t> transpose(
const panic::tensor::matrix<panic::types::uint_t>& A
);
template panic::tensor::matrix<panic::types::int_t> transpose(
const panic::tensor::matrix<panic::types::int_t>& A
);
template panic::tensor::matrix<panic::types::real_t> transpose(
const panic::tensor::matrix<panic::types::real_t>& A
);
} // namespace math
} // namespace panic
@@ -76,7 +76,9 @@ activation_relu::activation_relu() {
// 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& input_data){
inputs = input_data;
panic::math::clip_lower(inputs, 0.0f, outputs);
@@ -92,7 +94,11 @@ bool activation_relu::forward(const panic::tensor::real_matrix& inputs){
// Calculated the backward pass:
// ??
//--------------------------------------------------------------------------------------------------------------------------
bool activation_relu::backward(const panic::tensor::real_matrix& dinputs){
bool activation_relu::backward(const panic::tensor::real_matrix& dvalues){
// Zero gradients where input values were negative
panic::types::real_t zero = 0;
dinputs = panic::math::clip_lower(dvalues, zero);
return true;
@@ -80,7 +80,9 @@ activation_softmax::activation_softmax() {
// Calculated the forward pass:
// outputs = max(inputs, 0)
//--------------------------------------------------------------------------------------------------------------------------
bool activation_softmax::forward(const panic::tensor::real_matrix& inputs){
bool activation_softmax::forward(const panic::tensor::real_matrix& input_data){
inputs = input_data;
panic::tensor::real_vector row_maximums;
panic::tensor::real_vector row_sums;
@@ -133,9 +135,30 @@ bool activation_softmax::forward(const panic::tensor::real_matrix& inputs){
// Calculated the backward pass:
// ??
//--------------------------------------------------------------------------------------------------------------------------
bool activation_softmax::backward(const panic::tensor::real_matrix& dinputs){
bool activation_softmax::backward(const panic::tensor::real_matrix& dvalues){
const panic::types::uint_t rows = dvalues.rows();
const panic::types::uint_t cols = dvalues.cols();
const panic::types::uint_t work = rows*cols;
if (outputs.rows() != rows || outputs.cols() != cols ){
return false;
}
if (!dinputs.resize(rows, cols)){
return false;
}
PANIC_OMP_PARALLEL_FOR_IF(work > activation_softmax_omp_min_size)
for (panic::types::uint_t i = 0; i < rows; ++i){
panic::types::real_t dot = 0;
for (panic::types::uint_t j = 0; j < cols; ++j){
dot += outputs(i,j) * dvalues(i,j);
}
for (panic::types::uint_t j = 0; j < cols; ++j){
dinputs(i,j) = outputs(i,j) * (dvalues(i,j) -dot);
}
}
return true;
}
+16 -5
View File
@@ -43,6 +43,9 @@
#include <math/add.hpp>
#include <random/uniform.hpp>
#include <math/transpose.hpp>
#include <math/sum.hpp>
//---------------------------------------------------------------------------------------------------------------------------
// PRIVATE CONSTANTS
//---------------------------------------------------------------------------------------------------------------------------
@@ -70,7 +73,8 @@ namespace panic{
layer_dense::layer_dense() {
weights.resize(0,0);
biases.resize(0);
outputs.resize(0,0);
dweights.resize(0,0);
dbiases.resize(0);
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -86,9 +90,7 @@ layer_dense::layer_dense(panic::types::uint_t input_size, panic::types::uint_t n
biases.resize(neurons);
biases.fill(0);
//panic::random::uniform(biases);
outputs.resize(0,0);
}
@@ -99,7 +101,9 @@ layer_dense::layer_dense(panic::types::uint_t input_size, panic::types::uint_t n
// Calculated the forward pass:
// outputs = inputs * weights + biases
//--------------------------------------------------------------------------------------------------------------------------
bool layer_dense::forward(const panic::tensor::real_matrix& inputs){
bool layer_dense::forward(const panic::tensor::real_matrix& input_data){
inputs = input_data;
if (inputs.cols() != weights.rows()){
return false;
@@ -128,9 +132,16 @@ bool layer_dense::forward(const panic::tensor::real_matrix& inputs){
// Calculated the backward pass:
// ??
//--------------------------------------------------------------------------------------------------------------------------
bool layer_dense::backward(const panic::tensor::real_matrix& dinputs){
bool layer_dense::backward(const panic::tensor::real_matrix& dvalues){
// Gradients on parameters
dweights = panic::math::matmul(panic::math::transpose(inputs), dvalues);
dbiases = panic::math::sum_colwise(dvalues);
// Gradients on values
dinputs = panic::math::matmul(dvalues, panic::math::transpose(weights));
return true;
}
+2 -1
View File
@@ -95,7 +95,8 @@ bool loss::calculate(
return false;
}
//return calculate_mean();
data_loss = panic::math::mean(sample_losses);
return true;
}
@@ -40,8 +40,13 @@
#include <tensor/matrix.hpp> // panic::tensor::real_matrix (uint_matrix, int_matrix)
#include <tensor/vector.hpp>
#include <math/mean.hpp>
#include <math/clip.hpp>
#include <math/log.hpp>
#include <math/mul.hpp>
#include <tensor/generators/one_hot.hpp>
#include <math/div.hpp>
#include <math/sum.hpp>
//---------------------------------------------------------------------------------------------------------------------------
// PRIVATE CONSTANTS
@@ -53,6 +58,11 @@
* worker threads can be larger than the work itself.
*/
static const panic::types::uint_t loss_categorical_crossentropy_omp_min_size = 500;
static const panic::types::real_t clip_min = 1e-7;
static const panic::types::real_t clip_max = 1 - 1e-7;
static const panic::types::real_t neg = -1;
//---------------------------------------------------------------------------------------------------------------------------
@@ -63,13 +73,47 @@ namespace panic{
// Function Name : panic::neural_network::loss_categorical_crossentropy::forward
//
// Description:
// Default implementation. Derived classes can override it.
// Default implementation for catecorical labels. Derived classes can override it.
//--------------------------------------------------------------------------------------------------------------------------
bool loss_categorical_crossentropy::forward(
const panic::tensor::real_matrix& y_pred,
const panic::tensor::uint_vector& y_true){
// Number of samples in a batch
const panic::types::uint_t samples = y_pred.rows();
if (samples != y_true.size()){
return false;
}
// clip data to prevent log by 0
// Clip both sides to not drag the mean towards any value
panic::tensor::real_matrix y_pred_cliped = panic::math::clip(y_pred, clip_min, clip_max);
// Vector to hold the correct confidences
panic::tensor::real_vector correct_confidences(samples);
PANIC_OMP_PARALLEL_FOR_IF(samples > loss_categorical_crossentropy_omp_min_size)
for (panic::types::uint_t i = 0; i < samples; ++i){
const panic::types::uint_t idx = y_true[i];
//if (idx >= y_pred.cols()){
// return false;
//}
correct_confidences[i] = y_pred_cliped(i, idx);
}
// Calculate losses
panic::tensor::real_vector negative_log_likelihoos(samples);
negative_log_likelihoos = panic::math::mul(panic::math::log(correct_confidences), neg);
sample_losses = negative_log_likelihoos;
return true;
}
@@ -77,16 +121,120 @@ bool loss_categorical_crossentropy::forward(
// Function Name : panic::neural_network::loss_categorical_crossentropy::forward
//
// Description:
// Default matrix-target implementation. Derived classes can override it.
// Default one-hot encoded labels implementation. Derived classes can override it.
//--------------------------------------------------------------------------------------------------------------------------
bool loss_categorical_crossentropy::forward(
const panic::tensor::real_matrix& y_pred,
const panic::tensor::real_matrix& y_true){
if (y_pred.rows() != y_true.rows() || y_pred.cols() != y_true.cols()){
return false;
}
// Number of samples in a batch
const panic::types::uint_t samples = y_pred.rows();
// clip data to prevent log by 0
// Clip both sides to not drag the mean towards any value
panic::tensor::real_matrix y_pred_cliped = panic::math::clip(y_pred, clip_min, clip_max);
// Vector to hold the correct confidences
panic::tensor::real_vector correct_confidences(samples);
correct_confidences = panic::math::sum_rowwise(panic::math::mul(y_pred_cliped, y_true));
// Calculate losses
panic::tensor::real_vector negative_log_likelihoos(samples);
negative_log_likelihoos = panic::math::mul(panic::math::log(correct_confidences), neg);
sample_losses = negative_log_likelihoos;
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::neural_network::loss_categorical_crossentropy::backward
//
// Description:
// Default implementation for catecorical labels. Derived classes can override it.
//--------------------------------------------------------------------------------------------------------------------------
bool loss_categorical_crossentropy::backward(
const panic::tensor::real_matrix& dvalues,
const panic::tensor::uint_vector& y_true){
if (dvalues.rows() == 0 || dvalues.cols() == 0 || y_true.size() != dvalues.rows()){
return false;
}
panic::tensor::real_matrix y_true_one_hot;
// Transforms it to one_hot
if (! panic::tensor::one_hot(dvalues.cols(), y_true, y_true_one_hot)){
return false;
}
// Uses other backward overloaded function to handle the rest.
return backward(dvalues, y_true_one_hot);
}
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::neural_network::loss_categorical_crossentropy::backward
//
// Description:
// Default one-hot encoded labels implementation. Derived classes can override it.
//--------------------------------------------------------------------------------------------------------------------------
bool loss_categorical_crossentropy::backward(
const panic::tensor::real_matrix& dvalues,
const panic::tensor::real_matrix& y_true){
// Number of samples
const panic::types::uint_t samples = dvalues.rows();
if (samples == 0 || dvalues.cols() == 0 || y_true.rows() != dvalues.rows() || y_true.cols() != dvalues.cols()){
return false;
}
// dinputs = y_true / dvalues
if (!panic::math::div(y_true, dvalues, dinputs)){
return false;
}
// scale = -1 / samples
const panic::types::real_t scale = -static_cast<panic::types::real_t>(1) / static_cast<panic::types::real_t>(samples);
// dinputs *= scale
if (!panic::math::mul(dinputs, scale, dinputs)){
return false;
}
return true;
}
} // namespace tensor
} // namespace panic
+141
View File
@@ -0,0 +1,141 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
*
* 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: tensor
* File Name: eye.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to generate eye matrices
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include <tensor/generators/eye.hpp>
#include <config/omp.hpp>
#include <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // 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 eye_omp_min_work = 500;
//---------------------------------------------------------------------------------------------------------------------------
// INPLEMENTATION
//---------------------------------------------------------------------------------------------------------------------------
namespace panic {
namespace tensor {
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::tensor::eye
//
// Description:
// Creates a eye matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool eye(const panic::types::uint_t size, panic::tensor::matrix<T>& A){
if (!A.resize(size,size)){
return false;
}
PANIC_OMP_PARALLEL_FOR_IF(size*size > eye_omp_min_work)
for (panic::types::uint_t i = 0; i < size; ++i){
for (panic::types::uint_t j = 0; j < size; ++j){
if (i == j){
A(i,j) = T{1};
}
else{
A(i,j) = T{0};
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool eye(const panic::types::uint_t size,
panic::tensor::matrix<panic::types::uint_t>& A
);
template bool eye(const panic::types::uint_t size,
panic::tensor::matrix<panic::types::int_t>& A
);
template bool eye(const panic::types::uint_t size,
panic::tensor::matrix<panic::types::real_t>& A
);
/*
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::eye
//
// Description:
// Retuens a eye matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> eye(const T size){
panic::tensor::matrix<T> A(static_cast<panic::types::uint_t>(size), static_cast<panic::types::uint_t>(size));
if (!eye(A.rows(), A)){
return panic::tensor::matrix<T>();
}
return A;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::tensor::matrix<panic::types::uint_t> eye(const panic::types::uint_t size
);
template panic::tensor::matrix<panic::types::int_t> eye(const panic::types::int_t size
);
template panic::tensor::matrix<panic::types::real_t> eye(const panic::types::real_t size
);
*/
} // namespace tensor
} // namespace panic
+154
View File
@@ -0,0 +1,154 @@
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
*
* 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: tensor
* File Name: one_hot.hpp
* Revision: 0.1.0
* Date: 31-07-2026
* Author: Michelle Bausager
*
* Description:
* Functions to generate one_hot matrices
*
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include <tensor/generators/one_hot.hpp>
#include <config/omp.hpp>
#include <config/types.hpp>
#include <tensor/vector.hpp> // for panic::vector
#include <tensor/matrix.hpp> // 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 one_hot_omp_min_work = 500;
//---------------------------------------------------------------------------------------------------------------------------
// INPLEMENTATION
//---------------------------------------------------------------------------------------------------------------------------
namespace panic {
namespace tensor {
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::tensor::one_hot
//
// Description:
// Creates a one_hot matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
bool one_hot(const panic::types::uint_t size, const panic::tensor::uint_vector & a, panic::tensor::matrix<T>& B){
if (!B.resize(size,size)){
return false;
}
if (size != a.size()){
return false;
}
PANIC_OMP_PARALLEL_FOR_IF(size*size > one_hot_omp_min_work)
for (panic::types::uint_t i = 0; i < size; ++i){
for (panic::types::uint_t j = 0; j < size; ++j){
if (a[i] == j){
B(i,j) = T{1};
}
else{
B(i,j) = T{0};
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template bool one_hot(const panic::types::uint_t size,
const panic::tensor::uint_vector& a,
panic::tensor::matrix<panic::types::uint_t>& B
);
template bool one_hot(const panic::types::uint_t size,
const panic::tensor::uint_vector& a,
panic::tensor::matrix<panic::types::int_t>& B
);
template bool one_hot(const panic::types::uint_t size,
const panic::tensor::uint_vector& a,
panic::tensor::matrix<panic::types::real_t>& B
);
/*
//--------------------------------------------------------------------------------------------------------------------------
// Function Name : panic::math::one_hot
//
// Description:
// Retuens a one_hot matrix
//--------------------------------------------------------------------------------------------------------------------------
template <typename T>
panic::tensor::matrix<T> one_hot(const panic::types::uint_t size, const panic::tensor::uint_vector& a){
panic::tensor::matrix<T> B(size, size);
if (!one_hot(size, a, B)){
return panic::tensor::matrix<T>();
}
return B;
}
//--------------------------------------------------------------------------------------------------------------------------
// EXPLICIT TEMPLATE INSTANTIATION
//
// The implementation is in this .cpp file.
// Build the overload for the official PANIC numeric types.
//--------------------------------------------------------------------------------------------------------------------------
template panic::tensor::matrix<panic::types::uint_t> one_hot(const panic::types::uint_t size,
const panic::tensor::vector<panic::types::uint_t>& a
);
template panic::tensor::matrix<panic::types::int_t> one_hot(const panic::types::uint_t size,
const panic::tensor::vector<panic::types::int_t>& a
);
template panic::tensor::matrix<panic::types::real_t> one_hot(const panic::types::uint_t size,
const panic::tensor::vector<panic::types::real_t>& a
);
*/
} // namespace tensor
} // namespace panic