CMSIS-DSP: Correcting a bug in matrix inversion

When pivot is 0, the row permutation code was not correct and failing on
some matrixes (but not all matrixes).
pull/19/head
Christophe Favergeon 5 years ago
parent ac7da660b7
commit 1019e4c4a8

@ -3,6 +3,7 @@
## How to use ## How to use
This document is explaining how to use cmake with CMSIS-DSP. This document is explaining how to use cmake with CMSIS-DSP.
(It is not official so not supported. The official way to build is to use the CMSIS-Pack).
The example arm_variance_f32 in folder Examples/ARM/arm_variance_f32 has been modified to also The example arm_variance_f32 in folder Examples/ARM/arm_variance_f32 has been modified to also
support cmake and is used as an example in this document. support cmake and is used as an example in this document.

@ -67,7 +67,7 @@ arm_status arm_mat_inverse_f16(
float16_t *pTmpA, *pTmpB; float16_t *pTmpA, *pTmpB;
_Float16 in = 0.0f16; /* Temporary input values */ _Float16 in = 0.0f16; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */ uint32_t i, rowCnt, flag = 0U, j, loopCnt, l; /* loop counters */
arm_status status; /* status of matrix inverse */ arm_status status; /* status of matrix inverse */
uint32_t blkCnt; uint32_t blkCnt;
@ -191,10 +191,7 @@ arm_status arm_mat_inverse_f16(
* Temporary variable to hold the pivot value * Temporary variable to hold the pivot value
*/ */
in = *pInT1; in = *pInT1;
/*
* Destination pointer modifier
*/
k = 1U;
/* /*
* Check if the pivot element is zero * Check if the pivot element is zero
@ -210,7 +207,7 @@ arm_status arm_mat_inverse_f16(
* Update the input and destination pointers * Update the input and destination pointers
*/ */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* /*
* Check if there is a non zero pivot element to * Check if there is a non zero pivot element to
* * replace in the rows below * * replace in the rows below
@ -300,10 +297,7 @@ arm_status arm_mat_inverse_f16(
*/ */
break; break;
} }
/*
* Update the destination pointer modifier
*/
k++;
} }
} }
@ -569,7 +563,7 @@ arm_status arm_mat_inverse_f16(
uint32_t numCols = pSrc->numCols; /* Number of Cols in the matrix */ uint32_t numCols = pSrc->numCols; /* Number of Cols in the matrix */
_Float16 Xchg, in = 0.0f16, in1; /* Temporary input values */ _Float16 Xchg, in = 0.0f16, in1; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */ uint32_t i, rowCnt, flag = 0U, j, loopCnt, k,l; /* loop counters */
arm_status status; /* status of matrix inverse */ arm_status status; /* status of matrix inverse */
#ifdef ARM_MATH_MATRIX_CHECK #ifdef ARM_MATH_MATRIX_CHECK
@ -680,9 +674,6 @@ arm_status arm_mat_inverse_f16(
/* Temporary variable to hold the pivot value */ /* Temporary variable to hold the pivot value */
in = *pInT1; in = *pInT1;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is zero */ /* Check if the pivot element is zero */
if (*pInT1 == 0.0f16) if (*pInT1 == 0.0f16)
@ -693,7 +684,7 @@ arm_status arm_mat_inverse_f16(
{ {
/* Update the input and destination pointers */ /* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* Check if there is a non zero pivot element to /* Check if there is a non zero pivot element to
* replace in the rows below */ * replace in the rows below */
@ -735,10 +726,6 @@ arm_status arm_mat_inverse_f16(
break; break;
} }
/* Update the destination pointer modifier */
k++;
/* Decrement loop counter */
} }
} }

@ -28,6 +28,7 @@
#include "dsp/matrix_functions.h" #include "dsp/matrix_functions.h"
/** /**
@ingroup groupMatrix @ingroup groupMatrix
*/ */
@ -84,7 +85,7 @@ arm_status arm_mat_inverse_f32(
float32_t *pTmpA, *pTmpB; float32_t *pTmpA, *pTmpB;
float32_t in = 0.0f; /* Temporary input values */ float32_t in = 0.0f; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */ uint32_t i, rowCnt, flag = 0U, j, loopCnt, l; /* loop counters */
arm_status status; /* status of matrix inverse */ arm_status status; /* status of matrix inverse */
uint32_t blkCnt; uint32_t blkCnt;
@ -208,10 +209,7 @@ arm_status arm_mat_inverse_f32(
* Temporary variable to hold the pivot value * Temporary variable to hold the pivot value
*/ */
in = *pInT1; in = *pInT1;
/*
* Destination pointer modifier
*/
k = 1U;
/* /*
* Check if the pivot element is zero * Check if the pivot element is zero
@ -227,7 +225,7 @@ arm_status arm_mat_inverse_f32(
* Update the input and destination pointers * Update the input and destination pointers
*/ */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* /*
* Check if there is a non zero pivot element to * Check if there is a non zero pivot element to
* * replace in the rows below * * replace in the rows below
@ -317,10 +315,7 @@ arm_status arm_mat_inverse_f32(
*/ */
break; break;
} }
/*
* Update the destination pointer modifier
*/
k++;
} }
} }
@ -699,10 +694,6 @@ arm_status arm_mat_inverse_f32(
/* Temporary variable to hold the pivot value */ /* Temporary variable to hold the pivot value */
in = *pInT1; in = *pInT1;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is zero */ /* Check if the pivot element is zero */
if (*pInT1 == 0.0f) if (*pInT1 == 0.0f)
{ {
@ -711,7 +702,7 @@ arm_status arm_mat_inverse_f32(
{ {
/* Update the input and destination pointers */ /* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* Check if there is a non zero pivot element to /* Check if there is a non zero pivot element to
* replace in the rows below */ * replace in the rows below */
@ -753,8 +744,7 @@ arm_status arm_mat_inverse_f32(
break; break;
} }
/* Update the destination pointer modifier */
k++;
} }
} }
@ -997,7 +987,7 @@ arm_status arm_mat_inverse_f32(
#if defined (ARM_MATH_DSP) #if defined (ARM_MATH_DSP)
float32_t Xchg, in = 0.0f, in1; /* Temporary input values */ float32_t Xchg, in = 0.0f, in1; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */ uint32_t i, rowCnt, flag = 0U, j, loopCnt, k,l; /* loop counters */
arm_status status; /* status of matrix inverse */ arm_status status; /* status of matrix inverse */
#ifdef ARM_MATH_MATRIX_CHECK #ifdef ARM_MATH_MATRIX_CHECK
@ -1108,9 +1098,7 @@ arm_status arm_mat_inverse_f32(
/* Temporary variable to hold the pivot value */ /* Temporary variable to hold the pivot value */
in = *pInT1; in = *pInT1;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is zero */ /* Check if the pivot element is zero */
if (*pInT1 == 0.0f) if (*pInT1 == 0.0f)
@ -1121,7 +1109,7 @@ arm_status arm_mat_inverse_f32(
{ {
/* Update the input and destination pointers */ /* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* Check if there is a non zero pivot element to /* Check if there is a non zero pivot element to
* replace in the rows below */ * replace in the rows below */
@ -1163,8 +1151,6 @@ arm_status arm_mat_inverse_f32(
break; break;
} }
/* Update the destination pointer modifier */
k++;
/* Decrement loop counter */ /* Decrement loop counter */
} }
@ -1306,7 +1292,7 @@ arm_status arm_mat_inverse_f32(
#else #else
float32_t Xchg, in = 0.0f; /* Temporary input values */ float32_t Xchg, in = 0.0f; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */ uint32_t i, rowCnt, flag = 0U, j, loopCnt, l; /* loop counters */
arm_status status; /* status of matrix inverse */ arm_status status; /* status of matrix inverse */
#ifdef ARM_MATH_MATRIX_CHECK #ifdef ARM_MATH_MATRIX_CHECK
@ -1417,9 +1403,6 @@ arm_status arm_mat_inverse_f32(
/* Temporary variable to hold the pivot value */ /* Temporary variable to hold the pivot value */
in = *pInT1; in = *pInT1;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is zero */ /* Check if the pivot element is zero */
if (*pInT1 == 0.0f) if (*pInT1 == 0.0f)
{ {
@ -1428,7 +1411,7 @@ arm_status arm_mat_inverse_f32(
{ {
/* Update the input and destination pointers */ /* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* Check if there is a non zero pivot element to /* Check if there is a non zero pivot element to
* replace in the rows below */ * replace in the rows below */
@ -1457,12 +1440,10 @@ arm_status arm_mat_inverse_f32(
/* Break after exchange is done */ /* Break after exchange is done */
break; break;
} }
/* Update the destination pointer modifier */
k++;
} }
} }
/* Update the status if the matrix is singular */ /* Update the status if the matrix is singular */
if ((flag != 1U) && (in == 0.0f)) if ((flag != 1U) && (in == 0.0f))
{ {

@ -63,7 +63,7 @@ arm_status arm_mat_inverse_f64(
#if defined (ARM_MATH_DSP) #if defined (ARM_MATH_DSP)
float64_t Xchg, in = 0.0, in1; /* Temporary input values */ float64_t Xchg, in = 0.0, in1; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */ uint32_t i, rowCnt, flag = 0U, j, loopCnt,k, l; /* loop counters */
arm_status status; /* status of matrix inverse */ arm_status status; /* status of matrix inverse */
#ifdef ARM_MATH_MATRIX_CHECK #ifdef ARM_MATH_MATRIX_CHECK
@ -174,9 +174,6 @@ arm_status arm_mat_inverse_f64(
/* Temporary variable to hold the pivot value */ /* Temporary variable to hold the pivot value */
in = *pInT1; in = *pInT1;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is zero */ /* Check if the pivot element is zero */
if (*pInT1 == 0.0) if (*pInT1 == 0.0)
{ {
@ -185,7 +182,7 @@ arm_status arm_mat_inverse_f64(
{ {
/* Update the input and destination pointers */ /* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* Check if there is a non zero pivot element to /* Check if there is a non zero pivot element to
* replace in the rows below */ * replace in the rows below */
@ -227,11 +224,6 @@ arm_status arm_mat_inverse_f64(
break; break;
} }
/* Update the destination pointer modifier */
k++;
/* Decrement loop counter */
i--;
} }
} }
@ -371,7 +363,7 @@ arm_status arm_mat_inverse_f64(
#else #else
float64_t Xchg, in = 0.0; /* Temporary input values */ float64_t Xchg, in = 0.0; /* Temporary input values */
uint32_t i, rowCnt, flag = 0U, j, loopCnt, k, l; /* loop counters */ uint32_t i, rowCnt, flag = 0U, j, loopCnt, l; /* loop counters */
arm_status status; /* status of matrix inverse */ arm_status status; /* status of matrix inverse */
#ifdef ARM_MATH_MATRIX_CHECK #ifdef ARM_MATH_MATRIX_CHECK
@ -482,8 +474,7 @@ arm_status arm_mat_inverse_f64(
/* Temporary variable to hold the pivot value */ /* Temporary variable to hold the pivot value */
in = *pInT1; in = *pInT1;
/* Destination pointer modifier */
k = 1U;
/* Check if the pivot element is zero */ /* Check if the pivot element is zero */
if (*pInT1 == 0.0) if (*pInT1 == 0.0)
@ -493,7 +484,7 @@ arm_status arm_mat_inverse_f64(
{ {
/* Update the input and destination pointers */ /* Update the input and destination pointers */
pInT2 = pInT1 + (numCols * i); pInT2 = pInT1 + (numCols * i);
pOutT2 = pOutT1 + (numCols * k); pOutT2 = pOutT1 + (numCols * i);
/* Check if there is a non zero pivot element to /* Check if there is a non zero pivot element to
* replace in the rows below */ * replace in the rows below */
@ -523,8 +514,7 @@ arm_status arm_mat_inverse_f64(
break; break;
} }
/* Update the destination pointer modifier */
k++;
} }
} }

@ -172,9 +172,8 @@ def getInvertibleMatrix(d):
m=[[0.804738, -0.310617, 0.505879], [0.505879, m=[[0.804738, -0.310617, 0.505879], [0.505879,
0.804738, -0.310617], [-0.310617, 0.505879, 0.804738]] 0.804738, -0.310617], [-0.310617, 0.505879, 0.804738]]
if d == 4: if d == 4:
m = [[0.82826, 0.337671, 0.564395, 0.576988], [0.403359, 0.369414, m = [[1.0, 2.0, 3.0, 4.0], [2.0, 4.0, 5.0, 6.0],
0.597588, 0.436561], [0.783442, 0.3334, 0.525436, [3.0, 5.0, 9.0, 10.0], [4.0, 6.0, 10.0, 16.0]]
0.0858155], [0.329328, 0.397682, 0.12816, 0.775337]]
if d == 7: if d == 7:
m = [[0.978575, 0.330011, 0.951751, 0.304936, 0.924631, 0.502005, m = [[0.978575, 0.330011, 0.951751, 0.304936, 0.924631, 0.502005,
0.235223], [0.185314, 0.46862, 0.955398, 0.970953, 0.637389, 0.235223], [0.185314, 0.46862, 0.955398, 0.970953, 0.637389,
@ -680,6 +679,7 @@ def getSemidefinitePositiveMatrix(d,k=3):
return(np.matmul(p,np.matmul(a,np.transpose(p)))) return(np.matmul(p,np.matmul(a,np.transpose(p))))
def writeUnaryTests(config,format): def writeUnaryTests(config,format):
config.setOverwrite(False)
# For benchmarks # For benchmarks
NBSAMPLES=NBA*NBB NBSAMPLES=NBA*NBB
NBVECSAMPLES = NBB NBVECSAMPLES = NBB
@ -783,8 +783,12 @@ def writeUnaryTests(config,format):
else: else:
dims=[1,2,3,4,7,8,9,15,16,17,32,33] dims=[1,2,3,4,7,8,9,15,16,17,32,33]
# #
if format == Tools.F32 or format == Tools.F16 or format == Tools.F64:
config.setOverwrite(True)
vals = [] vals = []
inp=[] inp=[]
for d in dims: for d in dims:
ma = getInvertibleMatrix(d) ma = getInvertibleMatrix(d)
inp = inp + list(ma.reshape(d*d)) inp = inp + list(ma.reshape(d*d))
@ -801,6 +805,8 @@ def writeUnaryTests(config,format):
config.writeInputS16(1, dims,"DimsInvert") config.writeInputS16(1, dims,"DimsInvert")
config.writeInput(1, inp,"InputInvert") config.writeInput(1, inp,"InputInvert")
config.writeReference(1, vals,"RefInvert") config.writeReference(1, vals,"RefInvert")
config.setOverwrite(False)
# One kind of matrix shape # One kind of matrix shape
# Cholesky and LDLT definite positive (DPO) # Cholesky and LDLT definite positive (DPO)
@ -854,7 +860,6 @@ def writeUnaryTests(config,format):
config.writeInputS16(1, dims,"DimsCholeskyDPO") config.writeInputS16(1, dims,"DimsCholeskyDPO")
config.writeInput(1, inp,"InputCholeskyDPO") config.writeInput(1, inp,"InputCholeskyDPO")
config.writeReference(1, vals,"RefCholeskyDPO") config.writeReference(1, vals,"RefCholeskyDPO")
@ -916,6 +921,13 @@ def generatePatterns():
configBinaryq15=Tools.Config(PATTERNBINDIR,PARAMBINDIR,"q15") configBinaryq15=Tools.Config(PATTERNBINDIR,PARAMBINDIR,"q15")
configBinaryq7=Tools.Config(PATTERNBINDIR,PARAMBINDIR,"q7") configBinaryq7=Tools.Config(PATTERNBINDIR,PARAMBINDIR,"q7")
configBinaryf64.setOverwrite(False)
configBinaryf32.setOverwrite(False)
configBinaryf16.setOverwrite(False)
configBinaryq31.setOverwrite(False)
configBinaryq15.setOverwrite(False)
configBinaryq7.setOverwrite(False)
writeBinaryTests(configBinaryf64,Tools.F32) writeBinaryTests(configBinaryf64,Tools.F32)
writeBinaryTests(configBinaryf32,Tools.F32) writeBinaryTests(configBinaryf32,Tools.F32)
@ -934,6 +946,12 @@ def generatePatterns():
configUnaryq15=Tools.Config(PATTERNUNDIR,PARAMUNDIR,"q15") configUnaryq15=Tools.Config(PATTERNUNDIR,PARAMUNDIR,"q15")
configUnaryq7=Tools.Config(PATTERNUNDIR,PARAMUNDIR,"q7") configUnaryq7=Tools.Config(PATTERNUNDIR,PARAMUNDIR,"q7")
configUnaryf64.setOverwrite(False)
configUnaryf32.setOverwrite(False)
configUnaryf16.setOverwrite(False)
configUnaryq31.setOverwrite(False)
configUnaryq15.setOverwrite(False)
configUnaryq7.setOverwrite(False)
writeUnaryTests(configUnaryf64,Tools.F64) writeUnaryTests(configUnaryf64,Tools.F64)
writeUnaryTests(configUnaryf32,Tools.F32) writeUnaryTests(configUnaryf32,Tools.F32)

@ -28,38 +28,38 @@ H
0x380c 0x380c
// 0.804738 // 0.804738
0x3a70 0x3a70
// 0.828260 // 1.000000
0x3aa0 0x3c00
// 0.337671 // 2.000000
0x3567 0x4000
// 0.564395 // 3.000000
0x3884 0x4200
// 0.576988 // 4.000000
0x389e 0x4400
// 0.403359 // 2.000000
0x3674 0x4000
// 0.369414 // 4.000000
0x35e9 0x4400
// 0.597588 // 5.000000
0x38c8 0x4500
// 0.436561 // 6.000000
0x36fc 0x4600
// 0.783442 // 3.000000
0x3a44 0x4200
// 0.333400 // 5.000000
0x3556 0x4500
// 0.525436 // 9.000000
0x3834 0x4880
// 0.085816 // 10.000000
0x2d7e 0x4900
// 0.329328 // 4.000000
0x3545 0x4400
// 0.397682 // 6.000000
0x365d 0x4600
// 0.128160 // 10.000000
0x301a 0x4900
// 0.775337 // 16.000000
0x3a34 0x4c00
// 0.978575 // 0.978575
0x3bd4 0x3bd4
// 0.330011 // 0.330011

@ -28,38 +28,38 @@ H
0xb4f8 0xb4f8
// 0.804738 // 0.804738
0x3a70 0x3a70
// 1.413088 // -6.500000
0x3da7 0xc680
// -2.081372 // 1.500000
0xc02a 0x3e00
// 0.842716 // 0.500000
0x3abe 0x3800
// 0.027076 // 0.750000
0x26ee 0x3a00
// -5.114009 // 1.500000
0xc51d 0x3e00
// 0.949805 // 0.500000
0x3b99 0x3800
// 3.715447 // -0.500000
0x436e 0xb800
// 2.859700 // -0.250000
0x41b8 0xb400
// 0.830018 // 0.500000
0x3aa4 0x3800
// 2.503484 // -0.500000
0x4102 0xb800
// -1.378369 // 0.500000
0xbd83 0x3800
// -1.874732 // -0.250000
0xbf80 0xb400
// 1.885638 // 0.750000
0x3f8b 0x3a00
// -0.016912 // -0.250000
0xa454 0xb400
// -2.035818 // -0.250000
0xc012 0xb400
// 0.121363 // 0.125000
0x2fc4 0x3000
// 1.305635 // 1.305635
0x3d39 0x3d39
// -2.573542 // -2.573542

@ -28,38 +28,38 @@ W
0x3f018149 0x3f018149
// 0.804738 // 0.804738
0x3f4e034f 0x3f4e034f
// 0.828260 // 1.000000
0x3f5408d9 0x3f800000
// 0.337671 // 2.000000
0x3eace337 0x40000000
// 0.564395 // 3.000000
0x3f107c31 0x40400000
// 0.576988 // 4.000000
0x3f13b57c 0x40800000
// 0.403359 // 2.000000
0x3ece8512 0x40000000
// 0.369414 // 4.000000
0x3ebd23d5 0x40800000
// 0.597588 // 5.000000
0x3f18fb87 0x40a00000
// 0.436561 // 6.000000
0x3edf84ec 0x40c00000
// 0.783442 // 3.000000
0x3f488fa8 0x40400000
// 0.333400 // 5.000000
0x3eaab368 0x40a00000
// 0.525436 // 9.000000
0x3f0682f9 0x41100000
// 0.085816 // 10.000000
0x3dafc009 0x41200000
// 0.329328 // 4.000000
0x3ea89dae 0x40800000
// 0.397682 // 6.000000
0x3ecb9cfa 0x40c00000
// 0.128160 // 10.000000
0x3e033c60 0x41200000
// 0.775337 // 16.000000
0x3f467c7c 0x41800000
// 0.978575 // 0.978575
0x3f7a83e4 0x3f7a83e4
// 0.330011 // 0.330011

@ -28,38 +28,38 @@ W
0xbe9f093a 0xbe9f093a
// 0.804738 // 0.804738
0x3f4e0352 0x3f4e0352
// 1.413088 // -6.500000
0x3fb4e00e 0xc0d00000
// -2.081372 // 1.500000
0xc0053535 0x3fc00000
// 0.842716 // 0.500000
0x3f57bc42 0x3f000000
// 0.027076 // 0.750000
0x3cddcf41 0x3f400000
// -5.114009 // 1.500000
0xc0a3a5f6 0x3fc00000
// 0.949805 // 0.500000
0x3f732671 0x3f000000
// 3.715447 // -0.500000
0x406dc9e3 0xbf000000
// 2.859700 // -0.250000
0x40370551 0xbe800000
// 0.830018 // 0.500000
0x3f547c13 0x3f000000
// 2.503484 // -0.500000
0x40203916 0xbf000000
// -1.378369 // 0.500000
0xbfb06e66 0x3f000000
// -1.874732 // -0.250000
0xbfeff734 0xbe800000
// 1.885638 // 0.750000
0x3ff15c95 0x3f400000
// -0.016912 // -0.250000
0xbc8a8bec 0xbe800000
// -2.035818 // -0.250000
0xc0024ad6 0xbe800000
// 0.121363 // 0.125000
0x3df88d64 0x3e000000
// 1.305635 // 1.305635
0x3fa71f0a 0x3fa71f0a
// -2.573542 // -2.573542

@ -28,38 +28,38 @@ D
0x3fe030292817763e 0x3fe030292817763e
// 0.804738 // 0.804738
0x3fe9c069e7fb267c 0x3fe9c069e7fb267c
// 0.828260 // 1.000000
0x3fea811b1d92b7fe 0x3ff0000000000000
// 0.337671 // 2.000000
0x3fd59c66d373affb 0x4000000000000000
// 0.564395 // 3.000000
0x3fe20f861a60d456 0x4008000000000000
// 0.576988 // 4.000000
0x3fe276af89c5e6ff 0x4010000000000000
// 0.403359 // 2.000000
0x3fd9d0a244630660 0x4000000000000000
// 0.369414 // 4.000000
0x3fd7a47a9e2bcf92 0x4010000000000000
// 0.597588 // 5.000000
0x3fe31f70de8f6cf0 0x4014000000000000
// 0.436561 // 6.000000
0x3fdbf09d8c6d612c 0x4018000000000000
// 0.783442 // 3.000000
0x3fe911f4f50a02b8 0x4008000000000000
// 0.333400 // 5.000000
0x3fd5566cf41f212d 0x4014000000000000
// 0.525436 // 9.000000
0x3fe0d05f28848388 0x4022000000000000
// 0.085816 // 10.000000
0x3fb5f8012dfd694d 0x4024000000000000
// 0.329328 // 4.000000
0x3fd513b5bf6a0dbb 0x4010000000000000
// 0.397682 // 6.000000
0x3fd9739f340d4dc6 0x4018000000000000
// 0.128160 // 10.000000
0x3fc0678c0053e2d6 0x4024000000000000
// 0.775337 // 16.000000
0x3fe8cf8f8a4c1ebd 0x4030000000000000
// 0.978575 // 0.978575
0x3fef507c84b5dcc6 0x3fef507c84b5dcc6
// 0.330011 // 0.330011

@ -28,38 +28,38 @@ D
0xbfd3e1273621427c 0xbfd3e1273621427c
// 0.804738 // 0.804738
0x3fe9c06a4dbb030e 0x3fe9c06a4dbb030e
// 1.413088 // -6.500000
0x3ff69c01bcda645e 0xc019fffffffffffe
// -2.081372 // 1.500000
0xc000a6a6921dae82 0x3ff8000000000000
// 0.842716 // 0.500000
0x3feaf788323d9e48 0x3fdffffffffffff8
// 0.027076 // 0.750000
0x3f9bb9e81fc8d11d 0x3fe8000000000002
// -5.114009 // 1.500000
0xc01474bec0fff89f 0x3ff7ffffffffffff
// 0.949805 // 0.500000
0x3fee64ce235cf93e 0x3fe0000000000000
// 3.715447 // -0.500000
0x400db93c5f7d8b66 0xbfdffffffffffffe
// 2.859700 // -0.250000
0x4006e0aa2629c79f 0xbfd0000000000001
// 0.830018 // 0.500000
0x3fea8f8251c1a7fe 0x3fdffffffffffffe
// 2.503484 // -0.500000
0x40040722ce21a4d9 0xbfe0000000000000
// -1.378369 // 0.500000
0xbff60dccba5f5183 0x3fe0000000000000
// -1.874732 // -0.250000
0xbffdfee6844680da 0xbfd0000000000000
// 1.885638 // 0.750000
0x3ffe2b92ac107f21 0x3fe7ffffffffffff
// -0.016912 // -0.250000
0xbf91517d8bf08170 0xbfd0000000000000
// -2.035818 // -0.250000
0xc000495ac61bce71 0xbfcffffffffffffe
// 0.121363 // 0.125000
0x3fbf11ac8d7c1e33 0x3fbffffffffffffe
// 1.305635 // 1.305635
0x3ff4e3e14dd454c7 0x3ff4e3e14dd454c7
// -2.573542 // -2.573542

Loading…
Cancel
Save