From 4260418786f1ef828039c8f8a5989a49511044eb Mon Sep 17 00:00:00 2001
From: Vincent Danjean <Vincent.Danjean@ens-lyon.org>
Date: Wed, 31 Oct 2012 16:35:57 +0000
Subject: [PATCH] memory managed outside inner functions

outer functions can choose to allocate memory
with malloc or on their stack

git-svn-id: svn+ssh://imag/users/huron/danjean/svnroot/claire/altree/trunk@466 cf695345-040a-0410-a956-b889e835fe2e
---
 CUtils/CUtils.xs                      |  8 +++++--
 CUtils/c_sources/double_permutation.c | 12 +++++++++++
 CUtils/c_sources/resampling.c         | 10 ++++++---
 CUtils/c_sources/stats.c              | 30 +++++++++++++--------------
 CUtils/c_sources/stats.h              | 14 ++++++++-----
 5 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/CUtils/CUtils.xs b/CUtils/CUtils.xs
index 61a7253..9c977dd 100644
--- a/CUtils/CUtils.xs
+++ b/CUtils/CUtils.xs
@@ -263,6 +263,7 @@ CalculChi2(tabnodes, ddl, test_results, sign_util)
         int sign_util
     INIT:
 	struct cc *nodes;
+	struct cc *th;
 	int nb_nodes;
 	struct calcul_chi2_res res;
 	int i;
@@ -273,6 +274,7 @@ CalculChi2(tabnodes, ddl, test_results, sign_util)
 	  XSRETURN_UNDEF;
 	}
 	nodes=(struct cc*)malloc(nb_nodes*sizeof(struct cc));
+	th=(struct cc*)malloc(nb_nodes*sizeof(struct cc));
 
 	for (i=0; i<nb_nodes; i++) {
 	  SV* ref=*av_fetch(tabnodes, i, 0);
@@ -288,7 +290,7 @@ CalculChi2(tabnodes, ddl, test_results, sign_util)
 	  nodes[i].controls=SvNV(*svp);
 	}
 
-	res=calcul_chi2(nb_nodes, nodes, sign_util, 1);
+        res=calcul_chi2(nb_nodes, nodes, sign_util, 1, th);
 
 	if (res.texte) {
 	  hv_store(test_results, "texte", 5,
@@ -312,6 +314,7 @@ CalculChi2(tabnodes, ddl, test_results, sign_util)
 	}
 
 	free(nodes);
+        free(th);
 
 	EXTEND(SP, 2);
 	PUSHs(sv_2mortal(newSVnv(res.p_val)));
@@ -390,8 +393,9 @@ ReechChi2(sum_case, sum_control, nb_nodes, chi2_reel, clades)
 	    case_avail=0;
 	  }
 	}
+        struct cc th[nb_nodes];
 
-	RETVAL=reech_chi2(sum_case, sum_control, nb_nodes, chi2_reel, nodes);
+        RETVAL=reech_chi2(sum_case, sum_control, nb_nodes, chi2_reel, nodes, th);
 
 	free(nodes);
     OUTPUT:
diff --git a/CUtils/c_sources/double_permutation.c b/CUtils/c_sources/double_permutation.c
index 4cc4ae8..ea53dcd 100644
--- a/CUtils/c_sources/double_permutation.c
+++ b/CUtils/c_sources/double_permutation.c
@@ -151,6 +151,18 @@ datatype_t double_permutation(int nb_sample, int nb_chi2, matrice_t mat,
 	datatype_t min;
 	datatype_t local[nb_chi2];
 	
+	FILE*out=fopen("/tmp/out.txt", "w+");
+	fprintf(out, "nb_sample=%d nb_chi2=%d\n", nb_sample, nb_chi2);
+	for(i=0; i<nb_sample; i++) {
+		for(j=0; j<nb_chi2; j++) {
+			fprintf(out, "\t%.12g", mat[j][i]);
+		}
+		fprintf(out,"\n");
+	}
+	fclose(out);
+	
+	
+
 	i=0;
 	for (j=0; j<nb_chi2; j++) {
 		rep[j]=CALC_PVAL(count_superieur(mat[j], mat[j][i], nb_sample),
diff --git a/CUtils/c_sources/resampling.c b/CUtils/c_sources/resampling.c
index f7feab5..fbe1b0f 100644
--- a/CUtils/c_sources/resampling.c
+++ b/CUtils/c_sources/resampling.c
@@ -7,13 +7,15 @@
 struct chi2s {
 	int nb_leaves;
 	struct cc*leaves;
+	struct cc*th;
 	int nb_nodes;
 	int *stashed_nodes;
 	int *next_nodes;
 	struct cc*nodes;
 };
 
-static void compute_chi2s(struct tree *tree, struct cc *lcc, struct chi2s *temp,
+static void compute_chi2s(const struct tree *tree, const struct cc *lcc,
+			  struct chi2s *temp,
 			  int prolonge, datatype_t *results)
 {
 	int first_leaf=0;
@@ -32,7 +34,6 @@ static void compute_chi2s(struct tree *tree, struct cc *lcc, struct chi2s *temp,
 
 	int depth;
 	for (depth=tree->max_depth; depth>0; depth--){
-		struct cc *leaves=temp->leaves;
 		int nb_leaves=0;
 		int next_first_leaf;
 
@@ -75,7 +76,8 @@ static void compute_chi2s(struct tree *tree, struct cc *lcc, struct chi2s *temp,
 		first_leaf=next_first_leaf;
 
 		//debug("depth=%i, ddl=%i", depth, nb_leaves-1);
-		struct calcul_chi2_res r=calcul_chi2(nb_leaves, leaves, 0, 0);
+		struct calcul_chi2_res r=calcul_chi2(nb_leaves, temp->leaves,
+						     0, 0, temp->th);
 		assert(r.error==0);
 		results[depth-1]=r.chi2;
 	}
@@ -88,12 +90,14 @@ int resampling_chi2(struct tree *tree, struct cc *lcc, int prolonge,
 	struct cc rand_lcc[tree->nb_leaves];
 
 	struct cc leaves[tree->nb_leaves];
+	struct cc th[tree->nb_leaves];
 	struct cc nodes[tree->nb_nodes];
 	int stashed_nodes[tree->nb_nodes];
 	int next_nodes[tree->nb_nodes];
 	struct chi2s temp={
 		.nb_leaves=tree->nb_leaves,
 		.leaves=leaves,
+		.th=th,
 		.nb_nodes=tree->nb_nodes,
 		.stashed_nodes=stashed_nodes,
 		.next_nodes=next_nodes,
diff --git a/CUtils/c_sources/stats.c b/CUtils/c_sources/stats.c
index 4b3c4dd..8b3ec14 100644
--- a/CUtils/c_sources/stats.c
+++ b/CUtils/c_sources/stats.c
@@ -10,7 +10,8 @@
 #include <strings.h>
 #include <string.h>
 
-struct classical_chi2_res classical_chi2(int nb_nodes, struct cc *nodes) {
+struct classical_chi2_res classical_chi2(int nb_nodes,
+					 const struct cc *nodes) {
 	struct classical_chi2_res res={
 		.chi2=0.0,
 		.chi2invalid=0,
@@ -80,8 +81,8 @@ struct classical_chi2_res classical_chi2(int nb_nodes, struct cc *nodes) {
 		ch;							\
 	})
 
-struct calcul_chi2_res calcul_chi2(int nb_nodes, struct cc *nodes,
-				   int sign_util, int texte)
+struct calcul_chi2_res calcul_chi2(int nb_nodes, const struct cc *nodes,
+				   int sign_util, int texte, struct cc *th)
 {
 	struct classical_chi2_res r=
 		classical_chi2(nb_nodes, nodes);
@@ -141,7 +142,7 @@ struct calcul_chi2_res calcul_chi2(int nb_nodes, struct cc *nodes,
 			}
 		} else {
 			p_value = reech_chi2(r.sum_case, r.sum_control,
-					     nb_nodes, r.chi2, nodes);
+					     nb_nodes, r.chi2, nodes, th);
 			res.warning=msprintfcat(res.warning," (%.6g)",p_value);
 			if (sign_util) {
 				res.significatif = reech_significatif(p_value);
@@ -196,19 +197,16 @@ int chi2_fisher_significatif(datatype_t pvalue)
 	return pvalue < chi2_p;
 }
 
-datatype_t reech_chi2(int sum_case, int sum_control,
-		      int nb_nodes, int chi2_reel, struct cc *nodes)
+datatype_t reech_chi2(int sum_case, int sum_control, int nb_nodes,
+		      int chi2_reel, const struct cc *nodes, struct cc *th)
 {
 	int sum_total=sum_case+sum_control;
 	datatype_t p_val=0.0;
 
-	datatype_t th_c[nb_nodes];
-	datatype_t th_m[nb_nodes];
-
 	int i,k;
 	for(i=0; i<nb_nodes; i++) {
-		th_c[i]=((datatype_t)(sum_control*(nodes[i].cases+nodes[i].controls)))/sum_total;
-		th_m[i]=((datatype_t)(sum_case*(nodes[i].cases+nodes[i].controls)))/sum_total;
+		th[i].controls=((datatype_t)(sum_control*(nodes[i].cases+nodes[i].controls)))/sum_total;
+		th[i].cases=((datatype_t)(sum_case*(nodes[i].cases+nodes[i].controls)))/sum_total;
 	}
 
 	struct cc clades[nb_nodes];
@@ -218,10 +216,10 @@ datatype_t reech_chi2(int sum_case, int sum_control,
 		datatype_t chi2=0.0;
 		for(i=0; i<nb_nodes; i++) {
 			datatype_t t;
-			t=clades[i].cases - th_m[i];
-			chi2 += t*t/th_m[i];
-			t=clades[i].controls - th_c[i];
-			chi2 += t*t/th_c[i];
+			t=clades[i].cases - th[i].cases;
+			chi2 += t*t/th[i].cases;
+			t=clades[i].controls - th[i].controls;
+			chi2 += t*t/th[i].controls;
 		}
 		if (chi2 >= chi2_reel){
 			p_val++;
@@ -236,7 +234,7 @@ int reech_significatif(datatype_t p_val)
 	return (p_val<=chi2_p);
 }
 
-void random_clades(int nb_nodes, struct cc *nodes,
+void random_clades(int nb_nodes, const struct cc *nodes,
 		   int cases, int controls, struct cc *clades)
 {
 	bzero(clades, nb_nodes*sizeof(struct cc));
diff --git a/CUtils/c_sources/stats.h b/CUtils/c_sources/stats.h
index 18e140e..c747528 100644
--- a/CUtils/c_sources/stats.h
+++ b/CUtils/c_sources/stats.h
@@ -29,15 +29,19 @@ struct calcul_chi2_res {
 	char *warning;
 };
 
-struct classical_chi2_res classical_chi2(int nb_nodes, struct cc *nodes);
-struct calcul_chi2_res calcul_chi2(int nb_nodes, struct cc *nodes, int sign_util, int texte);
+struct classical_chi2_res classical_chi2(int nb_nodes, const struct cc *nodes);
+struct calcul_chi2_res calcul_chi2(int nb_nodes, const struct cc *nodes,
+				   int sign_util, int texte, struct cc *th);
 void definition_p_chi2(datatype_t p, datatype_t pprop);
 int chi2_significatif(int ddl, datatype_t chi2);
 int chi2_fisher_significatif(datatype_t pvalue);
-datatype_t reech_chi2(int sum_case, int sum_control,
-		      int nb_nodes, int chi2_reel, struct cc *nodes);
+/* nodes and th: array of size nb_nodes.
+   nodes is input only, th is used internally
+*/
+datatype_t reech_chi2(int sum_case, int sum_control, int nb_nodes,
+		      int chi2_reel, const struct cc *nodes, struct cc *th);
 int reech_significatif(datatype_t p_val);
-void random_clades(int nb_nodes, struct cc *nodes,
+void random_clades(int nb_nodes, const struct cc *nodes,
 		   int cases, int controls, struct cc *clades);
 
 #endif
-- 
GitLab