Minor corrections.
[mappings.git] / mappings.cc
1
2 ///////////////////////////////////////////////////////////////////////////
3 // This program is free software: you can redistribute it and/or modify  //
4 // it under the terms of the version 3 of the GNU General Public License //
5 // as published by the Free Software Foundation.                         //
6 //                                                                       //
7 // This program is distributed in the hope that it will be useful, but   //
8 // WITHOUT ANY WARRANTY; without even the implied warranty of            //
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
10 // General Public License for more details.                              //
11 //                                                                       //
12 // You should have received a copy of the GNU General Public License     //
13 // along with this program. If not, see <http://www.gnu.org/licenses/>.  //
14 //                                                                       //
15 // Written and (C) by Francois Fleuret                                   //
16 // Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
17 ///////////////////////////////////////////////////////////////////////////
18
19 #include <math.h>
20 #include "mappings.h"
21
22 #ifdef DEBUG
23 int nb_refs = 0;
24 #endif
25
26 // I looked a bit at string.h of the g++ library to do this ref
27 // counting things in the grab() and release(). This strategy allows
28 // to avoid useless copies.
29
30 // Each time you build an object which has a reference to a Map, you
31 // have to grab() the Map, and each time you destroy an object with a
32 // reference to a Map, you have to release() the Map. You should not
33 // have grab() or release() out of constructors / destructors and
34 // assignement operator.
35
36 // With such a policy, you should not need to worry about references
37 // anywhere else
38
39 class Map {
40   int ref;
41 public:
42   // If DEBUG is defined, we keep a count of the total number of
43   // constructed / deleted Maps. "NO REF!" is printed each time this
44   // counter goes to 0.
45
46   Map() { ref = 0;
47 #ifdef DEBUG
48  nb_refs++;
49 #endif
50 }
51   virtual ~Map() {
52 #ifdef DEBUG
53     nb_refs--; if(nb_refs == 0) cout << "NO REF!" << endl;
54 #endif
55   }
56   virtual float eval(float x) = 0;
57   virtual Map *derivative() = 0;
58   virtual Map *compose(Map *g) = 0;
59   void release() { if(--ref == 0) delete this; }
60   Map *grab() { ref++; return this; }
61   virtual void print(ostream &o) = 0;
62 };
63
64 class Cst : public Map {
65   float value;
66 public:
67   Cst(float v) : value(v) { }
68   virtual float eval(float x) { return value; }
69   virtual Map *derivative() { return new Cst(0.0); }
70   virtual Map *compose(Map *g) { return this; }
71   virtual void print(ostream &o) { o << value; }
72 };
73
74 class Var : public Map {
75 public:
76   Var() {}
77   virtual float eval(float x) { return x; }
78   virtual Map *derivative() { return new Cst(1.0); }
79   virtual Map *compose(Map *g) { return g; }
80   virtual void print(ostream &o) { o << "X"; }
81 };
82
83 class Sum : public Map {
84   Map *f1, *f2;
85 public:
86   Sum(Map *g1, Map *g2) : f1(g1->grab()), f2(g2->grab()) { }
87   ~Sum() { f1->release(); f2->release(); }
88   virtual float eval(float x) { return f1->eval(x) + f2->eval(x); }
89   virtual Map *derivative() { return new Sum(f1->derivative(), f2->derivative()); }
90   virtual Map *compose(Map *g) { return new Sum(f1->compose(g), f2->compose(g)); }
91   virtual void print(ostream &o) { o << "( "; f1->print(o); o<< " ) + ( " ; f2->print(o); o << " )"; }
92 };
93
94 class Prd : public Map {
95   Map *f1, *f2;
96 public:
97   Prd(Map *g1, Map *g2) : f1(g1->grab()), f2(g2->grab()) { }
98   ~Prd() { f1->release(); f2->release(); }
99   virtual float eval(float x) { return f1->eval(x) * f2->eval(x); }
100   virtual Map *derivative() { return new Sum(new Prd(f1->derivative(), f2), new Prd(f1, f2->derivative())); }
101   virtual Map *compose(Map *g) { return new Prd(f1->compose(g), f2->compose(g)); }
102   virtual void print(ostream &o) { o << "( "; f1->print(o); o<< " ) * ( " ; f2->print(o); o << " )"; }
103 };
104
105 class Sin : public Map {
106   Map *f;
107 public:
108   Sin(Map *g) : f(g->grab()) { }
109   ~Sin() { f->release(); }
110   virtual float eval(float x) { return sin(f->eval(x)); }
111   virtual Map *derivative() { return new Prd(f->derivative(), new Sin(new Sum(f, new Cst(M_PI/2)))); }
112   virtual Map *compose(Map *g) { return new Sin(f->compose(g)); }
113   virtual void print(ostream &o) { o << "sin( "; f->print(o); o<< " )"; }
114 };
115
116 class Inv : public Map {
117   Map *f;
118 public:
119   Inv(Map *g) : f(g->grab()) {}
120   ~Inv() { f->release(); }
121   virtual float eval(float x) { return 1.0/f->eval(x); }
122   virtual Map *derivative() { return new Prd(new Prd(new Cst(-1.0), f->derivative()), new Inv(new Prd(f, f))); }
123   virtual Map *compose(Map *g) { return new Inv(f->compose(g)); }
124   virtual void print(ostream &o) { o << "1 / ( "; f->print(o); o<< " )"; }
125 };
126
127 class Exp : public Map {
128   Map *f;
129 public:
130   Exp(Map *g) : f(g->grab()) {}
131   ~Exp() { f->release(); }
132   virtual float eval(float x) { return exp(f->eval(x)); }
133   virtual Map *derivative() { return new Prd(f->derivative(), new Exp(f)); }
134   virtual Map *compose(Map *g) { return new Exp(f->compose(g)); }
135   virtual void print(ostream &o) { o << "exp( "; f->print(o); o<< " )"; }
136 };
137
138 class Log : public Map {
139   Map *f;
140 public:
141   Log(Map *g) : f(g->grab()) {}
142   ~Log() { f->release(); }
143   virtual float eval(float x) { return log(f->eval(x)); }
144   virtual Map *derivative() { return new Prd(f->derivative(), new Prd(f->derivative(), new Inv(f))); }
145   virtual Map *compose(Map *g) { return new Log(f->compose(g)); }
146   virtual void print(ostream &o) { o << "log( "; f->print(o); o<< " )"; }
147 };
148
149 class Pow : public Map {
150   Map *f;
151   int exponent;
152 public:
153   Pow(Map *g, int e) : f(g->grab()), exponent(e) { }
154   ~Pow() { f->release(); }
155   virtual float eval(float x) { return pow(f->eval(x), exponent); }
156   virtual Map *derivative() { return new Prd(new Prd(new Cst(float(exponent)), f->derivative()), new Pow(f, exponent-1)); }
157   virtual Map *compose(Map *g) { return new Pow(f->compose(g), exponent); }
158   virtual void print(ostream &o) { o << "( "; f->print(o); o<< " )^" << exponent; }
159 };
160
161 const Mapping Mapping::X(new Var());
162
163 Mapping::Mapping() : f(0) { }
164 Mapping::Mapping(Map *g) : f(g ? g->grab(): 0) { }
165 Mapping::Mapping(const Mapping &s) : f(s.f ? s.f->grab() : 0) { }
166 Mapping::Mapping(float x) : f((new Cst(x))->grab()) { }
167 Mapping::~Mapping() { if(f) f->release(); }
168
169 // This is the only place where grab() and release() are not in a
170 // constructor / destructor
171 Mapping &Mapping::operator = (const Mapping &m) {
172   if(&m != this) {
173     if(f) f->release();
174     if(m.f) f = m.f->grab(); else f = 0;
175   }
176   return *this;
177 }
178
179 float Mapping::operator () (float x) const { return f->eval(x); }
180 Mapping Mapping::derivative() const { return Mapping(f->derivative()); }
181 Mapping Mapping::compose(const Mapping &m) const { return Mapping(f->compose(m.f)); }
182
183 Mapping Mapping::add(const Mapping &m) const { return Mapping(new Sum(f, m.f)); }
184 Mapping Mapping::sub(const Mapping &m) const { return Mapping(new Sum(f, new Prd(new Cst(-1.0), m.f))); }
185 Mapping Mapping::mul(const Mapping &m) const { return Mapping(new Prd(f, m.f)); }
186 Mapping Mapping::div(const Mapping &m) const { return Mapping(new Prd(f, new Inv(m.f))); }
187 Mapping Mapping::pow(int k) const { return Mapping(new Pow(f, k)); }
188 Mapping Mapping::neg() const { return Mapping(new Prd(new Cst(-1), f)); }
189
190 Mapping Mapping::sin() const { return Mapping(new Sin(f)); }
191 Mapping Mapping::cos() const { return Mapping(new Sin(new Sum(f, new Cst(M_PI/2)))); }
192 Mapping Mapping::log() const { return Mapping(new Log(f)); }
193 Mapping Mapping::exp() const { return Mapping(new Exp(f)); }
194
195 void Mapping::print(ostream &o) const { if(f) f->print(o); else o << "UNDEFINED"; }
196
197 ostream &operator << (ostream &o, const Mapping &m) { m.print(o); return o; }
198
199 Mapping operator + (const Mapping &mr) { return mr; }
200 Mapping operator + (const Mapping &ml, const Mapping &mr) { return ml.add(mr); }
201 Mapping operator - (const Mapping &mr) { return mr.neg(); }
202 Mapping operator - (const Mapping &ml, const Mapping &mr) { return ml.sub(mr); }
203 Mapping operator * (const Mapping &ml, const Mapping &mr) { return ml.mul(mr); }
204 Mapping operator / (const Mapping &ml, const Mapping &mr) { return ml.div(mr); }
205 Mapping operator ^ (const Mapping &ml, int k) { return ml.pow(k); }
206
207 Mapping sin(const Mapping &m) { return m.sin(); }
208 Mapping cos(const Mapping &m) { return m.cos(); }
209 Mapping log(const Mapping &m) { return m.log(); }
210 Mapping exp(const Mapping &m) { return m.exp(); }
211