bug #14144 and #12928 : %nan, %inf in intXX() functions and crash on int64(2^63)
[scilab.git] / scilab / modules / integer / sci_gateway / cpp / sci_int.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Antoine ELIAS
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 #include <limits>
13
14 #include "int.hxx"
15 #include "double.hxx"
16 #include "bool.hxx"
17 #include "function.hxx"
18 #include "integer_gw.hxx"
19 extern "C"
20 {
21 #include "Scierror.h"
22 }
23
24 template <class T, class U>
25 void convert_int(U* _pIn, int _iSize, T* _pOut)
26 {
27     static T minval = std::numeric_limits<T>::min();
28     static T maxval = std::numeric_limits<T>::max();
29
30     for (int i = 0 ; i < _iSize ; i++)
31     {
32         if (std::isnan((double)_pIn[i]))
33         {
34             _pOut[i] = 0;
35         }
36         else if (std::isinf((double)_pIn[i]))
37         {
38             if ((double)_pIn[i] > 0)
39             {
40                 _pOut[i] = maxval;
41             }
42             else
43             {
44                 _pOut[i] = minval;
45             }
46         }
47         else
48         {
49             _pOut[i] = (T)_pIn[i];
50         }
51     }
52 }
53
54 template <class T>
55 void convertInt(types::InternalType* _pIn, T* _pOut)
56 {
57     switch (_pIn->getType())
58     {
59         case types::InternalType::ScilabBool :
60         {
61             types::Bool* pBool = _pIn->getAs<types::Bool>();
62             convert_int(pBool->get(), pBool->getSize(), _pOut->get());
63             break;
64         }
65         case types::InternalType::ScilabDouble :
66         {
67             types::Double* pD = _pIn->getAs<types::Double>();
68             convert_int(pD->get(), pD->getSize(), _pOut->get());
69             break;
70         }
71         case types::InternalType::ScilabInt8 :
72         {
73             types::Int8* pD = _pIn->getAs<types::Int8>();
74             convert_int(pD->get(), pD->getSize(), _pOut->get());
75             break;
76         }
77         case types::InternalType::ScilabUInt8 :
78         {
79             types::UInt8* pD = _pIn->getAs<types::UInt8>();
80             convert_int(pD->get(), pD->getSize(), _pOut->get());
81             break;
82         }
83         case types::InternalType::ScilabInt16 :
84         {
85             types::Int16* pD = _pIn->getAs<types::Int16>();
86             convert_int(pD->get(), pD->getSize(), _pOut->get());
87             break;
88         }
89         case types::InternalType::ScilabUInt16 :
90         {
91             types::UInt16* pD = _pIn->getAs<types::UInt16>();
92             convert_int(pD->get(), pD->getSize(), _pOut->get());
93             break;
94         }
95         case types::InternalType::ScilabInt32 :
96         {
97             types::Int32* pD = _pIn->getAs<types::Int32>();
98             convert_int(pD->get(), pD->getSize(), _pOut->get());
99             break;
100         }
101         case types::InternalType::ScilabUInt32 :
102         {
103             types::UInt32* pD = _pIn->getAs<types::UInt32>();
104             convert_int(pD->get(), pD->getSize(), _pOut->get());
105             break;
106         }
107         case types::InternalType::ScilabInt64 :
108         {
109             types::Int64* pD = _pIn->getAs<types::Int64>();
110             convert_int(pD->get(), pD->getSize(), _pOut->get());
111             break;
112         }
113         case types::InternalType::ScilabUInt64 :
114         {
115             types::UInt64* pD = _pIn->getAs<types::UInt64>();
116             convert_int(pD->get(), pD->getSize(), _pOut->get());
117             break;
118         }
119         default:
120             return;
121     }
122 }
123
124 template< class T>
125 types::Callable::ReturnValue commonInt(types::typed_list &in, int _iRetCount, types::typed_list &out, std::string _stName)
126 {
127     if (in.size() != 1)
128     {
129         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), _stName.c_str(), 1);
130         return types::Function::Error;
131     }
132
133     if (in[0]->isDouble() == false && in[0]->isInt() == false && in[0]->isBool() == false)
134     {
135         Scierror(999, _("%s: Wrong type for input argument #%d: %s, %s or %s expected.\n"), _stName.c_str(), 1, "integer", "boolean", "double");
136         return types::Function::Error;
137     }
138
139     types::GenericType* pGT = in[0]->getAs<types::GenericType>();
140     if (pGT->getDims() == 2 && pGT->getRows() == 0 && pGT->getCols() == 0)
141     {
142         out.push_back(types::Double::Empty());
143         return types::Function::OK;
144     }
145
146     T* pOut = new T(pGT->getDims(), pGT->getDimsArray());
147
148     convertInt(in[0], pOut);
149     out.push_back(pOut);
150     return types::Function::OK;
151 }
152 /*--------------------------------------------------------------------------*/
153 types::Callable::ReturnValue sci_integer8(types::typed_list &in, int _iRetCount, types::typed_list &out)
154 {
155     return commonInt<types::Int8>(in, _iRetCount, out, "int8");
156 }
157
158 types::Callable::ReturnValue sci_uinteger8(types::typed_list &in, int _iRetCount, types::typed_list &out)
159 {
160     return commonInt<types::UInt8>(in, _iRetCount, out, "uint8");
161 }
162
163 types::Callable::ReturnValue sci_integer16(types::typed_list &in, int _iRetCount, types::typed_list &out)
164 {
165     return commonInt<types::Int16>(in, _iRetCount, out, "int16");
166 }
167
168 types::Callable::ReturnValue sci_uinteger16(types::typed_list &in, int _iRetCount, types::typed_list &out)
169 {
170     return commonInt<types::UInt16>(in, _iRetCount, out, "uint16");
171 }
172
173 types::Callable::ReturnValue sci_integer32(types::typed_list &in, int _iRetCount, types::typed_list &out)
174 {
175     return commonInt<types::Int32>(in, _iRetCount, out, "int32");
176 }
177
178 types::Callable::ReturnValue sci_uinteger32(types::typed_list &in, int _iRetCount, types::typed_list &out)
179 {
180     return commonInt<types::UInt32>(in, _iRetCount, out, "uint32");
181 }
182
183 types::Callable::ReturnValue sci_integer64(types::typed_list &in, int _iRetCount, types::typed_list &out)
184 {
185     return commonInt<types::Int64>(in, _iRetCount, out, "int64");
186 }
187
188 types::Callable::ReturnValue sci_uinteger64(types::typed_list &in, int _iRetCount, types::typed_list &out)
189 {
190     return commonInt<types::UInt64>(in, _iRetCount, out, "uint64");
191 }
192 /*--------------------------------------------------------------------------*/