CMSIS-DSP: Corrected problem with arm_mat_inverse.

Related to pull request 741 when pivot is 0.
pull/19/head
Christophe Favergeon 6 years ago
parent 767ed7b920
commit 26cb1690bc

@ -14,7 +14,7 @@
; </h>
*----------------------------------------------------------------------------*/
#define __ROM_BASE 0x00000000
#define __ROM_SIZE 0x00250000
#define __ROM_SIZE 0x00300000
/*--------------------- Embedded RAM Configuration ---------------------------
; <h> RAM Configuration

@ -14,7 +14,7 @@
; </h>
*----------------------------------------------------------------------------*/
#define __ROM_BASE 0x00000000
#define __ROM_SIZE 0x00250000
#define __ROM_SIZE 0x00300000
/*--------------------- Embedded RAM Configuration ---------------------------
; <h> RAM Configuration

@ -14,63 +14,75 @@
; </h>
*----------------------------------------------------------------------------*/
#define __ROM_BASE 0x10000000
#define __ROM_SIZE 0x00250000
#define __ROM_SIZE 0x00400000
/*--------------------- Embedded RAM Configuration ---------------------------
; <h> RAM Configuration
; <o0> RAM Base Address <0x0-0xFFFFFFFF:8>
; <o1> RAM Size (in Bytes) <0x0-0xFFFFFFFF:8>
; <o0> RAM1 Base Address <0x0-0xFFFFFFFF:8>
; <o1> RAM1 Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
*----------------------------------------------------------------------------*/
#define __RAM_BASE 0x30000000
#define __RAM_SIZE 0x00200000
#define __RAM1_BASE 0x20000000
#define __RAM1_SIZE 0x00400000
/*--------------------- Stack / Heap Configuration ---------------------------
; <h> Stack / Heap Configuration
; <o0> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; <o1> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
/*--------------------- Embedded RAM Configuration ---------------------------
; <h> RAM Configuration
; <o0> RAM2 Base Address <0x0-0xFFFFFFFF:8>
; <o1> RAM2 Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
*----------------------------------------------------------------------------*/
#define __STACK_SIZE STACK_SIZE
#define __HEAP_SIZE HEAP_SIZE
#define __RAM2_BASE 0x28000000
#define __RAM2_SIZE 0x00400000
/*----------------------------------------------------------------------------
User Stack & Heap boundery definition
/*--------------------- Embedded RAM Configuration ---------------------------
; <h> RAM Configuration
; <o0> RAM3 Base Address <0x0-0xFFFFFFFF:8>
; <o1> RAM3 Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
*----------------------------------------------------------------------------*/
#define __STACK_TOP (__RAM_BASE + __RAM_SIZE) /* starts at end of RAM */
#define __HEAP_BASE (AlignExpr(+0, 8)) /* starts after RW_RAM section, 8 byte aligned */
#define __RAM3_BASE 0x80000000
#define __RAM3_SIZE 0x01000000
/*----------------------------------------------------------------------------
Scatter File Definitions definition
/*--------------------- Stack / Heap Configuration ---------------------------
; <h> Stack / Heap Configuration
; <o0> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; <o1> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
*----------------------------------------------------------------------------*/
#define __RO_BASE __ROM_BASE
#define __RO_SIZE __ROM_SIZE
#define __STACK_SIZE STACK_SIZE
#define __HEAP_SIZE HEAP_SIZE
#define __RAM2_RW_SIZE (__RAM2_SIZE - __STACK_SIZE - __HEAP_SIZE)
#define __RW_BASE (__RAM_BASE )
#define __RW_SIZE (__RAM_SIZE - __STACK_SIZE - __HEAP_SIZE)
LR_ROM __RO_BASE __RO_SIZE { ; load region size_region
ER_ROM __RO_BASE __RO_SIZE { ; load address = execution address
LR_ROM __ROM_BASE __ROM_SIZE { ; load region size_region
ER_ROM +0 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
; *(Veneer$$CMSE) ; uncomment for secure applications
.ANY (+RO)
.ANY (+XO)
* (InRoot$$Sections)
; *(Veneer$$CMSE) ; uncomment for secure applications
* (+RO-CODE)
; * (+XO)
}
RW_RAM __RW_BASE __RW_SIZE { ; RW data
.ANY (+RW +ZI)
RW_RAM1 __RAM1_BASE __RAM1_SIZE { ; RW data
* (+RW +ZI)
}
#if __HEAP_SIZE > 0
ARM_LIB_HEAP __HEAP_BASE EMPTY __HEAP_SIZE { ; Reserve empty region for heap
/* make sure stack-overflow will cause bus-fault (which might be escalated to hardfault) */
ARM_LIB_STACK __RAM2_BASE ALIGN 8 EMPTY __STACK_SIZE { ; Reserve empty region for stack
}
RW_RAM2 +0 __RAM2_RW_SIZE {
* (+RO-DATA)
.ANY (+RW +ZI)
}
#endif
ARM_LIB_STACK __STACK_TOP EMPTY -__STACK_SIZE { ; Reserve empty region for stack
ARM_LIB_HEAP +0 ALIGN 8 EMPTY __HEAP_SIZE { ; Reserve empty region for heap
}
RW_RAM3 __RAM3_BASE __RAM3_SIZE { ; RW data
.ANY (+RW +ZI) ; Just in case the RAM1 and RAM2 is not big enough.
}
}

@ -226,7 +226,7 @@ arm_status arm_mat_inverse_f32(
/*
* Update the input and destination pointers
*/
pInT2 = pInT1 + (numCols * l);
pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k);
/*
* Check if there is a non zero pivot element to
@ -585,7 +585,6 @@ arm_status arm_mat_inverse_f32(
uint32_t numRows = pSrc->numRows; /* Number of rows in the matrix */
uint32_t numCols = pSrc->numCols; /* Number of Cols in the matrix */
float32_t maxC; /* maximum value in the column */
float32_t Xchg, in = 0.0f, in1; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */
@ -623,13 +622,12 @@ arm_status arm_mat_inverse_f32(
*
* 3. Begin with the first row. Let i = 1.
*
* 4. Check to see if the pivot for column i is the greatest of the column.
* 4. Check to see if the pivot for row i is zero.
* The pivot is the element of the main diagonal that is on the current row.
* For instance, if working with row i, then the pivot element is aii.
* If the pivot is not the most significant of the columns, exchange that row with a row
* below it that does contain the most significant value in column i. If the most
* significant value of the column is zero, then an inverse to that matrix does not exist.
* The most significant value of the column is the absolute maximum.
* If the pivot is zero, exchange that row with a row below it that does not
* contain a zero in column i. If this is not possible, then an inverse
* to that matrix does not exist.
*
* 5. Divide every element of row i by the pivot.
*
@ -701,42 +699,23 @@ arm_status arm_mat_inverse_f32(
/* Temporary variable to hold the pivot value */
in = *pInT1;
/* Grab the most significant value from column l */
maxC = 0;
for (i = l; i < numRows; i++)
{
maxC = *pInT1 > 0 ? (*pInT1 > maxC ? *pInT1 : maxC) : (-*pInT1 > maxC ? -*pInT1 : maxC);
pInT1 += numCols;
}
/* Update the status if the matrix is singular */
if (maxC == 0.0f)
{
return ARM_MATH_SINGULAR;
}
/* Restore pInT1 */
pInT1 = pIn;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is the most significant of the column */
if ( (in > 0.0f ? in : -in) != maxC)
/* Check if the pivot element is zero */
if (*pInT1 == 0.0f)
{
/* Loop over the number rows present below */
i = numRows - (l + 1U);
while (i > 0U)
for (i = (l + 1U); i < numRows; i++)
{
/* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * l);
pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k);
/* Look for the most significant element to
/* Check if there is a non zero pivot element to
* replace in the rows below */
if ((*pInT2 > 0.0f ? *pInT2: -*pInT2) == maxC)
if (*pInT2 != 0.0f)
{
/* Loop over number of columns
* to the right of the pilot element */
@ -776,9 +755,6 @@ arm_status arm_mat_inverse_f32(
/* Update the destination pointer modifier */
k++;
/* Decrement the loop counter */
i--;
}
}
@ -1019,7 +995,6 @@ arm_status arm_mat_inverse_f32(
uint32_t numCols = pSrc->numCols; /* Number of Cols in the matrix */
#if defined (ARM_MATH_DSP)
float32_t maxC; /* maximum value in the column */
float32_t Xchg, in = 0.0f, in1; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */
@ -1057,13 +1032,12 @@ arm_status arm_mat_inverse_f32(
*
* 3. Begin with the first row. Let i = 1.
*
* 4. Check to see if the pivot for column i is the greatest of the column.
* 4. Check to see if the pivot for row i is zero.
* The pivot is the element of the main diagonal that is on the current row.
* For instance, if working with row i, then the pivot element is aii.
* If the pivot is not the most significant of the columns, exchange that row with a row
* below it that does contain the most significant value in column i. If the most
* significant value of the column is zero, then an inverse to that matrix does not exist.
* The most significant value of the column is the absolute maximum.
* If the pivot is zero, exchange that row with a row below it that does not
* contain a zero in column i. If this is not possible, then an inverse
* to that matrix does not exist.
*
* 5. Divide every element of row i by the pivot.
*
@ -1134,41 +1108,24 @@ arm_status arm_mat_inverse_f32(
/* Temporary variable to hold the pivot value */
in = *pInT1;
/* Grab the most significant value from column l */
maxC = 0;
for (i = l; i < numRows; i++)
{
maxC = *pInT1 > 0 ? (*pInT1 > maxC ? *pInT1 : maxC) : (-*pInT1 > maxC ? -*pInT1 : maxC);
pInT1 += numCols;
}
/* Update the status if the matrix is singular */
if (maxC == 0.0f)
{
return ARM_MATH_SINGULAR;
}
/* Restore pInT1 */
pInT1 = pIn;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is the most significant of the column */
if ( (in > 0.0f ? in : -in) != maxC)
/* Check if the pivot element is zero */
if (*pInT1 == 0.0f)
{
/* Loop over the number rows present below */
i = numRows - (l + 1U);
while (i > 0U)
for (i = (l + 1U); i < numRows; i++)
{
/* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * l);
pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k);
/* Look for the most significant element to
/* Check if there is a non zero pivot element to
* replace in the rows below */
if ((*pInT2 > 0.0f ? *pInT2: -*pInT2) == maxC)
if (*pInT2 != 0.0f)
{
/* Loop over number of columns
* to the right of the pilot element */
@ -1210,7 +1167,6 @@ arm_status arm_mat_inverse_f32(
k++;
/* Decrement loop counter */
i--;
}
}
@ -1471,7 +1427,7 @@ arm_status arm_mat_inverse_f32(
for (i = (l + 1U); i < numRows; i++)
{
/* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * l);
pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k);
/* Check if there is a non zero pivot element to

@ -61,7 +61,6 @@ arm_status arm_mat_inverse_f64(
uint32_t numCols = pSrc->numCols; /* Number of Cols in the matrix */
#if defined (ARM_MATH_DSP)
float64_t maxC; /* maximum value in the column */
float64_t Xchg, in = 0.0, in1; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */
@ -99,13 +98,12 @@ arm_status arm_mat_inverse_f64(
*
* 3. Begin with the first row. Let i = 1.
*
* 4. Check to see if the pivot for column i is the greatest of the column.
* 4. Check to see if the pivot for row i is zero.
* The pivot is the element of the main diagonal that is on the current row.
* For instance, if working with row i, then the pivot element is aii.
* If the pivot is not the most significant of the columns, exchange that row with a row
* below it that does contain the most significant value in column i. If the most
* significant value of the column is zero, then an inverse to that matrix does not exist.
* The most significant value of the column is the absolute maximum.
* If the pivot is zero, exchange that row with a row below it that does not
* contain a zero in column i. If this is not possible, then an inverse
* to that matrix does not exist.
*
* 5. Divide every element of row i by the pivot.
*
@ -176,41 +174,22 @@ arm_status arm_mat_inverse_f64(
/* Temporary variable to hold the pivot value */
in = *pInT1;
/* Grab the most significant value from column l */
maxC = 0;
for (i = l; i < numRows; i++)
{
maxC = *pInT1 > 0 ? (*pInT1 > maxC ? *pInT1 : maxC) : (-*pInT1 > maxC ? -*pInT1 : maxC);
pInT1 += numCols;
}
/* Update the status if the matrix is singular */
if (maxC == 0.0)
{
return ARM_MATH_SINGULAR;
}
/* Restore pInT1 */
pInT1 = pIn;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is the most significant of the column */
if ( (in > 0.0 ? in : -in) != maxC)
/* Check if the pivot element is zero */
if (*pInT1 == 0.0)
{
/* Loop over the number rows present below */
i = numRows - (l + 1U);
while (i > 0U)
for (i = (l + 1U); i < numRows; i++)
{
/* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * l);
pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k);
/* Look for the most significant element to
/* Check if there is a non zero pivot element to
* replace in the rows below */
if ((*pInT2 > 0.0 ? *pInT2: -*pInT2) == maxC)
if (*pInT2 != 0.0)
{
/* Loop over number of columns
* to the right of the pilot element */
@ -513,7 +492,7 @@ arm_status arm_mat_inverse_f64(
for (i = (l + 1U); i < numRows; i++)
{
/* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * l);
pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k);
/* Check if there is a non zero pivot element to

@ -650,8 +650,9 @@ def writeUnaryTests(config,format):
vals = vals + r
config.writeReference(1, vals,"RefScale")
dims=NA
config.writeInputS16(1, dims,"DimsInvert")
# Current algo is not very accurate for big matrix.
# But big matrix required to check the vectorized code.
dims=[1,2,3,4,7,8,9,15,16,17,32,33]
vals = []
inp=[]
@ -660,6 +661,15 @@ def writeUnaryTests(config,format):
inp = inp + list(ma.reshape(d*d))
r = numpy.linalg.inv(ma)
vals = vals + list(r.reshape(d*d))
# Add matrix for testing null pivot condition
ma = np.array([[0., 3.], [4., 5.]])
inp = inp + list(ma.reshape(4))
r = np.linalg.inv(ma)
vals = vals + list(r.reshape(4))
dims.append(2)
config.writeInputS16(1, dims,"DimsInvert")
config.writeInput(1, inp,"InputInvert")
config.writeReference(1, vals,"RefInvert")
# One kind of matrix shape

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
H
7
13
// 1
0x0001
// 2
@ -8,9 +8,21 @@ H
0x0003
// 4
0x0004
// 3
0x0003
// 7
0x0007
// 8
0x0008
// 11
0x000B
// 9
0x0009
// 15
0x000F
// 16
0x0010
// 17
0x0011
// 32
0x0020
// 33
0x0021
// 2
0x0002

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
H
7
13
// 1
0x0001
// 2
@ -8,9 +8,21 @@ H
0x0003
// 4
0x0004
// 3
0x0003
// 7
0x0007
// 8
0x0008
// 11
0x000B
// 9
0x0009
// 15
0x000F
// 16
0x0010
// 17
0x0011
// 32
0x0020
// 33
0x0021
// 2
0x0002

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
H
7
13
// 1
0x0001
// 2
@ -10,7 +10,19 @@ H
0x0004
// 7
0x0007
// 8
0x0008
// 9
0x0009
// 15
0x000F
// 16
0x0010
// 23
0x0017
// 17
0x0011
// 32
0x0020
// 33
0x0021
// 2
0x0002

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
H
7
13
// 1
0x0001
// 2
@ -8,9 +8,21 @@ H
0x0003
// 4
0x0004
// 3
0x0003
// 7
0x0007
// 8
0x0008
// 11
0x000B
// 9
0x0009
// 15
0x000F
// 16
0x0010
// 17
0x0011
// 32
0x0020
// 33
0x0021
// 2
0x0002

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -12,6 +12,19 @@ a double precision computation.
#define REL_ERROR (1.0e-6)
#define ABS_ERROR (1.0e-5)
/*
Comparisons for inverse
*/
/* Not very accurate for big matrix.
But big matrix needed for checking the vectorized code */
#define SNR_THRESHOLD_INV 70
#define REL_ERROR_INV (1.0e-3)
#define ABS_ERROR_INV (1.0e-3)
/* Upper bound of maximum matrix dimension used by Python */
#define MAXMATRIXDIM 40
@ -184,6 +197,7 @@ void UnaryTestsF32::test_mat_inverse_f32()
int nbMatrixes = dims.nbSamples();
int rows,columns;
int i;
arm_status status;
for(i=0;i < nbMatrixes ; i ++)
{
@ -192,7 +206,8 @@ void UnaryTestsF32::test_mat_inverse_f32()
PREPAREDATA1(false);
arm_mat_inverse_f32(&this->in1,&this->out);
status=arm_mat_inverse_f32(&this->in1,&this->out);
//ASSERT_TRUE(status==ARM_MATH_SUCCESS);
outp += (rows * columns);
inp1 += (rows * columns);
@ -201,9 +216,9 @@ void UnaryTestsF32::test_mat_inverse_f32()
ASSERT_EMPTY_TAIL(output);
ASSERT_SNR(output,ref,(float32_t)SNR_THRESHOLD);
//ASSERT_SNR(output,ref,(float32_t)SNR_THRESHOLD_INV);
ASSERT_CLOSE_ERROR(output,ref,ABS_ERROR,REL_ERROR);
ASSERT_CLOSE_ERROR(output,ref,ABS_ERROR_INV,REL_ERROR_INV);
}

@ -111,6 +111,69 @@ class TextFormatter:
def end(self):
None
# Return test result as a text tree
class HTMLFormatter:
def __init__(self):
self.nb=1
self.suite=False
def start(self):
print("<html><head><title>Test Results</title></head><body>")
def printGroup(self,elem,theId):
if elem is None:
elem = root
message=elem.data["message"]
if not elem.data["deprecated"]:
kind = "Suite"
ident = " " * elem.ident
if elem.kind == TestScripts.Parser.TreeElem.GROUP:
kind = "Group"
if kind == "Group":
print("<h%d> %s (%d) </h%d>" % (self.nb,message,theId,self.nb))
else:
print("<h%d> %s (%d) </h%d>" % (self.nb,message,theId,self.nb))
self.suite=True
print("<table style=\"width:100%\">")
print("<tr>")
print("<td>Name</td>")
print("<td>ID</td>")
print("<td>Status</td>")
print("<td>Cycles</td>")
print("</tr>")
self.nb = self.nb + 1
def printTest(self,elem, theId, theError,errorDetail,theLine,passed,cycles,params):
message=elem.data["message"]
if not elem.data["deprecated"]:
kind = "Test"
ident = " " * elem.ident
p="<font color=\"red\">FAILED</font>"
if passed == 1:
p= "<font color=\"green\">PASSED</font>"
print("<tr>")
print("<td><pre>%s</pre></td>" % message)
print("<td>%d</td>" % theId)
print("<td>%s</td>" % p)
print("<td>%d</td>" % cycles)
print("</tr>")
#if params:
# print("%s %s" % (ident,params))
if passed != 1:
print("<tr><td colspan=4><font color=\"red\">%s at line %d</font></td></tr>" % (errorStr(theError), theLine))
if (len(errorDetail)>0):
print("<tr><td colspan=4><font color=\"red\">" + errorDetail + "</font></td></tr>")
def pop(self):
if self.suite:
print("</table>")
self.nb = self.nb - 1
self.suite=False
def end(self):
print("</body></html>")
# Return test result as a CSV
class CSVFormatter:
@ -454,6 +517,8 @@ def analyze(root,results,args,trace):
if args.c:
analyseResult(resultPath,root,results,args.e,args.b,trace,CSVFormatter())
elif args.html:
analyseResult(resultPath,root,results,args.e,args.b,trace,HTMLFormatter())
elif args.m:
analyseResult(resultPath,root,results,args.e,args.b,trace,MathematicaFormatter())
else:
@ -465,6 +530,7 @@ parser.add_argument('-f', nargs='?',type = str, default="Output.pickle", help="T
# Where the result file can be found
parser.add_argument('-r', nargs='?',type = str, default=None, help="Result file path")
parser.add_argument('-c', action='store_true', help="CSV output")
parser.add_argument('-html', action='store_true', help="HTML output")
parser.add_argument('-e', action='store_true', help="Embedded test")
# -o needed when -e is true to know where to extract the output files
parser.add_argument('-o', nargs='?',type = str, default="Output", help="Output dir path")

Loading…
Cancel
Save