Merge branch 'testing-uf' into master-uf
[gnucap-felix.git] / apps / bm_sin.cc
blob2fd992313c29ce7b07b2aff3c821e45d05a17fa5
1 /* -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *------------------------------------------------------------------
22 * SPICE compatible SIN
24 //testing=script,complete 2005.10.07
25 #include "e_elemnt.h"
26 #include "u_lang.h"
27 #include "l_denoise.h"
28 #include "bm.h"
29 /*--------------------------------------------------------------------------*/
30 namespace {
31 /*--------------------------------------------------------------------------*/
32 using std::map;
33 using std::string;
34 /*--------------------------------------------------------------------------*/
35 const double _default_offset (0);
36 const double _default_amplitude (1);
37 const double _default_frequency (NOT_INPUT);
38 const double _default_delay (0);
39 const double _default_damping (0);
40 const double _default_samples (4);
41 const bool _default_zero (false);
42 const bool _default_peak (false);
43 /*--------------------------------------------------------------------------*/
44 class EVAL_BM_SIN : public EVAL_BM_ACTION_BASE {
45 private:
46 PARAMETER<double> _offset;
47 PARAMETER<double> _amplitude;
48 PARAMETER<double> _frequency;
49 PARAMETER<double> _delay;
50 PARAMETER<double> _damping;
51 PARAMETER<double> _end;
52 PARAMETER<double> _samples;
53 PARAMETER<bool> _zero;
54 PARAMETER<bool> _peak;
55 void set_param_by_name(string Name, string Value);
57 mutable double _actual_frequency;
58 static std::map<string, PARA_BASE EVAL_BM_SIN::*> _param_dict;
59 explicit EVAL_BM_SIN(const EVAL_BM_SIN& p);
60 public:
61 explicit EVAL_BM_SIN(int c=0);
62 ~EVAL_BM_SIN() {}
63 int param_count()const {return 8 + EVAL_BM_ACTION_BASE::param_count();}
64 string param_name(int i)const;
65 string param_name(int i,int)const{return param_name(i);}
66 string param_value(int)const;
67 bool param_is_printable(int i)const;
68 private: // override vitrual
69 bool operator==(const COMMON_COMPONENT&)const;
70 COMMON_COMPONENT* clone()const {return new EVAL_BM_SIN(*this);}
71 void print_common_obsolete_callback(OMSTREAM&, LANGUAGE*)const;
72 bool use_obsolete_callback_print()const {return false;}
74 void precalc_last(const CARD_LIST*);
75 void tr_eval(ELEMENT*)const;
76 TIME_PAIR tr_review(COMPONENT*)const;
77 std::string name()const {return "sin";}
78 bool ac_too()const {return false;}
79 bool parse_numlist(CS&);
80 bool parse_params_obsolete_callback(CS&);
82 /*--------------------------------------------------------------------------*/
83 /*--------------------------------------------------------------------------*/
84 EVAL_BM_SIN::EVAL_BM_SIN(int c)
85 :EVAL_BM_ACTION_BASE(c),
86 _offset(_default_offset),
87 _amplitude(_default_amplitude),
88 _frequency(_default_frequency),
89 _delay(_default_delay),
90 _damping(_default_damping),
91 _end(NOT_VALID),
92 _samples(_default_samples),
93 _zero(_default_zero),
94 _peak(_default_peak),
95 _actual_frequency(0)
98 /*--------------------------------------------------------------------------*/
99 EVAL_BM_SIN::EVAL_BM_SIN(const EVAL_BM_SIN& p)
100 :EVAL_BM_ACTION_BASE(p),
101 _offset(p._offset),
102 _amplitude(p._amplitude),
103 _frequency(p._frequency),
104 _delay(p._delay),
105 _damping(p._damping),
106 _end(NOT_VALID),
107 _samples(p._samples),
108 _zero(p._zero),
109 _peak(p._peak),
110 _actual_frequency(p._actual_frequency)
113 /*--------------------------------------------------------------------------*/
114 bool EVAL_BM_SIN::operator==(const COMMON_COMPONENT& x)const
116 const EVAL_BM_SIN* p = dynamic_cast<const EVAL_BM_SIN*>(&x);
117 bool rv = p
118 && _offset == p->_offset
119 && _amplitude == p->_amplitude
120 && _frequency == p->_frequency
121 && _delay == p->_delay
122 && _damping == p->_damping
123 && _samples == p->_samples
124 && _zero == p->_zero
125 && _peak == p->_peak
126 && EVAL_BM_ACTION_BASE::operator==(x);
127 return rv;
129 /*--------------------------------------------------------------------------*/
130 void EVAL_BM_SIN::print_common_obsolete_callback(OMSTREAM& o, LANGUAGE* lang)const
132 assert(lang);
133 o << name();
134 print_pair(o, lang, "offset", _offset);
135 print_pair(o, lang, "amplitude", _amplitude);
136 print_pair(o, lang, "frequency", _frequency);
137 print_pair(o, lang, "delay", _delay, _delay.has_hard_value());
138 print_pair(o, lang, "damping", _damping, _damping.has_hard_value());
139 print_pair(o, lang, "samples", _samples, _samples.has_hard_value());
140 print_pair(o, lang, "zero", _zero, _zero.has_hard_value());
141 print_pair(o, lang, "peak", _peak, _peak.has_hard_value());
142 EVAL_BM_ACTION_BASE::print_common_obsolete_callback(o, lang);
144 /*--------------------------------------------------------------------------*/
145 void EVAL_BM_SIN::precalc_last(const CARD_LIST* Scope)
147 assert(Scope);
148 EVAL_BM_ACTION_BASE::precalc_last(Scope);
149 _offset.e_val(_default_offset, Scope);
150 _amplitude.e_val(_default_amplitude, Scope);
151 _frequency.e_val(_default_frequency, Scope);
152 _delay.e_val(_default_delay, Scope);
153 _damping.e_val(_default_damping, Scope);
154 _samples.e_val(_default_samples, Scope);
155 _zero.e_val(_default_zero, Scope);
156 _peak.e_val(_default_peak, Scope);
158 /*--------------------------------------------------------------------------*/
159 void EVAL_BM_SIN::tr_eval(ELEMENT* d)const
161 if (!_frequency.has_hard_value()) {
162 _actual_frequency = d->_sim->_freq;
163 }else{
164 _actual_frequency = _frequency;
167 double reltime = ioffset(d->_sim->_time0);
168 double ev = _offset;
169 if (reltime > _delay) {
170 double x=_amplitude*fixzero(sin(M_TWO_PI*_actual_frequency*(reltime-_delay)),1.);
171 if (_damping != 0.) {
172 x *= exp(-(reltime-_delay)*_damping);
173 }else{
175 ev += x;
176 }else{
178 tr_finish_tdv(d, ev);
180 /*--------------------------------------------------------------------------*/
181 TIME_PAIR EVAL_BM_SIN::tr_review(COMPONENT* d)const
183 double eps = d->_sim->_dtmin * .01;
184 double time = ioffset(d->_sim->_time0);
185 double reltime = time + eps;
186 ELEMENT* e = prechecked_cast<ELEMENT*>(d);
187 assert(e);
189 if (reltime > _delay) {
190 if (_peak && _zero) {
191 d->_time_by.min_event(floor(reltime * 4 * _actual_frequency + 1) / (4 * _actual_frequency));
192 }else if (_peak) {
193 d->_time_by.min_event((floor(reltime*2*_actual_frequency+.5) + .5) / (2*_actual_frequency));
194 }else if (_zero) {
195 d->_time_by.min_event(floor(reltime * 2 * _actual_frequency + 1) / (2 * _actual_frequency));
196 }else{
198 d->_time_by.min_error_estimate(d->_sim->_time0 + 1. / (_samples * _actual_frequency));
199 if (time < _delay+eps) {
200 e->_discont |= disSECOND;
201 d->q_accept();
203 }else{
204 d->_time_by.min_event(_delay);
207 return d->_time_by;
209 /*--------------------------------------------------------------------------*/
210 bool EVAL_BM_SIN::parse_numlist(CS& cmd)
212 unsigned start = cmd.cursor();
213 unsigned here = cmd.cursor();
214 for (PARAMETER<double>* i = &_offset; i < &_end; ++i) {
215 PARAMETER<double> val(NOT_VALID);
216 cmd >> val;
217 if (cmd.stuck(&here)) {
218 break;
219 }else{
220 *i = val;
223 return cmd.gotit(start);
225 /*--------------------------------------------------------------------------*/
226 bool EVAL_BM_SIN::parse_params_obsolete_callback(CS& cmd)
228 return ONE_OF
229 || Get(cmd, "o{ffset}", &_offset)
230 || Get(cmd, "a{mplitude}", &_amplitude)
231 || Get(cmd, "f{requency}", &_frequency)
232 || Get(cmd, "de{lay}", &_delay)
233 || Get(cmd, "da{mping}", &_damping)
234 || Get(cmd, "sa{mples}", &_samples)
235 || Get(cmd, "ze{ro}", &_zero)
236 || Get(cmd, "pe{ak}", &_peak)
237 || EVAL_BM_ACTION_BASE::parse_params_obsolete_callback(cmd)
240 /*--------------------------------------------------------------------------*/
241 bool EVAL_BM_SIN::param_is_printable(int i)const
243 switch (EVAL_BM_SIN::param_count() - 1 - i) { untested();
244 case 0: return (true);
245 case 1: return (true);
246 case 2: return (true);
247 case 3: return _delay.has_hard_value();
248 case 4: return _damping.has_hard_value();
249 case 5: return _samples.has_hard_value();
250 case 6: return _zero.has_hard_value();
251 case 7: return _peak.has_hard_value();
252 default: return EVAL_BM_ACTION_BASE::param_is_printable(i);
255 /*--------------------------------------------------------------------------*/
256 string EVAL_BM_SIN::param_name(int i)const
258 switch (EVAL_BM_SIN::param_count() - 1 - i) { untested();
259 case 0: return "offset";
260 case 1: return "amplitude";
261 case 2: return "frequency";
262 case 3: return "delay";
263 case 4: return "damping";
264 case 5: return "samples";
265 case 6: return "zero";
266 case 7: return "peak";
267 default: return EVAL_BM_ACTION_BASE::param_name(i);
270 /*--------------------------------------------------------------------------*/
271 string EVAL_BM_SIN::param_value(int i)const
273 switch (EVAL_BM_SIN::param_count() - 1 - i) { untested();
274 case 0: return _offset.string();
275 case 1: return _amplitude.string();
276 case 2: return _frequency.string();
277 case 3: return _delay.string();
278 case 4: return _damping.string();
279 case 5: return _samples.string();
280 case 6: return _zero.string();
281 case 7: return _peak.string();
282 default: return EVAL_BM_ACTION_BASE::param_value(i);
285 /*--------------------------------------------------------------------------*/
286 map<string, PARA_BASE EVAL_BM_SIN::*> EVAL_BM_SIN::_param_dict =
287 boost::assign::map_list_of
288 ("offset", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_offset)
289 ("o", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_offset)
290 ("amplitude",(PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_amplitude)
291 ("a", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_amplitude)
292 ("frequency",(PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_frequency)
293 ("f", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_frequency)
294 ("delay", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_delay)
295 ("de", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_delay)
296 ("damping", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_damping)
297 ("da", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_damping)
298 ("samples", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_samples)
299 ("sa", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_samples)
300 ("zero", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_zero)
301 ("ze", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_zero)
302 ("peak", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_peak)
303 ("pe", (PARA_BASE EVAL_BM_SIN::*) &EVAL_BM_SIN::_peak);
304 /*--------------------------------------------------------------------------*/
305 void EVAL_BM_SIN::set_param_by_name(std::string Name, std::string Value)
307 PARA_BASE EVAL_BM_SIN::* x = (_param_dict[Name]);
308 if (x) {
309 PARA_BASE* p = &(this->*x);
310 *p = Value;
311 }else{ untested();
312 EVAL_BM_ACTION_BASE::set_param_by_name(Name, Value);
315 /*--------------------------------------------------------------------------*/
316 /*--------------------------------------------------------------------------*/
317 EVAL_BM_SIN p1(CC_STATIC);
318 DISPATCHER<COMMON_COMPONENT>::INSTALL d1(&bm_dispatcher, "sin|sine", &p1);
320 /*--------------------------------------------------------------------------*/
321 /*--------------------------------------------------------------------------*/
322 // vim:ts=8:sw=2:noet: