File: m_interp.h

package info (click to toggle)
gnucap 1%3A20230520-dev-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 9,836 kB
  • sloc: cpp: 29,956; sh: 352; makefile: 139
file content (93 lines) | stat: -rw-r--r-- 3,285 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*$Id: m_interp.h,v 26.83 2008/06/05 04:46:59 al Exp $ -*- C++ -*-
 * interpolation on a sorted array
 *
 * Copyright (C) 2001 Albert Davis
 * Author: Albert Davis <aldavis@gnu.org>
 *
 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
//testing=script,sparse 2006.07.13
#ifndef M_INTERP_H
#define M_INTERP_H
#include "m_cpoly.h"
/*--------------------------------------------------------------------------*/
/* interpolate:  linear interpolation on a table.
 * Keys must be sorted in increasing order.
 */
template <class Iterator>
FPOLY1 interpolate(Iterator begin, Iterator end, double x,
		   double below, double above)
{
  double f1 = NOT_VALID;
  double f0 = NOT_VALID;
  if (begin == end) {
    untested();
    throw Exception("interpolate table is empty");
  }
  --end;
  if (begin == end) { // only 1 entry -- constant
    f1 = (x < (*begin).first)
      ? ((below != NOT_INPUT) ? below : 0.)
      : ((above != NOT_INPUT) ? above : 0.);
    f0 = (*begin).second + (x - (*begin).first) * f1;
  }else{
    ++begin;

    // x is the search key
    // xx is the search key converted to a "pair" as required by upper_bound
    // upper might point to a match for the key, exact match
    // if not, it points just above it, no exact match
    // lower points just below where a match would go
    // so the real match is between upper and lower
    DPAIR    xx(x,BIGBIG);
    Iterator upper = upper_bound(begin, end, xx);
    Iterator lower = upper-1;

    // set f1 (derivative)
    if ((upper == end) && (x > (*upper).first) && (above != NOT_INPUT)) {
      // x is out of bounds, above
      lower = upper;
      if (above != 0.) {
	untested();
      }
      f1 = above;
    }else if ((upper == begin) && (x < (*lower).first) && (below!=NOT_INPUT)) { itested();
      // x is out of bounds, below
      if (below != 0.) { itested();
      }else{ untested();
      }
      f1 = below;
    }else if ((*upper).first <= (*lower).first) {itested();
      throw Exception("interpolate table is not sorted or has duplicate keys");
      f1 = 0.;
    }else{
      // ordinary interpolation
      assert((*upper).first != (*lower).first);
      f1 = ((*upper).second-(*lower).second) / ((*upper).first-(*lower).first);
    }

    f0 = (*lower).second + (x - (*lower).first) * f1;
  }
  assert(f1 != NOT_VALID);
  assert(f0 != NOT_VALID);
  return FPOLY1(x, f0, f1);
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
#endif
// vim:ts=8:sw=2:noet: