remove useless file convertbase.*
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_dec2base.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2019 - St├ęphane MOTTELET
4  *
5  * This file is hereby licensed under the terms of the GNU GPL v2.0,
6  * For more information, see the COPYING file which you should have received
7  * along with this program.
8  *
9 /*--------------------------------------------------------------------------*/
10
11 #include <algorithm>
12 #include "elem_func_gw.hxx"
13 #include "function.hxx"
14 #include "double.hxx"
15 #include "int.hxx"
16 #include "string.hxx"
17 #include "overload.hxx"
18
19 extern "C"
20 {
21 #include "Scierror.h"
22 }
23
24 template <typename T> types::String* dectobase(T *_pIn, int iParam[]);
25
26 /*--------------------------------------------------------------------------*/
27 types::Function::ReturnValue sci_dec2base(types::typed_list &in, int _iRetCount, types::typed_list &out)
28 {
29     int iParam[2] = { 0, 0 };
30     types::String* pOut = NULL;
31
32     if (in.size() < 2 || in.size() > 3)
33     {
34         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "dec2base", 2, 3);
35         return types::Function::Error;
36     }
37
38     if (_iRetCount > 1)
39     {
40         Scierror(77, _("%s: Wrong number of output argument(s): %d expected.\n"), "dec2base", 1);
41         return types::Function::Error;
42     }
43
44     for (int i = 1; i < in.size(); i++)
45     {
46         if (in[i]->isDouble() == false)
47         {
48             Scierror(999, _("%s: Wrong value for input argument #%d: A positive integer expected.\n"), "dec2base", i + 1);
49             return types::Function::Error;
50         }
51         else
52         {
53             types::Double *pDbl = in[i]->getAs<types::Double>();
54             if (pDbl->isComplex() == true || pDbl->isScalar() == false ||
55                 pDbl->get(0) != trunc(pDbl->get(0)) || pDbl->get(0) < 0)
56             {
57                 Scierror(999, _("%s: Wrong value for input argument #%d: A positive integer expected.\n"), "dec2base", i + 1);
58                 return types::Function::Error;
59             }
60
61             iParam[i - 1] = (int)pDbl->get(0);
62         }
63     }
64
65     if (iParam[0] < 2 || iParam[0] > 36)
66     {
67         Scierror(999, _("%s: Wrong value for input argument #%d: Must be between %d and %d."), "dec2base", 2, 2, 36);
68         return types::Function::Error;
69     }
70
71     if (in[0]->isDouble())
72     {
73         types::Double* pDblIn = in[0]->getAs<types::Double>();
74
75         if (pDblIn->isEmpty())
76         {
77             out.push_back(types::Double::Empty());
78             return types::Function::OK;
79         }
80
81         if (pDblIn->isComplex())
82         {
83             Scierror(999, _("%s: Wrong type for input argument #%d: A matrix of integer value expected.\n"), "dec2base", 1);
84             return types::Function::Error;
85         }
86
87         double max_value = pow(2, 53);
88         double* dbl_in = pDblIn->get();
89         for (int i = 0; i < pDblIn->getSize(); i++)
90         {
91             if (trunc(dbl_in[i]) != dbl_in[i])
92             {
93                 Scierror(999, _("%s: Wrong value(s) for input argument #%d: A matrix of positive integer values expected.\n"), "dec2base", 1);
94                 return types::Function::Error;
95             }
96
97             if (dbl_in[i] > max_value)
98             {
99                 Scierror(999, _("%s: Wrong value for input argument #%d: Must be between 0 and 2^53.\n"), "dec2base", 1);
100                 return types::Function::Error;
101             }
102         }
103
104         pOut = dectobase(pDblIn, iParam);
105     }
106     else if (in[0]->isInt())
107     {
108         switch (in[0]->getType())
109         {
110         case types::InternalType::ScilabInt8:
111             pOut = dectobase(in[0]->getAs<types::Int8>(), iParam);
112             break;
113         case types::InternalType::ScilabUInt8:
114             pOut = dectobase(in[0]->getAs<types::UInt8>(), iParam);
115             break;
116         case types::InternalType::ScilabInt16:
117             pOut = dectobase(in[0]->getAs<types::Int16>(), iParam);
118             break;
119         case types::InternalType::ScilabUInt16:
120             pOut = dectobase(in[0]->getAs<types::UInt16>(), iParam);
121             break;
122         case types::InternalType::ScilabInt32:
123             pOut = dectobase(in[0]->getAs<types::Int32>(), iParam);
124             break;
125         case types::InternalType::ScilabUInt32:
126             pOut = dectobase(in[0]->getAs<types::UInt32>(), iParam);
127             break;
128         case types::InternalType::ScilabInt64:
129             pOut = dectobase(in[0]->getAs<types::Int64>(), iParam);
130             break;
131         case types::InternalType::ScilabUInt64:
132             pOut = dectobase(in[0]->getAs<types::UInt64>(), iParam);
133             break;
134         default: // should not happen
135             break;
136         }
137     }
138     else
139     {
140         Scierror(999, _("%s: Wrong type for input argument #%d : A real or integer matrix expected.\n"), "dec2base", 2);
141     }
142
143     if (pOut == NULL)
144     {
145         return types::Function::Error;
146     }
147
148     out.push_back(pOut);
149     return types::Function::OK;
150 }
151
152 template <typename T> types::String* dectobase(T *_pIn, int iParam[])
153 {
154     int iBaseUsed = iParam[0];
155     int iNbDigits = iParam[1];
156     unsigned long long int n;
157     const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
158     types::String* _pOut = new types::String(_pIn->getDims(), _pIn->getDimsArray());
159
160     if (iBaseUsed == 2)
161     {
162         // for binary conversion default iNbDigits is the largest needed number of bits among matrix terms
163         unsigned long long iMax;
164         iMax = (unsigned long long) *(std::max_element(_pIn->get(), _pIn->get() + _pIn->getSize()));
165         int iDepth = 0;
166         // iDepth is equal to trunc(log2(iMax))+1 i.e. number of needed bits
167         while (iMax)
168         {
169             iMax >>= 1;
170             iDepth++;
171         }
172
173         iNbDigits = iNbDigits > iDepth ? iNbDigits : iDepth;
174     }
175
176     for (int i = 0; i < _pIn->getSize(); i++)
177     {
178         if (_pIn->get(i) < 0)
179         {
180             Scierror(999, _("%s: Wrong value(s) for input argument #%d: A matrix of positive integer values expected.\n"), "dec2base", 1);
181             _pOut->killMe();
182             return NULL;
183         }
184
185         std::string s;
186         s.reserve(65);
187         n = (unsigned long long int) _pIn->get(i);
188
189         // digits are obtained in reverse order
190         do
191         {
192             s.append(1, digits[n % iBaseUsed]); // store and get next digit
193         } while ((n /= iBaseUsed) > 0); // "delete" it
194
195         s.append(std::max(iNbDigits - (int)s.length(), 0), '0');
196         reverse(s.begin(), s.end());
197         _pOut->set(i, s.data());
198     }
199     return _pOut;
200 }
201
202 /*--------------------------------------------------------------------------*/