/* * GVDR library for reading GVDR data files * Copyright (C) 1994 Michael J. Maurer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Michael Maurer * Durand Bldg - Room 232 * Stanford, CA 94305-4055 * (415) 723-1024 */ static char rcsid[]="$Id: gpack.c,v 1.1 1994/05/11 00:13:02 maurer Exp $"; /****************************************************************************** gpack.c Function: Pack and unpack quantities into 1 or 2 bytes. This file is part of the STARLab Magellan Altimeter Data Processing Software. Michael Maurer, February 1994. ******************************************************************************/ /* $Log: gpack.c,v $ * Revision 1.1 1994/05/11 00:13:02 maurer * Now computes a NaN only once. * * Revision 1.0 1994/03/04 22:13:03 maurer * Initial revision * */ #include #include #include #include "libmisc.h" #include "gpack.h" #define GPACK_C #include "gpack.p" static double s_NaN = 0.0; /****************************************************************************** gpack_uchar gunpack_uchar Functions to pack and unpack doubles into unsigned chars (1-byte values). ******************************************************************************/ static unsigned char gpack_uchar(double d, double lo, double hi) { if (isnan(d)) return UCHAR_RES5; if (dhi) d=hi; return UCHAR_LO + (unsigned char) floor((d-lo)*(UCHAR_HI-UCHAR_LO)/(hi-lo)+0.5); } static double gunpack_uchar(unsigned char u, double lo, double hi) { if (u>UCHAR_HI) { if (s_NaN==0) s_NaN=log(-1.0); return s_NaN; } return lo + (double)(u-UCHAR_LO)*(hi-lo)/(UCHAR_HI-UCHAR_LO); } static double gscaling_uchar(double lo, double hi) { return (hi-lo)/(UCHAR_HI-UCHAR_LO); } /****************************************************************************** gpack_ushort gunpack_ushort Functions to pack and unpack doubles into unsigned shorts (2-byte values). ******************************************************************************/ static unsigned short gpack_ushort(double d, double lo, double hi) { if (isnan(d)) return USHRT_RES5; if (dhi) d=hi; return USHRT_LO + (unsigned short) floor((d-lo)*(USHRT_HI-USHRT_LO)/(hi-lo)+0.5); } static double gunpack_ushort(unsigned short u, double lo, double hi) { if (u>USHRT_HI) { if (s_NaN==0) s_NaN=log(-1.0); return s_NaN; } return lo + (double)(u-USHRT_LO)*(hi-lo)/(USHRT_HI-UCHAR_LO); } static double gscaling_ushort(double lo, double hi) { return (hi-lo)/(USHRT_HI-USHRT_LO); } static double gpack_scale(double d, range_t rg) { switch (rg.sc) { case sc_Linear: break; case sc_Log10: d=log10(d); break; case sc_dBv: d=20*log10(d); break; case sc_dBp: d=10*log10(d); break; } return d; } static double gpack_unscale(double d, range_t rg) { if (isnan(d)) d=rg.lo; /* for now, NaN only comes from log(0) */ switch (rg.sc) { case sc_Linear: break; case sc_Log10: d=pow(10.0,d); break; case sc_dBv: d=pow(10.0,d/20.0); break; case sc_dBp: d=pow(10.0,d/10.0); break; } return d; } /****************************************************************************** gpack gunpack gscaling Interface to above routines using range_t structure. ******************************************************************************/ int gpack(double d, range_t rg) { int i; d=gpack_scale(d,rg); switch (rg.nb) { case 1: i=gpack_uchar(d,rg.lo,rg.hi); break; case 2: i=gpack_ushort(d,rg.lo,rg.hi); break; default: error(-1,0,"[gpack] illegal pack size %d",rg.nb); } return i; } double gunpack(int i, range_t rg) { double d; switch (rg.nb) { case 1: d=gunpack_uchar(i,rg.lo,rg.hi); break; case 2: d=gunpack_ushort(i,rg.lo,rg.hi); break; default: error(-1,0,"[gunpack] illegal pack size %d",rg.nb); } d=gpack_unscale(d,rg); return d; } double gpack_scaling(range_t rg) { double d; switch (rg.nb) { case 1: d=gscaling_uchar(rg.lo,rg.hi); break; case 2: d=gscaling_ushort(rg.lo,rg.hi); break; default: error(-1,0,"[gpack_scaling] illegal pack size %d",rg.nb); } return d; } double gpack_minimum(range_t rg) { int i; switch (rg.nb) { case 1: i=UCHAR_LO; break; case 2: i=USHRT_LO; break; default: error(-1,0,"[gpack_scaling] illegal pack size %d",rg.nb); } return gunpack(i,rg); } double gpack_maximum(range_t rg) { int i; switch (rg.nb) { case 1: i=UCHAR_HI; break; case 2: i=USHRT_HI; break; default: error(-1,0,"[gpack_scaling] illegal pack size %d",rg.nb); } return gunpack(i,rg); }