about summary refs log tree commit diff
path: root/generator/pamseq.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
commit1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch)
tree64c8c96cf54d8718847339a403e5e67b922e8c3f /generator/pamseq.c
downloadnetpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'generator/pamseq.c')
-rw-r--r--generator/pamseq.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/generator/pamseq.c b/generator/pamseq.c
new file mode 100644
index 00000000..58419d12
--- /dev/null
+++ b/generator/pamseq.c
@@ -0,0 +1,202 @@
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "pam.h"
+#include "shhopt.h"
+
+#define true (1)
+#define false (0)
+
+
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    unsigned int depth;
+    sample maxval;
+    const char * tupletype;
+};
+
+
+
+static void
+parseCommandLine(int argc, char ** argv,
+                 struct cmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+  Convert program invocation arguments (argc,argv) into a format the 
+  program can use easily, struct cmdlineInfo.  Validate arguments along
+  the way and exit program with message if invalid.
+
+  Note that some string information we return as *cmdlineP is in the storage 
+  argv[] points to.
+-----------------------------------------------------------------------------*/
+    optEntry *option_def = malloc(100*sizeof(optEntry));
+        /* Instructions to OptParseOptions2 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int tupletypeSpec;
+    unsigned int option_def_index;
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "tupletype",  OPT_STRING, &cmdlineP->tupletype, 
+            &tupletypeSpec,     0);
+
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (!tupletypeSpec)
+        cmdlineP->tupletype = "";
+    else {
+        struct pam pam;
+        if (strlen(cmdlineP->tupletype)+1 > sizeof(pam.tuple_type))
+            pm_error("The tuple type you specified is too long.  "
+                     "Maximum %d characters.", sizeof(pam.tuple_type)-1);
+    }        
+
+    if (argc-1 < 2)
+        pm_error("Need two arguments: depth and maxval.");
+    else if (argc-1 > 2)
+        pm_error("Only two argumeents allowed: depth and maxval.  "
+                 "You specified %d", argc-1);
+    else {
+        cmdlineP->depth = atoi(argv[1]);
+        cmdlineP->maxval = atoi(argv[2]);
+        if (cmdlineP->depth <= 0)
+            pm_error("depth argument must be a positive number.  You "
+                     "specified '%s'", argv[1]);
+        if (cmdlineP->maxval <= 0)
+            pm_error("maxval argument must be a positive number.  You "
+                     "specified '%s'", argv[2]);
+        if (cmdlineP->maxval > PNM_OVERALLMAXVAL)
+            pm_error("The maxval you specified (%u) is too big.  "
+                     "Maximum is %u", (unsigned int) cmdlineP->maxval, 
+                     PNM_OVERALLMAXVAL);
+        if (pm_maxvaltobits(cmdlineP->maxval) + 
+            pm_maxvaltobits(cmdlineP->depth-1) > sizeof(unsigned int)*8)
+            pm_error("The maxval (%u) and depth (%u) you specified result "
+                     "in a larger number of tuples than this program can "
+                     "handle (roughly %u)", 
+                     (unsigned int) cmdlineP->maxval, cmdlineP->depth,
+                     (unsigned int) -1);
+    }
+}
+
+
+
+static unsigned int
+powint(unsigned int base, unsigned int exponent) {
+/*----------------------------------------------------------------------------
+   This is standard pow(), but for integers and optimized for small
+   exponents.
+-----------------------------------------------------------------------------*/
+    unsigned int result;
+    unsigned int i;
+
+    result = 1;  /* initial value */
+    for (i = 0; i < exponent; ++i) 
+        result *= base;
+
+    return(result);
+}
+
+
+static void
+permuteHigherPlanes(struct pam const pam, int const nextplane, 
+                    tuple * const tuplerow, int * const colP, 
+                    tuple const lowerPlanes) {
+/*----------------------------------------------------------------------------
+   Create all the possible permutations of tuples whose lower-numbered planes
+   contain the values from 'lowerPlanes'.  I.e. vary the higher-numbered
+   planes between zero and maxval.
+
+   Write them sequentially into *tuplerow, starting at *colP.  Adjust
+   *colP to next the column after the ones we write.
+
+   lower-numbered means with plane numbers less than 'nextplane'.
+
+   We modify 'lowerPlanes' in the higher planes to undefined values.
+-----------------------------------------------------------------------------*/
+    if (nextplane == pam.depth - 1) {
+        sample value;
+        for (value = 0; value <= pam.maxval; ++value) {
+            unsigned int plane;
+            for (plane = 0; plane < nextplane; ++plane)
+                tuplerow[*colP][plane] = lowerPlanes[plane];
+            tuplerow[*colP][nextplane] = value;
+            ++(*colP);
+        }
+    } else {
+        sample value;
+
+        for (value = 0; value <= pam.maxval; ++value) {
+            /* We do something sleazy here and use Caller's lowerPlanes[]
+               variable as a local variable, modifying it in the higher
+               plane positions.  That's just for speed.
+            */
+            lowerPlanes[nextplane] = value;
+
+            permuteHigherPlanes(pam, nextplane+1, tuplerow, colP, lowerPlanes);
+        }
+    }
+}
+
+
+
+int
+main(int argc, char **argv) {
+
+    struct cmdlineInfo cmdline;
+    struct pam pam;
+    int col;
+    tuple lowerPlanes;
+        /* This is working storage passed to permuteHigherPlanes(),
+           which we call.  Note that because we always pass zero as the
+           "planes" argument to permuteHigherPlanes(), none of the 
+           "lower planes" value is defined as an input to 
+           permuteHigherPlanes().
+        */
+    tuple * tuplerow;
+    
+    pnm_init(&argc, argv);
+   
+    parseCommandLine(argc, argv, &cmdline);
+
+    pam.size = sizeof(pam);
+    pam.len = PAM_STRUCT_SIZE(tuple_type);
+    pam.file = stdout;
+    pam.format = PAM_FORMAT;
+    pam.plainformat = 0;
+    pam.width = powint(cmdline.maxval+1, cmdline.depth);
+    pam.height = 1;
+    pam.depth = cmdline.depth;
+    pam.maxval = cmdline.maxval;
+    strcpy(pam.tuple_type, cmdline.tupletype);
+
+    pnm_writepaminit(&pam);
+   
+    tuplerow = pnm_allocpamrow(&pam);
+
+    lowerPlanes = pnm_allocpamtuple(&pam);
+
+    col = 0;
+
+    permuteHigherPlanes(pam, 0, tuplerow, &col, lowerPlanes);
+
+    if (col != pam.width)
+        pm_error("INTERNAL ERROR: Wrote %d columns; should have written %d.",
+                 col, pam.width);
+
+    pnm_writepamrow(&pam, tuplerow);
+    
+    pnm_freepamrow(tuplerow);
+
+    return 0;
+}