/* $Id: Float,v 1.1.1.1 2008/11/28 17:57:26 kiesling Exp $ -*-C-*-*/

/*
  This file is part of ctalk.
  Copyright  2005-2008  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

/*
 *    Float class.
 */

Magnitude class Float;

/*
 *    = (double value)
 *      Set the value of the receiver to the argument.
 */

Float instanceMethod = set_value (double d) {
   if (!__ctalk_self_internal () -> instancevars) {
     __ctalkSetObjectValue 
       (__ctalk_self_internal (),
        (ARG(0)->instancevars ? 
 	ARG(0)->instancevars->__o_value :
 	ARG(0)->__o_value));
   } else {
     __ctalkSetObjectValue 
       (__ctalk_self_internal () -> instancevars,
        (ARG(0)->instancevars ? 
 	ARG(0)->instancevars->__o_value :
	ARG(0)->__o_value));
   }
   methodReturnSelf
}

Float instanceMethod + add (double d) {

  char buf[MAXMSG];
  OBJECT *op1, *op2, *result_object;
  double op1_val, op2_val;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  sprintf (buf, "%f", op1_val + op2_val);

  result_object = 
    __ctalkCreateObjectInit ("result", op1 -> __o_classname,
				op1 -> __o_superclassname,
				op1 -> scope, buf);
  return result_object;
}

Float instanceMethod - subtract (double d) {

  char buf[MAXMSG];
  OBJECT *op1, *op2, *result_object;
  double op1_val, op2_val;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  sprintf (buf, "%f", op1_val - op2_val);

  result_object = 
    __ctalkCreateObjectInit ("result", op1 -> __o_classname,
				op1 -> __o_superclassname,
				op1 -> scope, buf);
  return result_object;
}

Float instanceMethod * multiply (double d) {

  char buf[MAXMSG];
  OBJECT *op1, *op2, *result_object;
  double op1_val, op2_val;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  sprintf (buf, "%f", op1_val * op2_val);

  result_object = 
    __ctalkCreateObjectInit ("result", op1 -> __o_classname,
				op1 -> __o_superclassname,
				op1 -> scope, buf);
  return result_object;
}

Float instanceMethod / divide (double d) {

  char buf[MAXMSG];
  OBJECT *op1, *op2, *result_object;
  double op1_val, op2_val;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  sprintf (buf, "%f", op1_val / op2_val);

  result_object = 
    __ctalkCreateObjectInit ("result", op1 -> __o_classname,
				op1 -> __o_superclassname,
				op1 -> scope, buf);
  return result_object;
}

/*
 *   asInteger (void)
 *   Return the integer portion of the receiver.
 */

Float instanceMethod asInteger (void) {

  char buf[MAXMSG];
  OBJECT *rcvr, *result_object;
  int d;
  
  returnObjectClass Integer;

  rcvr = self value;
  sscanf (rcvr -> __o_value, "%d", &d);
  sprintf (buf, "%d", d);

  _warning ("asInteger (class Float): %lf truncated to Integer.\n", self);

  result_object = 
    __ctalkCreateObjectInit ("result", "Integer", "Magnitude",
				rcvr -> scope, buf);
  return result_object;
}

/*
 *    < (double d)
 *    Return TRUE if the receiver is less than the argument, 
 *    FALSE otherwise.
 */

Float instanceMethod < lt (double d) {

  OBJECT *op1, *op2;
  double op1_val, op2_val;

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  if (op1_val < op2_val) {
    methodReturnTrue
  } else {
    methodReturnFalse
  }
  methodReturnNULL
}

/*
 *    > (double d)
 *    Return TRUE if the receiver is greater than the argument, 
 *    FALSE otherwise.
 */

Float instanceMethod > gt (double d) {

  OBJECT *op1, *op2;
  double op1_val, op2_val;

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  if (op1_val > op2_val) {
    methodReturnTrue
  } else {
    methodReturnFalse
  }
  methodReturnNULL
}

/*
 *    <= (double d)
 *    Return TRUE if the receiver is greater than the argument, 
 *    FALSE otherwise.
 */

Float instanceMethod <= le (double d) {

  OBJECT *op1, *op2;
  double op1_val, op2_val;

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  if (op1_val <= op2_val) {
    methodReturnTrue
  } else {
    methodReturnFalse
  }
  methodReturnNULL
}

/*
 *    && (double d)
 *    Return TRUE if both operands evaluate to TRUE, 
 *    FALSE otherwise.
 */

Float instanceMethod && boolAnd (double d) {

  OBJECT *op1, *op2;
  double op1_val, op2_val;

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  if (op1_val && op2_val) {
    methodReturnTrue
  } else {
    methodReturnFalse
  }
  methodReturnNULL
}

/*
 *    || (double d)
 *    Return TRUE if both operands evaluate to TRUE, 
 *    FALSE otherwise.
 */

Float instanceMethod || boolOr (double d) {

  OBJECT *op1, *op2;
  double op1_val, op2_val;

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  if (op1_val || op2_val) {
    methodReturnTrue
  } else {
    methodReturnFalse
  }

  methodReturnNULL
}

/*
 *    >= (double d)
 *    Return TRUE if the receiver is greater than the argument, 
 *    FALSE otherwise.
 */

Float instanceMethod >= ge (double d) {

  OBJECT *op1, *op2;
  double op1_val, op2_val;

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;

  sscanf (op1 -> __o_value, "%lf", &op1_val);
  sscanf (op2 -> __o_value, "%lf", &op2_val);

  if (op1_val >= op2_val) {
    methodReturnTrue
  } else {
    methodReturnFalse
  }
  methodReturnNULL
}

/*
 *    == (double d)
 *    Return True if the receiver and the argument are equal,
 *    false otherwise.
 */

Float instanceMethod == equality (double d) {
  OBJECT *op1, *op2;
#ifdef __CYGWIN__
  float op1_val, op2_val;
#endif

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;
#ifdef __CYGWIN__
  op1_val = atof (op1 -> __o_value);
  op2_val = atof (op2 -> __o_value);
  if (op1_val == op2_val) {
#else
  if (atof (op1 -> __o_value) == atof (op2 -> __o_value)) {
#endif
    methodReturnTrue
  } else {
    methodReturnFalse
  }
  methodReturnNULL
} 

/*
 *    != (double d) 
 *
 *    Return True if the receiver is not equal
 *    to the argument, False otherwise.
 */

Float instanceMethod != inequality (double d) {
  OBJECT *op1, *op2;
#ifdef __CYGWIN__
  float op1_val, op2_val;
#endif

  returnObjectClass Boolean;

  op1 = self value;
  op2 = d value;

#ifdef __CYGWIN__
  op1_val = atof (op1 -> __o_value);
  op2_val = atof (op2 -> __o_value);
  if (op1_val != op2_val) {
#else
  if (atof (op1 -> __o_value) != atof (op2 -> __o_value)) {
#endif
    methodReturnTrue
  } else {
    methodReturnFalse
  }

  methodReturnNULL
} 
