bug 13918: Unmanaged operations on hypermatrix did not call overload functions.
[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 extern "C"
18 {
19 #include "matrix_left_division.h"
20 #include "sciprint.h"
21 #include "localization.h"
22 #include "charEncoding.h"
23 }
24
25 using namespace types;
26
27 InternalType *GenericLDivide(InternalType *_pLeftOperand, InternalType *_pRightOperand)
28 {
29     InternalType *pResult       = NULL;
30     GenericType::ScilabType TypeL = _pLeftOperand->getType();
31     GenericType::ScilabType TypeR = _pRightOperand->getType();
32
33     int iResult = 0;
34
35     if (_pLeftOperand->isDouble() && _pLeftOperand->getAs<Double>()->isEmpty())
36     {
37         return Double::Empty();
38     }
39
40     if (_pRightOperand->isDouble() && _pRightOperand->getAs<Double>()->isEmpty())
41     {
42         return Double::Empty();
43     }
44
45     /*
46     ** DOUBLE \ DOUBLE
47     */
48     if (TypeL == GenericType::ScilabDouble && TypeR == GenericType::ScilabDouble)
49     {
50         Double *pL  = _pLeftOperand->getAs<Double>();
51         Double *pR  = _pRightOperand->getAs<Double>();
52
53         iResult = LDivideDoubleByDouble(pL, pR, (Double**)&pResult);
54     }
55
56     /*
57     ** DOUBLE \ SPARSE
58     */
59     if (TypeL == GenericType::ScilabDouble && TypeR == GenericType::ScilabSparse)
60     {
61         Double *pL = _pLeftOperand->getAs<Double>();
62         Sparse *pR = _pRightOperand->getAs<Sparse>();
63
64         iResult = RDivideSparseByDouble(pR, pL, &pResult);
65     }
66
67     //manage errors
68     if (iResult)
69     {
70         switch (iResult)
71         {
72             case 1 :
73                 throw ast::InternalError(_W("Inconsistent row/column dimensions.\n"));
74             case 2 :
75                 throw ast::InternalError(_W("With NaN or Inf a left division by scalar expected.\n"));
76             case 3 :
77                 throw ast::InternalError(_W("Left division by zero...\n"));
78             case 4 :
79                 sciprint(_("Warning : Left division by zero...\n"));
80                 break;
81             default :
82                 sciprint(_("Operator \\ : Error %d not yet managed.\n"), iResult);
83         }
84     }
85
86     /*
87     ** Default case : Return NULL will Call Overloading.
88     */
89     return pResult;
90 }
91
92 int LDivideDoubleByDouble(Double *_pDouble1, Double *_pDouble2, Double **_pDoubleOut)
93 {
94     int iErr = 0;
95
96     //check finite values of _pDouble1 and _pDouble2
97     if (isDoubleFinite(_pDouble1) == false || isDoubleFinite(_pDouble2) == false)
98     {
99         if (_pDouble1->isScalar() == false)
100         {
101             return 2;
102         }
103     }
104
105     if (_pDouble1->isScalar())
106     {
107         //Y \ x => x / Y
108         return RDivideDoubleByDouble(_pDouble2, _pDouble1, _pDoubleOut);
109     }
110
111     if (_pDouble2->isScalar())
112     {
113         // managed in %s_l_s, call overload
114         return 0;
115     }
116
117     if (_pDouble1->getDims() > 2 || _pDouble2->getDims() > 2 || _pDouble1->getRows() != _pDouble2->getRows())
118     {
119         //not managed
120         return 0;
121     }
122
123     *_pDoubleOut = new Double(_pDouble1->getCols(), _pDouble2->getCols(), _pDouble1->isComplex() || _pDouble2->isComplex());
124     if ((*_pDoubleOut)->isComplex())
125     {
126         double dblRcond = 0;
127         iErr = iLeftDivisionOfComplexMatrix(
128                    _pDouble1->getReal(), _pDouble1->getImg(), _pDouble1->getRows(), _pDouble1->getCols(),
129                    _pDouble2->getReal(), _pDouble2->getImg(), _pDouble2->getRows(), _pDouble2->getCols(),
130                    (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getImg(), (*_pDoubleOut)->getRows(), (*_pDoubleOut)->getCols(), &dblRcond);
131     }
132     else
133     {
134         double dblRcond = 0;
135         iErr = iLeftDivisionOfRealMatrix(
136                    _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getCols(),
137                    _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getCols(),
138                    (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getRows(), (*_pDoubleOut)->getCols(), &dblRcond);
139     }
140
141     return iErr;
142 }
143