00001
00026 #ifndef __func_h
00027 #define __func_h
00028
00029 #include <math.h>
00030 #include <string>
00031 #include <iostream>
00032 #include <sstream>
00033 #include <mak/infinity.h>
00034 #include "punnets_base.h"
00035
00036 #define USE_DYNAMIC
00037
00038 namespace punnets_common {
00039
00048
00049 class message_base
00050 {
00051 public:
00052 message_base() { }
00053 virtual ~message_base() { }
00054
00058 virtual const char *getMessageId() const = 0;
00059 };
00060
00068
00069 class func_base
00070 {
00071 protected:
00075 virtual void valueChange() { }
00076
00077 public:
00078 func_base() { }
00079 virtual ~func_base() { }
00080
00082 virtual bool shouldDelete(ntime_t ) { return false; }
00085 virtual bool processMessage(ntime_t, const message_base &) { return false; }
00086
00088 virtual void setLambda(real ) { }
00090 virtual void setZeroPoint(real ) { }
00091
00093 virtual real getMaxGradient( ntime_t t ) const = 0;
00096 virtual ntime_t getNextIncontinuity( ntime_t ) const { return mak::Infinity; };
00097
00099 virtual real getValue( ntime_t t ) const = 0;
00101 virtual real get1stDeriv( ntime_t t ) const = 0;
00103 virtual real get2ndDeriv( ntime_t t ) const = 0;
00104
00106 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const = 0;
00108 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const = 0;
00110 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const = 0;
00111
00113 virtual func_base * clone() = 0;
00115 virtual std::string getDescription() = 0;
00116 };
00117
00124
00125 class func_deriveq_base : public func_base
00126 {
00127 protected:
00128 real lambda;
00129 ntime_t zerop;
00130
00134 virtual void zeropChange() { }
00135
00136 public:
00137 func_deriveq_base() : func_base(), lambda(1.0), zerop(-10000000.0) { }
00138 virtual ~func_deriveq_base() { }
00139
00141 virtual void setLambda(real new_lambda) { assert( new_lambda > 0.0 ); lambda = new_lambda; valueChange(); }
00143 virtual void setZeroPoint(real new_zeropoint) { zerop = new_zeropoint; zeropChange(); }
00144
00146 class message_set_lambda : public message_base
00147 {
00148 real lambda;
00149 public:
00150 message_set_lambda(real newlambda) : message_base() { lambda = newlambda; }
00151 static const char * const messageId;
00152 virtual const char *getMessageId() const { return messageId; }
00153 real getLambda() const { return lambda; }
00154 };
00156 class message_set_zero_point : public message_base
00157 {
00158 real zerop;
00159 public:
00160 message_set_zero_point(real newzerop) : message_base() { zerop = newzerop; }
00161 static const char * const messageId;
00162 virtual const char *getMessageId() const { return messageId; }
00163 real getZeroPoint() const { return zerop; }
00164 };
00165
00167 virtual bool processMessage(ntime_t t, const message_base &m) {
00168 #ifdef USE_DYNAMIC
00169 if( const message_set_lambda *mm = dynamic_cast<const message_set_lambda *>(&m) ) {
00170 setLambda( mm->getLambda() );
00171 return true;
00172 }
00173 #else
00174 if( m.getMessageId() == message_set_lambda::messageId ) {
00175 setLambda( dynamic_cast<const message_set_lambda &>(m).getLambda() );
00176 return true;
00177 }
00178 #endif
00179 #ifdef USE_DYNAMIC
00180 if( const message_set_zero_point *mm = dynamic_cast<const message_set_zero_point *>(&m) ) {
00181 setZeroPoint( mm->getZeroPoint() );
00182 return true;
00183 }
00184 #else
00185 if( m.getMessageId() == message_set_zero_point::messageId ) {
00186 setZeroPoint( dynamic_cast<const message_set_zero_point &>(m).getZeroPoint() );
00187 return true;
00188 }
00189 #endif
00190 return func_base::processMessage(t,m);
00191 }
00192 };
00194
00195
00200
00201 class func_const : public func_base
00202 {
00203 real c;
00204 public:
00206 func_const(real ic) : func_base(), c(ic) { }
00207
00208 virtual real getMaxGradient( ntime_t ) const { return 0; };
00209
00210 virtual real getValue( ntime_t ) const
00211 { return c; }
00212
00213 virtual real get1stDeriv( ntime_t ) const
00214 { return 0; }
00215 virtual real get2ndDeriv( ntime_t ) const
00216 { return 0; }
00217
00218 virtual void getValueDomain( ntime_t , real &upslope, real &ceil, real &downslope, real &floor ) const
00219 { upslope = downslope = 0; ceil = floor = c; }
00220
00221 virtual void get1stDerivDomain( ntime_t , real &upslope, real &ceil, real &downslope, real &floor ) const
00222 { upslope = downslope = 0; ceil = floor = 0; }
00223
00224 virtual void get2ndDerivDomain( ntime_t , real &upslope, real &ceil, real &downslope, real &floor ) const
00225 { upslope = downslope = 0; ceil = floor = 0; }
00226
00227 virtual func_const * clone() { return new func_const(*this); }
00228 virtual std::string getDescription() { std::ostringstream oss; oss << "func_const c=" << c; return oss.str(); }
00229 };
00230
00231
00237
00238 class func_const_int : public func_deriveq_base
00239 {
00240 real c;
00241
00242 real limit;
00243
00245 virtual void valueChange() { limit = c / lambda; }
00246 public:
00248 func_const_int(real ic) : func_deriveq_base(), c(ic) { valueChange(); }
00249
00250 virtual real getMaxGradient( ntime_t ) const { return limit < 0 ? 0 : c; };
00251
00252 virtual real getValue( ntime_t t ) const
00253 { return limit * (1 - exp(- lambda * (t - zerop))); }
00254
00255 virtual real get1stDeriv( ntime_t t ) const
00256 { return limit * lambda * exp(- lambda * (t - zerop)); }
00257 virtual real get2ndDeriv( ntime_t t ) const
00258 { return - limit * lambda * lambda * exp(- lambda * (t - zerop)); }
00259 virtual real get3rdDeriv( ntime_t t ) const
00260 { return limit * lambda * lambda * lambda * exp(- lambda * (t - zerop)); }
00261
00262 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00263 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00264 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00265
00266 virtual func_const_int * clone() { return new func_const_int(*this); }
00267 virtual std::string getDescription() { std::ostringstream oss; oss << "func_const_int c=" << c << ", lambda=" << lambda << ", zerop=" << zerop; return oss.str(); }
00268 };
00270
00271
00276
00277 class func_step : public func_base
00278 {
00279 real r;
00280 ntime_t t0;
00281 public:
00282 func_step(real ir, ntime_t it0) : func_base(), r(ir), t0(it0) { }
00283
00284 virtual real getMaxGradient( ntime_t ) const { return 0; };
00285
00286 virtual real getValue( ntime_t t ) const
00287 { return (t0 < t ? r : 0.0); }
00288
00289 virtual real get1stDeriv( ntime_t ) const
00290 { return 0; }
00291 virtual real get2ndDeriv( ntime_t ) const
00292 { return 0; }
00293
00294 virtual ntime_t getNextIncontinuity( ntime_t from ) const { return from < t0 ? t0 : mak::Infinity; };
00295
00296 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00297 { upslope = downslope = 0; ceil = floor = (t >= t0 ? r : 0); }
00298
00299 virtual void get1stDerivDomain( ntime_t , real &upslope, real &ceil, real &downslope, real &floor ) const
00300 { upslope = downslope = 0; ceil = floor = 0; }
00301
00302 virtual void get2ndDerivDomain( ntime_t , real &upslope, real &ceil, real &downslope, real &floor ) const
00303 { upslope = downslope = 0; ceil = floor = 0; }
00304
00305 virtual func_step * clone() { return new func_step(*this); }
00306 virtual std::string getDescription() { std::ostringstream oss; oss << "func_step r=" << r << ", t0=" << t0; return oss.str(); }
00307 };
00309
00315
00316 class func_delta_int : public func_deriveq_base
00317 {
00318 real r;
00319 ntime_t t0;
00320
00321 virtual void valueChange() { }
00322
00323 public:
00325 func_delta_int(real ir, ntime_t it0) : func_deriveq_base(), r(ir), t0(it0) { valueChange(); }
00326
00327 virtual real getMaxGradient( ntime_t ) const { return r<0 ? - lambda * r : 0 ; };
00328
00329 void setParam(real ir, ntime_t it0) { r = ir; t0 = it0; }
00330
00331 virtual real getValue( ntime_t t ) const
00334 {
00335
00336 return (zerop < t0 && t0 <= t) ? r * exp( - lambda * (t - t0) ) : 0.0; }
00337
00338 virtual real get1stDeriv( ntime_t t ) const
00339 { return (zerop < t0 && t0 <= t) ? - lambda * r * exp( - lambda * (t - t0) ) : 0.0; }
00340 virtual real get2ndDeriv( ntime_t t ) const
00341 { return (zerop < t0 && t0 <= t) ? lambda * lambda * r * exp( - lambda * (t - t0) ) : 0.0; }
00342 virtual real get3rdDeriv( ntime_t t ) const
00343 { return (zerop < t0 && t0 <= t) ? - lambda * lambda * lambda * r * exp( - lambda * (t - t0) ) : 0.0; }
00344
00345 virtual ntime_t getNextIncontinuity( ntime_t from ) const { return from < t0 ? t0 : mak::Infinity; };
00346
00347 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00348 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00349 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00350
00351 virtual std::string getDescription() { std::ostringstream oss; oss << "func_delta_int r=" << r << ", t0=" << t0 << ", lambda=" << lambda << ", zerop=" << zerop; return oss.str(); }
00352
00354 class message_add_pulse : public message_base
00355 {
00356 real pulselev;
00357 public:
00358 message_add_pulse(real ipl) : message_base() { pulselev = ipl; }
00359 static const char * const messageId;
00360 virtual const char *getMessageId() const { return messageId; }
00361 real getPulseLevel() const { return pulselev; }
00362 };
00363
00364 virtual bool processMessage(ntime_t t, const message_base &m) {
00365 #ifdef USE_DYNAMIC
00366 if( const message_add_pulse *mm = dynamic_cast<const message_add_pulse *>(&m) ) {
00367 setParam( getValue(t) + mm->getPulseLevel(), t );
00368 return true;
00369 }
00370 #else
00371 if( m.getMessageId() == message_add_pulse::messageId ) {
00372 setParam( getValue(t) + dynamic_cast<const message_add_pulse &>(m).getPulseLevel(), t );
00373 return true;
00374 }
00375 #endif
00376 return func_deriveq_base::processMessage(t, m);
00377 }
00378
00379 virtual func_delta_int * clone() { return new func_delta_int(*this); }
00380 };
00381
00386
00387 class func_response : public func_deriveq_base
00388 {
00389 real r, rinit;
00390
00391 virtual void valueChange() { }
00392
00393 public:
00394 func_response(real ir) : func_deriveq_base(), r(ir), rinit(ir) { valueChange(); }
00395
00396 virtual real getMaxGradient( ntime_t ) const { return r<0 ? - lambda * r : 0 ; };
00397
00398 virtual real getValue( ntime_t t ) const
00399 {
00400 return r * exp( - lambda * (t - zerop) ) ; }
00401
00402 virtual real get1stDeriv( ntime_t t ) const
00403 { return - lambda * r * exp( - lambda * (t - zerop) ); }
00404 virtual real get2ndDeriv( ntime_t t ) const
00405 { return lambda * lambda * r * exp( - lambda * (t - zerop) ); }
00406 virtual real get3rdDeriv( ntime_t t ) const
00407 { return - lambda * lambda * lambda * r * exp( - lambda * (t - zerop) ); }
00408
00409 virtual ntime_t getNextIncontinuity( ntime_t ) const { return mak::Infinity; };
00410
00411 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00412 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00413 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00414
00415 virtual std::string getDescription() { std::ostringstream oss; oss << "func_response r=" << r << ", lambda=" << lambda << ", zerop=" << zerop; return oss.str(); }
00416
00417 virtual func_response * clone() { return new func_response(*this); }
00418
00419 virtual void setZeroPoint(real new_zeropoint) {
00420 r = rinit + r * exp( - lambda * (new_zeropoint - zerop) );
00421 zerop = new_zeropoint; zeropChange(); }
00422 };
00423
00424
00425
00430
00431 class func_sine : public func_base
00432 {
00433 real r;
00434 real omega;
00435 real theta;
00436
00437 static const real alpha = 1.311;
00438 static const real beta = 0.375867;
00439
00440 void valueChange() { }
00441
00442 public:
00444 func_sine(real ir, real iomega, real itheta) : func_base(), r(ir), omega(iomega), theta(itheta) { valueChange(); }
00445
00446 virtual real getMaxGradient( ntime_t ) const { return omega * r; };
00447
00448 virtual real getValue( ntime_t t ) const
00449 { return r * sin(omega * t + theta); }
00450
00451 virtual real get1stDeriv( ntime_t t ) const
00452 { return omega * r * cos(omega * t + theta); }
00453
00454 virtual real get2ndDeriv( ntime_t t ) const
00455 { return - omega * omega * r * sin(omega * t + theta); }
00456
00457 virtual real get3rdDeriv( ntime_t t ) const
00458 { return - omega * omega * omega * r * cos(omega * t + theta); }
00459
00460 virtual ntime_t getNextIncontinuity( ntime_t ) const { return mak::Infinity; };
00461
00462 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00463 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00464 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00465
00466 virtual func_sine * clone() { return new func_sine(*this); }
00467 virtual std::string getDescription() { std::ostringstream oss; oss << "func_sine r=" << r << ", omega=" << omega << ", theta=" << theta; return oss.str(); }
00468 };
00469
00470
00476
00477 class func_sineshot : public func_base
00478 {
00479 real r;
00480 real omega;
00481 real t0;
00482
00483 real r_div_2;
00484 real omega_2;
00485 real duration;
00486
00487 static const real alpha = 1.311;
00488 static const real beta = 0.375867;
00489
00490 void valueChange() { duration = M_PI / omega; omega_2 = 2 * omega; r_div_2 = r * 0.5; }
00491
00492 public:
00494 func_sineshot(real ir, real iomega, real it0) : func_base(), r(ir), omega(iomega), t0(it0) { valueChange(); }
00495
00496 virtual real getMaxGradient( ntime_t ) const { return fabs(r_div_2) * omega_2; };
00497
00498 virtual bool shouldDelete(ntime_t current) { return (current >= t0 + duration); }
00499
00500 virtual real getValue( ntime_t t ) const
00501 { return (t0 <= t && t <= t0 + duration ? r_div_2 * (1-cos(omega_2 * (t-t0) )) : 0.0); }
00502
00503 virtual real get1stDeriv( ntime_t t ) const
00504 { return (t0 <= t && t <= t0 + duration ? r_div_2 * omega_2 * sin(omega_2 * (t-t0) ) : 0.0); }
00505
00506 virtual real get2ndDeriv( ntime_t t ) const
00507 { return (t0 <= t && t <= t0 + duration ? r_div_2 * omega_2 * omega_2 * cos(omega_2 * (t-t0) ) : 0.0); }
00508
00509 virtual ntime_t getNextIncontinuity( ntime_t from ) const { return from < t0 ? t0 : mak::Infinity; };
00512
00513 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00514 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00515 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00516 virtual func_sineshot * clone() { return new func_sineshot(*this); }
00517 virtual std::string getDescription() { std::ostringstream oss; oss << "func_sineshot r=" << r << ", omega=" << omega << ", t0=" << t0; return oss.str(); }
00518
00520 class message_set_t0 : public message_base
00521 {
00522 public:
00523 message_set_t0() : message_base() { }
00524 static const char * const messageId;
00525 virtual const char *getMessageId() const { return messageId; }
00526 };
00527
00528 virtual bool processMessage(ntime_t t, const message_base &m) {
00529 #ifdef USE_DYNAMIC
00530 if( dynamic_cast<const message_set_t0 *>(&m) != NULL )
00531 #else
00532 if( m.getMessageId() == message_set_t0::messageId )
00533 #endif
00534 {
00535 t0 = t;
00536 return true;
00537 }
00538 return func_base::processMessage(t, m);
00539 }
00540 };
00541
00542
00547
00548 class func_sine_int : public func_deriveq_base
00549 {
00550 real r;
00551 real omega;
00552 real theta;
00553
00554 real r_inv_lsq_osq;
00555 real zerop_value;
00556
00557 void valueChange() { r_inv_lsq_osq = r / (lambda * lambda + omega * omega); }
00558 void zeropChange() { zerop_value = lambda * sin( theta + omega * zerop ) - omega * cos( theta + omega * zerop ); }
00559
00560 public:
00562 func_sine_int(real ir, real iomega, real itheta) : func_deriveq_base(), r(ir), omega(iomega), theta(itheta) { valueChange(); }
00563
00564 virtual real getMaxGradient( ntime_t ) const { return r_inv_lsq_osq * (omega * (lambda + 1) - lambda * lambda * zerop_value); };
00565
00566 virtual real getValue(ntime_t t) const
00567 { return r_inv_lsq_osq * (
00568 lambda * sin( theta + omega * t ) - omega * cos( theta + omega * t )
00569 + exp( lambda * (zerop - t) ) * zerop_value );
00570 }
00571 virtual real get1stDeriv(ntime_t t) const
00572 { return r_inv_lsq_osq * (
00573 omega * (lambda * cos( theta + omega * t ) + omega * sin( theta + omega * t ))
00574 - lambda * exp( lambda * (zerop - t) ) * zerop_value );
00575 }
00576 virtual real get2ndDeriv(ntime_t t) const
00577 { return r_inv_lsq_osq * (
00578 omega * omega * (- lambda * sin( theta + omega * t ) + omega * cos( theta + omega * t ))
00579 + lambda * lambda * exp( lambda * (zerop - t) ) * zerop_value );
00580 }
00581 virtual real get3rdDeriv(ntime_t t) const
00582 { return r_inv_lsq_osq * (
00583 omega * omega * omega * (- lambda * cos( theta + omega * t ) - omega * sin( theta + omega * t ))
00584 - lambda * lambda * lambda * exp( lambda * (zerop - t) ) * zerop_value );
00585 }
00586
00587 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00588 { upslope = fabs(omega); downslope = -upslope; ceil = r; floor = -r;
00589 if( getValue(t) > 0 ) { upslope = get1stDeriv(t); if( upslope < 0 ) upslope *= -1; }
00590 else { downslope = get1stDeriv(t); if( downslope > 0 ) downslope *= -1; } }
00591
00592 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00593 { upslope = omega * omega; downslope = -upslope; ceil = fabs(omega) * r; floor = -ceil;
00594 if( get1stDeriv(t) > 0 ) { upslope = get2ndDeriv(t); if( upslope < 0 ) upslope *= -1; }
00595 else { downslope = get2ndDeriv(t); if( downslope > 0 ) downslope *= -1; } }
00596
00597 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00598 { upslope = fabs( omega * omega * omega); downslope = -upslope; ceil = omega * omega * r; floor = -ceil;
00599 if( get2ndDeriv(t) > 0 ) { upslope = get3rdDeriv(t); if( upslope < 0 ) upslope *= -1; }
00600 else { downslope = get3rdDeriv(t); if( downslope > 0 ) downslope *= -1; } }
00601
00602 virtual func_sine_int * clone() { return new func_sine_int(*this); }
00603 virtual std::string getDescription() { std::ostringstream oss; oss << "func_sine_int r=" << r << ", omega=" << omega << ", theta=" << theta << ", lambda=" << lambda << ", zerop=" << zerop; return oss.str(); }
00604 };
00605
00611
00612 class func_sineshot_int : public func_deriveq_base
00613 {
00614 real r;
00615 real omega;
00616
00617 real r_div_2;
00618 real omega_2;
00619 real duration;
00620
00621 static const real alpha = 1.311;
00622 static const real beta = 0.375867;
00623
00624 void valueChange() { duration = M_PI / omega; omega_2 = 2 * omega; r_div_2 = r * 0.5; }
00625 void zeropChange() { }
00626
00627 public:
00629 func_sineshot_int(real ir, real iomega) : func_deriveq_base(), r(ir), omega(iomega) { valueChange(); }
00630
00631 virtual real getMaxGradient( ntime_t ) const { return fabs(r_div_2) * omega_2; };
00632
00633 virtual real getValue( ntime_t t ) const
00634 { return (zerop <= t && t <= zerop + duration ? r_div_2 * (1-cos(omega_2 * (t-zerop) )) : 0.0); }
00635
00636 virtual real get1stDeriv( ntime_t t ) const
00637 { return (zerop <= t && t <= zerop + duration ? r_div_2 * omega_2 * sin(omega_2 * (t-zerop) ) : 0.0); }
00638
00639 virtual real get2ndDeriv( ntime_t t ) const
00640 { return (zerop <= t && t <= zerop + duration ? r_div_2 * omega_2 * omega_2 * cos(omega_2 * (t-zerop) ) : 0.0); }
00641
00642 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00643 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00644 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const;
00645
00646 virtual func_sineshot_int * clone() { return new func_sineshot_int(*this); }
00647 virtual std::string getDescription() { std::ostringstream oss; oss << "func_sineshot_int r=" << r << ", omega=" << omega; return oss.str(); }
00648 };
00649
00654
00655 class func_exp : public func_base
00656 {
00657 real r;
00658 real psi;
00659 real t0;
00660
00661 public:
00663 func_exp(real ir, real ipsi, real it0) : func_base(), r(ir), psi(ipsi), t0(it0) { if( psi < 0.0 ) throw "func_exp"; }
00664
00665 virtual real getMaxGradient( ntime_t t ) const { return r>0 ? 0 : get1stDeriv(t); }
00666
00667 virtual real getValue( ntime_t t ) const
00668 { return r * exp( -psi * (t - t0) ); }
00669
00670 virtual real get1stDeriv( ntime_t t ) const
00671 { return -psi * r * exp( -psi * (t - t0) ); }
00672
00673 virtual real get2ndDeriv( ntime_t t ) const
00674 { return psi * psi * r * exp( -psi * (t - t0) ); }
00675
00676 virtual real get3rdDeriv( ntime_t t ) const
00677 { return - psi * psi * psi * r * exp( -psi * (t - t0) ); }
00678
00679 virtual ntime_t getNextIncontinuity( ntime_t ) const { return mak::Infinity; };
00680
00681 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00682 { if( r >= 0 ) { upslope = 0; ceil = mak::Infinity; downslope = func_exp::get1stDeriv(t); floor = 0.0; }
00683 else { downslope = 0; floor= -mak::Infinity; upslope = func_exp::get1stDeriv(t); ceil = 0.0; } }
00684
00685 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00686 { if( r <= 0 ) { upslope = 0; ceil = mak::Infinity; downslope = func_exp::get2ndDeriv(t); floor = 0.0; }
00687 else { downslope = 0; floor= -mak::Infinity; upslope = func_exp::get2ndDeriv(t); ceil = 0.0; } }
00688
00689 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00690 { if( r >= 0 ) { upslope = 0; ceil = mak::Infinity; downslope = func_exp::get3rdDeriv(t); floor = 0.0; }
00691 else { downslope = 0; floor= -mak::Infinity; upslope = func_exp::get3rdDeriv(t); ceil = 0.0; } }
00692
00693 virtual func_exp * clone() { return new func_exp(*this); }
00694 virtual std::string getDescription() { std::ostringstream oss; oss << "func_exp r=" << r << ", psi=" << psi << ", t0=" << t0; return oss.str(); }
00695 };
00696
00697
00698
00704
00705 class func_exp_int : public func_deriveq_base
00706 {
00707 real r;
00708 real psi;
00709 real t0;
00710 real r_per_lambda_minus_psi;
00711
00712 void valueChange() { if( psi < 0.0 || lambda < 0.0 ) abort(); r_per_lambda_minus_psi = r / ( lambda - psi ); }
00713
00714 public:
00716 func_exp_int(real ir, real ipsi, real it0) : func_deriveq_base(), r(ir), psi(ipsi), t0(it0) { valueChange(); }
00717
00718 virtual real getMaxGradient( ntime_t ) const { throw "not supported"; }
00719
00720 virtual real getValue(ntime_t t) const
00721 { return r_per_lambda_minus_psi * (
00722 exp( - psi * (t - t0) )
00723 - exp( lambda * (zerop - t) - psi * (zerop - t0) ) );
00724 }
00725
00726 virtual real get1stDeriv(ntime_t t) const
00727 { return r_per_lambda_minus_psi * (
00728 - psi * exp( - psi * (t - t0) )
00729 + lambda * exp( lambda * (zerop - t) - psi * (zerop - t0) ) );
00730 }
00731
00732 virtual real get2ndDeriv(ntime_t t) const
00733 { return r_per_lambda_minus_psi * (
00734 psi*psi * exp( - psi * (t - t0) )
00735 - lambda*lambda * exp( lambda * (zerop - t) - psi * (zerop - t0) ) );
00736 }
00737
00738 virtual real get3rdDeriv(ntime_t t) const
00739 { return r_per_lambda_minus_psi * (
00740 -psi*psi*psi * exp( - psi * (t - t0) )
00741 +lambda*lambda*lambda * exp( lambda * (zerop - t) - psi * (zerop - t0) ) );
00742 }
00743
00744 virtual ntime_t getNextIncontinuity( ntime_t ) const { return mak::Infinity; };
00745
00746 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const
00747 {
00748 real value = getValue(t);
00749 real deriv = get1stDeriv(t);
00750 if( r >= 0 )
00751 {
00752 if( deriv > 0 )
00753 {
00754 real log_lambda_per_psi = log(lambda / psi) / (lambda - psi);
00755 upslope = deriv;
00756 ceil = r_per_lambda_minus_psi * exp( - psi * (zerop - t0) ) * ( exp( -psi * log_lambda_per_psi ) - exp( - lambda * log_lambda_per_psi) );
00757 downslope = - value / log_lambda_per_psi;
00758 floor = 0;
00759 }
00760 else {
00761 upslope = 0; ceil = mak::Infinity;
00762 downslope = -1; throw "Not supported";
00763 floor = 0;
00764 }
00765 }
00766 else {
00767 if( deriv < 0 )
00768 {
00769 real log_lambda_per_psi = log(lambda / psi) / (lambda - psi);
00770 downslope = deriv;
00771 floor = r_per_lambda_minus_psi * exp( - psi * (zerop - t0) ) * ( exp( -psi * log_lambda_per_psi ) - exp( - lambda * log_lambda_per_psi) );
00772 upslope = - value / log_lambda_per_psi;
00773 ceil = 0;
00774 }
00775 else {
00776 downslope = 0; floor = -mak::Infinity;
00777 upslope = 1; throw "Not supported";
00778 ceil = 0;
00779 }
00780 }
00781 }
00782
00783
00784 virtual void get1stDerivDomain( ntime_t , real &, real &, real &, real & ) const
00785 { throw "not supported"; }
00786
00787
00788 virtual void get2ndDerivDomain( ntime_t , real &, real &, real &, real & ) const
00789 { throw "not supported"; }
00790
00791 virtual func_exp_int * clone() { return new func_exp_int(*this); }
00792 virtual std::string getDescription() { std::ostringstream oss; oss << "func_exp_int r=" << r << ",t0=" << t0; return oss.str(); }
00793 };
00794
00800
00801 class func_exp_diff : public func_base
00802 {
00803 real psi1, psi2;
00804 real phi, scale, invscale;
00805 real t0orig;
00806 real r0, t0;
00807 real r1, t1;
00808 real r2, t2;
00809 real it0, ir1, ir2;
00810 real r1orig, r2orig;
00811 real maxval;
00812 real xi;
00813
00814 void valueChange();
00815
00816 public:
00818 func_exp_diff(real ir1, real ipsi1, real ir2, real ipsi2, real it0);
00819
00820 virtual real getMaxGradient( ntime_t t ) const { return r0<0 ? r0 * xi : (t >= t1 ? 0 : get1stDeriv(t)); }
00821
00822 virtual real getValue( ntime_t t ) const
00823 { return r0 * (exp( -psi1 * (t - t0) ) - exp( -psi2 * (t - t0) ) ); }
00824
00825 virtual real get1stDeriv( ntime_t t ) const
00826 { return r1 * (exp( -psi1 * (t - t1) ) - exp( -psi2 * (t - t1) ) ); }
00827
00828 virtual real get2ndDeriv( ntime_t t ) const
00829 { return r2 * (exp( -psi1 * (t - t2) ) - exp( -psi2 * (t - t2) ) ); }
00830
00831 virtual real get3rdDeriv( ntime_t t ) const
00832 { return r2 * (-psi1 * exp( -psi1 * (t - t2) ) + psi2 * exp( -psi2 * (t - t2) ) ); }
00833
00834 virtual ntime_t getNextIncontinuity( ntime_t ) const { return mak::Infinity; }
00835
00836 virtual void getValueDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const ;
00837 virtual void get1stDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const ;
00838 virtual void get2ndDerivDomain( ntime_t t, real &upslope, real &ceil, real &downslope, real &floor ) const ;
00839
00840 virtual func_exp_diff * clone() { return new func_exp_diff(*this); }
00841 virtual std::string getDescription() { std::ostringstream oss; oss << "func_exp_diff r0=" << r0 << ", psi1=" << psi1 << ", psi2=" << psi2 << ", t0=" << t0; return oss.str(); }
00842
00845
00846 class message_add_event_time : public message_base
00847 {
00848 public:
00849 message_add_event_time() { }
00850 static const char * const messageId;
00851 virtual const char *getMessageId() const { return messageId; }
00852 };
00853
00854 virtual bool processMessage(ntime_t t, const message_base &m);
00855 };
00856
00857
00858 }
00859
00860 #endif // __func_h