fix divide Sparse by Double
[scilab.git] / scilab / modules / ast / src / cpp / operations / types_ldivide.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2013 - Scilab Enterprises - Cedric Delamarre
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include "types_ldivide.hxx"
14 #include "types_divide.hxx"
15 #include "types_finite.hxx"
16
17 #include "scilabexception.hxx"
18
19 extern "C"
20 {
21 #include "matrix_left_division.h"
22 #include "sciprint.h"
23 #include "localization.h"
24 #include "charEncoding.h"
25 }
26
27 using namespace types;
28
29 InternalType *GenericLDivide(InternalType *_pLeftOperand, InternalType *_pRightOperand)
30 {
31     InternalType *pResult       = NULL;
32     GenericType::ScilabType TypeL = _pLeftOperand->getType();
33     GenericType::ScilabType TypeR = _pRightOperand->getType();
34
35     int iResult = 0;
36
37     if (_pLeftOperand->isDouble() && _pLeftOperand->getAs<Double>()->isEmpty())
38     {
39         return Double::Empty();
40     }
41
42     if (_pRightOperand->isDouble() && _pRightOperand->getAs<Double>()->isEmpty())
43     {
44         return Double::Empty();
45     }
46
47     /*
48     ** DOUBLE \ DOUBLE
49     */
50     if (TypeL == GenericType::ScilabDouble && TypeR == GenericType::ScilabDouble)
51     {
52         Double *pL  = _pLeftOperand->getAs<Double>();
53         Double *pR  = _pRightOperand->getAs<Double>();
54
55         iResult = LDivideDoubleByDouble(pL, pR, (Double**)&pResult);
56     }
57
58     /*
59     ** DOUBLE \ SPARSE
60     */
61     if (TypeL == GenericType::ScilabDouble && TypeR == GenericType::ScilabSparse)
62     {
63         Double *pL = _pLeftOperand->getAs<Double>();
64         Sparse *pR = _pRightOperand->getAs<Sparse>();
65
66         iResult = RDivideSparseByDouble(pR, pL, &pResult);
67     }
68
69     //manage errors
70     if (iResult)
71     {
72         switch (iResult)
73         {
74             case 1 :
75                 throw ast::ScilabError(_W("Inconsistent row/column dimensions.\n"));
76             case 2 :
77                 throw ast::ScilabError(_W("With NaN or Inf a left division by scalar expected.\n"));
78             case 3 :
79                 throw ast::ScilabError(_W("Left division by zero...\n"));
80             case 4 :
81                 sciprint(_("Warning : Left division by zero...\n"));
82                 break;
83             default :
84                 sciprint(_("Operator \\ : Error %d not yet managed.\n"), iResult);
85         }
86     }
87
88     /*
89     ** Default case : Return NULL will Call Overloading.
90     */
91     return pResult;
92 }
93
94 int LDivideDoubleByDouble(Double *_pDouble1, Double *_pDouble2, Double **_pDoubleOut)
95 {
96     int iErr = 0;
97
98     //check finite values of _pDouble1 and _pDouble2
99     if (isDoubleFinite(_pDouble1) == false || isDoubleFinite(_pDouble2) == false)
100     {
101         if (_pDouble2->isScalar() == false)
102         {
103             return 2;
104         }
105     }
106
107     if (_pDouble1->isScalar())
108     {
109         //Y \ x => x / Y
110         return RDivideDoubleByDouble(_pDouble2, _pDouble1, _pDoubleOut);
111     }
112
113     if (_pDouble2->isScalar())
114     {
115         // managed in %s_l_s, call overload
116         return 0;
117     }
118
119     if (_pDouble1->getDims() > 2 || _pDouble2->getDims() > 2 || _pDouble1->getRows() != _pDouble2->getRows())
120     {
121         //not managed
122         return 1;
123     }
124
125     *_pDoubleOut = new Double(_pDouble1->getCols(), _pDouble2->getCols(), _pDouble1->isComplex() || _pDouble2->isComplex());
126     if ((*_pDoubleOut)->isComplex())
127     {
128         double dblRcond = 0;
129         iErr = iLeftDivisionOfComplexMatrix(
130                    _pDouble1->getReal(), _pDouble1->getImg(), _pDouble1->getRows(), _pDouble1->getCols(),
131                    _pDouble2->getReal(), _pDouble2->getImg(), _pDouble2->getRows(), _pDouble2->getCols(),
132                    (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getImg(), (*_pDoubleOut)->getRows(), (*_pDoubleOut)->getCols(), &dblRcond);
133     }
134     else
135     {
136         double dblRcond = 0;
137         iErr = iLeftDivisionOfRealMatrix(
138                    _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getCols(),
139                    _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getCols(),
140                    (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getRows(), (*_pDoubleOut)->getCols(), &dblRcond);
141     }
142
143     return iErr;
144 }
145