add 'dec2base' function and optimize dec2bin, dec2oct, dec2hex functions.
[scilab.git] / scilab / modules / elementary_functions / src / c / convertbase.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - DIGITEO - Allan CORNET
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 <string.h>
14 #include <math.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include "convertbase.h"
18 #include "MALLOC.h"
19 #include "freeArrayOfString.h"
20 #include "stack-def.h"
21 /*--------------------------------------------------------------------------*/ 
22 #define char_a 'a'
23 #define char_A 'A'
24 #define char_z 'z'
25 #define char_Z 'Z'
26 #define char_zero '0'
27 #define char_nine '9'
28 /*--------------------------------------------------------------------------*/ 
29 static char *convertDec2Base(double dValue, int numberbase,
30                              unsigned int nbDigits, error_convertbase *err);
31 /*--------------------------------------------------------------------------*/ 
32 double convertBase2Dec(const char *pStr, int numberbase, error_convertbase *err)
33 {
34     double result = 0.;
35     *err = ERROR_CONVERTBASE_NOK;
36
37     if (pStr)
38     {
39         size_t i = 0;
40         size_t len = strlen(pStr);
41         for (i = 0; i < len; i++)
42         {
43             if ((pStr[i] >= char_zero) && (pStr[i] <= char_nine))
44             {
45                 result = (numberbase * result) + (int)pStr[i] - char_zero;
46             }
47             else if ((pStr[i] >= char_A) && (pStr[i] <= char_Z))
48             {
49                 int vTmp = (int)pStr[i] - char_A + 10;
50                 if (vTmp > numberbase)
51                 {
52                     *err = ERROR_CONVERTBASE_INVALID_REPRESENTATION;
53                     return 0;
54                 }
55                 else
56                 {
57                     result = (numberbase * result) + vTmp;
58                 }
59             }
60             else if ((pStr[i] >= char_a) && (pStr[i] <= char_z))
61             {
62                 int vTmp = (int)pStr[i] - char_a + 10;
63                 if ( vTmp > numberbase)
64                 {
65                     *err = ERROR_CONVERTBASE_INVALID_REPRESENTATION;
66                     return 0;
67                 }
68                 else
69                 {
70                     result = (numberbase * result) + vTmp;
71                 }
72             }
73             else
74             {
75                 return 0;
76             }
77         }
78         *err = ERROR_CONVERTBASE_OK;
79     }
80     return result;
81 }
82 /*--------------------------------------------------------------------------*/
83 static char *convertDec2Base(double dValue, int numberbase,
84                             unsigned int nbDigits, error_convertbase *err)
85 {
86     char symbols[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
87     long long int iDec = (long long int) dValue;
88     char *convertedValue = NULL;
89
90     *err = ERROR_CONVERTBASE_NOK;
91     if (iDec == 0)
92     {
93         convertedValue = (char*)MALLOC(sizeof(char));
94         if (convertedValue)
95         {
96             strcpy(convertedValue, "0");
97             *err = ERROR_CONVERTBASE_OK;
98         }
99         else
100         {
101             *err = ERROR_CONVERTBASE_ALLOCATION;
102             return NULL;
103         }
104     }
105     else
106     {
107         int count = 0;
108         char chResult[bsiz] = "";
109         char *pChResult = chResult;
110         while(iDec > 0 && count++ < bsiz)
111         {
112             *pChResult = symbols[iDec % numberbase];
113             pChResult++;
114             iDec = iDec / numberbase;
115         }
116
117         convertedValue = (char*)MALLOC(sizeof(char) * (strlen(chResult) + 1));
118         if (convertedValue)
119         {
120             size_t j = 0;
121             size_t i = strlen(chResult);
122             int t = !(i%2)? 1 : 0;
123             int k = 0;
124             strcpy(convertedValue, chResult);
125             for(j = i - 1; j > (i / 2 - t); j--) 
126             {
127                 char ch  = chResult[j];
128                 chResult[j] = chResult[k];
129                 chResult[k++] = ch;
130             }
131             strcpy(convertedValue, chResult);
132             *err = ERROR_CONVERTBASE_OK;
133         }
134         else
135         {
136             *err = ERROR_CONVERTBASE_ALLOCATION;
137             return NULL;
138         }
139     }
140
141     if (*err == ERROR_CONVERTBASE_OK)
142     {
143         size_t lenConvertedValue = strlen(convertedValue);
144         if ((nbDigits > lenConvertedValue) && (nbDigits > 0))
145         {
146             size_t i = 0;
147             char *tmp = (char*)MALLOC(sizeof(char) * (nbDigits + 1));
148             if (tmp)
149             {
150                 for (i = 0; i < nbDigits - lenConvertedValue; i++)
151                 {
152                     tmp[i] = '0';
153                 }
154                 tmp[i] = 0;
155                 strcat(tmp, convertedValue);
156                 FREE(convertedValue);
157                 convertedValue = tmp;
158             }
159         }
160     }
161
162     return convertedValue;
163 }
164 /*--------------------------------------------------------------------------*/
165 char **convertMatrixOfDec2Base(const double* dValues, int mn,
166                                int numberbase, unsigned int nbDigits,
167                                error_convertbase *err)
168 {
169     char **convertedValues = NULL;
170     int i = 0;
171     double maxVal = 0.;
172
173     for (i = 0; i < mn; i++)
174     {
175         long long int iValue = (long long int) dValues[i];
176
177         /* search max value */
178         if (dValues[i] > maxVal)
179         {
180             maxVal = dValues[i];
181         }
182
183         /* check if it is a integer value */
184         if (dValues[i] != (double)iValue)
185         {
186             *err = ERROR_CONVERTBASE_NOT_INTEGER_VALUE;
187             return NULL;
188         }
189
190         /* check if it is in the good interval */
191         if ((dValues[i] < 0) || (dValues[i] > pow(2, 52)))
192         {
193             *err = ERROR_CONVERTBASE_NOT_IN_INTERVAL;
194             return NULL;
195         }
196     }
197
198     if ((mn > 1) && (numberbase == 2)) /* Only binary base is uniformed about number of digits */
199     {
200         size_t maxDigits = 0;
201         char *maxBaseString = convertDec2Base(maxVal, numberbase, nbDigits, err);
202         if (maxBaseString)
203         {
204             maxDigits = strlen(maxBaseString);
205             FREE(maxBaseString);
206             if (maxDigits > nbDigits)
207             {
208                 nbDigits = maxDigits;
209             }
210         }
211     }
212
213     convertedValues = (char **)MALLOC(sizeof(char*) * (mn));
214     if (convertedValues)
215     {
216         for (i = 0; i < mn; i++)
217         {
218             convertedValues[i] = convertDec2Base(dValues[i], numberbase, nbDigits, err);
219             if (*err)
220             {
221                 freeArrayOfString(convertedValues, mn);
222                 return NULL;
223             }
224         }
225     }
226     else
227     {
228         *err = ERROR_CONVERTBASE_ALLOCATION;
229     }
230     return convertedValues;
231 }
232 /*--------------------------------------------------------------------------*/