aboutsummaryrefslogtreecommitdiff
path: root/solo.c
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2005-06-01 17:47:56 +0000
committerSimon Tatham <anakin@pobox.com>2005-06-01 17:47:56 +0000
commit50edaa578b614eb74c57a38faa2d05ab628ff81b (patch)
treea48afa49172e113d2f867f33bb8f1c216b4bda8f /solo.c
parentad3abd9867962c94feeb09956e53c6fde886df0e (diff)
downloadpuzzles-50edaa578b614eb74c57a38faa2d05ab628ff81b.zip
puzzles-50edaa578b614eb74c57a38faa2d05ab628ff81b.tar.gz
puzzles-50edaa578b614eb74c57a38faa2d05ab628ff81b.tar.bz2
puzzles-50edaa578b614eb74c57a38faa2d05ab628ff81b.tar.xz
Miscellaneous fixes from James Harvey's PalmOS porting work:
- fixed numerous memory leaks (not Palm-specific) - corrected a couple of 32-bit-int assumptions (vital for Palm but generally a good thing anyway) - lifted a few function pointer types into explicit typedefs (neutral for me but convenient for the source-munging Perl scripts he uses to deal with Palm code segment rules) - lifted a few function-level static arrays into global static arrays (neutral for me but apparently works round a Palm tools bug) - a couple more presets in Rectangles (so that Palm, or any other slow platform which can't handle the larger sizes easily, can still have some variety available) - in Solo, arranged a means of sharing scratch space between calls to nsolve to prevent a lot of redundant malloc/frees (gives a 10% speed increase even on existing platforms) [originally from svn r5897]
Diffstat (limited to 'solo.c')
-rw-r--r--solo.c67
1 files changed, 49 insertions, 18 deletions
diff --git a/solo.c b/solo.c
index 2cd406a..c8fac6e 100644
--- a/solo.c
+++ b/solo.c
@@ -96,8 +96,6 @@ int solver_show_working;
#include "puzzles.h"
-#define max(x,y) ((x)>(y)?(x):(y))
-
/*
* To save space, I store digits internally as unsigned char. This
* imposes a hard limit of 255 on the order of the puzzle. Since
@@ -177,8 +175,10 @@ static int game_fetch_preset(int i, char **name, game_params **params)
{ "3x3 Intermediate", { 3, 3, SYMM_ROT2, DIFF_INTERSECT } },
{ "3x3 Advanced", { 3, 3, SYMM_ROT2, DIFF_SET } },
{ "3x3 Unreasonable", { 3, 3, SYMM_ROT2, DIFF_RECURSIVE } },
+#ifndef SLOW_SYSTEM
{ "3x4 Basic", { 3, 4, SYMM_ROT2, DIFF_SIMPLE } },
{ "4x4 Basic", { 4, 4, SYMM_ROT2, DIFF_SIMPLE } },
+#endif
};
if (i < 0 || i >= lenof(presets))
@@ -844,7 +844,12 @@ static int nsolve_intersect(struct nsolve_usage *usage,
return ret;
}
+struct nsolve_scratch {
+ unsigned char *grid, *rowidx, *colidx, *set;
+};
+
static int nsolve_set(struct nsolve_usage *usage,
+ struct nsolve_scratch *scratch,
int start, int step1, int step2
#ifdef STANDALONE_SOLVER
, char *fmt, ...
@@ -853,10 +858,10 @@ static int nsolve_set(struct nsolve_usage *usage,
{
int c = usage->c, r = usage->r, cr = c*r;
int i, j, n, count;
- unsigned char *grid = snewn(cr*cr, unsigned char);
- unsigned char *rowidx = snewn(cr, unsigned char);
- unsigned char *colidx = snewn(cr, unsigned char);
- unsigned char *set = snewn(cr, unsigned char);
+ unsigned char *grid = scratch->grid;
+ unsigned char *rowidx = scratch->rowidx;
+ unsigned char *colidx = scratch->colidx;
+ unsigned char *set = scratch->set;
/*
* We are passed a cr-by-cr matrix of booleans. Our first job
@@ -999,10 +1004,6 @@ static int nsolve_set(struct nsolve_usage *usage,
}
if (progress) {
- sfree(set);
- sfree(colidx);
- sfree(rowidx);
- sfree(grid);
return TRUE;
}
}
@@ -1021,17 +1022,33 @@ static int nsolve_set(struct nsolve_usage *usage,
break; /* done */
}
- sfree(set);
- sfree(colidx);
- sfree(rowidx);
- sfree(grid);
-
return FALSE;
}
+static struct nsolve_scratch *nsolve_new_scratch(struct nsolve_usage *usage)
+{
+ struct nsolve_scratch *scratch = snew(struct nsolve_scratch);
+ int cr = usage->cr;
+ scratch->grid = snewn(cr*cr, unsigned char);
+ scratch->rowidx = snewn(cr, unsigned char);
+ scratch->colidx = snewn(cr, unsigned char);
+ scratch->set = snewn(cr, unsigned char);
+ return scratch;
+}
+
+static void nsolve_free_scratch(struct nsolve_scratch *scratch)
+{
+ sfree(scratch->set);
+ sfree(scratch->colidx);
+ sfree(scratch->rowidx);
+ sfree(scratch->grid);
+ sfree(scratch);
+}
+
static int nsolve(int c, int r, digit *grid)
{
struct nsolve_usage *usage;
+ struct nsolve_scratch *scratch;
int cr = c*r;
int x, y, n;
int diff = DIFF_BLOCK;
@@ -1055,6 +1072,8 @@ static int nsolve(int c, int r, digit *grid)
memset(usage->col, FALSE, cr * cr);
memset(usage->blk, FALSE, cr * cr);
+ scratch = nsolve_new_scratch(usage);
+
/*
* Place all the clue numbers we are given.
*/
@@ -1204,7 +1223,7 @@ static int nsolve(int c, int r, digit *grid)
*/
for (x = 0; x < cr; x += r)
for (y = 0; y < r; y++)
- if (nsolve_set(usage, cubepos(x,y,1), r*cr, 1
+ if (nsolve_set(usage, scratch, cubepos(x,y,1), r*cr, 1
#ifdef STANDALONE_SOLVER
, "set elimination, block (%d,%d)", 1+x/r, 1+y
#endif
@@ -1217,7 +1236,7 @@ static int nsolve(int c, int r, digit *grid)
* Row-wise set elimination.
*/
for (y = 0; y < cr; y++)
- if (nsolve_set(usage, cubepos(0,y,1), cr*cr, 1
+ if (nsolve_set(usage, scratch, cubepos(0,y,1), cr*cr, 1
#ifdef STANDALONE_SOLVER
, "set elimination, row %d", 1+YUNTRANS(y)
#endif
@@ -1230,7 +1249,7 @@ static int nsolve(int c, int r, digit *grid)
* Column-wise set elimination.
*/
for (x = 0; x < cr; x++)
- if (nsolve_set(usage, cubepos(x,0,1), cr, 1
+ if (nsolve_set(usage, scratch, cubepos(x,0,1), cr, 1
#ifdef STANDALONE_SOLVER
, "set elimination, column %d", 1+x
#endif
@@ -1246,6 +1265,8 @@ static int nsolve(int c, int r, digit *grid)
break;
}
+ nsolve_free_scratch(scratch);
+
sfree(usage->cube);
sfree(usage->row);
sfree(usage->col);
@@ -1448,6 +1469,16 @@ static char *new_game_desc(game_params *params, random_state *rs,
ai->r = r;
ai->grid = snewn(cr * cr, digit);
memcpy(ai->grid, grid, cr * cr * sizeof(digit));
+ /*
+ * We might already have written *aux the last time we
+ * went round this loop, in which case we should free
+ * the old aux_info before overwriting it with the new
+ * one.
+ */
+ if (*aux) {
+ sfree((*aux)->grid);
+ sfree(*aux);
+ }
*aux = ai;
}