1 /*********************************************************************
2 Type -- Type information and basic operations.
3 This is part of GNU Astronomy Utilities (Gnuastro) package.
4 
5 Original author:
6      Mohammad Akhlaghi <mohammad@akhlaghi.org>
7 Contributing author(s):
8 Copyright (C) 2016-2021, Free Software Foundation, Inc.
9 
10 Gnuastro is free software: you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation, either version 3 of the License, or (at your
13 option) any later version.
14 
15 Gnuastro is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
22 **********************************************************************/
23 #include <config.h>
24 
25 #include <stdio.h>
26 #include <errno.h>
27 #include <error.h>
28 #include <float.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <inttypes.h>
33 
34 #include <gnuastro/type.h>
35 #include <gnuastro/data.h>
36 #include <gnuastro/list.h>
37 #include <gnuastro/pointer.h>
38 #include <gnuastro-internal/checkset.h>
39 
40 
41 
42 
43 
44 
45 /*************************************************************
46  **************         General info           ***************
47  *************************************************************/
48 size_t
gal_type_sizeof(uint8_t type)49 gal_type_sizeof(uint8_t type)
50 {
51   /* Allocate space for the array to keep the image. */
52   switch(type)
53     {
54     case GAL_TYPE_BIT:
55       error(EXIT_FAILURE, 0, "%s: bit types are not currently supported, "
56             "please get in touch with us to implement it", __func__);
57 
58       /* The parenthesis after sizeof is not a function, it is actually a
59          type cast, so we have put a space between size of and the
60          parenthesis to highlight this. In C, 'sizeof' is an operator, not
61          a function.*/
62     case GAL_TYPE_UINT8:     return sizeof (uint8_t);
63     case GAL_TYPE_INT8:      return sizeof (int8_t);
64     case GAL_TYPE_UINT16:    return sizeof (uint16_t);
65     case GAL_TYPE_INT16:     return sizeof (int16_t);
66     case GAL_TYPE_UINT32:    return sizeof (uint32_t);
67     case GAL_TYPE_INT32:     return sizeof (int32_t);
68     case GAL_TYPE_UINT64:    return sizeof (uint64_t);
69     case GAL_TYPE_INT64:     return sizeof (int64_t);
70 
71     case GAL_TYPE_FLOAT32:
72       if( sizeof (float) != 4 )
73         error(EXIT_FAILURE, 0, "%s: 'float' is not 32 bits on this machine",
74               __func__);
75       return sizeof (float);
76 
77     case GAL_TYPE_FLOAT64:
78       if( sizeof (double) != 8 )
79         error(EXIT_FAILURE, 0, "%s: 'double' is not 64 bits on this machine",
80               __func__);
81       return sizeof (double);
82 
83     case GAL_TYPE_COMPLEX32:
84       if( sizeof (float) != 4 )
85         error(EXIT_FAILURE, 0, "%s: 'float' is not 32 bits on this machine",
86               __func__);
87       return sizeof (gsl_complex_float);
88 
89     case GAL_TYPE_COMPLEX64:
90       if( sizeof (double) != 8 )
91         error(EXIT_FAILURE, 0, "%s: 'double' is not 64 bits on this machine",
92               __func__);
93       return sizeof (gsl_complex);
94 
95     case GAL_TYPE_STRING:
96       return sizeof (char *);
97 
98     default:
99       error(EXIT_FAILURE, 0, "%s: type value of %d not recognized",
100             __func__, type);
101     }
102 
103   error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s so we can find "
104         "the cause of the problem. Control should not have reached the end of "
105         "this function", __func__, PACKAGE_BUGREPORT);
106   return -1;
107 }
108 
109 
110 
111 
112 
113 char *
gal_type_name(uint8_t type,int long_name)114 gal_type_name(uint8_t type, int long_name)
115 {
116   switch(type)
117     {
118     case GAL_TYPE_BIT:
119       if(long_name) return "bit";                 else return "b";
120 
121     case GAL_TYPE_UINT8:
122       if(long_name) return "uint8";               else return "u8";
123 
124     case GAL_TYPE_INT8:
125       if(long_name) return "int8";                else return "i8";
126 
127     case GAL_TYPE_UINT16:
128       if(long_name) return "uint16";              else return "u16";
129 
130     case GAL_TYPE_INT16:
131       if(long_name) return "int16";               else return "i16";
132 
133     case GAL_TYPE_UINT32:
134       if(long_name) return "uint32";              else return "u32";
135 
136     case GAL_TYPE_INT32:
137       if(long_name) return "int32";               else return "i32";
138 
139     case GAL_TYPE_UINT64:
140       if(long_name) return "uint64";              else return "u64";
141 
142     case GAL_TYPE_INT64:
143       if(long_name) return "int64";               else return "i64";
144 
145     case GAL_TYPE_FLOAT32:
146       if(long_name) return "float32";             else return "f32";
147 
148     case GAL_TYPE_FLOAT64:
149       if(long_name) return "float64";             else return "f64";
150 
151     case GAL_TYPE_COMPLEX32:
152       if(long_name) return "complex32";           else return "c32";
153 
154     case GAL_TYPE_COMPLEX64:
155       if(long_name) return "complex64";           else return "c64";
156 
157     case GAL_TYPE_STRING:
158       if(long_name) return "string";              else return "str";
159 
160     case GAL_TYPE_STRLL:
161       if(long_name) return "string linked list";  else return "strll";
162 
163     default:
164       error(EXIT_FAILURE, 0, "%s: type value of %d not recognized",
165             __func__, type);
166     }
167 
168   /* Any of the cases above should return this function, so if control
169      reaches here, there is a bug. */
170   error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s so we can "
171         "address the problem. Control should not have reached the end of "
172         "this function", __func__, PACKAGE_BUGREPORT);
173   return NULL;
174 }
175 
176 
177 
178 
179 
180 uint8_t
gal_type_from_name(char * str)181 gal_type_from_name(char *str)
182 {
183   if(      !strcmp(str, "b")     || !strcmp(str, "bit") )
184     return GAL_TYPE_BIT;
185 
186   else if( !strcmp(str, "u8")    || !strcmp(str, "uint8") )
187     return GAL_TYPE_UINT8;
188 
189   else if( !strcmp(str, "i8")    || !strcmp(str, "int8") )
190     return GAL_TYPE_INT8;
191 
192   else if( !strcmp(str, "u16")   || !strcmp(str, "uint16") )
193     return GAL_TYPE_UINT16;
194 
195   else if( !strcmp(str, "i16")   || !strcmp(str, "int16") )
196     return GAL_TYPE_INT16;
197 
198   else if( !strcmp(str, "u32")   || !strcmp(str, "uint32") )
199     return GAL_TYPE_UINT32;
200 
201   else if( !strcmp(str, "i32")   || !strcmp(str, "int32") )
202     return GAL_TYPE_INT32;
203 
204   else if( !strcmp(str, "u64")   || !strcmp(str, "uint64") )
205     return GAL_TYPE_UINT64;
206 
207   else if( !strcmp(str, "i64")   || !strcmp(str, "int64") )
208     return GAL_TYPE_INT64;
209 
210   else if( !strcmp(str, "f32")   || !strcmp(str, "float32") )
211     return GAL_TYPE_FLOAT32;
212 
213   else if( !strcmp(str, "f64")   || !strcmp(str, "float64") )
214     return GAL_TYPE_FLOAT64;
215 
216   else if( !strcmp(str, "c32")   || !strcmp(str, "complex32") )
217     return GAL_TYPE_COMPLEX32;
218 
219   else if( !strcmp(str, "c64")   || !strcmp(str, "complex64") )
220     return GAL_TYPE_COMPLEX64;
221 
222   else if( !strcmp(str, "str")   || !strcmp(str, "string") )
223     return GAL_TYPE_STRING;
224 
225   else
226     return GAL_TYPE_INVALID;
227 
228   /* Any of the cases above should return this function, so if control
229      reaches here, there is a bug. */
230   error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s so we can "
231         "address the problem. Control must not have reached the end of this "
232         "function", __func__, PACKAGE_BUGREPORT);
233   return 0;
234 }
235 
236 
237 
238 
239 
240 /* Put the minimum (or maximum for the 'gal_data_type_max') value for the
241    type in the space (that must already be allocated before the call to
242    this function) pointed to by in.  */
243 void
gal_type_min(uint8_t type,void * in)244 gal_type_min(uint8_t type, void *in)
245 {
246   switch(type)
247     {
248     case GAL_TYPE_UINT8:        *(uint8_t *)  in = 0;            break;
249     case GAL_TYPE_INT8:         *(int8_t *)   in = INT8_MIN;     break;
250     case GAL_TYPE_UINT16:       *(uint16_t *) in = 0;            break;
251     case GAL_TYPE_INT16:        *(int16_t *)  in = INT16_MIN;    break;
252     case GAL_TYPE_UINT32:       *(uint32_t *) in = 0;            break;
253     case GAL_TYPE_INT32:        *(int32_t *)  in = INT32_MIN;    break;
254     case GAL_TYPE_UINT64:       *(uint64_t *) in = 0;            break;
255     case GAL_TYPE_INT64:        *(int64_t *)  in = INT64_MIN;    break;
256     case GAL_TYPE_FLOAT32:      *(float *)    in = -FLT_MAX;     break;
257     case GAL_TYPE_FLOAT64:      *(double *)   in = -DBL_MAX;     break;
258     default:
259       error(EXIT_FAILURE, 0, "%s: type code %d not recognized", __func__, type);
260     }
261 }
262 
263 
264 
265 
266 
267 void
gal_type_max(uint8_t type,void * in)268 gal_type_max(uint8_t type, void *in)
269 {
270   switch(type)
271     {
272     case GAL_TYPE_UINT8:        *(uint8_t *)  in = UINT8_MAX;    break;
273     case GAL_TYPE_INT8:         *(int8_t *)   in = INT8_MAX;     break;
274     case GAL_TYPE_UINT16:       *(uint16_t *) in = UINT16_MAX;   break;
275     case GAL_TYPE_INT16:        *(int16_t *)  in = INT16_MAX;    break;
276     case GAL_TYPE_UINT32:       *(uint32_t *) in = UINT32_MAX;   break;
277     case GAL_TYPE_INT32:        *(int32_t *)  in = INT32_MAX;    break;
278     case GAL_TYPE_UINT64:       *(uint64_t *) in = UINT64_MAX;   break;
279     case GAL_TYPE_INT64:        *(int64_t *)  in = INT64_MAX;    break;
280     case GAL_TYPE_FLOAT32:      *(float *)    in = FLT_MAX;      break;
281     case GAL_TYPE_FLOAT64:      *(double *)   in = DBL_MAX;      break;
282     default:
283       error(EXIT_FAILURE, 0, "%s: type code %d not recognized", __func__,
284             type);
285     }
286 }
287 
288 
289 
290 
291 
292 int
gal_type_is_int(uint8_t type)293 gal_type_is_int(uint8_t type)
294 {
295   switch(type)
296     {
297     case GAL_TYPE_UINT8:  return 1;
298     case GAL_TYPE_INT8:   return 1;
299     case GAL_TYPE_UINT16: return 1;
300     case GAL_TYPE_INT16:  return 1;
301     case GAL_TYPE_UINT32: return 1;
302     case GAL_TYPE_INT32:  return 1;
303     case GAL_TYPE_UINT64: return 1;
304     case GAL_TYPE_INT64:  return 1;
305     default:              return 0;
306     }
307 }
308 
309 
310 
311 
312 
313 /* Since linked lists need a different process than arrays, for functions
314    that work on both, it is convenient to simiplify the check with this
315    function. */
316 int
gal_type_is_list(uint8_t type)317 gal_type_is_list(uint8_t type)
318 {
319   return type==GAL_TYPE_STRLL;
320 }
321 
322 
323 
324 
325 
326 int
gal_type_out(int first_type,int second_type)327 gal_type_out(int first_type, int second_type)
328 {
329   return first_type > second_type ? first_type : second_type;
330 }
331 
332 
333 
334 
335 
336 
337 
338 
339 
340 
341 
342 
343 
344 
345 
346 
347 
348 
349 
350 
351 /*************************************************************
352  **************         To/from string         ***************
353  *************************************************************/
354 /* Write the bit (0 or 1) contents of 'in' into a string ready for
355    printing. 'size' is used to determine the number of bytes to print. The
356    output string will be dynamically allocated within this function. This
357    can be useful for easy checking of bit flag values, for example in an
358    expression like below:
359 
360       printf("flag: %s\n", gal_type_bit_string(&flag, sizeof flag) );    */
361 char *
gal_type_bit_string(void * in,size_t size)362 gal_type_bit_string(void *in, size_t size)
363 {
364   size_t i;
365   char *byte=in;
366   char *str=gal_pointer_allocate(GAL_TYPE_UINT8, 8*size+1, 0, __func__,
367                                  "str");
368 
369   /* Print the bits into the allocated string. This was inspired from
370 
371      http://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format */
372   for(i=0;i<size;++i)
373     sprintf(str+i*8, "%c%c%c%c%c%c%c%c ",
374            (byte[i] & 0x80 ? '1' : '0'), (byte[i] & 0x40 ? '1' : '0'),
375            (byte[i] & 0x20 ? '1' : '0'), (byte[i] & 0x10 ? '1' : '0'),
376            (byte[i] & 0x08 ? '1' : '0'), (byte[i] & 0x04 ? '1' : '0'),
377            (byte[i] & 0x02 ? '1' : '0'), (byte[i] & 0x01 ? '1' : '0') );
378 
379   /* Return the allocated and filled string. */
380   return str;
381 }
382 
383 
384 
385 
386 
387 /* Write the contents of memory that 'ptr' points to as a string of type
388    'type'.*/
389 #define TO_STRING(CTYPE, FMT) {                                         \
390   if( asprintf(&str, FMT, *(CTYPE *)ptr)<0 )                            \
391     error(EXIT_FAILURE, 0, "%s: asprintf allocation", __func__); }
392 
393 char *
gal_type_to_string(void * ptr,uint8_t type,int quote_if_str_has_space)394 gal_type_to_string(void *ptr, uint8_t type, int quote_if_str_has_space)
395 {
396   char *c, *str=NULL;
397   switch(type)
398     {
399     /* For a string we might need to make sure it has no white space
400        characters, if it does, it can be printed it within quotation
401        signs. */
402     case GAL_TYPE_STRING:
403       if(quote_if_str_has_space)
404         {
405           c=*(char **)ptr; while(*c!='\0') if(isspace(*c++)) break;
406           if(*c=='\0')
407             {
408               if( asprintf(&str, "%s", *(char **)ptr)<0 )
409                 error(EXIT_FAILURE, 0, "%s: asprintf allocation", __func__);
410             }
411           else
412             {
413               if( asprintf(&str, "\"%s\" ", *(char **)ptr)<0 )
414                 error(EXIT_FAILURE, 0, "%s: asprintf allocation", __func__);
415             }
416         }
417       else
418         if( asprintf(&str, "%s", *(char **)ptr)<0 )
419           error(EXIT_FAILURE, 0, "%s: asprintf allocation", __func__);
420       break;
421 
422     case GAL_TYPE_UINT8:   TO_STRING( uint8_t,  "%"PRIu8  );  break;
423     case GAL_TYPE_INT8:    TO_STRING( int8_t,   "%"PRId8  );  break;
424     case GAL_TYPE_UINT16:  TO_STRING( uint16_t, "%"PRIu16 );  break;
425     case GAL_TYPE_INT16:   TO_STRING( int16_t,  "%"PRId16 );  break;
426     case GAL_TYPE_UINT32:  TO_STRING( uint32_t, "%"PRIu32 );  break;
427     case GAL_TYPE_INT32:   TO_STRING( int32_t,  "%"PRId32 );  break;
428     case GAL_TYPE_UINT64:  TO_STRING( uint64_t, "%"PRIu64 );  break;
429     case GAL_TYPE_INT64:   TO_STRING( int64_t,  "%"PRId64 );  break;
430     case GAL_TYPE_FLOAT32: TO_STRING( float,    "%.6g"    );  break;
431     case GAL_TYPE_FLOAT64: TO_STRING( double,   "%.10g"   );  break;
432 
433     default:
434       error(EXIT_FAILURE, 0, "%s: type code %d not recognized",
435             __func__, type);
436     }
437   return str;
438 }
439 
440 
441 
442 
443 
444 /* Read a string as a given data type and put a the pointer to it in
445    *out. When the input '*out!=NULL', then it is assumed to be allocated
446    and the value will be simply put there. If '*out==NULL', then space will
447    be allocated for the given type and the string's value (in the given
448    type) will be stored there.
449 
450    Note that when we are dealing with a string type, '*out' should be
451    interpretted as 'char **' (one element in an array of pointers to
452    different strings). In other words, 'out' should be 'char ***'.
453 
454    This function can be used to fill in arrays of numbers from strings (in
455    an already allocated data structure), or add nodes to a linked list. For
456    an array, you have to pass the pointer to the 'i'th element where you
457    want the value to be stored, for example &(array[i]).
458 
459    If parsing was successful, it will return a 0. If there was a problem,
460    it will return 1.  */
461 int
gal_type_from_string(void ** out,char * string,uint8_t type)462 gal_type_from_string(void **out, char *string, uint8_t type)
463 {
464   long l;
465   double d;
466   void *value;
467   char *tailptr;
468   int status=0, allocated=0;
469 
470   /* If the output is NULL, then allocate the necessary space if we are not
471      dealing with a linked list. In a linked list, a NULL value is
472      meaningful (it is the end of the list). */
473   if( *out==NULL && !gal_type_is_list(type) )
474     {
475       allocated=1;
476       *out=gal_pointer_allocate(type, 1, 0, __func__, "out");
477     }
478   value=*out;
479 
480   /* Read the string depending on the type. */
481   switch(type)
482     {
483 
484     /* Linked lists, currently only string linked lists. */
485     case GAL_TYPE_STRLL:
486       gal_list_str_add( (struct gal_list_str_t **)out, string, 1);
487       break;
488 
489     /* String, just allocate and copy the string and keep its pointer in
490        the place '*out' points to (for strings, '*out' is 'char **'). */
491     case GAL_TYPE_STRING:
492       gal_checkset_allocate_copy(string, value);
493       break;
494 
495     /* Floating point: Read it as a double or long, then put it in the
496        array. When the conversion can't be done (the string isn't a number
497        for example), then just assume no blank value was given. */
498     case GAL_TYPE_FLOAT32:
499     case GAL_TYPE_FLOAT64:
500       d=strtod(string, &tailptr);
501       if(*tailptr!='\0')
502         status=1;
503       else
504         {
505           if(type==GAL_TYPE_FLOAT32) *(float  *) value=d;
506           else                       *(double *) value=d;
507         }
508       break;
509 
510     /* Integers. */
511     default:
512       l=strtol(string, &tailptr, 0);
513       if(*tailptr!='\0')
514         status=1;
515       else
516         switch(type)
517           {
518           /* The signed values can easily be put in. */
519           case GAL_TYPE_INT8:  *(int8_t  *) value = l; break;
520           case GAL_TYPE_INT16: *(int16_t *) value = l; break;
521           case GAL_TYPE_INT32: *(int32_t *) value = l; break;
522           case GAL_TYPE_INT64: *(int64_t *) value = l; break;
523 
524           /* For the unsigned types, the value has to be positive, so if
525              the input was negative, then just return a status of one and
526              don't store the value. */
527           default:
528             if(l<0)
529               status=1;
530             else
531               switch(type)
532                 {
533                 case GAL_TYPE_UINT8:  *(uint8_t  *) value=l;   break;
534                 case GAL_TYPE_UINT16: *(uint16_t *) value=l;   break;
535                 case GAL_TYPE_UINT32: *(uint32_t *) value=l;   break;
536                 case GAL_TYPE_UINT64: *(uint64_t *) value=l;   break;
537                 default:
538                   error(EXIT_FAILURE, 0, "%s: type code %d not recognized",
539                         __func__, type);
540                 }
541           }
542     }
543 
544   /* If reading was unsuccessful, then free the space if it was allocated,
545      then return the status, don't touch the pointer. */
546   if(status && allocated)
547     {
548       free(*out);
549       *out=NULL;
550     }
551   return status;
552 }
553 
554 
555 
556 
557 
558 /* If the data structure was correctly created (the string was a number),
559    then return its pointer. Otherwise, return NULL. */
560 void *
gal_type_string_to_number(char * string,uint8_t * type)561 gal_type_string_to_number(char *string, uint8_t *type)
562 {
563   void *ptr, *out;
564   int fnz=-1, lnz=0;     /* 'F'irst (or 'L'ast) 'N'on-'Z'ero. */
565   uint8_t forcedfloat=0;
566   char *c, *tailptr, *cp;
567 
568   /* Define initial spaces to keep the value. */
569   uint8_t   u8;   int8_t   i8;      uint16_t u16;   int16_t i16;
570   uint32_t u32;   int32_t i32;      uint64_t u64;   int64_t i64;
571   float      f;   double    d;
572 
573   /* First see if the number is a double (the most generic). */
574   d=strtod(string, &tailptr);
575   if(*tailptr=='f') { if(tailptr[1]=='\0') forcedfloat=1; else return NULL; }
576   else if (*tailptr!='\0')  return NULL;
577 
578   /* The number has been parsed successfully as a number. But if it
579      contains a '.', then it must a "forced" float also. This won't be a
580      problem in scenarios like '.2', but people may use '2.' or '2.0' to
581      force a float and this loop is necessary in such cases. */
582   for(c=string; *c!='\0'; ++c) if(*c=='.') { forcedfloat=1; break; }
583 
584   /* See if the number is actually an integer: */
585   if( forcedfloat==0 && ceil(d) == d )
586     {
587       /* If the number is negative, put it in the signed types (based on
588          its value). If its zero or positive, then put it in the unsigned
589          types. */
590       if( d < 0 )
591         {
592           if     (d>INT8_MIN)    { i8=d;  ptr=&i8;  *type=GAL_TYPE_INT8;   }
593           else if(d>INT16_MIN)   { i16=d; ptr=&i16; *type=GAL_TYPE_INT16;  }
594           else if(d>INT32_MIN)   { i32=d; ptr=&i32; *type=GAL_TYPE_INT32;  }
595           else                   { i64=d; ptr=&i64; *type=GAL_TYPE_INT64;  }
596         }
597       else
598         {
599           /* Note that the blank values are set to the maximum values in
600              unsigned types. A blank value should be given as a blank
601              string to this function ('GAL_BLANK_STRING'). So, to avoid
602              confusing situations (for example when the user gives 255), if
603              the value is equal to the given maximum of the given type,
604              we'll assign it to a larger type. In other words, we won't be
605              using the '<=MAX', but '<MAX'. */
606           if     (d<UINT8_MAX)  { u8=d;  ptr=&u8;  *type=GAL_TYPE_UINT8;  }
607           else if(d<UINT16_MAX) { u16=d; ptr=&u16; *type=GAL_TYPE_UINT16; }
608           else if(d<UINT32_MAX) { u32=d; ptr=&u32; *type=GAL_TYPE_UINT32; }
609           else                  { u64=d; ptr=&u64; *type=GAL_TYPE_UINT64; }
610         }
611     }
612   else
613     {
614       /* The maximum number of decimal digits to store in float or double
615          precision floating point are:
616 
617          float:  23 mantissa bits + 1 hidden bit: log(224)÷log(10) = 7.22
618          double: 52 mantissa bits + 1 hidden bit: log(253)÷log(10) = 15.95
619 
620          FLT_DIG (at least 6 in ISO C) keeps the number of digits (not zero
621          before or after) that can be represented by a single precision
622          floating point number. If there are more digits, then we should
623          store the value as a double precision.
624 
625          Note that the number can have non-digit characters that we don't
626          want, like: '.', 'e', 'E', ','. */
627       for(cp=string;*cp!='\0';++cp)
628         if(isdigit(*cp) && *cp!='0' && fnz==-1)
629           fnz=cp-string;
630 
631       /* In the previous loop, we went to the end of the string, so 'cp'
632          now points to its '\0'. We just have to iterate backwards! */
633       for(;cp!=string;--cp)
634         if(isdigit(*cp) && *cp!='0')
635           {
636             lnz=cp-string;
637             break;
638           }
639 
640       /* Calculate the number of decimal digits and decide if it the number
641          should be a float or a double. */
642       if( lnz-fnz < FLT_DIG || ( d<FLT_MAX && d>FLT_MIN ) )
643         { f=d; ptr=&f; *type=GAL_TYPE_FLOAT32; }
644       else
645         {      ptr=&d; *type=GAL_TYPE_FLOAT64; }
646     }
647 
648   /* Allocate a one-element dataset, then copy the number into it. */
649   out=gal_pointer_allocate(*type, 1, 0, __func__, "out");
650   memcpy(out, ptr, gal_type_sizeof(*type));
651   return out;
652 }
653