/* factor.c

	Copyright (c) Kapteyn Laboratorium Groningen 1990
	All Rights Reserved.

#>            factor.dc2

Function:     factor

Purpose:      Factor returns the conversion factor between two different
              units (i.e. M en KM)

Category:     PHYSICAL COORDINATES

File:         factor.c

Author:       K.G. Begeman

Use:          INTEGER FACTOR( CUNIT1 ,     Input    CHARACTER*(*)
                              CUNIT2 ,     Input    CHARACTER*(*)
                              CFACT  )     Output   DOUBLE PRECISION

              CUNIT1     Type of unit to convert from.
                         The units can be abbreviated, i.e enough
                         characters must be given to find a unique
                         match in a list of known units.
              CUNIT2     Type of unit to convert to.
              CFACT      Factor to convert from CUNIT1 to CUNIT2.
              FACTOR     Returns:
                          0: successful conversion
                         51: unknown units to convert from
                         52: unknown units to convert to
                         53: both units are unknown
                         54: incompatible units
                         55: ambiguous units to convert from
                         56: ambiguous units to convert to


Notes:        The following type of units are implemented:
              DEGREE      ARCSEC      ARCMIN      RADIAN
              CIRCLE      DMSSEC      DMSMIN      DMSDEG
              HMSSEC      HMSMIN      HMSHOUR     
              METER       ANGSTROM    NM          MICRON      
              MM          CM          INCH        FOOT        
              YARD        M           KM          MILE        
              PC          KPC         MPC
              TICK        SECOND      MINUTE      HOUR
              DAY         YEAR        
              HZ          KHZ         MHZ         GHZ         
              M/S         MM/S        CM/S        KM/S        
              K           MK
              JY          MJY         
              TAU

Updates:      Dec 23, 1989: KGB, document created.
              May  9, 1995: VOG, minimal match.
                                 DMSSEC/MIN/DEG,
                                 HMSSEC/MIN/HOUR

#<

F2CVV:

@integer function factor( character, character, double precision )

*/

#include	"stdio.h"		/* <stdio.h> */
#include	"ctype.h"		/* <ctype.h> */
#include	"string.h"		/* <string.h> */
#include	"gipsyc.h"		/* GIPSY symbols and definitions */
#include	"nelc.h"		/* defines nelc_c */
#include        "wmatch.h"              /* match 2 strings (wildcards allowed) */

typedef	struct { char *unit; char *match; fint type; double fact; } f_struct;

static f_struct TABLE[] = {
   { "DEGREE",     "DE*",      1,                        1.0000000000000000000 },
   { "ARCSEC",     "ARCS*",    1,                        0.0002777777777777778 },
   { "ARCMIN",     "ARCM*",    1,                        0.0166666666666666667 },
   { "RADIAN",     "RAD*",     1,                       57.2957795130823208767 },
   { "CIRCLE",     "CI*",      1,                      360.0000000000000000000 },
   { "DMSSEC",     "DMSS*",    1,                        0.0002777777777777778 },
   { "DMSMIN",     "DMSM*",    1,                        0.0166666666666666667 },
   { "DMSDEG",     "DMSD*",    1,                        1.0000000000000000000 },
   { "HMSSEC",     "HMSS*",    1,                   15.0*0.0002777777777777778 },
   { "HMSMIN",     "HMSM*",    1,                   15.0*0.0166666666666666667 },
   { "HMSHOUR",    "HMSH*",    1,                       15.0000000000000000000 },
   { "METER",      "ME*",      2,                        1.0000000000000000000 },
   { "ANGSTROM",   "AN*",      2,                        0.0000000001000000000 },
   { "NM",         "NM",       2,                        0.0000000010000000000 },
   { "MICRON",     "MIC*",     2,                        0.0000010000000000000 },
   { "MM",         "MM",       2,                        0.0010000000000000000 },
   { "CM",         "CM",       2,                        0.0100000000000000000 },
   { "INCH",       "IN*",      2,                        0.0254000000000000000 },
   { "FOOT",       "F*",       2,                        0.3048000000000000000 },
   { "YARD",       "YA*",      2,                        0.9144000000000000000 },
   { "M",          "M",        2,                        1.0000000000000000000 },
   { "KM",         "KM",       2,                     1000.0000000000000000000 },
   { "MILE",       "MIL*",     2,                     1609.3440000000000000000 },
   { "PC",         "PC",       2,        30800000000000000.0000000000000000000 },
   { "KPC",        "KPC",      2,     30800000000000000000.0000000000000000000 },
   { "MPC",        "MPC",      2,  30800000000000000000000.0000000000000000000 },
   { "TICK",       "TI*",      3,                        1.0000500000000000000 },
   { "SECOND",     "SEC*",     3,                        1.0000000000000000000 },
   { "MINUTE",     "MIN*",     3,                       60.0000000000000000000 },
   { "HOUR",       "HO*",      3,                     3600.0000000000000000000 },
   { "DAY",        "DA*",      3,                    86400.0000000000000000000 },
   { "YEAR",       "YE*",      3,                 31557600.0000000000000000000 },
   { "HZ",         "HZ*",      4,                        1.0000000000000000000 },
   { "KHZ",        "KH*",      4,                     1000.0000000000000000000 },
   { "MHZ",        "MH*",      4,                  1000000.0000000000000000000 },
   { "GHZ",        "GH*",      4,               1000000000.0000000000000000000 },
   { "M/S",        "M/S*",     5,                        1.0000000000000000000 },
   { "MM/S",       "MM/S*",    5,                        0.0010000000000000000 },
   { "CM/S",       "CM/S*",    5,                        0.0100000000000000000 },
   { "KM/S",       "KM/S*",    5,                     1000.0000000000000000000 },
   { "K",          "K",        6,                        1.0000000000000000000 },
   { "MK",         "MK*",      6,                        0.0010000000000000000 },
   { "JY",         "J*",       7,                       10e-26                 },
   { "MJY",        "MJ*",      7,                       10e-29                 },
   { "TAU",        "TA*",      9,                        1.0000000000000000000 }
};

#define MAXTABLEN (sizeof(TABLE)/sizeof(f_struct))
#define MAXBUFLEN 80

fint factor_c( fchar cunit1, fchar cunit2, double *cfact )
{
   fint   r = 0;
   fint   n;
   fint   u1;
   fint   u2;
   fint   found1 = 0;
   fint   found2 = 0;
   fint   casesensitive = 0;


   *cfact = 0.0;                                                     /* reset */
   u1 = u2 = -1;
   for (n = 0; n < MAXTABLEN; n++) {
      if (wmatch_c( cunit1, tofchar(TABLE[n].match), tofchar("*"), &casesensitive )) {
         found1++;
         u1 = n;
      }
      if (wmatch_c( cunit2, tofchar(TABLE[n].match), tofchar("*"), &casesensitive )) {
         found2++;
         u2 = n;
      }
   }

   if (!found1 && !found2) return( 53 );
   if (!found1) return( 51 );
   if (!found2) return( 52 );
   if (found1 > 1) return( 55 );
   if (found2 > 1) return( 56 );
   if (TABLE[u1].type == TABLE[u2].type) {
      *cfact = (TABLE[u1].fact / TABLE[u2].fact);
   } else {
      r = 54;
   }
   return( r );
}


/*
#>            units.dc2

Function:     units

Purpose:      Units returns the type of units.

Category:     PHYSICAL COORDINATES

File:         factor.c

Author:       P.R. Roelfsema

Use:          INTEGER UNITS( CUNIT )     Input    CHARACTER*(*)

              UNITS      Returns:
                          0: unknown units.
                          1: angle units (degrees, seconds etc.)
                          2: length units (kilometers, Angstrom etc.)
                          3: time units (seconds, hours days etc.
                          4: frequency units (Hz, MHz etc.)
                          5: speed units (m/s, km/s etc. )
                          6: teperature units (kelvin, millikelvin )
                          7: fluxdensity units (Jy, mJy)
                          9: optical depth (tau)
              CUNIT      Name of unit.

Notes:        The type of units which are implemented are listed in
              factor.dc2.

Updates:      Aug 28, 1991: PRR, document created.

#<

F2CVV:

@integer function units( character )

*/
fint units_c( fchar cunit )
{
   char		unit[ MAXBUFLEN + 1 ] ;		/* internal buffer	*/

   fint		r = 0 ;				/* return result	*/
   fint		n ;				/* counter		*/
   fint		l = nelc_c( cunit ) ;		/* length of input	*/

   n = 0;
   while ((n < MAXBUFLEN) && (n < l )) {	/* set input uppercase	*/
      unit[n] = toupper( cunit.a[n] );
      n++;
   }
   unit[n]  = 0 ;

   for (n = 0; n < MAXTABLEN; n++) {		/* loop to find units	*/
      if ( !strcmp( unit, TABLE[n].unit ) ) {	/* is this it ?		*/
         r = TABLE[n].type ;			/* yes => set result	*/
         break ;				/* exit search loop	*/
      }
   }						/* end search loop	*/

   return( r ) ;
}

#if defined(TESTBED)

#include	"cmain.h"

int cmain( int argc, char *argv[] )
{
   fchar cunit1;
   fchar cunit2;
   char  a1[MAXBUFLEN+1];
   char  a2[MAXBUFLEN+1];

   if (argc > 2) {
      double f;
      fint   r;
      strncpy( a1, argv[1], MAXBUFLEN ); a1[MAXBUFLEN] = 0;
      cunit1.a = a1; cunit1.l = strlen( cunit1.a );
      strncpy( a2, argv[2], MAXBUFLEN ); a2[MAXBUFLEN] = 0;
      cunit2.a = a2; cunit2.l = strlen( cunit2.a );
      r = factor_c( cunit1, cunit2, &f );
      printf( "factor(%2ld), %f\n", r, f );
   }
   return( 0 );
}
#endif

