bump to -rc12
[gnucap-felix.git] / apps / measure_min.cc
blobdc846730673b56becd360bc3d1ca7af79905af65
1 /* -*- C++ -*-
2 * Copyright (C) 2008 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 *------------------------------------------------------------------
23 #include "u_parameter.h"
24 #include "m_wave.h"
25 #include "u_function.h"
26 /*--------------------------------------------------------------------------*/
27 namespace {
28 /*--------------------------------------------------------------------------*/
29 class MIN : public WAVE_FUNCTION {
30 PARAMETER<double> before;
31 PARAMETER<double> after;
32 bool last;
33 bool arg;
34 bool derivative;
36 public:
37 MIN():
38 WAVE_FUNCTION(),
39 before(BIGBIG),
40 after(-BIGBIG),
41 last(false),
42 arg(false),
43 derivative(false)
45 virtual FUNCTION_BASE* clone()const { return new MIN(*this);}
46 string label()const{return "min";}
47 void expand(CS& Cmd, const CARD_LIST* Scope)
49 before = BIGBIG;
50 after = -BIGBIG;
51 last = false;
52 arg = false;
53 derivative = false;
54 unsigned here = Cmd.cursor();
55 Cmd >> probe_name;
56 _w = find_wave(probe_name);
58 if (!_w) {
59 Cmd.reset(here);
60 }else{
63 here = Cmd.cursor();
64 do {
65 ONE_OF
66 || Get(Cmd, "probe", &probe_name)
67 || Get(Cmd, "before", &before)
68 || Get(Cmd, "after", &after)
69 || Get(Cmd, "end", &before)
70 || Get(Cmd, "begin", &after)
71 || Set(Cmd, "deriv{ative}", &derivative, true)
72 || Set(Cmd, "arg", &arg, true)
73 || Set(Cmd, "last", &last, true)
74 || Set(Cmd, "first", &last, false)
76 }while (Cmd.more() && !Cmd.stuck(&here));
78 if (!_w) {
79 _w = find_wave(probe_name);
80 }else{
82 before.e_val(BIGBIG, Scope);
83 after.e_val(-BIGBIG, Scope);
86 double wave_eval()const
88 trace1("MIN::wave_eval", probe_name);
89 if (_w) {
91 double time = (last) ? -BIGBIG : BIGBIG;
92 double m = BIGBIG;
93 WAVE::const_iterator begin = lower_bound(_w->begin(), _w->end(), DPAIR(after, -BIGBIG));
94 WAVE::const_iterator end = upper_bound(_w->begin(), _w->end(), DPAIR(before, BIGBIG));
95 if (begin == end) return(NAN);
97 double prev = 0;
98 double t1 = begin->first;
100 for (WAVE::const_iterator i = begin; i < end; ++i) {
101 double val;
102 if(derivative){ // very simple difference quotient.
103 double dt = i->first - t1;
104 t1 = i->first;
105 if(!dt) {
106 prev = i->second;
107 continue;
109 val = (i->second - prev)/(dt);
110 prev = i->second;
111 }else{
112 val = i->second;
115 double at = i->first;
116 trace3("MIN::wave_eval", probe_name, at, val);
117 if (val < m || (last && (val == m))) {
118 time = at;
119 m = val;
120 }else{
123 return ((arg) ? (time) : (m));
124 }else{
125 throw Exception_No_Match(probe_name);
128 } p2;
129 DISPATCHER<FUNCTION_BASE>::INSTALL d2(&measure_dispatcher, "min", &p2);
130 /*--------------------------------------------------------------------------*/
132 /*--------------------------------------------------------------------------*/
133 /*--------------------------------------------------------------------------*/
134 // vim:ts=8:sw=2:noet: