* Bug 16474 fixed: imult(%z) crashed Scilab (6.0 regression)
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_imult.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - 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
17 #include <complex>
18
19 #include "elem_func_gw.hxx"
20 #include "function.hxx"
21 #include "double.hxx"
22 #include "overload.hxx"
23 #include "sparse.hxx"
24 #include "polynom.hxx"
25
26 extern "C"
27 {
28 #include "Scierror.h"
29 #include "localization.h"
30 #include "elem_common.h"
31 }
32
33 /*
34 clear a;nb = 2500;a = rand(nb, nb);tic();imult(a);toc
35 clear a;nb = 2500;a = rand(nb, nb); a = a + a *%i;tic();imult(a);toc
36 */
37 /*--------------------------------------------------------------------------*/
38 types::Function::ReturnValue sci_imult(types::typed_list &in, int _iRetCount, types::typed_list &out)
39 {
40     if (in.size() != 1)
41     {
42         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "imult", 1);
43         return types::Function::Error;
44     }
45
46     if (_iRetCount > 1)
47     {
48         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "imult", 1);
49         return types::Function::Error;
50     }
51
52     if (in[0]->isDouble())
53     {
54         types::Double* pDblIn = in[0]->getAs<types::Double>();
55         types::Double* pDblOut = new types::Double(pDblIn->getDims(), pDblIn->getDimsArray(), true);
56
57         int iSize = pDblIn->getSize();
58         int iOne = 1;
59
60         if (pDblIn->isComplex())
61         {
62             double* pOutR = pDblOut->get();
63             double* pInI = pDblIn->getImg();
64             for (int i = 0; i < iSize; i++)
65             {
66                 pOutR[i] = pInI[i] * -1;
67             }
68         }
69         else
70         {
71             memset(pDblOut->getReal(), 0x00, iSize * sizeof(double));
72         }
73
74         C2F(dcopy)(&iSize, pDblIn->getReal(), &iOne, pDblOut->getImg(), &iOne);
75
76         out.push_back(pDblOut);
77     }
78     else if (in[0]->isSparse())
79     {
80         types::Sparse* pSparseIn = in[0]->getAs<types::Sparse>();
81         types::Sparse* pSparseOut = new types::Sparse(pSparseIn->getRows(), pSparseIn->getCols(), true);
82
83         int const nonZeros = static_cast<int>(pSparseIn->nonZeros());
84         int* pRows = new int[nonZeros * 2];
85         pSparseIn->outputRowCol(pRows);
86         int* pCols = pRows + nonZeros;
87
88         if (pSparseIn->isComplex())
89         {
90             for (int i = 0 ; i < nonZeros ; i++)
91             {
92                 std::complex<double> cplxIn = pSparseIn->getImg(pRows[i] - 1, pCols[i] - 1);
93                 std::complex<double> cplxOut(cplxIn.imag() * -1, cplxIn.real());
94                 pSparseOut->set(pRows[i] - 1, pCols[i] - 1, cplxOut);
95             }
96         }
97         else
98         {
99             for (int i = 0 ; i < nonZeros ; i++)
100             {
101                 double dReal = pSparseIn->get(pRows[i] - 1, pCols[i] - 1);
102                 std::complex<double> cplxOut(0, dReal);
103                 pSparseOut->set(pRows[i] - 1, pCols[i] - 1, cplxOut);
104             }
105         }
106
107         delete[] pRows;
108
109         out.push_back(pSparseOut);
110     }
111     else if (in[0]->isPoly())
112     {
113         types::Polynom* pPolyIn = in[0]->getAs<types::Polynom>();
114         types::Polynom* pPolyOut = pPolyIn->clone();
115         pPolyOut->setComplex(true);
116
117         for (int i = 0; i < pPolyOut->getSize(); i++)
118         {
119             types::SinglePoly* pSP = pPolyOut->get(i);
120             double* dataReal = pSP->get();
121             double* dataImg = pSP->getImg();
122             int rank = pSP->getRank();
123             if (pPolyIn->isComplex())
124             {
125                 for (int j = 0; j < rank + 1; j++)
126                 {
127                     double dblBuf = dataReal[j];
128                     dataReal[j] = -dataImg[j];
129                     dataImg[j] = dblBuf;
130                 }
131             }
132             else
133             {
134                 for (int j = 0; j < rank + 1; j++)
135                 {
136                     dataImg[j] = dataReal[j];
137                     dataReal[j] = 0;
138                 }
139             }
140         }
141
142         out.push_back(pPolyOut);
143     }
144     else
145     {
146         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_imult";
147         return Overload::call(wstFuncName, in, _iRetCount, out);
148     }
149
150     return types::Function::OK;
151 }
152 /*--------------------------------------------------------------------------*/