reforge "|" operator
[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     //manage errors
59     if (iResult)
60     {
61         switch (iResult)
62         {
63             case 1 :
64                 throw ast::ScilabError(_W("Inconsistent row/column dimensions.\n"));
65             case 2 :
66                 throw ast::ScilabError(_W("With NaN or Inf a left division by scalar expected.\n"));
67             case 3 :
68                 throw ast::ScilabError(_W("Left division by zero...\n"));
69             case 4 :
70                 sciprint(_("Warning : Left division by zero...\n"));
71                 break;
72             default :
73                 sciprint(_("Operator \\ : Error %d not yet managed.\n"), iResult);
74         }
75     }
76
77     /*
78     ** Default case : Return NULL will Call Overloading.
79     */
80     return pResult;
81 }
82
83 InternalType *GenericDotLDivide(InternalType *_pLeftOperand, InternalType *_pRightOperand)
84 {
85     InternalType *pResult       = NULL;
86     GenericType::ScilabType TypeL = _pLeftOperand->getType();
87     GenericType::ScilabType TypeR = _pRightOperand->getType();
88
89     int iResult = 0;
90
91     if (_pLeftOperand->isDouble() && _pLeftOperand->getAs<Double>()->isEmpty())
92     {
93         return Double::Empty();
94     }
95
96     if (_pRightOperand->isDouble() && _pRightOperand->getAs<Double>()->isEmpty())
97     {
98         return Double::Empty();
99     }
100
101     /*
102     ** DOUBLE .\ DOUBLE
103     */
104     if (TypeL == GenericType::ScilabDouble && TypeR == GenericType::ScilabDouble)
105     {
106         Double *pL  = _pLeftOperand->getAs<Double>();
107         Double *pR  = _pRightOperand->getAs<Double>();
108
109         // left .\ rigth => rigth ./ left
110         iResult = DotRDivideDoubleByDouble(pR, pL, (Double**)&pResult);
111     }
112
113     //manage errors
114     if (iResult)
115     {
116         switch (iResult)
117         {
118             case 1 :
119                 throw ast::ScilabError(_W("Inconsistent row/column dimensions.\n"));
120             case 2 :
121                 throw ast::ScilabError(_W("With NaN or Inf a left division by scalar expected.\n"));
122             case 3 :
123                 throw ast::ScilabError(_W("Left division by zero...\n"));
124             case 4 :
125                 sciprint(_("Warning : Left division by zero...\n"));
126                 break;
127             default :
128                 sciprint(_("Operator .\\ : Error %d not yet managed.\n"), iResult);
129         }
130     }
131
132     /*
133     ** Default case : Return NULL will Call Overloading.
134     */
135     return pResult;
136 }
137
138 int LDivideDoubleByDouble(Double *_pDouble1, Double *_pDouble2, Double **_pDoubleOut)
139 {
140     int iErr = 0;
141
142     //check finite values of _pDouble1 and _pDouble2
143     if (isDoubleFinite(_pDouble1) == false || isDoubleFinite(_pDouble2) == false)
144     {
145         if (_pDouble2->isScalar() == false)
146         {
147             return 2;
148         }
149     }
150
151     if (_pDouble1->isScalar())
152     {
153         //Y \ x => x / Y
154         return RDivideDoubleByDouble(_pDouble2, _pDouble1, _pDoubleOut);
155     }
156
157     if (_pDouble2->isScalar())
158     {
159         // managed in %s_l_s, call overload
160         return 0;
161     }
162
163     if (_pDouble1->getDims() > 2 || _pDouble2->getDims() > 2 || _pDouble1->getRows() != _pDouble2->getRows())
164     {
165         //not managed
166         return 1;
167     }
168
169     *_pDoubleOut = new Double(_pDouble1->getCols(), _pDouble2->getCols(), _pDouble1->isComplex() || _pDouble2->isComplex());
170     if ((*_pDoubleOut)->isComplex())
171     {
172         double dblRcond = 0;
173         iErr = iLeftDivisionOfComplexMatrix(
174                    _pDouble1->getReal(), _pDouble1->getImg(), _pDouble1->getRows(), _pDouble1->getCols(),
175                    _pDouble2->getReal(), _pDouble2->getImg(), _pDouble2->getRows(), _pDouble2->getCols(),
176                    (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getImg(), (*_pDoubleOut)->getRows(), (*_pDoubleOut)->getCols(), &dblRcond);
177     }
178     else
179     {
180         double dblRcond = 0;
181         iErr = iLeftDivisionOfRealMatrix(
182                    _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getCols(),
183                    _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getCols(),
184                    (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getRows(), (*_pDoubleOut)->getCols(), &dblRcond);
185     }
186
187     return iErr;
188 }
189