Code consolidation

A

Aaron Jackson

I am in the process of writing my first large scale program and I find
myself in the position of writing several copies of functions that do
the same thing, with mostly the same code, but only slightly different.
For example:

double
Chisqrd1(double *params, double *weight) { // CHANGE
int i;
double deltay, chiSqrd;
xy_t *data;

chiSqrd = 0.0;
data = dataList;
for (i = 0; data != NULL; i++) {
deltay = data->y - netCarriers(params, data->x); // CHANGE
chiSqrd += weight * deltay * deltay;
data = data->next;
}
return(chiSqrd);
}

double
Chisqrd2(dopant_t *dopants, double *weight, double *Ef, double Eg) { //
CHANGE
int i;
double deltay, chiSqrd;
xy_t *data;

chiSqrd = 0.0;
data = dataList;
for (i = 0; data != NULL; i++) {
deltay = data->y - netIonized(dopants, data->x, Ef); // CHANGE
chiSqrd += weight * deltay * deltay;
data = data->next;
}
return(chiSqrd);
}

I was wondering if there are common ways to cut down on this type of
duplication without adding too much to the overall complexity. Does
anybody have any suggestions? Thanks.

Aaron
 
C

Chris McDonald

Aaron Jackson said:
I am in the process of writing my first large scale program and I find
myself in the position of writing several copies of functions that do
the same thing, with mostly the same code, but only slightly different.
For example:
double
Chisqrd1(double *params, double *weight) { // CHANGE
int i;
double deltay, chiSqrd;
xy_t *data;
chiSqrd = 0.0;
data = dataList;
for (i = 0; data != NULL; i++) {
deltay = data->y - netCarriers(params, data->x); // CHANGE
chiSqrd += weight * deltay * deltay;
data = data->next;
}
return(chiSqrd);
}

double
Chisqrd2(dopant_t *dopants, double *weight, double *Ef, double Eg) { //
CHANGE
int i;
double deltay, chiSqrd;
xy_t *data;
chiSqrd = 0.0;
data = dataList;
for (i = 0; data != NULL; i++) {
deltay = data->y - netIonized(dopants, data->x, Ef); // CHANGE
chiSqrd += weight * deltay * deltay;
data = data->next;
}
return(chiSqrd);
}

I was wondering if there are common ways to cut down on this type of
duplication without adding too much to the overall complexity. Does
anybody have any suggestions? Thanks.

I suggest making all of your functions, netXXXX, to be of the same
type signature (they all receive the same parameter types (even if they
don't use them all), and all return the same type), and then passing the
required netXXXX function as a parameter to a single Chisqrd function.
 
Z

Zara

Aaron said:
I am in the process of writing my first large scale program and I find
myself in the position of writing several copies of functions that do
the same thing, with mostly the same code, but only slightly different.
(...)
try macros:

#define CHI(funDeclare,specifics)\
double funDeclare{\
int i;\
double deltay,chiSqrd;\
xy_t *data;\
\
chiSqrd = 0.0;\
data = dataList;\
for (i = 0; data != NULL; i++) {\
deltay = data->y - specifics;\
chiSqrd += weight * deltay * deltay;
data = data->next;\
}\
return(chiSqrd);\
}

CHI(
Chisqrd1(double *params, double *weight),
netCarriers(params, data->x)
)

CHI(
Chisqrd2(dopant_t *dopants, double *weight, double *Ef, double Eg),
netIonized(dopants,data->x, Ef)
)

I don't like it at all, bit it is a valid solution

Have you read about templates in C++? They could have been a nicer solution!
 
G

GMM50

Consider putting all the similay functions in their own files.
Then they're all in front of you and then decisions perhaps will become
clearer.

george
 
M

Malcolm

Aaron Jackson said:
I am in the process of writing my first large scale program and I find
myself in the position of writing several copies of functions that do
the same thing, with mostly the same code, but only slightly different.
For example:

double
Chisqrd1(double *params, double *weight) { // CHANGE
int i;
double deltay, chiSqrd;
xy_t *data;

chiSqrd = 0.0;
data = dataList;
for (i = 0; data != NULL; i++) {
deltay = data->y - netCarriers(params, data->x); // CHANGE
chiSqrd += weight * deltay * deltay;
data = data->next;
}
return(chiSqrd);
}

double
Chisqrd2(dopant_t *dopants, double *weight, double *Ef, double Eg) { //
CHANGE
int i;
double deltay, chiSqrd;
xy_t *data;

chiSqrd = 0.0;
data = dataList;
for (i = 0; data != NULL; i++) {
deltay = data->y - netIonized(dopants, data->x, Ef); // CHANGE
chiSqrd += weight * deltay * deltay;
data = data->next;
}
return(chiSqrd);
}

I was wondering if there are common ways to cut down on this type of
duplication without adding too much to the overall complexity. Does
anybody have any suggestions? Thanks.

The chi-squared test is inherently a comparision between two counts.
So write the function

double chi_squared(double *observed, double *expected, int N)

Now you data may not come in flat arrays of doubles. Not to worry, simply
write a little bit of "glue" code to transform it.
It is most unlikely that your chi-squared test is time critical. If it is,
then you do need to hard code some aspects of the test, to avoid this
overhead. Software engineering is often about compromises.
 
E

E. Robert Tisdale

Aaron said:
I am in the process of writing my first large scale program and I find
myself in the position of writing several copies of functions that do
the same thing, with mostly the same code, but only slightly different.
For example:
> expand chisqrd.c
#include <stdlib.h>

typedef struct dopant_t dopant_t;
typedef struct xy_t xy_t;
struct xy_t {
double x;
double y;
xy_t* next;
};

extern
xy_t* dataList;

double
netCarriers(const double[], double);

double
Chisqrd1(const double params[], const double weight[]) {
// CHANGE
xy_t* data = dataList;
double chiSqrd = 0.0;
for (size_t i = 0; NULL != data; ++i) {
double deltay = data->y - netCarriers(params, data->x);
// CHANGE
chiSqrd += weight*deltay*deltay;
data = data->next;
}
return chiSqrd;
}

double
netIonized(const dopant_t*, double, double);

double
Chisqrd2(const dopant_t* dopants, const double weight[],
const double Ef[], const double Eg[]) {
// CHANGE

xy_t* data = dataList;
double chiSqrd = 0.0;
for (size_t i = 0; NULL != data; ++i) {
double
deltay = data->y - netIonized(dopants, data->x, Ef);
// CHANGE
chiSqrd += weight*deltay*deltay;
data = data->next;
}
return chiSqrd;
}
 
M

Martin Ambuhl

This is unbelievable. We try hard to make people understand that in
posting to newsgroups they should use spaces rather than tabs, and
Trollsdale purposely turns spaces into tabs.
 
J

jxh

Martin said:
This is unbelievable. We try hard to make people understand that in
posting to newsgroups they should use spaces rather than tabs, and
Trollsdale purposely turns spaces into tabs.

Well, expand actually turns tabs into spaces.

-- James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,169
Messages
2,570,919
Members
47,458
Latest member
Chris#

Latest Threads

Top