Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / ast / src / cpp / operations / types_kronecker.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011 - DIGITEO - Cedric Delamarre
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include "types_kronecker.hxx"
17
18 extern "C" {
19 #include "matrix_kronecker.h"
20 }
21
22 // DOUBLE .*. DOUBLE
23 types::InternalType *GenericKrontimes(types::InternalType *_pLeftOperand, types::InternalType *_pRightOperand)
24 {
25     types::Double *pResult = NULL;
26     types::GenericType::ScilabType TypeL = _pLeftOperand->getType();
27     types::GenericType::ScilabType TypeR = _pRightOperand->getType();
28
29     if (TypeL == types::GenericType::ScilabDouble && TypeR == types::GenericType::ScilabDouble)
30     {
31         types::Double *pL = _pLeftOperand->getAs<types::Double>();
32         types::Double *pR = _pRightOperand->getAs<types::Double>();
33
34         if (pL->getDims() > 2 || pR->getDims() > 2)
35         {
36             return NULL;
37         }
38
39         int iResult = KroneckerMultiplyDoubleByDouble(pL, pR, &pResult);
40         if (iResult)
41         {
42             throw ast::InternalError(_("Inconsistent row/column dimensions.\n"));
43         }
44
45         return pResult;
46     }
47
48     // Default case : Return NULL will Call Overloading.
49     return NULL;
50 }
51
52 int KroneckerMultiplyDoubleByDouble(types::Double* _pDouble1, types::Double* _pDouble2, types::Double** _pDoubleOut)
53 {
54     bool bComplex1 = _pDouble1->isComplex();
55     bool bComplex2 = _pDouble2->isComplex();
56
57     int iRowResult = _pDouble1->getRows() * _pDouble2->getRows();
58     int iColResult = _pDouble1->getCols() * _pDouble2->getCols();
59
60     //Output variables
61     bool bComplexOut = bComplex1 || bComplex2;
62     (*_pDoubleOut)   = new types::Double(iRowResult, iColResult, bComplexOut);
63
64     if (bComplex1 && bComplex2) // Complex .*. Complex
65     {
66         vKronC( _pDouble1->getReal(), _pDouble1->getImg(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
67                 _pDouble2->getReal(), _pDouble2->getImg(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
68                 (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getImg(), iRowResult);
69     }
70     else if (bComplex1) // Complex .*. Real
71     {
72         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
73                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
74                 (*_pDoubleOut)->getReal(), iRowResult);
75
76         vKronR( _pDouble1->getImg(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
77                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
78                 (*_pDoubleOut)->getImg(), iRowResult);
79     }
80     else if (bComplex2) // Real .*. Complex
81     {
82         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
83                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
84                 (*_pDoubleOut)->getReal(), iRowResult);
85
86         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
87                 _pDouble2->getImg(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
88                 (*_pDoubleOut)->getImg(), iRowResult);
89     }
90     else // Real .*. Real
91     {
92         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
93                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
94                 (*_pDoubleOut)->getReal(), iRowResult);
95     }
96
97     return 0; //No Error;
98 }
99
100 // DOUBLE ./. DOUBLE
101 types::InternalType *GenericKronrdivide(types::InternalType *_pLeftOperand, types::InternalType *_pRightOperand)
102 {
103     types::Double *pResult = NULL;
104     types::GenericType::ScilabType TypeL = _pLeftOperand->getType();
105     types::GenericType::ScilabType TypeR = _pRightOperand->getType();
106
107     if (TypeL == types::GenericType::ScilabDouble && TypeR == types::GenericType::ScilabDouble)
108     {
109         types::Double *pL = _pLeftOperand->getAs<types::Double>();
110         types::Double *pR = _pRightOperand->getAs<types::Double>();
111
112         int iErr = KroneckerRDivideDoubleByDouble(pL, pR, &pResult);
113         if (iErr == 1)
114         {
115             throw ast::InternalError(_("Division by zero...\n"));
116         }
117         else if (iErr == 2)
118         {
119             throw ast::InternalError(_("Bad value in the left or right operand.\n"));
120         }
121         else if (iErr == 3)
122         {
123             throw ast::InternalError(_("Bad size for left or right operand.\n"));
124         }
125
126         return pResult;
127     }
128
129     // Default case : Return NULL will Call Overloading.
130     return NULL;
131 }
132
133 int KroneckerRDivideDoubleByDouble(types::Double* _pDouble1, types::Double* _pDouble2, types::Double** _pDoubleOut)
134 {
135     int iErr = 0;
136     types::Double* clone = _pDouble2->clone()->getAs<types::Double>();
137
138     if (_pDouble2->isComplex())
139     {
140         iErr = conv_img_input(clone->getReal(), clone->getImg(), clone->getSize());
141     }
142     else
143     {
144         iErr = conv_real_input(clone->get(), clone->getSize());
145     }
146
147     if (iErr)
148     {
149         delete clone;
150         return iErr;
151     }
152
153     iErr = KroneckerMultiplyDoubleByDouble(_pDouble1, clone, _pDoubleOut);
154     delete clone;
155
156     return iErr;
157 }
158
159 // DOUBLE .\. DOUBLE
160 types::InternalType *GenericKronldivide(types::InternalType *_pLeftOperand, types::InternalType *_pRightOperand)
161 {
162     types::Double *pResult = NULL;
163     types::GenericType::ScilabType TypeL = _pLeftOperand->getType();
164     types::GenericType::ScilabType TypeR = _pRightOperand->getType();
165
166     if (TypeL == types::GenericType::ScilabDouble && TypeR == types::GenericType::ScilabDouble)
167     {
168         types::Double *pL = _pLeftOperand->getAs<types::Double>();
169         types::Double *pR = _pRightOperand->getAs<types::Double>();
170
171         int iErr = KroneckerLDivideDoubleByDouble(pL, pR, &pResult);
172         if (iErr == 1)
173         {
174             throw ast::InternalError(_("Division by zero...\n"));
175         }
176         else if (iErr == 2)
177         {
178             throw ast::InternalError(_("Bad value in the left operand.\n"));
179         }
180
181         return pResult;
182     }
183
184     // Default case : Return NULL will Call Overloading.
185     return NULL;
186 }
187
188 int KroneckerLDivideDoubleByDouble(types::Double* _pDouble1, types::Double* _pDouble2, types::Double** _pDoubleOut)
189 {
190     int iErr = 0;
191     types::Double* clone = _pDouble1->clone()->getAs<types::Double>();
192     if (_pDouble1->isComplex())
193     {
194         iErr = conv_img_input(clone->getReal(), clone->getImg(), clone->getSize());
195     }
196     else
197     {
198         iErr = conv_real_input(clone->get(), clone->getSize());
199     }
200
201     if (iErr)
202     {
203         delete clone;
204         return iErr;
205     }
206
207     iErr = KroneckerMultiplyDoubleByDouble(clone, _pDouble2, _pDoubleOut);
208     delete clone;
209
210     return iErr;
211 }
212