|
|
|
|
@ -1,24 +1,24 @@
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* $Date: 19. March 2015
|
|
|
|
|
* $Revision: V.1.4.5
|
|
|
|
|
*
|
|
|
|
|
* Project: CMSIS DSP Library
|
|
|
|
|
* Title: arm_mat_mult_q15.c
|
|
|
|
|
*
|
|
|
|
|
* Description: Q15 matrix multiplication.
|
|
|
|
|
*
|
|
|
|
|
* $Revision: V.1.4.5a
|
|
|
|
|
*
|
|
|
|
|
* Project: CMSIS DSP Library
|
|
|
|
|
* Title: arm_mat_mult_q15.c
|
|
|
|
|
*
|
|
|
|
|
* Description: Q15 matrix multiplication.
|
|
|
|
|
*
|
|
|
|
|
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
|
* are met:
|
|
|
|
|
* - Redistributions of source code must retain the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
|
* distribution.
|
|
|
|
|
* - Neither the name of ARM LIMITED nor the names of its contributors
|
|
|
|
|
* may be used to endorse or promote products derived from this
|
|
|
|
|
@ -27,7 +27,7 @@
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
|
@ -35,52 +35,52 @@
|
|
|
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
|
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
#include "arm_math.h"
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @ingroup groupMatrix
|
|
|
|
|
/**
|
|
|
|
|
* @ingroup groupMatrix
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @addtogroup MatrixMult
|
|
|
|
|
* @{
|
|
|
|
|
/**
|
|
|
|
|
* @addtogroup MatrixMult
|
|
|
|
|
* @{
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Q15 matrix multiplication
|
|
|
|
|
* @param[in] *pSrcA points to the first input matrix structure
|
|
|
|
|
* @param[in] *pSrcB points to the second input matrix structure
|
|
|
|
|
* @param[out] *pDst points to output matrix structure
|
|
|
|
|
* @param[in] *pState points to the array for storing intermediate results (Unused)
|
|
|
|
|
* @return The function returns either
|
|
|
|
|
* <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
|
|
|
|
|
*
|
|
|
|
|
* @details
|
|
|
|
|
* <b>Scaling and Overflow Behavior:</b>
|
|
|
|
|
*
|
|
|
|
|
* \par
|
|
|
|
|
* The function is implemented using a 64-bit internal accumulator. The inputs to the
|
|
|
|
|
* multiplications are in 1.15 format and multiplications yield a 2.30 result.
|
|
|
|
|
* The 2.30 intermediate
|
|
|
|
|
* results are accumulated in a 64-bit accumulator in 34.30 format. This approach
|
|
|
|
|
* provides 33 guard bits and there is no risk of overflow. The 34.30 result is then
|
|
|
|
|
* truncated to 34.15 format by discarding the low 15 bits and then saturated to
|
|
|
|
|
* 1.15 format.
|
|
|
|
|
*
|
|
|
|
|
* \par
|
|
|
|
|
* Refer to <code>arm_mat_mult_fast_q15()</code> for a faster but less precise version of this function for Cortex-M3 and Cortex-M4.
|
|
|
|
|
*
|
|
|
|
|
/**
|
|
|
|
|
* @brief Q15 matrix multiplication
|
|
|
|
|
* @param[in] *pSrcA points to the first input matrix structure
|
|
|
|
|
* @param[in] *pSrcB points to the second input matrix structure
|
|
|
|
|
* @param[out] *pDst points to output matrix structure
|
|
|
|
|
* @param[in] *pState points to the array for storing intermediate results (Unused)
|
|
|
|
|
* @return The function returns either
|
|
|
|
|
* <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
|
|
|
|
|
*
|
|
|
|
|
* @details
|
|
|
|
|
* <b>Scaling and Overflow Behavior:</b>
|
|
|
|
|
*
|
|
|
|
|
* \par
|
|
|
|
|
* The function is implemented using a 64-bit internal accumulator. The inputs to the
|
|
|
|
|
* multiplications are in 1.15 format and multiplications yield a 2.30 result.
|
|
|
|
|
* The 2.30 intermediate
|
|
|
|
|
* results are accumulated in a 64-bit accumulator in 34.30 format. This approach
|
|
|
|
|
* provides 33 guard bits and there is no risk of overflow. The 34.30 result is then
|
|
|
|
|
* truncated to 34.15 format by discarding the low 15 bits and then saturated to
|
|
|
|
|
* 1.15 format.
|
|
|
|
|
*
|
|
|
|
|
* \par
|
|
|
|
|
* Refer to <code>arm_mat_mult_fast_q15()</code> for a faster but less precise version of this function for Cortex-M3 and Cortex-M4.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
arm_status arm_mat_mult_q15(
|
|
|
|
|
const arm_matrix_instance_q15 * pSrcA,
|
|
|
|
|
const arm_matrix_instance_q15 * pSrcB,
|
|
|
|
|
arm_matrix_instance_q15 * pDst,
|
|
|
|
|
q15_t * pState CMSIS_UNUSED)
|
|
|
|
|
q15_t * pState)
|
|
|
|
|
{
|
|
|
|
|
q63_t sum; /* accumulator */
|
|
|
|
|
|
|
|
|
|
@ -109,7 +109,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
q15_t in; /* Temporary variable to hold the input value */
|
|
|
|
|
q15_t inA1, inB1, inA2, inB2;
|
|
|
|
|
|
|
|
|
|
#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
|
|
|
|
|
#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
|
|
|
|
|
|
|
|
|
|
#ifdef ARM_MATH_MATRIX_CHECK
|
|
|
|
|
/* Check for matrix mismatch condition */
|
|
|
|
|
@ -131,7 +131,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
/* The pointer px is set to starting address of the column being processed */
|
|
|
|
|
px = pSrcBT + i;
|
|
|
|
|
|
|
|
|
|
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
|
|
|
|
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
|
|
|
|
** a second loop below computes the remaining 1 to 3 samples. */
|
|
|
|
|
while(col > 0u)
|
|
|
|
|
{
|
|
|
|
|
@ -149,7 +149,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
*px = (q15_t) ((in & (q31_t) 0xffff0000) >> 16);
|
|
|
|
|
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
@ -163,7 +163,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
*px = (q15_t) in;
|
|
|
|
|
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
@ -180,7 +180,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
*px = (q15_t) ((in & (q31_t) 0xffff0000) >> 16);
|
|
|
|
|
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
@ -195,7 +195,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
*px = (q15_t) in;
|
|
|
|
|
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
@ -207,7 +207,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
/* Store one element in the destination */
|
|
|
|
|
*px = in;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
|
|
|
|
|
@ -216,7 +216,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
/* Store one element in the destination */
|
|
|
|
|
*px = in;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
|
|
|
|
|
@ -225,7 +225,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
/* Store one element in the destination */
|
|
|
|
|
*px = in;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
|
|
|
|
|
@ -234,17 +234,17 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
|
|
|
|
|
/* Store one element in the destination */
|
|
|
|
|
*px = in;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Update the pointer px to point to the next row of the transposed matrix */
|
|
|
|
|
px += numRowsB;
|
|
|
|
|
|
|
|
|
|
#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
|
|
|
|
|
#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
|
|
|
|
|
|
|
|
|
|
/* Decrement the column loop counter */
|
|
|
|
|
col--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the columns of pSrcB is not a multiple of 4, compute any remaining output samples here.
|
|
|
|
|
/* If the columns of pSrcB is not a multiple of 4, compute any remaining output samples here.
|
|
|
|
|
** No loop unrolling is used. */
|
|
|
|
|
col = numColsB % 0x4u;
|
|
|
|
|
|
|
|
|
|
@ -279,7 +279,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
/* For every row wise process, the column loop counter is to be initiated */
|
|
|
|
|
col = numColsB;
|
|
|
|
|
|
|
|
|
|
/* For every row wise process, the pIn2 pointer is set
|
|
|
|
|
/* For every row wise process, the pIn2 pointer is set
|
|
|
|
|
** to the starting address of the transposed pSrcB data */
|
|
|
|
|
pInB = pSrcBT;
|
|
|
|
|
|
|
|
|
|
@ -333,7 +333,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
sum += inA1 * inB1;
|
|
|
|
|
sum += inA2 * inB2;
|
|
|
|
|
|
|
|
|
|
#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
|
|
|
|
|
#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
|
|
|
|
|
|
|
|
|
|
/* Decrement the loop counter */
|
|
|
|
|
colCnt--;
|
|
|
|
|
@ -393,7 +393,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
status = ARM_MATH_SIZE_MISMATCH;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif /* #ifdef ARM_MATH_MATRIX_CHECK */
|
|
|
|
|
#endif /* #ifdef ARM_MATH_MATRIX_CHECK */
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
/* The following loop performs the dot-product of each row in pSrcA with each column in pSrcB */
|
|
|
|
|
@ -406,7 +406,7 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
/* For every row wise process, the column loop counter is to be initiated */
|
|
|
|
|
col = numColsB;
|
|
|
|
|
|
|
|
|
|
/* For every row wise process, the pIn2 pointer is set
|
|
|
|
|
/* For every row wise process, the pIn2 pointer is set
|
|
|
|
|
** to the starting address of the pSrcB data */
|
|
|
|
|
pIn2 = pSrcB->pData;
|
|
|
|
|
|
|
|
|
|
@ -464,6 +464,6 @@ arm_status arm_mat_mult_q15(
|
|
|
|
|
return (status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @} end of MatrixMult group
|
|
|
|
|
/**
|
|
|
|
|
* @} end of MatrixMult group
|
|
|
|
|
*/
|
|
|
|
|
|