chiark / gitweb /
Merge multiprocessor support; fix up Makefile runes
authorIan Jackson <ian@davenant.relativity.greenend.org.uk>
Sat, 27 Sep 2008 23:12:47 +0000 (00:12 +0100)
committerIan Jackson <ian@davenant.relativity.greenend.org.uk>
Sat, 27 Sep 2008 23:12:47 +0000 (00:12 +0100)
Makefile
common.c
common.h
energy.c
minimise.h
primer.c

index 9443d70dc9241974290d08ee973b243854564fba..927f45d1a8e60855abc87ebb43f1652cc1f26387 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,8 +11,6 @@ SGTATHAM=sgtatham
 CWARNS=        -Wall -Wwrite-strings -Wpointer-arith -Werror -Wshadow
 CXXWARNS= $(CWARNS) -Wno-shadow -Wno-error
 
-NPROCCFLAGS := -DNPROCESSORS=$(shell ./nprocessors)
-
 OPTIMISE=      -O2
 CFLAGS_UNIPROC=        -MMD $(OPTIMISE) -g $(CWARNS) $(DIMCFLAGS)
 CXXFLAGS=      -MMD $(OPTIMISE) -g $(CXXWARNS)
@@ -40,6 +38,13 @@ nprocessors: nprocessors.o common.o
 common.o nprocessors.o: %.o: %.c
                $(CC) -c $(CPPFLAGS) $(CFLAGS_UNIPROC) $< -o $@
 
+.nprocessors.make: ./nprocessors
+       set -e; n=`./nprocessors`; \
+       echo "NPROCCFLAGS := -DNPROCESSORS=$$n" $o
+
+include .nprocessors.make
+
+
 prime.data:    primer
                ./$^ $o
 
index fe58990f2c76888b5189682e76e988966b486149..3b036aaa29f54508a5708a1965347734dc5cfa5e 100644 (file)
--- a/common.c
+++ b/common.c
@@ -15,6 +15,14 @@ double magnD(const double pq[D3]) {
   return gsl_blas_dnrm2(&v);
 }
 
+double magnD2(const double pq[D3]) {
+  int k;
+  double d2= 0;
+  
+  K d2= ffsqa(pq[k], d2);
+  return d2;
+}
+
 double hypotD(const double p[D3], const double q[D3]) {
   int k;
   double pq[D3];
@@ -43,6 +51,18 @@ void xprod(double r[D3], const double a[D3], const double b[D3]) {
   r[2]= a[0]*b[1] - a[1]*b[0];
 }
 
+void normalise(double v[D3], double one, double absepsilon) {
+  int k;
+  double multby= one/(magnD(v) + absepsilon);
+  K v[k] *= multby;
+}
+
+void xprod_norm(double r[D3], const double a[D3], const double b[D3],
+               double one, double absepsilon) {
+  xprod(r,a,b);
+  normalise(r, absepsilon, one);
+}
+
 double dotprod(const double a[D3], const double b[D3]) {
   int k;
   double result= 0;
index 7e70a752666e8ad45ee485451bbb13b72d2cd6cb..58bc1cc11bb1396e892e827a22352923c75202ab 100644 (file)
--- a/common.h
+++ b/common.h
@@ -36,8 +36,12 @@ double hypotD2(const double p[D3], const double q[D3]);
 double hypotD2plus(const double p[D3], const double q[D3], double add);
 
 double magnD(const double pq[D3]);
+double magnD2(const double pq[D3]);
 void xprod(double r[D3], const double a[D3], const double b[D3]);
 double dotprod(const double a[D3], const double b[D3]);
+void xprod_norm(double r[D3], const double a[D3], const double b[D3],
+               double one, double absepsilon);
+void normalise(double v[D3], double one, double absepsilon);
 
 void flushoutput(void);
 void diee(const char *what);
index 5aa1c602b8387cd75f6c0e75437f7f63bd6f3edc..e43ecede21c987bdc638805ccc069d2ab10eff6a 100644 (file)
--- a/energy.c
+++ b/energy.c
@@ -26,27 +26,35 @@ static const CostContribution costs[]= {
 #define COST(weight, compute) { (weight),(compute) },
 
 #if XBITS==3
-#define STOP_EPSILON 1e-6;
-    COST(  3e2,   line_bending_cost)
-    COST(  1e3,   edge_length_variation_cost)
-    COST( 0.2e3,  rim_proximity_cost)
-    COST(  1e8,   noncircular_rim_cost)
+#define STOP_EPSILON 1e-6
+    COST(  3e3,   line_bending_cost)
+    COST(  3e3,   edge_length_variation_cost)
+    COST( 0.4e3,  rim_proximity_cost)
+    COST(  1e6,   edge_angle_cost)
+                  #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.7)
+//    COST(  1e1,   small_triangles_cost)
+    COST(  1e12,   noncircular_rim_cost)
 #endif
 
 #if XBITS==4
-#define STOP_EPSILON 1e-5;
-    COST(  3e2,   line_bending_cost)
-    COST(  3e3,   edge_length_variation_cost)
-    COST( 3.8e1,  rim_proximity_cost) // 5e1 is too much
-                                        // 2.5e1 is too little
+#define STOP_EPSILON 1e-6
+    COST(  3e5,   line_bending_cost)
+    COST( 10e2,   edge_length_variation_cost)
+    COST( 9.0e1,  rim_proximity_cost) // 5e1 is too much
+                                     // 2.5e1 is too little
     // 0.2e1 grows compared to previous ?
     // 0.6e0 shrinks compared to previous ?
-    COST(  1e12,   noncircular_rim_cost)
+
+    COST(  1e12,   edge_angle_cost)
+                  #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.3)
+    COST(  1e18,   noncircular_rim_cost)
 #endif
 };
 
 #define NCOSTS ((sizeof(costs)/sizeof(costs[0])))
 
+const double edge_angle_cost_circcircrat= EDGE_ANGLE_COST_CIRCCIRCRAT;
+
 void energy_init(void) {
   stop_epsilon= STOP_EPSILON;
 }
@@ -138,7 +146,7 @@ static void addcost(double *energy, double tweight, double tcost, int pr) {
 void compute_edge_lengths(const Vertices vertices, int section) {
   int v1,e,v2;
 
-  FOR_EDGE(v1,e,v2,OUTER)
+  FOR_EDGE(v1,e,v2, OUTER)
     edge_lengths[v1][e]= hypotD(vertices[v1],vertices[v2]);
 }
 
@@ -146,7 +154,7 @@ void compute_vertex_areas(const Vertices vertices, int section) {
   int v0,v1,v2, e1,e2;
 //  int k;
 
-  FOR_VERTEX(v0,OUTER) {
+  FOR_VERTEX(v0, OUTER) {
     double total= 0.0, edges_total=0;
     int count= 0;
 
@@ -210,7 +218,7 @@ void compute_vertex_areas(const Vertices vertices, int section) {
 
 double line_bending_cost(const Vertices vertices, int section) {
   static const double axb_epsilon= 1e-6;
-  static const double exponent_r= 3;
+  static const double exponent_r= 4;
 
   int pi,e,qi,ri, k;
   double  a[D3], b[D3], axb[D3];
@@ -219,6 +227,8 @@ double line_bending_cost(const Vertices vertices, int section) {
   FOR_EDGE(qi,e,ri, OUTER) {
     pi= EDGE_END2(qi,(e+3)%V6); if (pi<0) continue;
 
+//if (!(qi&XMASK)) fprintf(stderr,"%02x-%02x-%02x (%d)\n",pi,qi,ri,e);
+
     K a[k]= -vertices[pi][k] + vertices[qi][k];
     K b[k]= -vertices[qi][k] + vertices[ri][k];
 
@@ -227,9 +237,6 @@ double line_bending_cost(const Vertices vertices, int section) {
     double delta= atan2(magnD(axb) + axb_epsilon, dotprod(a,b));
     double cost= pow(delta,exponent_r);
 
-    if (!e && !(qi & ~XMASK))
-      cost *= 10;
-
     total_cost += cost;
   }
   return total_cost;
@@ -305,3 +312,128 @@ double noncircular_rim_cost(const Vertices vertices, int section) {
   }
   return cost;
 }
+
+/*---------- overly sharp edge cost ----------*/
+
+  /*
+   *
+   *                       Q `-_
+   *              / |    `-_                          P'Q' ------ S'
+   *             /  |       `-.                             _,' `.       .
+   *            /   |           S                _,'     :      .
+   *           /    |      _,-'                _,'        :r    .r
+   *          /     |  _,-'               R' '           `.   .
+   *         /    , P '                               ` .   r     :  .
+   *        /  ,-'                                 `  .   : 
+   *       /,-'                                                 ` C'
+   *      /'
+   *            R
+   *
+   *
+   *
+   *  Let delta =  angle between two triangles' normals
+   *
+   *  Giving energy contribution:
+   *
+   *                                   2
+   *    E             =  F   .  delta
+   *     vd, edge PQ      vd
+   */
+
+double edge_angle_cost(const Vertices vertices, int section) {
+  double pq1[D3], rp[D3], ps[D3], rp_2d[D3], ps_2d[D3], rs_2d[D3];
+  double a,b,c,s,r;
+  const double minradius_base= 0.2;
+
+  int pi,e,qi,ri,si, k;
+//  double our_epsilon=1e-6;
+  double total_cost= 0;
+
+  FOR_EDGE(pi,e,qi, OUTER) {
+//    if (!(RIM_VERTEX_P(pi) || RIM_VERTEX_P(qi))) continue;
+
+    si= EDGE_END2(pi,(e+V6-1)%V6);  if (si<0) continue;
+    ri= EDGE_END2(pi,(e   +1)%V6);  if (ri<0) continue;
+
+    K {
+      pq1[k]= -vertices[pi][k] + vertices[qi][k];
+      rp[k]=  -vertices[ri][k] + vertices[pi][k];
+      ps[k]=  -vertices[pi][k] + vertices[si][k];
+    }
+
+    normalise(pq1,1,1e-6);
+    xprod(rp_2d, rp,pq1); /* projects RP into plane normal to PQ */
+    xprod(ps_2d, ps,pq1); /* likewise PS */
+    K rs_2d[k]= rp_2d[k] + ps_2d[k];
+    /* radius of circumcircle of R'P'S' from Wikipedia
+     * `Circumscribed circle' */
+    a= magnD(rp_2d);
+    b= magnD(ps_2d);
+    c= magnD(rs_2d);
+    s= 0.5*(a+b+c);
+    r= a*b*c / sqrt((a+b+c)*(a-b+c)*(b-c+a)*(c-a+b) + 1e-6);
+
+    double minradius= minradius_base + edge_angle_cost_circcircrat*(a+b);
+    double deficit= minradius - r;
+    if (deficit < 0) continue;
+    double cost= deficit*deficit;
+
+    total_cost += cost;
+  }
+
+  return total_cost;
+}
+
+/*---------- small triangles cost ----------*/
+
+  /*
+   *
+   *                       Q `-_
+   *              / |    `-_
+   *             /  |       `-.
+   *            /   |           S
+   *           /    |      _,-'
+   *          /     |  _,-'
+   *         /    , P '
+   *        /  ,-'
+   *       /,-'
+   *      /'
+   *            R
+   *
+   *  Let delta =  angle between two triangles' normals
+   *
+   *  Giving energy contribution:
+   *
+   *                                   2
+   *    E             =  F   .  delta
+   *     vd, edge PQ      vd
+   */
+
+double small_triangles_cost(const Vertices vertices, int section) {
+  double pq[D3], ps[D3];
+  double x[D3];
+  int pi,e,qi,si, k;
+//  double our_epsilon=1e-6;
+  double total_cost= 0;
+
+  FOR_EDGE(pi,e,qi, OUTER) {
+//    if (!(RIM_VERTEX_P(pi) || RIM_VERTEX_P(qi))) continue;
+
+    si= EDGE_END2(pi,(e+V6-1)%V6);  if (si<0) continue;
+
+    K {
+      pq[k]= vertices[qi][k] - vertices[pi][k];
+      ps[k]= vertices[si][k] - vertices[pi][k];
+    }
+    xprod(x, pq,ps);
+
+    double cost= 1/(magnD2(x) + 0.01);
+
+//double cost= pow(magnD(spqxpqr), 3);
+//assert(dot>=-1 && dot <=1);
+//double cost= 1-dot;
+    total_cost += cost;
+  }
+
+  return total_cost;
+}
index 097b8ac42bedc42942799c8919792822e074872b..c2e13e7b40fef83169495c5b2754fc91333c90d1 100644 (file)
@@ -18,10 +18,14 @@ void compute_edge_lengths(const Vertices vertices, int section);
 
 extern double vertex_areas[N], vertex_mean_edge_lengths[N], edge_lengths[N][V6];
 
+extern const double edge_angle_cost_circcircrat;
+
 double line_bending_cost(const Vertices vertices, int section);
 double noncircular_rim_cost(const Vertices vertices, int section);
 double edge_length_variation_cost(const Vertices vertices, int section);
 double rim_proximity_cost(const Vertices vertices, int section);
+double edge_angle_cost(const Vertices vertices, int section);
+double small_triangles_cost(const Vertices vertices, int section);
 
 extern const char *input_file, *best_file;
 extern char *best_file_tmp;
index 70cbcfeda45883205414c05c6b285df43fbb790c..76939a6356b9911dc59e29913603cf8af5ee671b 100644 (file)
--- a/primer.c
+++ b/primer.c
@@ -17,7 +17,7 @@ int main(int argc, const char **argv) {
         X*Y, N, X, Y, D3,
         prec+5,prec);
 
-  FOR_VERTEX(vi) {
+  FOR_VERTEX(vi, INNER) {
     int x= vi & XMASK; /* distance along strip */
     int y= vi >> YSHIFT; /* distance across strip */
     double u= y * 1.0 / (Y-1); /* SGT's u runs 0..1 across the strip */