gdrsclib
blockmath.c
Go to the documentation of this file.
1 /***************************************************
2 Apache License Version 2.0
3 
4 Copyright 2007-2011 EcoEquity and Stockholm Environment Institute
5 
6 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
7 file except in compliance with the License. You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software distributed under
12 the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 KIND, either express or implied. See the License for the specific language governing
14 permissions and limitations under the License.
15 ****************************************************/
16 
21 #include <math.h>
22 #include <stdlib.h>
23 #include "datastruct.h"
24 #include "blockmath.h"
25 #ifdef DMALLOC
26 #include <dmalloc.h>
27 #endif
28 
29 
38 struct datablock transform(struct datablock dbin, double (*f)(double), struct appdata ad) {
39  struct datablock dbout;
40  int row, year;
41 
42  dbout.y_start = dbin.y_start;
43  dbout.y_end = dbin.y_end;
44  // Constrain by time range of overall analysis
45  if (ad.minyear > dbout.y_start) dbout.y_start = ad.minyear;
46  if (ad.maxyear < dbout.y_end) dbout.y_end = ad.maxyear;
47  dbout.data = NULL;
48 
49  allocdata(&dbout, ad);
50 
51  for (row = 0; row < ad.numrecs; row++) {
52  for (year = dbout.y_start; year <= dbout.y_end; year++) {
53  setval(dbout, (*f)(getval(dbin, row, year, ad)), row, year, ad);
54  }
55  }
56 
57  return dbout;
58 }
59 
69 struct datablock binop(struct datablock a, struct datablock b, char op, struct appdata ad) {
70  struct datablock result;
71  int row, year;
72 
73  // Constrain by time range of arguments
74  result.y_start = a.y_start > b.y_start ? a.y_start : b.y_start;
75  result.y_end = a.y_end < b.y_end ? a.y_end : b.y_end;
76  // Constrain by time range of overall analysis
77  if (ad.minyear > result.y_start) result.y_start = ad.minyear;
78  if (ad.maxyear < result.y_end) result.y_end = ad.maxyear;
79  allocdata(&result, ad);
80 
81  for (row = 0; row < ad.numrecs; row++) {
82  for (year = result.y_start; year <= result.y_end; year++) {
83  switch (op) {
84  case '+': setval(result, getval(a, row, year, ad) + getval(b, row, year, ad), row, year, ad); break;
85  case '-': setval(result, getval(a, row, year, ad) - getval(b, row, year, ad), row, year, ad); break;
86  case '*': setval(result, getval(a, row, year, ad) * getval(b, row, year, ad), row, year, ad); break;
87  case '/': setval(result, getval(a, row, year, ad) / getval(b, row, year, ad), row, year, ad); break;
88  default: setval(result, NAN, row, year, ad);
89  }
90  }
91  }
92  return result;
93 }
94 
103 struct datablock scalmult(double scalar, struct datablock dbin, struct appdata ad) {
104  struct datablock result;
105  int row, year;
106 
107  result.y_start = dbin.y_start;
108  result.y_end = dbin.y_end;
109  // Constrain by time range of overall analysis
110  if (ad.minyear > result.y_start) result.y_start = ad.minyear;
111  if (ad.maxyear < result.y_end) result.y_end = ad.maxyear;
112  allocdata(&result, ad);
113 
114  for (row = 0; row < ad.numrecs; row++) {
115  for (year = result.y_start; year <= result.y_end; year++) {
116  setval(result, scalar * getval(dbin, row, year, ad), row, year, ad);
117  }
118  }
119  return result;
120 }
121 
128 double pnorm(double x) {
129  return 0.5 * erfc(-M_SQRT1_2 * x);
130 }
131 
140 double quick_qnorm(double p) {
141  double a0 = 2.30753, a1 = 0.27061, b1 = 0.99229, b2 = 0.04481;
142  double num, denom;
143  double sign, t;
144 
145  sign = -1;
146  if (p > 0.5) {
147  p = 1 - p;
148  sign = 1;
149  }
150 
151  t = sqrt(-2.0 * log(p));
152 
153  num = a0 + a1 * t;
154  denom = 1.0 + b1 * t + b2 * t * t;
155 
156  return sign * (t - num/denom);
157 }
158 
167 double qnorm(double p) {
168  int niter;
169  double pstar, pderiv, x;
170 
171  if (p < EPSILON) {
172  return quick_qnorm(EPSILON);
173  }
174  if (p > 1 - EPSILON) {
175  return quick_qnorm(1 - EPSILON);
176  }
177 
178  // Get initial guess (to within 3e-3)
179  x = quick_qnorm(p);
180 
181  pstar = pnorm(x);
182  for (niter = 0; (fabs(pstar - p) > EPSILON) && (niter < MAXITER); niter++) {
183  pderiv = dnorm(x);
184  x = x + (p - pstar)/pderiv;
185  pstar = pnorm(x);
186  }
187 
188  if (niter == MAXITER) {
189  return NAN;
190  } else {
191  return x;
192  }
193 }
194 
201 double dnorm(double x) {
202  return INV_SQRT_2PI * exp(-0.5 * x * x);
203 }
204 
213 double ztransf(double y, double ybar, double sigma) {
214  double z;
215 
216  if (ybar == 0 || sigma == 0) {
217  z = NAN;
218  } else if (y == 0) {
219  z = -INFINITY;
220  } else if (isinf(y) == 1) {
221  z = INFINITY;
222  } else {
223  z = (1/sigma) * log(y/ybar) + 0.5 * sigma;
224  }
225 
226  return z;
227 }
228 
235 double gini2sdlog(double gini) {
236  if (gini <= 0 || gini >= 100) {
237  return NAN;
238  }
239  return M_SQRT2 * qnorm(0.5 * (1.0 + gini/100.0));
240 }
241 
250 struct timeseries filter(struct datablock data, struct fixedfactor filter, struct appdata ad) {
251  struct timeseries result;
252  int year, i;
253  double accum;
254 
255  result.y_start = data.y_start;
256  result.y_end = data.y_end;
257  allocts(&result, ad);
258 
259  for (year = result.y_start; year <= result.y_end; year++) {
260  accum = 0.0;
261  for (i = 0; i < ad.numrecs; i++) {
262  accum += filter.data[i] * getval(data, i, year, ad);
263  }
264  settsval(result, accum, year, ad);
265  }
266 
267  return result;
268 }
269 
279 double filteryr(int year, struct datablock data, struct fixedfactor filter, struct appdata ad) {
280  int i;
281  double accum;
282 
283  accum = 0.0;
284  for (i = 0; i < ad.numrecs; i++) {
285  accum += filter.data[i] * getval(data, i, year, ad);
286  }
287 
288  return accum;
289 }
For the application, basic dimensions: number of countries and bounding years.
Definition: datastruct.h:48
#define MAXITER
Definition: blockmath.h:20
int y_start
The start year.
Definition: datastruct.h:60
struct datablock binop(struct datablock a, struct datablock b, char op, struct appdata ad)
Carry out a binary operation (+, -, *, /) on two datablock structures.
Definition: blockmath.c:69
double qnorm(double p)
The inverse cumulative standardized normal distribution.
Definition: blockmath.c:167
double quick_qnorm(double p)
Abramowitz & Stegun approximation to qnorm to get a good first guess.
Definition: blockmath.c:140
A one-dimensional array that contains information on countries that is the same for all years...
Definition: datastruct.h:84
int numrecs
Number of records (i.e., number of countries)
Definition: datastruct.h:49
int y_end
The end year.
Definition: datastruct.h:95
#define INV_SQRT_2PI
Definition: blockmath.h:24
double * data
The array, dimensioned (y_start - y_end + 1) * ad.numrecs when created.
Definition: datastruct.h:62
int y_end
The end year.
Definition: datastruct.h:61
A one-dimensional array that contains global information that is the same for all countries...
Definition: datastruct.h:93
struct datablock scalmult(double scalar, struct datablock dbin, struct appdata ad)
Multiply a datablock by a scaling factor.
Definition: blockmath.c:103
int allocdata(struct datablock *dblock, struct appdata ad)
Create a datablock in memory, using application-specific dimensions.
Definition: datastruct.c:223
void settsval(struct timeseries ts, double val, int year, struct appdata ad)
Set the value for a particular year in a timeseries.
Definition: datastruct.c:491
double gini2sdlog(double gini)
The standard deviation of the log of income corresponding to a given Gini, assuming lognormal...
Definition: blockmath.c:235
double ztransf(double y, double ybar, double sigma)
The transformed value .
Definition: blockmath.c:213
double getval(struct datablock db, int row, int year, struct appdata ad)
Get the data value from the datablock for specified row & year.
Definition: datastruct.c:432
double dnorm(double x)
The standard normal probability density.
Definition: blockmath.c:201
int allocts(struct timeseries *ts, struct appdata ad)
Create a timeseries in memory, of length = y_start - y_end + 1.
Definition: datastruct.c:278
struct datablock z(double y, struct gdrs_struct *gdrs, int ppp_or_mer)
Calculate the "z" transformed version of an income level for all countries and years.
Definition: gdrs.c:1754
#define EPSILON
Definition: blockmath.h:22
double * data
The data, length = y_start - y_end + 1 when created.
Definition: datastruct.h:96
double pnorm(double x)
The cumulative standardized normal distribution.
Definition: blockmath.c:128
double filteryr(int year, struct datablock data, struct fixedfactor filter, struct appdata ad)
Aggregate data in a datablock using a fixedfactor "filter" for a particular year. ...
Definition: blockmath.c:279
int y_start
The start year.
Definition: datastruct.h:94
A two-dimensional array that contains information for country/year combinations.
Definition: datastruct.h:59
struct timeseries filter(struct datablock data, struct fixedfactor filter, struct appdata ad)
Aggregate data in a datablock using a fixedfactor "filter" to produce a timeseries.
Definition: blockmath.c:250
void setval(struct datablock db, double val, int row, int year, struct appdata ad)
Set a specific value in a datablock, specified by row and year.
Definition: datastruct.c:454
struct datablock transform(struct datablock dbin, double(*f)(double), struct appdata ad)
Apply a function to a datablock.
Definition: blockmath.c:38