2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010-2011 - DIGITEO - Allan CORNET
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.1-en.txt
18 #include "stringToComplex.h"
19 #include "stringToDouble.h"
20 #include "sci_malloc.h"
21 #include "os_string.h"
24 /* ========================================================================== */
27 #define ComplexCharI 'i'
28 #define ComplexCharJ 'j'
29 #define ComplexScilab "%i"
31 /* ========================================================================== */
34 #define strnicmp strncasecmp
37 #define stricmp _stricmp
41 #define strnicmp _strnicmp
43 /* ========================================================================== */
44 static int ParseNumber(const char* tx);
45 static stringToComplexError ParseComplexValue(const char *tx, BOOL bConvertByNAN, double *real, double *imag);
46 static char* midstring(const char *tx, size_t pos, int nb);
47 static char *leftstring(const char *tx, size_t pos);
48 static BOOL is_unit_imaginary (const char *src, double *im);
49 static double returnNAN(void);
50 /* ========================================================================== */
51 complexArray *stringsToComplexArray(const char **pSTRs, int nbElements,
54 stringToComplexError *ierr)
56 complexArray *pComplexArray = NULL;
58 *ierr = STRINGTOCOMPLEX_ERROR;
66 *ierr = STRINGTOCOMPLEX_MEMORY_ALLOCATION;
70 pComplexArray = createComplexArrayEmpty(nbElements);
74 for (i = 0; i < nbElements; i++)
76 doublecomplex dComplexValue = stringToComplex(pSTRs[i], decimal, bConvertByNAN, ierr);
77 if (*ierr != STRINGTOCOMPLEX_NO_ERROR)
79 freeComplexArray(pComplexArray);
84 pComplexArray->realPart[i] = dComplexValue.r;
85 pComplexArray->imagPart[i] = dComplexValue.i;
88 cleanImagPartComplexArray(pComplexArray);
92 *ierr = STRINGTOCOMPLEX_MEMORY_ALLOCATION;
97 /* ========================================================================== */
98 doublecomplex stringToComplex(const char *pSTR, const char *decimal, BOOL bConvertByNAN, stringToComplexError *ierr)
100 doublecomplex dComplexValue;
101 *ierr = STRINGTOCOMPLEX_ERROR;
103 dComplexValue.r = 0.;
104 dComplexValue.i = 0.;
110 char *pStrTemp = strsub((char*)pSTR, " ", "");
114 char *pStrFormatted = strsub(pStrTemp, decimal, ".");
119 int lenStrFormatted = (int) strlen(pStrFormatted);
121 /* case .4 replaced by 0.4 */
122 if (pStrFormatted[0] == '.')
124 /* case .4 replaced by 0.4 */
125 char *pstStrTemp = (char*)MALLOC(sizeof(char) * (lenStrFormatted + strlen("0") + 1));
126 strcpy(pstStrTemp, "0");
127 strcat(pstStrTemp, pStrFormatted);
129 pStrFormatted = pstStrTemp;
132 if (lenStrFormatted > 1)
134 if (((pStrFormatted[0] == '+') || (pStrFormatted[0] == '-')) &&
135 (pStrFormatted[1] == '.'))
137 /* case +.4 replaced by +0.4 */
138 char *pstStrTemp = strsub(pStrFormatted, "+.", "+0.");
141 /* case -.4 replaced by -0.4 */
142 pStrFormatted = strsub(pstStrTemp, "-.", "-0.");
147 /* Case: "i", "+i", "-i", and with "j" */
148 if (is_unit_imaginary (pStrFormatted, &imag))
150 *ierr = STRINGTOCOMPLEX_NO_ERROR;
151 dComplexValue.r = 0.;
152 dComplexValue.i = imag;
156 *ierr = ParseComplexValue(pStrFormatted, bConvertByNAN, &real, &imag);
161 dComplexValue.r = real;
162 dComplexValue.i = imag;
164 return dComplexValue;
166 /* ========================================================================== */
167 static int ParseNumber(const char* tx)
181 // Special cases: constants
182 if (strlen(tx) >= 5 && (strncmp(tx, "+%eps", 5) == 0 || strncmp(tx, "-%eps", 5) == 0 || strncmp(tx, "+%nan", 5) == 0 || strncmp(tx, "-%nan", 5) == 0 || strncmp(tx, "+%inf", 5) == 0 || strncmp(tx, "-%inf", 5) == 0))
186 else if (strlen(tx) >= 4 && (strncmp(tx, "%eps", 4) == 0 || strncmp(tx, "+%pi", 4) == 0 || strncmp(tx, "-%pi", 4) == 0 ||
187 strncmp(tx, "+Inf", 4) == 0 || strncmp(tx, "-Inf", 4) == 0 || strncmp(tx, "+Nan", 4) == 0 ||
188 strncmp(tx, "-Nan", 4) == 0 || strncmp(tx, "%nan", 4) == 0 || strncmp(tx, "%inf", 4) == 0 ))
192 else if (strlen(tx) >= 3 && (strncmp(tx, "+%e", 3) == 0 || strncmp(tx, "-%e", 3) == 0 || strncmp(tx, "%pi", 3) == 0 ||
193 strncmp(tx, "Nan", 3) == 0 || strncmp(tx, "Inf", 3) == 0 || strncmp(tx, "%pi", 3) == 0))
197 else if (strlen(tx) >= 2 && strncmp(tx, "%e", 2) == 0)
202 if ((tx[len] == '+') || (tx[len] == '-'))
207 while (isdigit(tx[len]))
213 if (tx[lookahead] == '.')
217 while (isdigit(tx[len + lookahead]))
224 if ((tx[lookahead] == 'E') || (tx[lookahead] == 'e') ||
225 (tx[lookahead] == 'D') || (tx[lookahead] == 'd'))
229 if ((tx[lookahead] == '+') || (tx[lookahead] == '-'))
235 while (isdigit(tx[len + lookahead]))
244 /* ========================================================================== */
245 static stringToComplexError ParseComplexValue(const char *tx, BOOL bConvertByNAN, double *real, double *imag)
247 stringToDoubleError ierrDouble = STRINGTODOUBLE_NO_ERROR;
248 stringToComplexError ierr = STRINGTOCOMPLEX_NO_ERROR;
249 char *rnum_string = NULL;
250 char *inum_string = NULL;
252 BOOL haveImagI = FALSE;
253 char *modifiedTxt = NULL;
256 *real = stringToDouble(tx, FALSE, &ierrDouble);
259 /* test on strlen(tx) > 1 to remove case 'e' */
260 if ((int)strlen(tx) < 2)
262 if (ierrDouble == STRINGTODOUBLE_NO_ERROR)
264 ierr = (stringToComplexError) ierrDouble;
270 ierrDouble = STRINGTODOUBLE_NOT_A_NUMBER;
278 ierr = (stringToComplexError) ierrDouble;
282 else if (ierrDouble != STRINGTODOUBLE_NO_ERROR)
284 modifiedTxt = strsub((char*)tx, ComplexScilab, ComplexI);
285 lnum = ParseNumber(modifiedTxt);
288 /* manages special cases nan + nani, ... */
289 if (strnicmp(modifiedTxt, NanString, strlen(NanString)) == 0)
291 lnum = strlen(NanString);
293 else if (strnicmp(modifiedTxt, InfString, strlen(InfString)) == 0)
295 lnum = strlen(InfString);
297 else if (strnicmp(modifiedTxt, NegInfString, strlen(NegInfString)) == 0)
299 lnum = strlen(NegInfString);
301 else if (strnicmp(modifiedTxt, PosInfString, strlen(PosInfString)) == 0)
303 lnum = strlen(PosInfString);
305 else if (strnicmp(modifiedTxt, NegNanString, strlen(NegNanString)) == 0)
307 lnum = strlen(NegNanString);
309 else if (strnicmp(modifiedTxt, PosNanString, strlen(PosNanString)) == 0)
311 lnum = strlen(PosNanString);
314 inum_string = midstring(modifiedTxt, lnum, -1);
316 if ((inum_string[strlen(inum_string) - 1] == 'i') ||
317 (inum_string[strlen(inum_string) - 1] == 'j')) // The imaginary part looks like "a*%i"
319 inum_string[strlen(inum_string) - 1] = 0;
320 if (inum_string[strlen(inum_string) - 1] == '*')
322 inum_string[strlen(inum_string) - 1] = 0;
325 if (strcmp(inum_string, "+") == 0)
328 inum_string = os_strdup("+1");
331 if (strcmp(inum_string, "-") == 0)
334 inum_string = os_strdup("-1");
338 else if (inum_string[1] == 'i' || inum_string[1] == 'j') // The imaginary part looks like "%i*a". For instance if string() has been used
340 int len_inum_string = (int)strlen(inum_string);
341 for (i = 1; i < len_inum_string; ++i)
343 inum_string[i] = inum_string[i + 1]; // Removing the "i"
345 if (inum_string[1] == '*')
347 for (i = 1; i < len_inum_string; ++i)
349 inum_string[i] = inum_string[i + 1]; // Removing the "*"
353 if (strcmp(inum_string, "+") == 0)
356 inum_string = os_strdup("+1");
359 if (strcmp(inum_string, "-") == 0)
362 inum_string = os_strdup("-1");
370 rnum_string = leftstring(modifiedTxt, lnum);
372 if (strcmp(inum_string, "") == 0)
374 *imag = stringToDouble(rnum_string, bConvertByNAN, &ierrDouble);
375 ierr = (stringToComplexError)(ierrDouble);
383 stringToDoubleError ierrReal = STRINGTODOUBLE_NO_ERROR;
384 stringToDoubleError ierrImag = STRINGTODOUBLE_NO_ERROR;
385 dReal = stringToDouble(rnum_string, FALSE, &ierrReal);
386 dImag = stringToDouble(inum_string, FALSE, &ierrImag);
388 if ((ierrReal == STRINGTODOUBLE_NO_ERROR) && (ierrImag == STRINGTODOUBLE_NO_ERROR))
394 ierr = STRINGTOCOMPLEX_NO_ERROR;
400 ierr = STRINGTOCOMPLEX_ERROR;
405 ierr = STRINGTOCOMPLEX_NO_ERROR;
414 ierr = STRINGTOCOMPLEX_NO_ERROR;
420 ierr = STRINGTOCOMPLEX_ERROR;
431 /* ========================================================================== */
432 static char *midstring(const char *tx, size_t pos, int nb)
434 char *returnString = NULL;
437 int lenTx = (int) strlen(tx);
452 returnString = (char*)MALLOC(sizeof(char) * newLen);
453 strncpy(returnString, &tx[pos], posEnd);
454 returnString[posEnd] = 0;
459 /* ========================================================================== */
460 static char *leftstring(const char *tx, size_t pos)
462 char *returnString = NULL;
465 int lenTx = (int) strlen(tx);
466 returnString = os_strdup(tx);
473 returnString[pos] = 0;
478 /* ========================================================================== */
479 static BOOL is_unit_imaginary (const char *src, double *im)
481 char *modifiedSrc = strsub((char*)src, ComplexScilab, ComplexI);
482 char *nextChar = NULL;
483 BOOL isUnitImag = FALSE;
485 if (modifiedSrc == NULL)
490 if (modifiedSrc[0] == LessChar)
493 nextChar = modifiedSrc + 1;
498 if (modifiedSrc[0] == PlusChar)
500 nextChar = modifiedSrc + 1;
504 nextChar = modifiedSrc;
510 if ((nextChar[0] == ComplexCharI || nextChar[0] == ComplexCharJ) && nextChar[1] == 0)
523 /* ========================================================================== */
524 static double returnNAN(void)
526 static int first = 1;
527 static double nan = 1.0;
531 nan = (nan - (double) first) / (nan - (double) first);
536 // =============================================================================