/* Math conversion API.
   Rick Smereka, Copyright (C) 2002-2004.

   This program 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 2 of the License, or
   (at your option) any later version.

   This program 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 this program; if not, get a copy via the Internet at
   http://gnu.org/copyleft/gpl.html or write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
   MA 02111-1307 USA

   You can contact the author via email at rsmereka@future-lab.com

   The functions in this module perform math conversions. Any
   calculation that that supports floating point numbers will
   use the fixed point math API ('fxp.c').

   Original Linux version. Apr/2002, Rick Smereka

   Ported to 32-bit Windows. May/2002, Rick Smereka

   Ported to DOS and QNX 4.x. Jul/2002, Rick Smereka

   Ported to Debian Linux. Nov/2002, Rick Smereka

   Removed the function 'rnd' as it is now located in
   'misc.c'. Oct/2003

   Changed all logging calls from 'log_file_date' to
   'logman'. Mar/2004, Rick Smereka */

#include "stdhead.h"

struct fxp *conv_fah_2_cel(struct fxp *s1)
{
   /* Convert a temperature from fahrenheit to celisus. The
      fahrenheit temperature is expected in 's1'. Upon success,
      the converted celisus temperature will be loaded into
      a newly created 'fxp' structure. This structure must be
      deallocated by the caller. Function returns 'TRUE' upon
      success, 'FALSE' otherwise. Formula used is:

         (far - 32) / 1.8 */

   struct fxp *f1, *f2, *f3;
   char mname[] = "conv_fah_2_cel";

   if (s1 == FXP_OT_NULL)
      {
      logman("%s:null[s1]", mname);
      return(FXP_OT_NULL);
      }

   if ((f1 = fxp_iconv("32")) == FXP_OT_NULL)
      {
      logman("%s:bad rc from fxp_iconv[f1]", mname);
      return(FXP_OT_NULL);
      }

   if ((f2 = fxp_sub(s1, f1)) == FXP_OT_NULL)
      {
      fxp_free(f1);
      logman("%s:bad rc from fxp_sub[s1,f1]", mname);
      return(FXP_OT_NULL);
      }

   fxp_free(f1);

   if ((f1 = fxp_iconv("1.8")) == FXP_OT_NULL)
      {
      fxp_free(f2);
      logman("%s:bad rc from fxp_iconv[1.8]", mname);
      return(FXP_OT_NULL);
      }
   
   if ((f3 = fxp_div(f2, f1)) == FXP_OT_NULL)
      {
      fxp_free(f1);
      fxp_free(f2);
      logman("%s:bad rc from fxp_div[f2,f1]", mname);
      return(FXP_OT_NULL);
      }
   
   fxp_free(f2);
   fxp_free(f1);
   logman("%s:normal exit[TRUE]", mname);
   return(f3);
}

struct fxp *conv_cel_2_fah(struct fxp *s1)
{
   /* Convert a temperature from celisus to fahrenheit. The
      celisus temperature is expected in 's1'. Upon success,
      the converted fahrenheit temperature will be returned
      in a new 'fxp' structure which must be de-allocated by
      the caller. Formula used is:

         cel * 1.8 + 32 */

   struct fxp *f1, *f2, *f3;
   char mname[] = "conv_cel_2_fah";

   if (s1 == FXP_OT_NULL)
      {
      logman("%s:null[s1]", mname);
      return(FXP_OT_NULL);
      }

   if ((f1 = fxp_iconv("1.8")) == FXP_OT_NULL)
      {
      logman("%s:bd rc from fxp_iconv[f1]", mname);
      return(FXP_OT_NULL);
      }

   if ((f2 = fxp_mul(s1, f1)) == FXP_OT_NULL)
      {
      fxp_free(f1);
      logman("%s:bad rc from fxp_mul[s1,f1]", mname);
      return(FXP_OT_NULL);
      }

   fxp_free(f1);

   if ((f1 = fxp_iconv("32")) == FXP_OT_NULL)
      {
      fxp_free(f2);
      logman("%s:bad rc from fxp_iconv[32]", mname);
      return(FXP_OT_NULL);
      }
   
   if ((f3 = fxp_add(f2, f1)) == FXP_OT_NULL)
      {
      fxp_free(f1);
      fxp_free(f2);
      logman("%s:bad rc from fxp_add[f2,f1]", mname);
      return(FXP_OT_NULL);
      }
   
   fxp_free(f2);
   fxp_free(f1);
   logman("%s:normal exit[TRUE]", mname);
   return(f3);
}
