gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 25038d1 1/2: Library (Units): deg. to hh:mm:ss


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 25038d1 1/2: Library (Units): deg. to hh:mm:ss and dd:mm:ss and vice-versa functions
Date: Wed, 8 Apr 2020 22:31:54 -0400 (EDT)

branch: master
commit 25038d195574d1a0bf8a3e9e7d8b4ae7a4213513
Author: Kartik Ohri <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Library (Units): deg. to hh:mm:ss and dd:mm:ss and vice-versa functions
    
    New functions, `gal_units_ra_to_decimal`, `gal_units_dec_to_decimal`,
    `gal_units_decimal_to_ra` and `gal_units_decimal_to_dec` have been added to
    convert right ascension and declination units from string to decimal form
    and vice versa.
    
    This partially completes task #15567.
---
 lib/Makefile.am           |   4 +-
 lib/arithmetic.c          |  97 ++++++++++++-
 lib/gnuastro/arithmetic.h |   5 +
 lib/gnuastro/units.h      |  81 +++++++++++
 lib/units.c               | 340 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 524 insertions(+), 3 deletions(-)

diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2b36836..f880d6a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -62,7 +62,7 @@ libgnuastro_la_SOURCES = arithmetic.c arithmetic-and.c 
arithmetic-bitand.c \
   interpolate.c jpeg.c label.c list.c match.c options.c pdf.c              \
   permutation.c pointer.c polygon.c qsort.c dimension.c speclines.c        \
   statistics.c table.c tableintern.c threads.c tiff.c tile.c               \
-  tile-internal.c timing.c txt.c type.c wcs.c
+  tile-internal.c timing.c txt.c type.c units.c wcs.c
 
 
 
@@ -83,7 +83,7 @@ pkginclude_HEADERS = gnuastro/config.h 
$(headersdir)/arithmetic.h          \
   $(headersdir)/speclines.h $(headersdir)/statistics.h                     \
   $(headersdir)/table.h $(headersdir)/threads.h $(headersdir)/tiff.h       \
   $(headersdir)/tile.h $(headersdir)/txt.h $(headersdir)/type.h            \
-  $(headersdir)/wcs.h
+  $(headersdir)/units.h $(headersdir)/wcs.h
 
 
 
diff --git a/lib/arithmetic.c b/lib/arithmetic.c
index bab5707..5367c40 100644
--- a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ -31,6 +31,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/list.h>
 #include <gnuastro/blank.h>
+#include <gnuastro/units.h>
 #include <gnuastro/qsort.h>
 #include <gnuastro/pointer.h>
 #include <gnuastro/threads.h>
@@ -396,6 +397,44 @@ arithmetic_abs(int flags, gal_data_t *in)
             "UNIARY_FUNCTION_ON_ELEMENT", in->type);                    \
     }
 
+#define UNIARY_FUNCTION_ON_ELEMENT_OUTPUT_STRING(OP)                    \
+  switch(in->type)                                                      \
+    {                                                                   \
+    case GAL_TYPE_UINT8:                                                \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, uint8_t,  OP)             \
+        break;                                                          \
+    case GAL_TYPE_INT8:                                                 \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, int8_t,   OP)             \
+        break;                                                          \
+    case GAL_TYPE_UINT16:                                               \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, uint16_t, OP)             \
+        break;                                                          \
+    case GAL_TYPE_INT16:                                                \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, int16_t,  OP)             \
+        break;                                                          \
+    case GAL_TYPE_UINT32:                                               \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, uint32_t, OP)             \
+        break;                                                          \
+    case GAL_TYPE_INT32:                                                \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, int32_t,  OP)             \
+        break;                                                          \
+    case GAL_TYPE_UINT64:                                               \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, uint64_t, OP)             \
+        break;                                                          \
+    case GAL_TYPE_INT64:                                                \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, int64_t,  OP)             \
+        break;                                                          \
+    case GAL_TYPE_FLOAT32:                                              \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, float,    OP)             \
+      break;                                                            \
+    case GAL_TYPE_FLOAT64:                                              \
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT(char *, double,   OP)             \
+      break;                                                            \
+    default:                                                            \
+      error(EXIT_FAILURE, 0, "%s: type code %d not recognized",         \
+            "UNIARY_FUNCTION_ON_ELEMENT_OUTPUT_STRING", in->type);      \
+    }
+
 #define UNIARY_FUNCTION_ON_ELEMENT(OP)                                  \
   switch(in->type)                                                      \
     {                                                                   \
@@ -434,6 +473,13 @@ arithmetic_abs(int flags, gal_data_t *in)
             "UNIARY_FUNCTION_ON_ELEMENT", in->type);                    \
     }
 
+
+#define UNIFUNC_RUN_FUNCTION_ON_ELEMENT_STRING(OT, OP){                 \
+    OT *oa=o->array;                                                    \
+    char **ia=in->array, **iaf=ia + in->size;                           \
+    do *oa++ = OP(*ia++); while(ia<iaf);                                \
+}
+
 static gal_data_t *
 arithmetic_unary_function(int operator, int flags, gal_data_t *in)
 {
@@ -446,7 +492,11 @@ arithmetic_unary_function(int operator, int flags, 
gal_data_t *in)
      point). So even if the user requested inplace opereation, if its not a
      floating point type, its not useful.*/
   if( (flags & GAL_ARITHMETIC_INPLACE)
-      && (in->type==GAL_TYPE_FLOAT32 || in->type==GAL_TYPE_FLOAT64) )
+      && (in->type==GAL_TYPE_FLOAT32 || in->type==GAL_TYPE_FLOAT64)
+      && (operator != GAL_ARITHMETIC_CONVERT_DECIMAL_RA
+      &&  operator != GAL_ARITHMETIC_CONVERT_DECIMAL_DEC
+      &&  operator != GAL_ARITHMETIC_CONVERT_RA_DECIMAL
+      &&  operator != GAL_ARITHMETIC_CONVERT_DEC_DECIMAL ) )
     inplace=1;
 
   if(inplace)
@@ -459,6 +509,16 @@ arithmetic_unary_function(int operator, int flags, 
gal_data_t *in)
       otype = ( in->type==GAL_TYPE_FLOAT64
                 ? GAL_TYPE_FLOAT64
                 : GAL_TYPE_FLOAT32 );
+
+      /* Check for operators which have fixed output types */
+      if ( operator == GAL_ARITHMETIC_CONVERT_RA_DECIMAL ||
+           operator == GAL_ARITHMETIC_CONVERT_DEC_DECIMAL )
+        otype = GAL_TYPE_FLOAT64;
+
+      if (operator == GAL_ARITHMETIC_CONVERT_DECIMAL_RA ||
+          operator == GAL_ARITHMETIC_CONVERT_DECIMAL_DEC)
+        otype = GAL_TYPE_STRING;
+
       o = gal_data_alloc(NULL, otype, in->ndim, in->dsize, in->wcs,
                          0, in->minmapsize, in->quietmmap,
                          NULL, NULL, NULL);
@@ -479,6 +539,22 @@ arithmetic_unary_function(int operator, int flags, 
gal_data_t *in)
       UNIARY_FUNCTION_ON_ELEMENT( log10 );
       break;
 
+    case GAL_ARITHMETIC_CONVERT_RA_DECIMAL:
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT_STRING( double, gal_units_ra_to_decimal  
);
+      break;
+
+    case GAL_ARITHMETIC_CONVERT_DEC_DECIMAL:
+      UNIFUNC_RUN_FUNCTION_ON_ELEMENT_STRING( double, gal_units_dec_to_decimal 
 );
+      break;
+
+    case GAL_ARITHMETIC_CONVERT_DECIMAL_RA:
+      UNIARY_FUNCTION_ON_ELEMENT_OUTPUT_STRING( gal_units_decimal_to_ra );
+      break;
+
+    case GAL_ARITHMETIC_CONVERT_DECIMAL_DEC:
+      UNIARY_FUNCTION_ON_ELEMENT_OUTPUT_STRING( gal_units_decimal_to_dec );
+      break;
+
     default:
       error(EXIT_FAILURE, 0, "%s: operator code %d not recognized",
             __func__, operator);
@@ -1738,6 +1814,16 @@ gal_arithmetic_set_operator(char *string, size_t 
*num_operands)
   else if (!strcmp(string, "log10"))
     { op=GAL_ARITHMETIC_OP_LOG10;             *num_operands=1;  }
 
+  /* Units conversion functions */
+  else if (!strcmp(string, "ra-to-decimal"))
+    { op=GAL_ARITHMETIC_CONVERT_RA_DECIMAL;   *num_operands=1;  }
+  else if (!strcmp(string, "dec-to-decimal"))
+    { op=GAL_ARITHMETIC_CONVERT_DEC_DECIMAL;  *num_operands=1;  }
+  else if (!strcmp(string, "decimal-to-ra"))
+    { op=GAL_ARITHMETIC_CONVERT_DECIMAL_RA;   *num_operands=1;  }
+  else if (!strcmp(string, "decimal-to-dec"))
+    { op = GAL_ARITHMETIC_CONVERT_DECIMAL_DEC;*num_operands=1;  }
+
   /* Statistical/higher-level operators. */
   else if (!strcmp(string, "minvalue"))
     { op=GAL_ARITHMETIC_OP_MINVAL;            *num_operands=1;  }
@@ -1888,6 +1974,11 @@ gal_arithmetic_operator_string(int operator)
     case GAL_ARITHMETIC_OP_LOG:             return "log";
     case GAL_ARITHMETIC_OP_LOG10:           return "log10";
 
+    case GAL_ARITHMETIC_CONVERT_RA_DECIMAL: return "ra-to-decimal";
+    case GAL_ARITHMETIC_CONVERT_DEC_DECIMAL:return "dec-to-decimal";
+    case GAL_ARITHMETIC_CONVERT_DECIMAL_RA: return "decimal-to-ra";
+    case GAL_ARITHMETIC_CONVERT_DECIMAL_DEC:return "decimal-to-dec";
+
     case GAL_ARITHMETIC_OP_MINVAL:          return "minvalue";
     case GAL_ARITHMETIC_OP_MAXVAL:          return "maxvalue";
     case GAL_ARITHMETIC_OP_NUMBERVAL:       return "numbervalue";
@@ -1986,6 +2077,10 @@ gal_arithmetic(int operator, size_t numthreads, int 
flags, ...)
     case GAL_ARITHMETIC_OP_SQRT:
     case GAL_ARITHMETIC_OP_LOG:
     case GAL_ARITHMETIC_OP_LOG10:
+    case GAL_ARITHMETIC_CONVERT_RA_DECIMAL:
+    case GAL_ARITHMETIC_CONVERT_DEC_DECIMAL:
+    case GAL_ARITHMETIC_CONVERT_DECIMAL_RA:
+    case GAL_ARITHMETIC_CONVERT_DECIMAL_DEC:
       d1 = va_arg(va, gal_data_t *);
       out=arithmetic_unary_function(operator, flags, d1);
       break;
diff --git a/lib/gnuastro/arithmetic.h b/lib/gnuastro/arithmetic.h
index 55fb624..f39fc1e 100644
--- a/lib/gnuastro/arithmetic.h
+++ b/lib/gnuastro/arithmetic.h
@@ -106,6 +106,11 @@ enum gal_arithmetic_operators
   GAL_ARITHMETIC_OP_LOG,          /* log()   */
   GAL_ARITHMETIC_OP_LOG10,        /* log10() */
 
+  GAL_ARITHMETIC_CONVERT_RA_DECIMAL,    /* right ascension to decimal      */
+  GAL_ARITHMETIC_CONVERT_DEC_DECIMAL,   /* declination to decimal          */
+  GAL_ARITHMETIC_CONVERT_DECIMAL_RA,    /* right ascension to decimal      */
+  GAL_ARITHMETIC_CONVERT_DECIMAL_DEC,   /* declination to decimal          */
+
   GAL_ARITHMETIC_OP_MINVAL,       /* Minimum value of array.               */
   GAL_ARITHMETIC_OP_MAXVAL,       /* Maximum value of array.               */
   GAL_ARITHMETIC_OP_NUMBERVAL,    /* Number of (non-blank) elements.       */
diff --git a/lib/gnuastro/units.h b/lib/gnuastro/units.h
new file mode 100644
index 0000000..952e141
--- /dev/null
+++ b/lib/gnuastro/units.h
@@ -0,0 +1,81 @@
+/*********************************************************************
+Units -- Convert data from one unit to other.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Kartik Ohri <address@hidden>
+Contributing author(s):
+     Mohammad Akhlaghi <address@hidden>
+Copyright (C) 2020, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#ifndef __GAL_UNITS_H__
+#define __GAL_UNITS_H__
+
+/* When we are within Gnuastro's building process, `IN_GNUASTRO_BUILD' is
+   defined. In the build process, installation information (in particular
+   `GAL_CONFIG_SIZEOF_SIZE_T' that we need below) is kept in
+   `config.h'. When building a user's programs, this information is kept in
+   `gnuastro/config.h'. Note that all `.c' files in Gnuastro's source must
+   start with the inclusion of `config.h' and that `gnuastro/config.h' is
+   only created at installation time (not present during the building of
+   Gnuastro). */
+#ifndef IN_GNUASTRO_BUILD
+#include <gnuastro/config.h>
+#endif
+
+
+/* C++ Preparations */
+#undef __BEGIN_C_DECLS
+#undef __END_C_DECLS
+#ifdef __cplusplus
+# define __BEGIN_C_DECLS extern "C" {
+# define __END_C_DECLS }
+#else
+# define __BEGIN_C_DECLS                /* empty */
+# define __END_C_DECLS                  /* empty */
+#endif
+/* End of C++ preparations */
+
+
+
+/* Actual header contants (the above were for the Pre-processor). */
+__BEGIN_C_DECLS  /* From C++ preparations */
+
+
+
+
+
+/*************************************************************
+ **************     Convert units to decimal   ***************
+ *************************************************************/
+double
+gal_units_ra_to_decimal (char *convert);
+
+double
+gal_units_dec_to_decimal (char *convert);
+
+/*************************************************************
+ **************     Convert decimal to units   ***************
+ *************************************************************/
+char *
+gal_units_decimal_to_ra (double decimal);
+
+char *
+gal_units_decimal_to_dec (double decimal);
+
+__END_C_DECLS    /* From C++ preparations */
+
+#endif           /* __GAL_UNITS_H__ */
\ No newline at end of file
diff --git a/lib/units.c b/lib/units.c
new file mode 100644
index 0000000..e23fc35
--- /dev/null
+++ b/lib/units.c
@@ -0,0 +1,340 @@
+/*********************************************************************
+Units -- Convert data from one unit to other.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Kartik Ohri <address@hidden>
+Contributing author(s):
+     Mohammad Akhlaghi <address@hidden>
+Copyright (C) 2020, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#include <config.h>
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <error.h>
+
+
+
+
+
+/**********************************************************************/
+/****************      Functions to parse strings     *****************/
+/**********************************************************************/
+
+
+/* Parse the input string consisting of numbers separated by given
+ * delimiter into an array. */
+int
+gal_units_extract_decimal (char *convert, const char *delimiter,
+                           double *args, size_t n)
+{
+  char *copy, *token, *end;
+  size_t i = 0;
+  /* Create a copy of the string to be parsed */
+  copy = strdup (convert);
+
+  do
+    {
+      /* Check if the required number of arguments are passed */
+      if (i == n + 1)
+        {
+          free (copy);
+          error (0, 0, "'%s' exceeds maximum number of "
+                       "arguments\n", convert);
+          return 0;
+        }
+
+
+      /* Extract the substring till the next delimiter */
+      token = strtok (i == 0 ? copy : NULL, delimiter);
+
+      if (token)
+        {
+          /* Parse extracted string as a number */
+          args[i++] = strtod (token, &end);
+          /* Check if strtod fails to parse any character in substring */
+          if (*end && *end != delimiter)
+            {
+              free (copy);
+              error (0, 0, "Unable to parse element %lu in "
+                           "'%s'\n", i, convert);
+              return 0;
+            }
+        }
+
+    }
+  while (token && *token);
+
+  free (copy);
+  /* Check if the number of elements parsed is unequal to numbers of
+   * elements requested */
+  if (i != n)
+    {
+      error (0, 0, "`%s' must contain %lu numbers, but has "
+                   "%lu numbers\n", convert, n, i);
+      return 0;
+    }
+
+  return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**********************************************************************/
+/****************      Convert string to decimal      *****************/
+/**********************************************************************/
+
+
+/* Parse the right ascension input as a string in form of hh:mm:ss to a
+ * single decimal value calculated by (hh + mm / 60 + ss / 3600 ) * 15. */
+double
+gal_units_ra_to_decimal (char *convert)
+{
+  double val[3];
+  double decimal = 0.0;
+
+  /* Check whether the string is successfully parsed */
+  if (gal_units_extract_decimal (convert, ":", val, 3))
+    {
+      /* Check whether value of hours is in within limits */
+      if (val[0] < 0.0 || val[0] > 24.0)
+        {
+          error (0, 0, "Error: Value of hours should be "
+                       "between be 0 and 24. %s\n", convert);
+          return NAN;
+        }
+      /* Add hours to the decimal value */
+      decimal += val[0];
+
+      /* Check whether value of minutes is in within limits */
+      if (val[1] < 0.0 || val[1] > 60.0)
+        {
+          error (0, 0, "Error: Value of minutes should be "
+                       "between be 0 and 60. %s\n", convert);
+          return NAN;
+        }
+      /* Convert minutes to hours and add to the decimal value */
+      decimal += val[1] / 60;
+
+      /* Check whether value of seconds is in within limits */
+      if (val[2] < 0.0 || val[2] > 60.0)
+        {
+          error (0, 0, "Error: Value of seconds should be "
+                       "between be 0 and 60. %s\n", convert);
+          return NAN;
+        }
+      /* Convert seconds to hours and add to the decimal value */
+      decimal += val[2] / 3600;
+
+      /* Convert value to decimal */
+      decimal *= 15.0;
+
+      return decimal;
+    }
+  else
+    return NAN;
+}
+
+/* Parse the declination input as a string in form of dd:mm:ss to a decimal
+ * calculated by (dd + mm / 60 + ss / 3600 ). */
+double
+gal_units_dec_to_decimal (char *convert)
+{
+  double val[3];
+  double decimal = 0.0;
+  int sign = 1;
+
+  if (gal_units_extract_decimal (convert, ":", val, 3))
+    {
+      /* Check whether value of decimal is in within limits */
+      if (val[0] < -90.0 || val[0] > 90.0)
+        {
+          error (0, 0, "Error: Value of decimal should be "
+                       "between be -90 and 90. %s\n", convert);
+          return NAN;
+        }
+
+      /* If declination is negative, the first value in the array will be
+       * negative and all other values will be positive. In that case, we
+       * set sign equal to -1. Therefore, we multiply the first value by
+       * sign to make it positive. The final answer is again multiplied by
+       * sign to make its sign same as original. */
+      if (val[0] < 0.0)
+        sign = -1;
+
+      /* Add decimal to the decimal value after making it positive */
+      decimal += val[0] * sign;
+
+      /* Check whether value of arc-minutes is in within limits */
+      if (val[1] < 0.0 || val[1] > 60.0)
+        {
+          error (0, 0, "Error: Value of arc-minutes should be "
+                       "between be 0 and 60. %s\n", convert);
+          return NAN;
+        }
+      /* Convert arc-minutes to decimal and add to the decimal value */
+      decimal += val[1] / 60;
+
+      /* Check whether value of arc-seconds is in within limits */
+      if (val[2] < 0.0 || val[2] > 60.0)
+        {
+          error (0, 0, "Error: Value of arc-seconds should be "
+                       "between be 0 and 60. %s\n", convert);
+          return NAN;
+        }
+      /* Convert arc-seconds to decimal and add to the decimal value */
+      decimal += val[2] / 3600;
+
+      /* Make the sign of the decimal value same as input */
+      decimal *= sign;
+
+      return decimal;
+    }
+  else
+    return NAN;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**********************************************************************/
+/****************      Convert decimal to string      *****************/
+/**********************************************************************/
+
+
+/* Parse the right ascension input as a decimal to a string in form of
+ * hh:mm:ss.ss . */
+char *
+gal_units_decimal_to_ra (double decimal)
+{
+  int hours = 0, minutes = 0;
+  float seconds = 0.0; /* For sub-second accuracy */
+  /* Allocate string of length 15 which is large enough for string of
+   * format hh:mm:ss.ss and sign */
+  char *ra = ( char * ) malloc (sizeof (char) * 15);
+
+  /* Check if decimal value is within bounds otherwise return error */
+  if (decimal < 0 || decimal > 360)
+    {
+      error (0, 0, "Error: Value of decimal should be "
+                   "between be 0 and 360. %.10f\n", decimal);
+      return 0;
+    }
+
+  /* Divide decimal value by 15 */
+  decimal /= 15.0;
+
+  /* Extract integer part of decimal value to obtain hours */
+  hours = ( int ) (decimal);
+
+  /* Subtract hours from decimal and multiply remaining value by 60 to
+   * obtain minutes. */
+  minutes = ( int ) ((decimal - hours) * 60);
+
+  /* Subtract hours and minutes from decimal and multiply remaining value
+   * by 3600 to obtain seconds. */
+  seconds = (decimal - hours - minutes / 60.0) * 3600;
+
+  /* Format the extracted hours, minutes and seconds as a string with
+   * leading zeros if required, in hh:mm:ss format */
+  snprintf (ra,
+            sizeof (char) * 15, "%02d:%02d:%05.2f", hours, minutes, seconds);
+
+  return ra;
+}
+
+/* Parse the declination input as a decimal to a string in form of dd:mm:ss*/
+char *
+gal_units_decimal_to_dec (double decimal)
+{
+  int degrees = 0, arc_minutes = 0;
+  float arc_seconds = 0.0;
+  /* Allocate string of length 15 which is large enough for string of
+   * format hh:mm:ss.ss and sign */
+  char *dec = ( char * ) malloc (sizeof (char) * 15);
+  int sign = 1;
+
+  /* Check if decimal value is within bounds otherwise return error */
+  if (decimal < -90 || decimal > 90)
+    {
+      error (0, 0, "Error: Value of decimal should be "
+                   "between be -90 and 90. %.10f\n", decimal);
+      return 0;
+    }
+
+  /* If declination is negative, we set sign equal to -1. We multiply the
+   * decimal by to make sure it is positive. We then extract degrees,
+   * arc-minutes and arc-seconds from the decimal. Finally, we add a minus
+   * sign in beginning of string if input was negative. */
+  if (decimal < 0)
+    sign = -1;
+
+  /* Multiply decimal by sign to make its positive. */
+  decimal *= sign;
+
+  /* Extract integer part of decimal value to obtain degrees. */
+  degrees = ( int ) (decimal);
+
+  /* Subtract degrees from decimal and multiply remaining value by 60 to
+   * obtain arc-minutes. */
+  arc_minutes = ( int ) ((decimal - degrees) * 60);
+
+  /* Subtract degrees and arc-minutes from decimal and multiply remaining
+   * value by 3600 to obtain arc-seconds. */
+  arc_seconds = (decimal - degrees - arc_minutes / 60.0) * 3600;
+
+  /* Format the extracted degrees, arc-minutes and arc-seconds as a string
+   * with leading zeros if required, in hh:mm:ss format with correct sign */
+  if (sign < 0)
+    snprintf (dec, sizeof (char)
+                   * 15, "-%02d:%02d:%05.2f", degrees, arc_minutes, 
arc_seconds);
+  else
+    snprintf (dec, sizeof (char)
+                   * 15, "%02d:%02d:%05.2f", degrees, arc_minutes, 
arc_seconds);
+
+  return dec;
+}
\ No newline at end of file



reply via email to

[Prev in Thread] Current Thread [Next in Thread]