reforge "&" operator
[scilab.git] / scilab / modules / ast / src / cpp / operations / types_or.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2012 - Scilab Enterprises - Antoine ELIAS
4  *  Copyright (C) 2012 - Scilab Enterprises - Cedric Delamarre
5  *
6  *  This file must be used under the terms of the CeCILL.
7  *  This source file is licensed as described in the file COPYING, which
8  *  you should have received as part of this distribution.  The terms
9  *  are also available at
10  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 extern "C"
15 {
16 #include "os_swprintf.h"
17 }
18
19 #include "types_or.hxx"
20 #include "int.hxx"
21 #include "bool.hxx"
22 #include "sparse.hxx"
23
24 using namespace types;
25
26 // ||
27 InternalType* GenericShortcutOr(InternalType* _pL)
28 {
29     InternalType* pResult = NULL;
30
31     if (_pL->isBool())
32     {
33         BoolOrBool(_pL->getAs<Bool>(), (Bool**)&pResult);
34     }
35
36     if (_pL->isInt())
37     {
38         IntOrInt(_pL, (Bool**)&pResult);
39     }
40
41     if (_pL->isSparseBool())
42     {
43         SparseBoolOrSparseBool(_pL, (Bool**)&pResult);
44     }
45
46     return pResult;
47 }
48
49 // |
50 InternalType* GenericLogicalOr(InternalType* _pL, InternalType* _pR)
51 {
52     InternalType* pResult = NULL;
53
54     if (_pL->isBool() && _pR->isBool())
55     {
56         Bool *pL = (Bool*)_pL;
57         Bool *pR = (Bool*)_pR;
58
59         int iResult = BoolLogicalOrBool(pL, pR, (Bool**)&pResult);
60         if (iResult != 0)
61         {
62             wchar_t pMsg[bsiz];
63             os_swprintf(pMsg, bsiz, _W("Error: operator %ls: Matrix dimensions must agree (op1 is %ls, op2 is %ls).\n").c_str(), L"|", pL->DimToString().c_str(), pR->DimToString().c_str());
64             throw ast::ScilabError(pMsg);
65         }
66         return pResult;
67     }
68
69     if (_pL->isInt() && _pR->isInt())
70     {
71         int iResult = IntLogicalOrInt(_pL, _pR, &pResult);
72         if (iResult != 0)
73         {
74             GenericType* pL = _pL->getAs<GenericType>();
75             GenericType* pR = _pR->getAs<GenericType>();
76             wchar_t pMsg[bsiz];
77             os_swprintf(pMsg, bsiz, _W("Error: operator %ls: Matrix dimensions must agree (op1 is %ls, op2 is %ls).\n").c_str(), L"|", pL->DimToString().c_str(), pR->DimToString().c_str());
78             throw ast::ScilabError(pMsg);
79         }
80         return pResult;
81     }
82
83     if (_pL->isSparseBool() && _pR->isSparseBool())
84     {
85         int iResult = SparseBoolLogicalOrSparseBool(_pL, _pR, &pResult);
86         if (iResult != 0)
87         {
88             GenericType* pL = _pL->getAs<GenericType>();
89             GenericType* pR = _pR->getAs<GenericType>();
90             wchar_t pMsg[bsiz];
91             os_swprintf(pMsg, bsiz, _W("Error: operator %ls: Matrix dimensions must agree (op1 is %ls, op2 is %ls).\n").c_str(), L"|", pL->DimToString().c_str(), pR->DimToString().c_str());
92             throw ast::ScilabError(pMsg);
93         }
94         return pResult;
95     }
96
97     return NULL;
98 }
99
100 int BoolOrBool(Bool* _pL, Bool** _pOut)
101 {
102     for (int i = 0 ; i < _pL->getSize() ; i++)
103     {
104         if (_pL->get(i) == 0)
105         {
106             //call non shorcut opearion
107             *_pOut = NULL;
108             return 0;
109         }
110     }
111
112     *_pOut = new Bool(1); //true && something -> true
113     return 0;
114 }
115
116 template <class K>
117 static int IntOrInt(K* _pL, Bool** _pOut)
118 {
119     for (int i = 0 ; i < _pL->getSize() ; i++)
120     {
121         if (_pL->get(i) == 0)
122         {
123             //call non shorcut opearion
124             *_pOut = NULL;
125             return 0;
126         }
127     }
128
129     *_pOut = new Bool(1); //true && something -> true
130     return 0;
131 }
132
133 int IntOrInt(InternalType* _pL, Bool** _pOut)
134 {
135     switch (_pL->getType())
136     {
137         case InternalType::ScilabInt8 :
138         {
139             return IntOrInt(_pL->getAs<Int8>(), _pOut);
140         }
141         case InternalType::ScilabUInt8 :
142         {
143             return IntOrInt(_pL->getAs<UInt8>(), _pOut);
144         }
145         case InternalType::ScilabInt16 :
146         {
147             return IntOrInt(_pL->getAs<Int16>(), _pOut);
148         }
149         case InternalType::ScilabUInt16 :
150         {
151             return IntOrInt(_pL->getAs<UInt16>(), _pOut);
152         }
153         case InternalType::ScilabInt32 :
154         {
155             return IntOrInt(_pL->getAs<Int32>(), _pOut);
156         }
157         case InternalType::ScilabUInt32 :
158         {
159             return IntOrInt(_pL->getAs<UInt32>(), _pOut);
160         }
161         case InternalType::ScilabInt64 :
162         {
163             return IntOrInt(_pL->getAs<Int64>(), _pOut);
164         }
165         case InternalType::ScilabUInt64 :
166         {
167             return IntOrInt(_pL->getAs<UInt64>(), _pOut);
168         }
169         default:
170         {
171             return 3;
172         }
173     }
174 }
175
176 template <class K>
177 static int IntLogicalOrInt(K* _pL, K* _pR, InternalType** _pOut)
178 {
179     // left scalar bitwise or right matrix
180     if (_pL->isScalar())
181     {
182         K *pI = new K(_pR->getDims(), _pR->getDimsArray());
183         const typename K::type x = _pL->get(0);
184
185         for (int i = 0 ; i < pI->getSize() ; i++)
186         {
187             pI->set(i, x | _pR->get(i));
188         }
189
190         *_pOut = pI;
191         return 0;
192     }
193
194     // right scalar bitwise or left matrix
195     if (_pR->isScalar())
196     {
197         K *pI = new K(_pL->getDims(), _pL->getDimsArray());
198         const typename K::type x = _pL->get(0);
199
200         for (int i = 0 ; i < pI->getSize() ; i++)
201         {
202             pI->set(i, x | _pL->get(i));
203         }
204
205         *_pOut = pI;
206         return 0;
207     }
208
209     // check dims
210     if (_pL->getDims() != _pR->getDims())
211     {
212         return 1;
213     }
214
215     int* piDimsL = _pL->getDimsArray();
216     int* piDimsR = _pR->getDimsArray();
217
218     for (int i = 0 ; i < _pL->getDims() ; i++)
219     {
220         if (piDimsL[i] != piDimsR[i])
221         {
222             return 1;
223         }
224     }
225
226     // left matrix bitwise or right matrix
227     K* pI = new K(_pR->getDims(), _pR->getDimsArray());
228     for (int i = 0 ; i < _pL->getSize() ; i++)
229     {
230         pI->set(i, _pL->get(i) | _pR->get(i));
231     }
232
233     *_pOut = pI;
234     return 0;
235 }
236
237 int IntLogicalOrInt(InternalType* _pL, InternalType*  _pR, InternalType** _pOut)
238 {
239     switch (_pL->getType())
240     {
241         case InternalType::ScilabInt8 :
242         {
243             Int8* pI1 = _pL->getAs<Int8>();
244             Int8* pI2 = _pR->getAs<Int8>();
245             return IntLogicalOrInt(pI1, pI2, _pOut);
246         }
247         case InternalType::ScilabUInt8 :
248         {
249             UInt8* pI1 = _pL->getAs<UInt8>();
250             UInt8* pI2 = _pR->getAs<UInt8>();
251             return IntLogicalOrInt(pI1, pI2, _pOut);
252         }
253         case InternalType::ScilabInt16 :
254         {
255             Int16* pI1 = _pL->getAs<Int16>();
256             Int16* pI2 = _pR->getAs<Int16>();
257             return IntLogicalOrInt(pI1, pI2, _pOut);
258         }
259         case InternalType::ScilabUInt16 :
260         {
261             UInt16* pI1 = _pL->getAs<UInt16>();
262             UInt16* pI2 = _pR->getAs<UInt16>();
263             return IntLogicalOrInt(pI1, pI2, _pOut);
264         }
265         case InternalType::ScilabInt32 :
266         {
267             Int32* pI1 = _pL->getAs<Int32>();
268             Int32* pI2 = _pR->getAs<Int32>();
269             return IntLogicalOrInt(pI1, pI2, _pOut);
270         }
271         case InternalType::ScilabUInt32 :
272         {
273             UInt32* pI1 = _pL->getAs<UInt32>();
274             UInt32* pI2 = _pR->getAs<UInt32>();
275             return IntLogicalOrInt(pI1, pI2, _pOut);
276         }
277         case InternalType::ScilabInt64 :
278         {
279             Int64* pI1 = _pL->getAs<Int64>();
280             Int64* pI2 = _pR->getAs<Int64>();
281             return IntLogicalOrInt(pI1, pI2, _pOut);
282         }
283         case InternalType::ScilabUInt64 :
284         {
285             UInt64* pI1 = _pL->getAs<UInt64>();
286             UInt64* pI2 = _pR->getAs<UInt64>();
287             return IntLogicalOrInt(pI1, pI2, _pOut);
288         }
289         default:
290         {
291             return 3;
292         }
293     }
294 }
295
296 int BoolLogicalOrBool(Bool* _pL, Bool*  _pR, Bool** _pOut)
297 {
298     int* piR = _pR->get();
299     int* piL = _pL->get();
300     int* piB = NULL;
301
302     // M | scalar
303     if (_pR->getSize() == 1)
304     {
305         *_pOut = new Bool(_pL->getDims(), _pL->getDimsArray());
306         piB = (*_pOut)->get();
307         for (int i = 0 ; i < _pL->getSize(); i++)
308         {
309             piB[i] = (piR[0] == 1) || (piL[i] == 1);
310         }
311
312         return 0;
313     }
314
315     if (_pL->getSize() == 1)
316     {
317         // scalar | M
318         *_pOut = new Bool(_pR->getDims(), _pR->getDimsArray());
319         piB = (*_pOut)->get();
320         for (int i = 0 ; i < _pR->getSize(); i++)
321         {
322             piB[i] = (piR[i] == 1) || (piL[0] == 1);
323         }
324
325         return 0;
326     }
327
328     if (_pL->getDims() != _pR->getDims())
329     {
330         return 1;
331     }
332
333     int* piDimsL = _pL->getDimsArray();
334     int* piDimsR = _pR->getDimsArray();
335
336     for (int i = 0; i < _pL->getDims(); i++)
337     {
338         if (piDimsL[i] != piDimsR[i])
339         {
340             return 1;
341         }
342     }
343
344     // M | N (generic case)
345     *_pOut = new Bool(_pR->getDims(), piDimsR);
346     piB = (*_pOut)->get();
347     for (int i = 0 ; i < _pR->getSize(); i++)
348     {
349         piB[i] = (piR[i] == 1) || (piL[i] == 1);
350     }
351
352     return 0;
353 }
354
355 int SparseBoolOrSparseBool(InternalType* _pL, Bool** _pOut)
356 {
357     SparseBool* pL = _pL->getAs<SparseBool>();
358     if (pL->nbTrue() == pL->getSize())
359     {
360         *_pOut = new Bool(1);
361         return 0;
362     }
363
364     *_pOut = NULL;
365     return 0;
366 }
367
368 int SparseBoolLogicalOrSparseBool(InternalType* _pL, InternalType*  _pR, InternalType** _pOut)
369 {
370     SparseBool *pL = (SparseBool*)_pL;
371     SparseBool *pR = (SparseBool*)_pR;
372
373     if (pL->isScalar())
374     {
375         if (pL->get(0, 0))
376         {
377             *_pOut = _pR->clone();
378         }
379         else
380         {
381             *_pOut = new SparseBool(pR->getRows(), pR->getCols());
382         }
383
384         return 0;
385     }
386
387     if (pR->isScalar())
388     {
389         if (pR->get(0, 0))
390         {
391             *_pOut = _pL->clone();
392         }
393         else
394         {
395             *_pOut = new SparseBool(pL->getRows(), pL->getCols());
396         }
397
398         return 0;
399     }
400
401     if (pL->getRows() == pR->getRows() && pL->getCols() == pR->getCols())
402     {
403         *_pOut = pL->newLogicalOr(*pR);
404         return 0;
405     }
406     return 1;
407 }