fix divide Sparse by Double 36/15436/5
Sylvain GENIN [Tue, 28 Oct 2014 14:51:44 +0000 (15:51 +0100)]
test_run("ast","divide",["no_check_error_output" ]);

Change-Id: Ia511d8edacb9d93f39328655e1e313aa2c4a560c

scilab/modules/ast/includes/operations/types_divide.hxx
scilab/modules/ast/src/cpp/operations/types_divide.cpp
scilab/modules/ast/src/cpp/operations/types_ldivide.cpp
scilab/modules/ast/tests/unit_tests/divide.dia.ref
scilab/modules/ast/tests/unit_tests/divide.tst

index 196b973..8bf999e 100644 (file)
 #define __TYPES_DIVIDE_HXX__
 
 #include "generic_operations.hxx"
+#include "internal.hxx"
 #include "double.hxx"
 #include "polynom.hxx"
+#include "sparse.hxx"
 
 int RDivideDoubleByDouble(types::Double *_pDouble1, types::Double *_pDouble2, types::Double **_pDoubleOut);
 int RDividePolyByDouble(types::Polynom* _pPoly, types::Double* _pDouble, types::Polynom** _pPolyOut);
 int RDivideDoubleByPoly(types::Double* _pDouble, types::Polynom* _pPoly, types::Polynom** _pPolyOut);
+int RDivideSparseByDouble(types::Sparse* _pSp, types::Double* _pDouble, types::InternalType** _pSpOut);
+
 
 int DotRDivideDoubleByDouble(types::Double *_pDouble1, types::Double *_pDouble2, types::Double **_pDoubleOut);
 int DotRDividePolyByDouble(types::Polynom *_pPoly1, types::Double *_pDouble2, types::Polynom **_pPolyOut);
index 9455ea3..b8f2f9e 100644 (file)
@@ -78,6 +78,17 @@ InternalType *GenericRDivide(InternalType *_pLeftOperand, InternalType *_pRightO
         iResult = RDivideDoubleByPoly(pL, pR, (Polynom**)&pResult);
     }
 
+    /*
+    ** SPARSE / DOUBLE
+    */
+    else if (TypeL == GenericType::ScilabSparse && TypeR == GenericType::ScilabDouble)
+    {
+        Sparse *pL = _pLeftOperand->getAs<types::Sparse>();
+        Double *pR = _pRightOperand->getAs<Double>();
+
+        iResult = RDivideSparseByDouble(pL, pR, &pResult);
+    }
+
     //manage errors
     if (iResult)
     {
@@ -431,6 +442,111 @@ int RDivideDoubleByPoly(Double* /*_pDouble*/, Polynom* /*_pPoly*/, Polynom** /*_
     return 0;
 }
 
+int RDivideSparseByDouble(types::Sparse* _pSp, types::Double* _pDouble, InternalType** _pSpOut)
+{
+    if (_pDouble->isEmpty())
+    {
+        //sp / []
+        *_pSpOut = Double::Empty();
+        return 0;
+    }
+
+    size_t iSize = _pSp->nonZeros();
+    int* Col = new int[iSize];
+    int* Row = new int[iSize];
+    _pSp->getColPos(Col);
+    _pSp->getNbItemByRow(Row);
+    int* iPositVal = new int[iSize];
+
+    int j = 0;
+    for (int i = 0; i < iSize; j++)
+    {
+        for (int k = 0; k < Row[j]; k++)
+        {
+            iPositVal[i] = (Col[i] - 1) * _pSp->getRows() + j;
+            i++;
+        }
+    }
+
+    Double** pDbl = new Double*[iSize];
+    Double** pDblSp = new Double*[iSize];
+    double* pdbl = _pDouble->get();
+
+    if (_pDouble->isScalar())
+    {
+        if (_pDouble->isComplex())
+        {
+            double* pdblImg = _pDouble->getImg();
+            for (int i = 0; i < iSize; i++)
+            {
+                pDbl[i] = new Double(pdbl[0], pdblImg[0]);
+                pDblSp[i] = new Double(_pSp->get(iPositVal[i]), _pSp->getImg(iPositVal[i]).imag());
+            }
+        }
+        else
+        {
+            for (int i = 0; i < iSize; i++)
+            {
+                pDbl[i] = new Double(pdbl[0]);
+                pDblSp[i] = new Double(_pSp->getReal(iPositVal[i]), _pSp->getImg(iPositVal[i]).imag());
+            }
+        }
+    }
+    else if (_pDouble->getSize() == iSize)
+    {
+        if (_pDouble->isComplex())
+        {
+            double* pdblImg = _pDouble->getImg();
+            for (int i = 0; i < iSize; i++)
+            {
+                pDbl[i] = new Double(pdbl[i], pdblImg[i]);
+                pDblSp[i] = new Double(_pSp->getReal(iPositVal[i]), _pSp->getImg(iPositVal[i]).imag());
+            }
+        }
+        else
+        {
+            for (int i = 0; i < iSize; i++)
+            {
+                pDbl[i] = new Double(pdbl[i]);
+                pDblSp[i] = new Double(_pSp->getReal(iPositVal[i]), _pSp->getImg(iPositVal[i]).imag());
+            }
+        }
+    }
+    else
+    {
+        delete[] pDblSp;
+        throw ast::ScilabError(_W("Invalid exponent.\n"));
+        return 1;
+    }
+
+    Sparse* pSpTemp = new Sparse(_pSp->getRows(), _pSp->getCols(), _pSp->isComplex() || _pDouble->isComplex());
+    pSpTemp->zero_set();
+
+    Double* ppDblGet = NULL;
+    int iResultat;
+    for (int i = 0; i < iSize; i++)
+    {
+        if ((pDblSp[i]->get(0) != 0) || (pDblSp[i]->getImg(0) != 0))
+        {
+            iResultat = RDivideDoubleByDouble(pDblSp[i], pDbl[i], &ppDblGet);
+            if (iResultat != 0)
+            {
+                return iResultat;
+            }
+            std::complex<double> cplx(ppDblGet->get(0), ppDblGet->getImg(0));
+            pSpTemp->set(iPositVal[i], cplx, true);
+        }
+    }
+    delete Col;
+    delete iPositVal;
+
+    *_pSpOut = pSpTemp;
+    return 0;
+}
+
+
+
+
 int DotRDivideDoubleByDouble(Double* _pDouble1, Double* _pDouble2, Double** _pDoubleOut)
 {
     int iErr        = 0;
index c738b9a..1b3ac1d 100644 (file)
@@ -55,6 +55,17 @@ InternalType *GenericLDivide(InternalType *_pLeftOperand, InternalType *_pRightO
         iResult = LDivideDoubleByDouble(pL, pR, (Double**)&pResult);
     }
 
+    /*
+    ** DOUBLE \ SPARSE
+    */
+    if (TypeL == GenericType::ScilabDouble && TypeR == GenericType::ScilabSparse)
+    {
+        Double *pL = _pLeftOperand->getAs<Double>();
+        Sparse *pR = _pRightOperand->getAs<Sparse>();
+
+        iResult = RDivideSparseByDouble(pR, pL, &pResult);
+    }
+
     //manage errors
     if (iResult)
     {
index 4d59d25..407b68c 100644 (file)
@@ -13,6 +13,8 @@ c = 1 + 2*%i;
 C = [1+2*%i,2+4*%i;3+6*%i,4+8*%i];
 C3(:,:,1) = C;
 C3(:,:,2) = C';
+SP = sparse([1,2;4,5;3,10],[1,2,3]);
+SPC = sparse([1,2;4,5;3,10],[1,2,3]) * ( 1 + 4*%i);
 //double / double
 //r / r
 assert_checkalmostequal(r / r, 1);
@@ -61,3 +63,12 @@ assert_checkalmostequal(R / C, [0.2-0.4*%i,0;0,0.2-0.4*%i]);
 assert_checkalmostequal(C / R, [1+2*%i,0;0,1+2*%i]);
 //C / C
 assert_checkalmostequal(C / C, [1,0;0,1]);
+//SPARSE / double
+//SP / r
+assert_checkalmostequal(SP/ r, sparse([1,2;4,5;3,10],[0.5,1,1.5]));
+//SP / c
+assert_checkalmostequal(SP/ c, sparse([1,2;4,5;3,10],[0.2-0.4*%i,0.4-0.8*%i,0.6-1.2*%i]));
+//SPC /r
+assert_checkalmostequal(SPC/ r, sparse([1,2;4,5;3,10],[0.5+2*%i,1+4*%i,1.5+6*%i]));
+//SPC /c
+assert_checkalmostequal(SPC/ c, sparse([1,2;4,5;3,10],[1.8+0.4*%i,3.6+0.8*%i,5.4+1.2*%i]));
index e18e1b6..b90ffd4 100644 (file)
@@ -15,6 +15,8 @@ c = 1 + 2*%i;
 C = [1+2*%i,2+4*%i;3+6*%i,4+8*%i];
 C3(:,:,1) = C;
 C3(:,:,2) = C';
+SP = sparse([1,2;4,5;3,10],[1,2,3]);
+SPC = sparse([1,2;4,5;3,10],[1,2,3]) * ( 1 + 4*%i);
 
 //double / double
 
@@ -75,3 +77,15 @@ assert_checkalmostequal(R / C, [0.2-0.4*%i,0;0,0.2-0.4*%i]);
 assert_checkalmostequal(C / R, [1+2*%i,0;0,1+2*%i]);
 //C / C
 assert_checkalmostequal(C / C, [1,0;0,1]);
+
+//SPARSE / double
+
+//SP / r
+assert_checkalmostequal(SP/ r, sparse([1,2;4,5;3,10],[0.5,1,1.5]));
+//SP / c
+assert_checkalmostequal(SP/ c, sparse([1,2;4,5;3,10],[0.2-0.4*%i,0.4-0.8*%i,0.6-1.2*%i]));
+//SPC /r
+assert_checkalmostequal(SPC/ r, sparse([1,2;4,5;3,10],[0.5+2*%i,1+4*%i,1.5+6*%i]));
+//SPC /c
+assert_checkalmostequal(SPC/ c, sparse([1,2;4,5;3,10],[1.8+0.4*%i,3.6+0.8*%i,5.4+1.2*%i]));
+