and a fix for the splitter code
[feisty_meow.git] / nucleus / library / mathematics / double_plus.h
1 #ifndef DOUBLE_PLUS_CLASS
2 #define DOUBLE_PLUS_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : double_plus (an extension for double floating point numbers)      *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 1993-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include "math_ops.h"
19
20 #include <basis/contracts.h>
21 #include <basis/enhance_cpp.h>
22 #include <basis/functions.h>
23
24 #include <stdio.h>//temp
25
26 //! An extension to floating point primitives providing approximate equality.
27 /*!
28   Allows a programmer to ignore issues of rounding errors on floating point
29   numbers by specifying that two floating point numbers are equivalent if
30   they are equal within a small number "delta".  This can help to eliminate
31   errors in floating point logic.
32 */
33
34 namespace mathematics {
35
36 class double_plus : public basis::orderable
37 {
38 public:
39   #define DEFAULT_DELTA 0.0001
40     /*!< the delta is the acceptable amount of difference between two floating
41     point numbers that are considered equivalent by this class.  if they
42     differ by more than that, they are considered non-equivalent (and
43     hence must be greater than or less than each other). */
44
45   //! initializes using "init" as the initial value and equality within "delta".
46   double_plus(double init = 0.0, double delta = DEFAULT_DELTA) : c_value(init), c_delta(delta) {}
47
48   //! initializes this from "to_copy".
49   double_plus(const double_plus &to_copy) : c_value(to_copy.c_value), c_delta(to_copy.c_delta) {}
50
51   virtual ~double_plus() {}
52
53   DEFINE_CLASS_NAME("double_plus");
54
55   //! standard assignment operator.
56   double_plus &operator = (const double_plus &cp)
57       { c_value = cp.c_value; c_delta = cp.c_delta; return *this; }
58
59   double value() const { return truncate(); }
60     //!< observes the value held in this.
61   operator double () const { return truncate(); }
62     //!< observes the value held in this.
63
64   double delta() const { return c_delta; }
65     //!< observes the precision for equality comparisons.
66   void delta(double new_delta) { c_delta = new_delta; }
67     //!< modifies the precision for equality comparisons.
68
69   double truncate() const { return math_ops::round_it(c_value / c_delta) * c_delta; }
70     //!< returns a version of the number that is chopped off past the delta after rounding.
71
72   //! returns true if this equals "f2" within the "delta" precision.
73   virtual bool equal_to(const basis::equalizable &f2) const {
74      const double_plus *cast = dynamic_cast<const double_plus *>(&f2);
75      if (!cast) return false;
76      return this->d_eq(*cast);
77   }
78
79   //!< returns true if this is less than "f2".
80   virtual bool less_than(const basis::orderable &f2) const
81   {
82      const double_plus *cast = dynamic_cast<const double_plus *>(&f2);
83      if (!cast) return false;
84      return !this->d_eq(*cast) && (c_value < cast->c_value);
85   }
86
87 private:
88   double c_value;  //!< the contained floating point value.
89   double c_delta;  //!< the offset within which equality is still granted.
90
91   //! returns true if "to_compare" is within the delta of this.
92   bool d_eq(const double_plus &to_compare) const {
93     double diff = basis::absolute_value(c_value - to_compare.value());
94     return diff < basis::absolute_value(c_delta); 
95   }
96 };
97
98 } //namespace.
99
100 #endif
101