Leptonica 1.68
C Image Processing Library

fhmtauto.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 
00017 /*
00018  *  fhmtauto.c
00019  *      
00020  *    Main function calls:
00021  *       l_int32             fhmtautogen()
00022  *       l_int32             fhmtautogen1()
00023  *       l_int32             fhmtautogen2()
00024  *
00025  *    Static helpers:
00026  *       static SARRAY      *sarrayMakeWplsCode()
00027  *       static SARRAY      *sarrayMakeInnerLoopDWACode()
00028  *       static char        *makeBarrelshiftString()
00029  *
00030  *    This automatically generates dwa code for the hit-miss transform.
00031  *    Here's a road map for how it all works.
00032  *
00033  *    (1) You generate an array (a SELA) of hit-miss transform SELs.
00034  *        This can be done in several ways, including
00035  *           (a) calling the function selaAddHitMiss() for
00036  *               pre-compiled SELs
00037  *           (b) generating the SELA in code in line
00038  *           (c) reading in a SELA from file, using selaRead()
00039  *               or various other formats.
00040  *
00041  *    (2) You call fhmtautogen1() and fhmtautogen2() on this SELA.
00042  *        This uses the text files hmttemplate1.txt and
00043  *        hmttemplate2.txt for building up the source code.  See the file
00044  *        prog/fhmtautogen.c for an example of how this is done.
00045  *        The output is written to files named fhmtgen.*.c
00046  *        and fhmtgenlow.*.c, where "*" is an integer that you
00047  *        input to this function.  That integer labels both
00048  *        the output files, as well as all the functions that
00049  *        are generated.  That way, using different integers,
00050  *        you can invoke fhmtautogen() any number of times
00051  *        to get functions that all have different names so that
00052  *        they can be linked into one program.
00053  *        
00054  *    (3) You copy the generated source code back to your src
00055  *        directory for compilation.  Put their names in the
00056  *        Makefile, regnerate the prototypes, and recompile
00057  *        the libraries.  Look at the Makefile to see how I've
00058  *        included fhmtgen.1.c and fhmtgenlow.1.c.  These files
00059  *        provide the high-level interfaces for the hmt, and
00060  *        the low-level interfaces to do the actual work.
00061  *
00062  *    (4) In an application, you now use this interface.  Again
00063  *        for the example files generated, using integer "1":
00064  *
00065  *           PIX   *pixHMTDwa_1(PIX *pixd, PIX *pixs, char *selname);
00066  *
00067  *              or
00068  *
00069  *           PIX   *pixFHMTGen_1(PIX *pixd, PIX *pixs, char *selname);
00070  *
00071  *        where the selname is one of the set that were defined
00072  *        as the name field of sels.  This set is listed at the
00073  *        beginning of the file fhmtgen.1.c.
00074  *        As an example, see the file prog/fmtauto_reg.c, which
00075  *        verifies the correctness of the implementation by
00076  *        comparing the dwa result with that of full-image
00077  *        rasterops. 
00078  */
00079 
00080 #include <string.h>
00081 #include "allheaders.h"
00082 
00083 #define   OUTROOT         "fhmtgen"
00084 #define   TEMPLATE1       "hmttemplate1.txt"
00085 #define   TEMPLATE2       "hmttemplate2.txt"
00086 
00087 #define   BUFFER_SIZE     512
00088 
00089 #define   PROTOARGS   "(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);"
00090 
00091 static char * makeBarrelshiftString(l_int32 delx, l_int32 dely, l_int32 type);
00092 static SARRAY * sarrayMakeInnerLoopDWACode(SEL *sel, l_int32 nhits, l_int32 nmisses);
00093 static SARRAY * sarrayMakeWplsCode(SEL *sel);
00094 
00095 static char wpldecls[][60] = {
00096             "l_int32             wpls2;",
00097             "l_int32             wpls2, wpls3;",
00098             "l_int32             wpls2, wpls3, wpls4;",
00099             "l_int32             wpls5;",
00100             "l_int32             wpls5, wpls6;",
00101             "l_int32             wpls5, wpls6, wpls7;",
00102             "l_int32             wpls5, wpls6, wpls7, wpls8;",
00103             "l_int32             wpls9;",
00104             "l_int32             wpls9, wpls10;",
00105             "l_int32             wpls9, wpls10, wpls11;",
00106             "l_int32             wpls9, wpls10, wpls11, wpls12;",
00107             "l_int32             wpls13;",
00108             "l_int32             wpls13, wpls14;",
00109             "l_int32             wpls13, wpls14, wpls15;",
00110             "l_int32             wpls13, wpls14, wpls15, wpls16;",
00111             "l_int32             wpls17;",
00112             "l_int32             wpls17, wpls18;",
00113             "l_int32             wpls17, wpls18, wpls19;",
00114             "l_int32             wpls17, wpls18, wpls19, wpls20;",
00115             "l_int32             wpls21;",
00116             "l_int32             wpls21, wpls22;",
00117             "l_int32             wpls21, wpls22, wpls23;",
00118             "l_int32             wpls21, wpls22, wpls23, wpls24;",
00119             "l_int32             wpls25;",
00120             "l_int32             wpls25, wpls26;",
00121             "l_int32             wpls25, wpls26, wpls27;",
00122             "l_int32             wpls25, wpls26, wpls27, wpls28;",
00123             "l_int32             wpls29;",
00124             "l_int32             wpls29, wpls30;",
00125             "l_int32             wpls29, wpls30, wpls31;"};
00126 
00127 static char wpldefs[][24] = {
00128             "    wpls2 = 2 * wpls;",
00129             "    wpls3 = 3 * wpls;",
00130             "    wpls4 = 4 * wpls;",
00131             "    wpls5 = 5 * wpls;",
00132             "    wpls6 = 6 * wpls;",
00133             "    wpls7 = 7 * wpls;",
00134             "    wpls8 = 8 * wpls;",
00135             "    wpls9 = 9 * wpls;",
00136             "    wpls10 = 10 * wpls;",
00137             "    wpls11 = 11 * wpls;",
00138             "    wpls12 = 12 * wpls;",
00139             "    wpls13 = 13 * wpls;",
00140             "    wpls14 = 14 * wpls;",
00141             "    wpls15 = 15 * wpls;",
00142             "    wpls16 = 16 * wpls;",
00143             "    wpls17 = 17 * wpls;",
00144             "    wpls18 = 18 * wpls;",
00145             "    wpls19 = 19 * wpls;",
00146             "    wpls20 = 20 * wpls;",
00147             "    wpls21 = 21 * wpls;",
00148             "    wpls22 = 22 * wpls;",
00149             "    wpls23 = 23 * wpls;",
00150             "    wpls24 = 24 * wpls;",
00151             "    wpls25 = 25 * wpls;",
00152             "    wpls26 = 26 * wpls;",
00153             "    wpls27 = 27 * wpls;",
00154             "    wpls28 = 28 * wpls;",
00155             "    wpls29 = 29 * wpls;",
00156             "    wpls30 = 30 * wpls;",
00157             "    wpls31 = 31 * wpls;"};
00158 
00159 static char wplstrp[][10] = {"+ wpls", "+ wpls2", "+ wpls3", "+ wpls4",
00160                              "+ wpls5", "+ wpls6", "+ wpls7", "+ wpls8",
00161                              "+ wpls9", "+ wpls10", "+ wpls11", "+ wpls12",
00162                              "+ wpls13", "+ wpls14", "+ wpls15", "+ wpls16",
00163                              "+ wpls17", "+ wpls18", "+ wpls19", "+ wpls20",
00164                              "+ wpls21", "+ wpls22", "+ wpls23", "+ wpls24",
00165                              "+ wpls25", "+ wpls26", "+ wpls27", "+ wpls28",
00166                              "+ wpls29", "+ wpls30", "+ wpls31"};
00167 
00168 static char wplstrm[][10] = {"- wpls", "- wpls2", "- wpls3", "- wpls4",
00169                              "- wpls5", "- wpls6", "- wpls7", "- wpls8",
00170                              "- wpls9", "- wpls10", "- wpls11", "- wpls12",
00171                              "- wpls13", "- wpls14", "- wpls15", "- wpls16",
00172                              "- wpls17", "- wpls18", "- wpls19", "- wpls20",
00173                              "- wpls21", "- wpls22", "- wpls23", "- wpls24",
00174                              "- wpls25", "- wpls26", "- wpls27", "- wpls28",
00175                              "- wpls29", "- wpls30", "- wpls31"};
00176 
00177 
00178 /*!
00179  *  fhmtautogen()
00180  *
00181  *      Input:  sela
00182  *              fileindex
00183  *              filename (<optional>; can be null)
00184  *      Return: 0 if OK; 1 on error
00185  *
00186  *  Notes:
00187  *      (1) This function generates all the code for implementing
00188  *          dwa morphological operations using all the sels in the sela.
00189  *      (2) See fhmtautogen1() and fhmtautogen2() for details.
00190  */
00191 l_int32
00192 fhmtautogen(SELA        *sela,
00193             l_int32      fileindex,
00194             const char  *filename)
00195 {
00196 l_int32  ret1, ret2;
00197 
00198     PROCNAME("fhmtautogen");
00199 
00200     if (!sela)
00201         return ERROR_INT("sela not defined", procName, 1);
00202     ret1 = fhmtautogen1(sela, fileindex, filename);
00203     ret2 = fhmtautogen2(sela, fileindex, filename);
00204     if (ret1 || ret2)
00205         return ERROR_INT("code generation problem", procName, 1);
00206     return 0;
00207 }
00208 
00209 
00210 /*!
00211  *  fhmtautogen1()
00212  *
00213  *      Input:  sel array
00214  *              fileindex
00215  *              filename (<optional>; can be null)
00216  *      Return: 0 if OK; 1 on error
00217  *
00218  *  Notes:
00219  *      (1) This function uses hmttemplate1.txt to create a
00220  *          top-level file that contains two functions that carry
00221  *          out the hit-miss transform for any of the sels in
00222  *          the input sela.
00223  *      (2) The fileindex parameter is inserted into the output
00224  *          filename, as described below.
00225  *      (3) If filename == NULL, the output file is fhmtgen.<n>.c,
00226  *          where <n> is equal to the 'fileindex' parameter.
00227  *      (4) If filename != NULL, the output file is <filename>.<n>.c.
00228  *      (5) Each sel must have at least one hit.  A sel with only misses
00229  *          generates code that will abort the operation if it is called.
00230  */
00231 l_int32
00232 fhmtautogen1(SELA        *sela,
00233              l_int32      fileindex,
00234              const char  *filename)
00235 {
00236 char    *filestr;
00237 char    *str_proto1, *str_proto2, *str_proto3;
00238 char    *str_doc1, *str_doc2, *str_doc3, *str_doc4;
00239 char    *str_def1, *str_def2, *str_proc1, *str_proc2;
00240 char    *str_dwa1, *str_low_dt, *str_low_ds;
00241 char     bigbuf[BUFFER_SIZE];
00242 l_int32  i, nsels, nbytes, actstart, end, newstart;
00243 size_t   size;
00244 SARRAY  *sa1, *sa2, *sa3;
00245 
00246     PROCNAME("fhmtautogen1");
00247 
00248     if (!sela)
00249         return ERROR_INT("sela not defined", procName, 1);
00250     if (fileindex < 0)
00251         fileindex = 0;
00252     if ((nsels = selaGetCount(sela)) == 0)
00253         return ERROR_INT("no sels in sela", procName, 1);
00254     
00255         /* Make array of sel names */
00256     sa1 = selaGetSelnames(sela);
00257 
00258         /* Make array of textlines from from hmttemplate1.txt */
00259     if ((filestr = (char *)l_binaryRead(TEMPLATE1, &size)) == NULL)
00260         return ERROR_INT("filestr not made", procName, 1);
00261     if ((sa2 = sarrayCreateLinesFromString(filestr, 1)) == NULL)
00262         return ERROR_INT("sa2 not made", procName, 1);
00263     FREE(filestr);
00264 
00265         /* Make strings containing function call names */
00266     sprintf(bigbuf, "PIX *pixHMTDwa_%d(PIX *pixd, PIX *pixs, "
00267                     "char *selname);", fileindex);
00268     str_proto1 = stringNew(bigbuf);
00269     sprintf(bigbuf, "PIX *pixFHMTGen_%d(PIX *pixd, PIX *pixs, "
00270                     "char *selname);", fileindex);
00271     str_proto2 = stringNew(bigbuf);
00272     sprintf(bigbuf, "l_int32 fhmtgen_low_%d(l_uint32 *datad, l_int32 w,\n"
00273             "                      l_int32 h, l_int32 wpld,\n"
00274             "                      l_uint32 *datas, l_int32 wpls,\n"
00275             "                      l_int32 index);", fileindex);
00276     str_proto3 = stringNew(bigbuf);
00277     sprintf(bigbuf, " *             PIX     *pixHMTDwa_%d()", fileindex);
00278     str_doc1 = stringNew(bigbuf);
00279     sprintf(bigbuf, " *             PIX     *pixFHMTGen_%d()", fileindex);
00280     str_doc2 = stringNew(bigbuf);
00281     sprintf(bigbuf, " *  pixHMTDwa_%d()", fileindex);
00282     str_doc3 = stringNew(bigbuf);
00283     sprintf(bigbuf, " *  pixFHMTGen_%d()", fileindex);
00284     str_doc4 = stringNew(bigbuf);
00285     sprintf(bigbuf, "pixHMTDwa_%d(PIX   *pixd,", fileindex);
00286     str_def1 = stringNew(bigbuf);
00287     sprintf(bigbuf, "pixFHMTGen_%d(PIX   *pixd,", fileindex);
00288     str_def2 = stringNew(bigbuf);
00289     sprintf(bigbuf, "    PROCNAME(\"pixHMTDwa_%d\");", fileindex);
00290     str_proc1 = stringNew(bigbuf);
00291     sprintf(bigbuf, "    PROCNAME(\"pixFHMTGen_%d\");", fileindex);
00292     str_proc2 = stringNew(bigbuf);
00293     sprintf(bigbuf, "    pixt2 = pixFHMTGen_%d(NULL, pixt1, selname);",
00294             fileindex);
00295     str_dwa1 = stringNew(bigbuf);
00296     sprintf(bigbuf,
00297             "        fhmtgen_low_%d(datad, w, h, wpld, datat, wpls, index);",
00298             fileindex);
00299     str_low_dt = stringNew(bigbuf);
00300     sprintf(bigbuf,
00301             "        fhmtgen_low_%d(datad, w, h, wpld, datas, wpls, index);",
00302             fileindex);
00303     str_low_ds = stringNew(bigbuf);
00304 
00305         /* Make the output sa */
00306     if ((sa3 = sarrayCreate(0)) == NULL)
00307         return ERROR_INT("sa3 not made", procName, 1);
00308 
00309         /* Copyright notice and info header */
00310     sarrayParseRange(sa2, 0, &actstart, &end, &newstart, "--", 0);
00311     sarrayAppendRange(sa3, sa2, actstart, end);
00312 
00313         /* Insert function names as documentation */
00314     sarrayAddString(sa3, str_doc1, L_INSERT);
00315     sarrayAddString(sa3, str_doc2, L_INSERT);
00316 
00317         /* Add '#include's */
00318     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00319     sarrayAppendRange(sa3, sa2, actstart, end);
00320 
00321         /* Insert function prototypes */
00322     sarrayAddString(sa3, str_proto1, L_INSERT);
00323     sarrayAddString(sa3, str_proto2, L_INSERT);
00324     sarrayAddString(sa3, str_proto3, L_INSERT);
00325 
00326         /* Add static globals */
00327     sprintf(bigbuf, "\nstatic l_int32   NUM_SELS_GENERATED = %d;", nsels);
00328     sarrayAddString(sa3, bigbuf, L_COPY);
00329     sprintf(bigbuf, "static char  SEL_NAMES[][80] = {");
00330     sarrayAddString(sa3, bigbuf, L_COPY);
00331     for (i = 0; i < nsels - 1; i++) {
00332         sprintf(bigbuf,
00333         "                             \"%s\",", sarrayGetString(sa1, i, 0));
00334         sarrayAddString(sa3, bigbuf, L_COPY);
00335     }
00336     sprintf(bigbuf,
00337         "                             \"%s\"};", sarrayGetString(sa1, i, 0));
00338     sarrayAddString(sa3, bigbuf, L_COPY);
00339 
00340         /* Start pixHMTDwa_*() function description */
00341     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00342     sarrayAppendRange(sa3, sa2, actstart, end);
00343     sarrayAddString(sa3, str_doc3, L_INSERT);
00344     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00345     sarrayAppendRange(sa3, sa2, actstart, end);
00346 
00347         /* Finish pixMorphDwa_*() function definition */
00348     sarrayAddString(sa3, str_def1, L_INSERT);
00349     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00350     sarrayAppendRange(sa3, sa2, actstart, end);
00351     sarrayAddString(sa3, str_proc1, L_INSERT);
00352     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00353     sarrayAppendRange(sa3, sa2, actstart, end);
00354     sarrayAddString(sa3, str_dwa1, L_INSERT);
00355     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00356     sarrayAppendRange(sa3, sa2, actstart, end);
00357 
00358         /* Start pixFHMTGen_*() function description */
00359     sarrayAddString(sa3, str_doc4, L_INSERT);
00360     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00361     sarrayAppendRange(sa3, sa2, actstart, end);
00362 
00363         /* Finish pixFHMTGen_*() function description */
00364     sarrayAddString(sa3, str_def2, L_INSERT);
00365     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00366     sarrayAppendRange(sa3, sa2, actstart, end);
00367     sarrayAddString(sa3, str_proc2, L_INSERT);
00368     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00369     sarrayAppendRange(sa3, sa2, actstart, end);
00370     sarrayAddString(sa3, str_low_dt, L_INSERT);
00371     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00372     sarrayAppendRange(sa3, sa2, actstart, end);
00373     sarrayAddString(sa3, str_low_ds, L_INSERT);
00374     sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
00375     sarrayAppendRange(sa3, sa2, actstart, end);
00376 
00377     if ((filestr = sarrayToString(sa3, 1)) == NULL)
00378         return ERROR_INT("filestr from sa3 not made", procName, 1);
00379     nbytes = strlen(filestr);
00380     if (filename)
00381         sprintf(bigbuf, "%s.%d.c", filename, fileindex);
00382     else
00383         sprintf(bigbuf, "%s.%d.c", OUTROOT, fileindex);
00384     l_binaryWrite(bigbuf, "w", filestr, nbytes);
00385     sarrayDestroy(&sa1);
00386     sarrayDestroy(&sa2);
00387     sarrayDestroy(&sa3);
00388     FREE(filestr);
00389     return 0;
00390 }
00391 
00392 
00393 /*!
00394  *  fhmtautogen2()
00395  *
00396  *      Input:  sel array
00397  *              fileindex
00398  *              filename (<optional>; can be null)
00399  *      Return: 0 if OK; 1 on error
00400  *
00401  *  Notes:
00402  *      (1) This function uses hmttemplate2.txt to create a
00403  *          low-level file that contains the low-level functions for
00404  *          implementing the hit-miss transform for every sel
00405  *          in the input sela.
00406  *      (2) The fileindex parameter is inserted into the output
00407  *          filename, as described below.
00408  *      (3) If filename == NULL, the output file is fhmtgenlow.<n>.c,
00409  *          where <n> is equal to the 'fileindex' parameter.
00410  *      (4) If filename != NULL, the output file is <filename>low.<n>.c.
00411  */
00412 l_int32
00413 fhmtautogen2(SELA        *sela,
00414              l_int32      fileindex,
00415              const char  *filename)
00416 {
00417 char    *filestr, *fname, *linestr;
00418 char    *str_doc1, *str_doc2, *str_doc3, *str_def1;
00419 char     bigbuf[BUFFER_SIZE];
00420 char     breakstring[] = "        break;";
00421 char     staticstring[] = "static void";
00422 l_int32  i, k, l, nsels, nbytes, nhits, nmisses;
00423 l_int32  actstart, end, newstart;
00424 l_int32  argstart, argend, loopstart, loopend, finalstart, finalend;
00425 size_t   size;
00426 SARRAY  *sa1, *sa2, *sa3, *sa4, *sa5, *sa6;
00427 SEL     *sel;
00428 
00429     PROCNAME("fhmtautogen2");
00430 
00431     if (!sela)
00432         return ERROR_INT("sela not defined", procName, 1);
00433     if (fileindex < 0)
00434         fileindex = 0;
00435     if ((nsels = selaGetCount(sela)) == 0)
00436         return ERROR_INT("no sels in sela", procName, 1);
00437     
00438         /* Make the array of textlines from hmttemplate2.txt */
00439     if ((filestr = (char *)l_binaryRead(TEMPLATE2, &size)) == NULL)
00440         return ERROR_INT("filestr not made", procName, 1);
00441     if ((sa1 = sarrayCreateLinesFromString(filestr, 1)) == NULL)
00442         return ERROR_INT("sa1 not made", procName, 1);
00443     FREE(filestr);
00444 
00445         /* Make the array of static function names */
00446     if ((sa2 = sarrayCreate(nsels)) == NULL)
00447         return ERROR_INT("sa2 not made", procName, 1);
00448     for (i = 0; i < nsels; i++) {
00449         sprintf(bigbuf, "fhmt_%d_%d", fileindex, i);
00450         sarrayAddString(sa2, bigbuf, 1);
00451     }
00452 
00453         /* Make the static prototype strings */
00454     if ((sa3 = sarrayCreate(2 * nsels)) == NULL)
00455         return ERROR_INT("sa3 not made", procName, 1);
00456     for (i = 0; i < nsels; i++) {
00457         fname = sarrayGetString(sa2, i, 0);
00458         sprintf(bigbuf, "static void  %s%s", fname, PROTOARGS);
00459         sarrayAddString(sa3, bigbuf, 1);
00460     }
00461 
00462         /* Make strings containing function names */
00463     sprintf(bigbuf, " *             l_int32    fhmtgen_low_%d()",
00464             fileindex);
00465     str_doc1 = stringNew(bigbuf);
00466     sprintf(bigbuf, " *             void       fhmt_%d_*()", fileindex);
00467     str_doc2 = stringNew(bigbuf);
00468     sprintf(bigbuf, " *  fhmtgen_low_%d()", fileindex);
00469     str_doc3 = stringNew(bigbuf);
00470     sprintf(bigbuf, "fhmtgen_low_%d(l_uint32  *datad,", fileindex);
00471     str_def1 = stringNew(bigbuf);
00472 
00473         /* Output to this sa */
00474     if ((sa4 = sarrayCreate(0)) == NULL)
00475         return ERROR_INT("sa4 not made", procName, 1);
00476 
00477         /* Copyright notice and info header */
00478     sarrayParseRange(sa1, 0, &actstart, &end, &newstart, "--", 0);
00479     sarrayAppendRange(sa4, sa1, actstart, end);
00480 
00481         /* Insert function names as documentation */
00482     sarrayAddString(sa4, str_doc1, L_INSERT);
00483     sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
00484     sarrayAppendRange(sa4, sa1, actstart, end);
00485     sarrayAddString(sa4, str_doc2, L_INSERT);
00486     sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
00487     sarrayAppendRange(sa4, sa1, actstart, end);
00488 
00489         /* Insert static protos */
00490     for (i = 0; i < nsels; i++) {
00491         if ((linestr = sarrayGetString(sa3, i, L_COPY)) == NULL)
00492             return ERROR_INT("linestr not retrieved", procName, 1);
00493         sarrayAddString(sa4, linestr, L_INSERT);
00494     }
00495         
00496         /* Insert function header */
00497     sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
00498     sarrayAppendRange(sa4, sa1, actstart, end);
00499     sarrayAddString(sa4, str_doc3, L_INSERT);
00500     sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
00501     sarrayAppendRange(sa4, sa1, actstart, end);
00502     sarrayAddString(sa4, str_def1, L_INSERT);
00503     sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
00504     sarrayAppendRange(sa4, sa1, actstart, end);
00505 
00506         /* Generate and insert the dispatcher code */
00507     for (i = 0; i < nsels; i++) {
00508         sprintf(bigbuf, "    case %d:", i);
00509         sarrayAddString(sa4, bigbuf, L_COPY);
00510         sprintf(bigbuf, "        %s(datad, w, h, wpld, datas, wpls);",
00511                sarrayGetString(sa2, i, L_NOCOPY));
00512         sarrayAddString(sa4, bigbuf, L_COPY);
00513         sarrayAddString(sa4, breakstring, L_COPY);
00514     }
00515 
00516         /* Finish the dispatcher and introduce the low-level code */
00517     sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
00518     sarrayAppendRange(sa4, sa1, actstart, end);
00519 
00520         /* Get the range for the args common to all functions */
00521     sarrayParseRange(sa1, newstart, &argstart, &argend, &newstart, "--", 0);
00522 
00523         /* Get the range for the loop code common to all functions */
00524     sarrayParseRange(sa1, newstart, &loopstart, &loopend, &newstart, "--", 0);
00525 
00526         /* Get the range for the ending code common to all functions */
00527     sarrayParseRange(sa1, newstart, &finalstart, &finalend, &newstart, "--", 0);
00528 
00529         /* Do all the static functions */
00530     for (i = 0; i < nsels; i++) {
00531             /* Generate the function header and add the common args */
00532         sarrayAddString(sa4, staticstring, L_COPY);
00533         fname = sarrayGetString(sa2, i, L_NOCOPY);
00534         sprintf(bigbuf, "%s(l_uint32  *datad,", fname);
00535         sarrayAddString(sa4, bigbuf, L_COPY);
00536         sarrayAppendRange(sa4, sa1, argstart, argend);
00537 
00538             /* Declare and define wplsN args, as necessary */
00539         if ((sel = selaGetSel(sela, i)) == NULL)
00540             return ERROR_INT("sel not returned", procName, 1);
00541         if ((sa5 = sarrayMakeWplsCode(sel)) == NULL) 
00542             return ERROR_INT("sa5 not made", procName, 1);
00543         sarrayConcatenate(sa4, sa5);
00544         sarrayDestroy(&sa5);
00545         
00546             /* Make sure sel has at least one hit */
00547         nhits = 0;
00548         nmisses = 0;
00549         for (k = 0; k < sel->sy; k++) {
00550             for (l = 0; l < sel->sx; l++) {
00551                 if (sel->data[k][l] == 1)
00552                     nhits++;
00553                 else if (sel->data[k][l] == 2)
00554                     nmisses++;
00555             }
00556         }
00557         if (nhits == 0) {
00558             linestr = stringNew("    fprintf(stderr, \"Error in HMT: no hits in sel!\\n\");\n}\n\n");
00559             sarrayAddString(sa4, linestr, L_INSERT);
00560             continue;
00561         }
00562 
00563             /* Add the function loop code */
00564         sarrayAppendRange(sa4, sa1, loopstart, loopend);
00565 
00566             /* Insert barrel-op code for *dptr */
00567         if ((sa6 = sarrayMakeInnerLoopDWACode(sel, nhits, nmisses)) == NULL)
00568             return ERROR_INT("sa6 not made", procName, 1);
00569         sarrayConcatenate(sa4, sa6);
00570         sarrayDestroy(&sa6);
00571 
00572             /* Finish the function code */
00573         sarrayAppendRange(sa4, sa1, finalstart, finalend);
00574     }
00575 
00576         /* Output to file */
00577     if ((filestr = sarrayToString(sa4, 1)) == NULL)
00578         return ERROR_INT("filestr from sa4 not made", procName, 1);
00579     nbytes = strlen(filestr);
00580     if (filename)
00581         sprintf(bigbuf, "%slow.%d.c", filename, fileindex);
00582     else
00583         sprintf(bigbuf, "%slow.%d.c", OUTROOT, fileindex);
00584     l_binaryWrite(bigbuf, "w", filestr, nbytes);
00585     sarrayDestroy(&sa1);
00586     sarrayDestroy(&sa2);
00587     sarrayDestroy(&sa3);
00588     sarrayDestroy(&sa4);
00589     FREE(filestr);
00590         
00591     return 0;
00592 }
00593 
00594 
00595 
00596 /*--------------------------------------------------------------------------*
00597  *                            Helper code for sel                           *
00598  *--------------------------------------------------------------------------*/
00599 /*!
00600  *  sarrayMakeWplsCode()
00601  */
00602 static SARRAY *
00603 sarrayMakeWplsCode(SEL  *sel)
00604 {
00605 char     spacestring[] = "    ";
00606 l_int32  i, j, ymax, dely;
00607 SARRAY  *sa;
00608 
00609     PROCNAME("sarrayMakeWplsCode");
00610 
00611     if (!sel)
00612         return (SARRAY *)ERROR_PTR("sel not defined", procName, NULL);
00613 
00614     ymax = 0;
00615     for (i = 0; i < sel->sy; i++) {
00616         for (j = 0; j < sel->sx; j++) {
00617             if (sel->data[i][j] == 1) {
00618                 dely = L_ABS(i - sel->cy);
00619                 ymax = L_MAX(ymax, dely);
00620             }
00621         }
00622     }
00623     if (ymax > 31) {
00624         L_WARNING("ymax > 31; truncating to 31", procName);
00625         ymax = 31;
00626     }
00627 
00628     if ((sa = sarrayCreate(0)) == NULL)
00629         return (SARRAY *)ERROR_PTR("sa not made", procName, NULL);
00630 
00631         /* Declarations */
00632     if (ymax > 4)
00633         sarrayAddString(sa, wpldecls[2], 1);
00634     if (ymax > 8)
00635         sarrayAddString(sa, wpldecls[6], 1);
00636     if (ymax > 12)
00637         sarrayAddString(sa, wpldecls[10], 1);
00638     if (ymax > 16)
00639         sarrayAddString(sa, wpldecls[14], 1);
00640     if (ymax > 20)
00641         sarrayAddString(sa, wpldecls[18], 1);
00642     if (ymax > 24)
00643         sarrayAddString(sa, wpldecls[22], 1);
00644     if (ymax > 28)
00645         sarrayAddString(sa, wpldecls[26], 1);
00646     if (ymax > 1)
00647         sarrayAddString(sa, wpldecls[ymax - 2], 1);
00648 
00649     sarrayAddString(sa, spacestring, 1);
00650 
00651         /* Definitions */
00652     for (i = 2; i <= ymax; i++)
00653         sarrayAddString(sa, wpldefs[i - 2], 1);
00654 
00655     return sa;
00656 }
00657 
00658 
00659 /*!
00660  *  sarrayMakeInnerLoopDWACode()
00661  */
00662 static SARRAY *
00663 sarrayMakeInnerLoopDWACode(SEL     *sel,
00664                            l_int32  nhits,
00665                            l_int32  nmisses)
00666 {
00667 char    *string;
00668 char     land[] = "&";
00669 char     bigbuf[BUFFER_SIZE];
00670 l_int32  i, j, ntot, nfound, type, delx, dely;
00671 SARRAY  *sa;
00672 
00673     PROCNAME("sarrayMakeInnerLoopDWACode");
00674 
00675     if (!sel)
00676         return (SARRAY *)ERROR_PTR("sel not defined", procName, NULL);
00677 
00678     if ((sa = sarrayCreate(0)) == NULL)
00679         return (SARRAY *)ERROR_PTR("sa not made", procName, NULL);
00680 
00681     ntot = nhits + nmisses;
00682     nfound = 0;
00683     for (i = 0; i < sel->sy; i++) {
00684         for (j = 0; j < sel->sx; j++) {
00685             type = sel->data[i][j];
00686             if (type == SEL_HIT || type == SEL_MISS) {
00687                 nfound++;
00688                 dely = i - sel->cy;
00689                 delx = j - sel->cx;
00690                 if ((string = makeBarrelshiftString(delx, dely, type))
00691                         == NULL) {
00692                     L_WARNING("barrel shift string not made", procName);
00693                     continue;
00694                 }
00695                 if (ntot == 1)  /* just one item */
00696                     sprintf(bigbuf, "            *dptr = %s;", string);
00697                 else if (nfound == 1)
00698                     sprintf(bigbuf, "            *dptr = %s %s", string, land);
00699                 else if (nfound < ntot)
00700                     sprintf(bigbuf, "                    %s %s", string, land);
00701                 else  /* nfound == ntot */
00702                     sprintf(bigbuf, "                    %s;", string);
00703                 sarrayAddString(sa, bigbuf, 1);
00704                 FREE(string);
00705             }
00706         }
00707     }
00708 
00709     return sa;
00710 }
00711 
00712 
00713 /*!
00714  *  makeBarrelshiftString()
00715  */
00716 static char *
00717 makeBarrelshiftString(l_int32  delx,    /* j - cx */
00718                       l_int32  dely,    /* i - cy */
00719                       l_int32  type)    /* SEL_HIT or SEL_MISS */
00720 {
00721 l_int32  absx, absy;
00722 char     bigbuf[BUFFER_SIZE];
00723 
00724     PROCNAME("makeBarrelshiftString");
00725 
00726     if (delx < -31 || delx > 31)
00727         return (char *)ERROR_PTR("delx out of bounds", procName, NULL);
00728     if (dely < -31 || dely > 31)
00729         return (char *)ERROR_PTR("dely out of bounds", procName, NULL);
00730     absx = L_ABS(delx);
00731     absy = L_ABS(dely);
00732 
00733     if (type == SEL_HIT) {
00734         if ((delx == 0) && (dely == 0))
00735             sprintf(bigbuf, "(*sptr)");
00736         else if ((delx == 0) && (dely < 0))
00737             sprintf(bigbuf, "(*(sptr %s))", wplstrm[absy - 1]);
00738         else if ((delx == 0) && (dely > 0))
00739             sprintf(bigbuf, "(*(sptr %s))", wplstrp[absy - 1]);
00740         else if ((delx < 0) && (dely == 0))
00741             sprintf(bigbuf, "((*(sptr) >> %d) | (*(sptr - 1) << %d))",
00742                   absx, 32 - absx);
00743         else if ((delx > 0) && (dely == 0))
00744             sprintf(bigbuf, "((*(sptr) << %d) | (*(sptr + 1) >> %d))",
00745                   absx, 32 - absx);
00746         else if ((delx < 0) && (dely < 0))
00747             sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))",
00748                   wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx);
00749         else if ((delx > 0) && (dely < 0))
00750             sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))",
00751                   wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx);
00752         else if ((delx < 0) && (dely > 0))
00753             sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))",
00754                   wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx);
00755         else  /*  ((delx > 0) && (dely > 0))  */
00756             sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))",
00757                   wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx);
00758     }
00759     else {  /* type == SEL_MISS */
00760         if ((delx == 0) && (dely == 0))
00761             sprintf(bigbuf, "(~*sptr)");
00762         else if ((delx == 0) && (dely < 0))
00763             sprintf(bigbuf, "(~*(sptr %s))", wplstrm[absy - 1]);
00764         else if ((delx == 0) && (dely > 0))
00765             sprintf(bigbuf, "(~*(sptr %s))", wplstrp[absy - 1]);
00766         else if ((delx < 0) && (dely == 0))
00767             sprintf(bigbuf, "((~*(sptr) >> %d) | (~*(sptr - 1) << %d))",
00768                   absx, 32 - absx);
00769         else if ((delx > 0) && (dely == 0))
00770             sprintf(bigbuf, "((~*(sptr) << %d) | (~*(sptr + 1) >> %d))",
00771                   absx, 32 - absx);
00772         else if ((delx < 0) && (dely < 0))
00773             sprintf(bigbuf, "((~*(sptr %s) >> %d) | (~*(sptr %s - 1) << %d))",
00774                   wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx);
00775         else if ((delx > 0) && (dely < 0))
00776             sprintf(bigbuf, "((~*(sptr %s) << %d) | (~*(sptr %s + 1) >> %d))",
00777                   wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx);
00778         else if ((delx < 0) && (dely > 0))
00779             sprintf(bigbuf, "((~*(sptr %s) >> %d) | (~*(sptr %s - 1) << %d))",
00780                   wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx);
00781         else  /*  ((delx > 0) && (dely > 0))  */
00782             sprintf(bigbuf, "((~*(sptr %s) << %d) | (~*(sptr %s + 1) >> %d))",
00783                   wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx);
00784     }
00785             
00786     return stringNew(bigbuf);
00787 }
00788 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines