/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * * PANIC * Portable Algorithms and Numerics In C++ * * Scientific computing from scratch, with feeling. * * Copyright (c) 2026 Michelle Bausager * * This file is part of PANIC. * * PANIC is free software licensed under the GNU General Public License v3.0 or later. * You may redistribute and/or modify it under the terms of the GPL. * * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the LICENSE file for the full license text. * * SPDX-License-Identifier: GPL-3.0-or-later * *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Project Name: PANIC * Module Name: math * File Name: div.cpp * Revision: 0.1.0 * Date: 25-06-2026 * Author: Michelle Bausager * * Description: * Functions to divdes panic::tensor * *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ //--------------------------------------------------------------------------------------------------------------------------- // INCLUDE DESCRIPTION //----------------------------------------------------------------------------------------------------- #include #include #include // for panic::vector #include // for panic::matrix //--------------------------------------------------------------------------------------------------------------------------- // PRIVATE CONSTANTS //--------------------------------------------------------------------------------------------------------------------------- /** * @brief Minimum number of element operations before using the OpenMP-enabled loop. * * Small vectors and matrices are kept serial because the overhead of starting * worker threads can be larger than the work itself. */ static const panic::types::uint_t div_omp_min_work = 500; //--------------------------------------------------------------------------------------------------------------------------- // INPLEMENTATION //--------------------------------------------------------------------------------------------------------------------------- namespace panic { namespace math { //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divedes a constant to a vector //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::vector& a, const T k, panic::tensor::vector& c){ if (!c.resize(a.size())){ return false; } if (k == T{0}){ return false; } PANIC_OMP_PARALLEL_FOR_IF(a.size() > div_omp_min_work) for (panic::types::uint_t i = 0; i < a.size(); ++i){ c[i] = a[i] / k; } return true; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::vector& a, const panic::types::uint_t k, panic::tensor::vector& c ); template bool div(const panic::tensor::vector& a, const panic::types::int_t k, panic::tensor::vector& c ); template bool div(const panic::tensor::vector& a, const panic::types::real_t k, panic::tensor::vector& c ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divides a constant to a vector //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::vector div(const panic::tensor::vector& a, const T k){ panic::tensor::vector c(a.size()); if (!div(a, k, c)){ return panic::tensor::vector(); } return c; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::vector div(const panic::tensor::vector& a, const panic::types::uint_t k ); template panic::tensor::vector div(const panic::tensor::vector& a, const panic::types::int_t k ); template panic::tensor::vector div(const panic::tensor::vector& a, const panic::types::real_t k ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divides a vector to a vector //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c){ if (a.size() != b.size()){ return false; } if (!c.resize(a.size())){ return false; } bool valid = true; // Check all divisors in parallel. // valid remains true only if every divisor is nonzero. PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( a.size() > div_omp_min_work, &&, valid ) for (panic::types::uint_t i = 0; i < a.size(); ++i){ const bool nonzero = b[i] != T{0}; valid = valid && nonzero; if (nonzero){ c[i] = a[i] / b[i]; } } return valid; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c ); template bool div(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c ); template bool div(const panic::tensor::vector& a, const panic::tensor::vector& b, panic::tensor::vector& c ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divides a vector to a vector //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::vector div(const panic::tensor::vector& a, const panic::tensor::vector& b){ panic::tensor::vector c(a.size()); if (!div(a, b, c)){ return panic::tensor::vector(); } return c; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::vector div(const panic::tensor::vector& a, const panic::tensor::vector& b ); template panic::tensor::vector div(const panic::tensor::vector& a, const panic::tensor::vector& b ); template panic::tensor::vector div(const panic::tensor::vector& a, const panic::tensor::vector& b ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divides a constant to a matrix //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::matrix& A, const T k, panic::tensor::matrix& C){ panic::types::uint_t rows = A.rows(); panic::types::uint_t cols = A.cols(); panic::types::uint_t work = rows*cols; if ( !C.resize(rows, cols) ){ return false; } if (k == T{0}){ return false; } PANIC_OMP_PARALLEL_FOR_IF(work > div_omp_min_work) for (panic::types::uint_t i = 0; i < rows; ++i){ for (panic::types::uint_t j = 0; j < cols; ++j){ C(i,j) = A(i,j) / k; } } return true; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::matrix& A, const panic::types::uint_t k, panic::tensor::matrix& C ); template bool div(const panic::tensor::matrix& A, const panic::types::int_t k, panic::tensor::matrix& C ); template bool div(const panic::tensor::matrix& A, const panic::types::real_t k, panic::tensor::matrix& C ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divides a constant to a matrix //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div(const panic::tensor::matrix& A, const T k){ panic::tensor::matrix C; if (!div(A, k, C)){ return panic::tensor::matrix(); } return C; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::types::uint_t k ); template panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::types::int_t k ); template panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::types::real_t k ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divides a matrix to a matrix elementwise //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C){ panic::types::uint_t rows = A.rows(); panic::types::uint_t cols = A.cols(); panic::types::uint_t work = rows*cols; if ( (rows != B.rows()) || (cols != B.cols())){ return false; } if ( !C.resize(rows, cols) ){ return false; } bool valid = true; // Check all divisors in parallel. // valid remains true only if every divisor is nonzero. PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( work > div_omp_min_work, &&, valid ) for (panic::types::uint_t i = 0; i < rows; ++i) { for (panic::types::uint_t j = 0; j < cols; ++j) { const bool nonzero = B(i,j) != T{0}; valid = valid && nonzero; if (nonzero) { C(i,j) = A(i,j) / B(i,j); } } } return valid; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template bool div(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C ); template bool div(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C ); template bool div(const panic::tensor::matrix& A, const panic::tensor::matrix& B, panic::tensor::matrix& C ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div // // Description: // Divides a matrix to a matrix elementwise //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::tensor::matrix& B){ panic::tensor::matrix C; if (!div(A, B, C)){ return panic::tensor::matrix(); } return C; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::tensor::matrix& B ); template panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::tensor::matrix& B ); template panic::tensor::matrix div(const panic::tensor::matrix& A, const panic::tensor::matrix& B ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div_rowwise // // Description: // Divides a vector row-wise to a matrix //-------------------------------------------------------------------------------------------------------------------------- template bool div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C){ panic::types::uint_t rows = A.rows(); panic::types::uint_t cols = A.cols(); panic::types::uint_t work = rows*cols; if ( cols != b.size() ){ return false; } if ( !C.resize(rows, cols) ){ return false; } bool valid = true; // Check all divisors in parallel. // valid remains true only if every divisor is nonzero. PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( work > div_omp_min_work, &&, valid ) for (panic::types::uint_t i = 0; i < cols; ++i){ const bool nonzero = b[i] != T{0}; valid = valid && nonzero; for (panic::types::uint_t j = 0; j < rows; ++j){ if (nonzero){ C(j,i) = A(j,i) / b[i]; } } } return valid; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template bool div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C ); template bool div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C ); template bool div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div_rowwise // // Description: // Divides a vector row-wise to a matrix //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b){ panic::tensor::matrix C; if (!div_rowwise(A, b, C)){ return panic::tensor::matrix(); } return C; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b ); template panic::tensor::matrix div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b ); template panic::tensor::matrix div_rowwise(const panic::tensor::matrix& A, const panic::tensor::vector& b ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div_colwise // // Description: // Divides a vector coloumn-wise to a matrix //-------------------------------------------------------------------------------------------------------------------------- template bool div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C){ panic::types::uint_t rows = A.rows(); panic::types::uint_t cols = A.cols(); panic::types::uint_t work = rows*cols; if ( rows != b.size() ){ return false; } if ( !C.resize(rows, cols) ){ return false; } bool valid = true; // Check all divisors in parallel. // valid remains true only if every divisor is nonzero. PANIC_OMP_PARALLEL_FOR_REDUCTION_IF( work > div_omp_min_work, &&, valid ) for (panic::types::uint_t i = 0; i < rows; ++i){ const bool nonzero = b[i] != T{0}; valid = valid && nonzero; for (panic::types::uint_t j = 0; j < cols; ++j){ if (nonzero){ C(i,j) = A(i,j) / b[i]; } } } return valid; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template bool div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C ); template bool div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C ); template bool div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b, panic::tensor::matrix& C ); //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::math::div_colwise // // Description: // Divides a vector coloumn-wise to a matrix //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b){ panic::tensor::matrix C; if (!div_colwise(A, b, C)){ return panic::tensor::matrix(); } return C; } //-------------------------------------------------------------------------------------------------------------------------- // EXPLICIT TEMPLATE INSTANTIATION // // The implementation is in this .cpp file. // Build the overload for the official PANIC numeric types. //-------------------------------------------------------------------------------------------------------------------------- template panic::tensor::matrix div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b ); template panic::tensor::matrix div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b ); template panic::tensor::matrix div_colwise(const panic::tensor::matrix& A, const panic::tensor::vector& b ); } // namespace math } // namespace panic