Skip to content

Commit b3db374

Browse files
jan-malekkbieganski
authored andcommitted
Replace std::function used as callbacks with templates
Signed-off-by: Jan Malek <[email protected]>
1 parent 3f52687 commit b3db374

File tree

4 files changed

+82
-124
lines changed

4 files changed

+82
-124
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ set(STA_SOURCE
7373
dcalc/DelayCalcBase.cc
7474
dcalc/DmpCeff.cc
7575
dcalc/DmpDelayCalc.cc
76-
dcalc/FindRoot.cc
7776
dcalc/GraphDelayCalc.cc
7877
dcalc/LumpedCapDelayCalc.cc
7978
dcalc/NetCaps.cc

dcalc/DmpCeff.cc

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,14 @@ gateModelRd(const LibertyCell *cell,
9292
double c1,
9393
const Pvt *pvt,
9494
bool pocv_enabled);
95+
template <typename Eval>
9596
static void
9697
newtonRaphson(const int max_iter,
9798
double x[],
9899
const int n,
99100
const double x_tol,
100101
// eval(state) is called to fill fvec and fjac.
101-
function<void ()> eval,
102+
const Eval &eval,
102103
// Temporaries supplied by caller.
103104
double *fvec,
104105
double **fjac,
@@ -494,9 +495,9 @@ DmpAlg::findVoCrossing(double vth,
494495
double t_lower,
495496
double t_upper)
496497
{
497-
FindRootFunc vo_func = [&] (double t,
498-
double &y,
499-
double &dy) {
498+
const auto vo_func = [&] (double t,
499+
double &y,
500+
double &dy) {
500501
double vo, vo_dt;
501502
Vo(t, vo, vo_dt);
502503
y = vo - vth;
@@ -612,9 +613,9 @@ DmpAlg::findVlCrossing(double vth,
612613
double t_lower,
613614
double t_upper)
614615
{
615-
FindRootFunc vl_func = [&] (double t,
616-
double &y,
617-
double &dy) {
616+
const auto vl_func = [&] (double t,
617+
double &y,
618+
double &dy) {
618619
double vl, vl_dt;
619620
Vl(t, vl, vl_dt);
620621
y = vl - vth;
@@ -1278,12 +1279,14 @@ DmpZeroC2::voCrossingUpperBound()
12781279
// x_tol is percentage that all changes in x must be less than (1.0 = 100%).
12791280
// Eval(state) is called to fill fvec and fjac (returns false if fails).
12801281
// Return error msg on failure.
1282+
// Eval should be callable like void(void)
1283+
template <typename Eval>
12811284
static void
12821285
newtonRaphson(const int max_iter,
12831286
double x[],
12841287
const int size,
12851288
const double x_tol,
1286-
function<void ()> eval,
1289+
const Eval &eval,
12871290
// Temporaries supplied by caller.
12881291
double *fvec,
12891292
double **fjac,

dcalc/FindRoot.cc

Lines changed: 0 additions & 106 deletions
This file was deleted.

dcalc/FindRoot.hh

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,95 @@
1616

1717
#pragma once
1818

19-
#include <functional>
19+
#include <algorithm> // abs
2020

2121
namespace sta {
2222

23-
typedef const std::function<void (double x,
24-
// Return values.
25-
double &y,
26-
double &dy)> FindRootFunc;
23+
using std::abs;
2724

25+
// FindRootFunc should be callable like void(double, double&, double&)
26+
template <typename FindRootFunc>
2827
double
29-
findRoot(FindRootFunc func,
28+
findRoot(const FindRootFunc &func,
3029
double x1,
3130
double x2,
3231
double x_tol,
3332
int max_iter,
3433
// Return value.
35-
bool &fail);
34+
bool &fail)
35+
{
36+
double y1, y2, dy1;
37+
func(x1, y1, dy1);
38+
func(x2, y2, dy1);
39+
return findRoot(func, x1, y1, x2, y2, x_tol, max_iter, fail);
40+
}
3641

42+
// FindRootFunc should be callable like void(double, double&, double&)
43+
template <typename FindRootFunc>
3744
double
38-
findRoot(FindRootFunc func,
45+
findRoot(const FindRootFunc &func,
3946
double x1,
4047
double y1,
4148
double x2,
4249
double y2,
4350
double x_tol,
4451
int max_iter,
4552
// Return value.
46-
bool &fail);
53+
bool &fail)
54+
{
55+
if ((y1 > 0.0 && y2 > 0.0) || (y1 < 0.0 && y2 < 0.0)) {
56+
// Initial bounds do not surround a root.
57+
fail = true;
58+
return 0.0;
59+
}
60+
61+
if (y1 == 0.0) {
62+
fail = false;
63+
return x1;
64+
}
65+
66+
if (y2 == 0.0) {
67+
fail = false;
68+
return x2;
69+
}
70+
71+
if (y1 > 0.0)
72+
// Swap x1/x2 so func(x1) < 0.
73+
std::swap(x1, x2);
74+
double root = (x1 + x2) * 0.5;
75+
double dx_prev = abs(x2 - x1);
76+
double dx = dx_prev;
77+
double y, dy;
78+
func(root, y, dy);
79+
for (int iter = 0; iter < max_iter; iter++) {
80+
// Newton/raphson out of range.
81+
if ((((root - x2) * dy - y) * ((root - x1) * dy - y) > 0.0)
82+
// Not decreasing fast enough.
83+
|| (abs(2.0 * y) > abs(dx_prev * dy))) {
84+
// Bisect x1/x2 interval.
85+
dx_prev = dx;
86+
dx = (x2 - x1) * 0.5;
87+
root = x1 + dx;
88+
}
89+
else {
90+
dx_prev = dx;
91+
dx = y / dy;
92+
root -= dx;
93+
}
94+
if (abs(dx) <= x_tol * abs(root)) {
95+
// Converged.
96+
fail = false;
97+
return root;
98+
}
99+
100+
func(root, y, dy);
101+
if (y < 0.0)
102+
x1 = root;
103+
else
104+
x2 = root;
105+
}
106+
fail = true;
107+
return root;
108+
}
47109

48110
} // namespace

0 commit comments

Comments
 (0)