reforge "|" operator
[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  *  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_kronecker.hxx"
14
15 extern "C" {
16 #include "matrix_kronecker.h"
17 }
18
19 // DOUBLE .*. DOUBLE
20 types::InternalType *GenericKrontimes(types::InternalType *_pLeftOperand, types::InternalType *_pRightOperand)
21 {
22     types::Double *pResult = NULL;
23     types::GenericType::ScilabType TypeL = _pLeftOperand->getType();
24     types::GenericType::ScilabType TypeR = _pRightOperand->getType();
25
26     if (TypeL == types::GenericType::ScilabDouble && TypeR == types::GenericType::ScilabDouble)
27     {
28         types::Double *pL = _pLeftOperand->getAs<types::Double>();
29         types::Double *pR = _pRightOperand->getAs<types::Double>();
30
31         if (pL->getDims() > 2 || pR->getDims() > 2)
32         {
33             return NULL;
34         }
35
36         int iResult = KroneckerMultiplyDoubleByDouble(pL, pR, &pResult);
37         if (iResult)
38         {
39             throw ast::ScilabError(_W("Inconsistent row/column dimensions.\n"));
40         }
41
42         return pResult;
43     }
44
45     // Default case : Return NULL will Call Overloading.
46     return NULL;
47 }
48
49 int KroneckerMultiplyDoubleByDouble(types::Double* _pDouble1, types::Double* _pDouble2, types::Double** _pDoubleOut)
50 {
51     bool bComplex1 = _pDouble1->isComplex();
52     bool bComplex2 = _pDouble2->isComplex();
53
54     int iRowResult = _pDouble1->getRows() * _pDouble2->getRows();
55     int iColResult = _pDouble1->getCols() * _pDouble2->getCols();
56
57     //Output variables
58     bool bComplexOut = bComplex1 || bComplex2;
59     (*_pDoubleOut)   = new types::Double(iRowResult, iColResult, bComplexOut);
60
61     if (bComplex1 && bComplex2) // Complex .*. Complex
62     {
63         vKronC( _pDouble1->getReal(), _pDouble1->getImg(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
64                 _pDouble2->getReal(), _pDouble2->getImg(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
65                 (*_pDoubleOut)->getReal(), (*_pDoubleOut)->getImg(), iRowResult);
66     }
67     else if (bComplex1) // Complex .*. Real
68     {
69         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
70                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
71                 (*_pDoubleOut)->getReal(), iRowResult);
72
73         vKronR( _pDouble1->getImg(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
74                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
75                 (*_pDoubleOut)->getImg(), iRowResult);
76     }
77     else if (bComplex2) // Real .*. Complex
78     {
79         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
80                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
81                 (*_pDoubleOut)->getReal(), iRowResult);
82
83         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
84                 _pDouble2->getImg(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
85                 (*_pDoubleOut)->getImg(), iRowResult);
86     }
87     else // Real .*. Real
88     {
89         vKronR( _pDouble1->getReal(), _pDouble1->getRows(), _pDouble1->getRows(), _pDouble1->getCols(),
90                 _pDouble2->getReal(), _pDouble2->getRows(), _pDouble2->getRows(), _pDouble2->getCols(),
91                 (*_pDoubleOut)->getReal(), iRowResult);
92     }
93
94     return 0; //No Error;
95 }
96
97 // DOUBLE ./. DOUBLE
98 types::InternalType *GenericKronrdivide(types::InternalType *_pLeftOperand, types::InternalType *_pRightOperand)
99 {
100     types::Double *pResult = NULL;
101     types::GenericType::ScilabType TypeL = _pLeftOperand->getType();
102     types::GenericType::ScilabType TypeR = _pRightOperand->getType();
103
104     if (TypeL == types::GenericType::ScilabDouble && TypeR == types::GenericType::ScilabDouble)
105     {
106         types::Double *pL = _pLeftOperand->getAs<types::Double>();
107         types::Double *pR = _pRightOperand->getAs<types::Double>();
108
109         int iErr = KroneckerRDivideDoubleByDouble(pL, pR, &pResult);
110         if (iErr == 1)
111         {
112             throw ast::ScilabError(_W("Division by zero...\n"));
113         }
114         else if (iErr == 2)
115         {
116             throw ast::ScilabError(_W("Bad value in the left or right operand.\n"));
117         }
118         else if (iErr == 3)
119         {
120             throw ast::ScilabError(_W("Bad size for left or right operand.\n"));
121         }
122
123         return pResult;
124     }
125
126     // Default case : Return NULL will Call Overloading.
127     return NULL;
128 }
129
130 int KroneckerRDivideDoubleByDouble(types::Double* _pDouble1, types::Double* _pDouble2, types::Double** _pDoubleOut)
131 {
132     int iErr = 0;
133     types::Double* clone = _pDouble2->clone()->getAs<types::Double>();
134
135     if (_pDouble2->isComplex())
136     {
137         iErr = conv_img_input(clone->getReal(), clone->getImg(), clone->getSize());
138     }
139     else
140     {
141         iErr = conv_real_input(clone->get(), clone->getSize());
142     }
143
144     if (iErr)
145     {
146         delete clone;
147         return iErr;
148     }
149
150     iErr = KroneckerMultiplyDoubleByDouble(_pDouble1, clone, _pDoubleOut);
151     delete clone;
152
153     return iErr;
154 }
155
156 // DOUBLE .\. DOUBLE
157 types::InternalType *GenericKronldivide(types::InternalType *_pLeftOperand, types::InternalType *_pRightOperand)
158 {
159     types::Double *pResult = NULL;
160     types::GenericType::ScilabType TypeL = _pLeftOperand->getType();
161     types::GenericType::ScilabType TypeR = _pRightOperand->getType();
162
163     if (TypeL == types::GenericType::ScilabDouble && TypeR == types::GenericType::ScilabDouble)
164     {
165         types::Double *pL = _pLeftOperand->getAs<types::Double>();
166         types::Double *pR = _pRightOperand->getAs<types::Double>();
167
168         int iErr = KroneckerLDivideDoubleByDouble(pL, pR, &pResult);
169         if (iErr == 1)
170         {
171             throw ast::ScilabError(_W("Division by zero...\n"));
172         }
173         else if (iErr == 2)
174         {
175             throw ast::ScilabError(_W("Bad value in the left operand.\n"));
176         }
177
178         return pResult;
179     }
180
181     // Default case : Return NULL will Call Overloading.
182     return NULL;
183 }
184
185 int KroneckerLDivideDoubleByDouble(types::Double* _pDouble1, types::Double* _pDouble2, types::Double** _pDoubleOut)
186 {
187     int iErr = 0;
188     types::Double* clone = _pDouble1->clone()->getAs<types::Double>();
189     if (_pDouble1->isComplex())
190     {
191         iErr = conv_img_input(clone->getReal(), clone->getImg(), clone->getSize());
192     }
193     else
194     {
195         iErr = conv_real_input(clone->get(), clone->getSize());
196     }
197
198     if (iErr)
199     {
200         delete clone;
201         return iErr;
202     }
203
204     iErr = KroneckerMultiplyDoubleByDouble(clone, _pDouble2, _pDoubleOut);
205     delete clone;
206
207     return iErr;
208 }
209