Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/leptonica/src/fhmtauto.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*====================================================================* | |
| 2 - Copyright (C) 2001 Leptonica. All rights reserved. | |
| 3 - | |
| 4 - Redistribution and use in source and binary forms, with or without | |
| 5 - modification, are permitted provided that the following conditions | |
| 6 - are met: | |
| 7 - 1. Redistributions of source code must retain the above copyright | |
| 8 - notice, this list of conditions and the following disclaimer. | |
| 9 - 2. Redistributions in binary form must reproduce the above | |
| 10 - copyright notice, this list of conditions and the following | |
| 11 - disclaimer in the documentation and/or other materials | |
| 12 - provided with the distribution. | |
| 13 - | |
| 14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY | |
| 18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 25 *====================================================================*/ | |
| 26 | |
| 27 | |
| 28 /*! | |
| 29 * \file fhmtauto.c | |
| 30 * <pre> | |
| 31 * | |
| 32 * Main function calls: | |
| 33 * l_int32 fhmtautogen() | |
| 34 * l_int32 fhmtautogen1() | |
| 35 * l_int32 fhmtautogen2() | |
| 36 * | |
| 37 * Static helpers: | |
| 38 * static SARRAY *sarrayMakeWplsCode() | |
| 39 * static SARRAY *sarrayMakeInnerLoopDWACode() | |
| 40 * static char *makeBarrelshiftString() | |
| 41 * | |
| 42 * This automatically generates dwa code for the hit-miss transform. | |
| 43 * Here's a road map for how it all works. | |
| 44 * | |
| 45 * (1) You generate an array (a SELA) of hit-miss transform SELs. | |
| 46 * This can be done in several ways, including | |
| 47 * (a) calling the function selaAddHitMiss() for | |
| 48 * pre-compiled SELs | |
| 49 * (b) generating the SELA in code in line | |
| 50 * (c) reading in a SELA from file, using selaRead() | |
| 51 * or various other formats. | |
| 52 * | |
| 53 * (2) You call fhmtautogen1() and fhmtautogen2() on this SELA. | |
| 54 * This uses the text files hmttemplate1.txt and | |
| 55 * hmttemplate2.txt for building up the source code. See the file | |
| 56 * prog/fhmtautogen.c for an example of how this is done. | |
| 57 * The output is written to files named fhmtgen.*.c | |
| 58 * and fhmtgenlow.*.c, where "*" is an integer that you | |
| 59 * input to this function. That integer labels both | |
| 60 * the output files, as well as all the functions that | |
| 61 * are generated. That way, using different integers, | |
| 62 * you can invoke fhmtautogen() any number of times | |
| 63 * to get functions that all have different names so that | |
| 64 * they can be linked into one program. | |
| 65 * | |
| 66 * (3) You copy the generated source code back to your src | |
| 67 * directory for compilation. Put their names in the | |
| 68 * Makefile, regnerate the prototypes, and recompile | |
| 69 * the libraries. Look at the Makefile to see how I've | |
| 70 * included fhmtgen.1.c and fhmtgenlow.1.c. These files | |
| 71 * provide the single high-level interface for the hmt, and | |
| 72 * the lower-level functions to do the actual work. | |
| 73 * | |
| 74 * (4) In an application, you now use this interface. Again | |
| 75 * for the example files generated, using integer "1": | |
| 76 * | |
| 77 * PIX *pixHMTDwa_1(PIX *pixd, PIX *pixs, const char *selname); | |
| 78 * | |
| 79 * where the selname is one of the set that were defined | |
| 80 * as the name field of sels. This set is listed at the | |
| 81 * beginning of the file fhmtgen.1.c. | |
| 82 * | |
| 83 * N.B. Although pixFHMTGen_1() is global, you must NOT | |
| 84 * use it, because it assumes that 32 or 64 border pixels | |
| 85 * have been added to each side, and it will crash without those | |
| 86 * added pixels. | |
| 87 * | |
| 88 * As an example, see the file prog/fhmtauto_reg.c, which | |
| 89 * verifies the correctness of the implementation by | |
| 90 * comparing the dwa result with that of full-image | |
| 91 * rasterops. | |
| 92 * </pre> | |
| 93 */ | |
| 94 | |
| 95 #ifdef HAVE_CONFIG_H | |
| 96 #include <config_auto.h> | |
| 97 #endif /* HAVE_CONFIG_H */ | |
| 98 | |
| 99 #include <string.h> | |
| 100 #include "allheaders.h" | |
| 101 | |
| 102 #define OUTROOT "fhmtgen" | |
| 103 #define TEMPLATE1 "hmttemplate1.txt" | |
| 104 #define TEMPLATE2 "hmttemplate2.txt" | |
| 105 | |
| 106 #define PROTOARGS "(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);" | |
| 107 | |
| 108 #define L_BUF_SIZE 512 | |
| 109 | |
| 110 static char * makeBarrelshiftString(l_int32 delx, l_int32 dely, l_int32 type); | |
| 111 static SARRAY * sarrayMakeInnerLoopDWACode(SEL *sel, l_int32 nhits, l_int32 nmisses); | |
| 112 static SARRAY * sarrayMakeWplsCode(SEL *sel); | |
| 113 | |
| 114 static char wpldecls[][60] = { | |
| 115 "l_int32 wpls2;", | |
| 116 "l_int32 wpls2, wpls3;", | |
| 117 "l_int32 wpls2, wpls3, wpls4;", | |
| 118 "l_int32 wpls5;", | |
| 119 "l_int32 wpls5, wpls6;", | |
| 120 "l_int32 wpls5, wpls6, wpls7;", | |
| 121 "l_int32 wpls5, wpls6, wpls7, wpls8;", | |
| 122 "l_int32 wpls9;", | |
| 123 "l_int32 wpls9, wpls10;", | |
| 124 "l_int32 wpls9, wpls10, wpls11;", | |
| 125 "l_int32 wpls9, wpls10, wpls11, wpls12;", | |
| 126 "l_int32 wpls13;", | |
| 127 "l_int32 wpls13, wpls14;", | |
| 128 "l_int32 wpls13, wpls14, wpls15;", | |
| 129 "l_int32 wpls13, wpls14, wpls15, wpls16;", | |
| 130 "l_int32 wpls17;", | |
| 131 "l_int32 wpls17, wpls18;", | |
| 132 "l_int32 wpls17, wpls18, wpls19;", | |
| 133 "l_int32 wpls17, wpls18, wpls19, wpls20;", | |
| 134 "l_int32 wpls21;", | |
| 135 "l_int32 wpls21, wpls22;", | |
| 136 "l_int32 wpls21, wpls22, wpls23;", | |
| 137 "l_int32 wpls21, wpls22, wpls23, wpls24;", | |
| 138 "l_int32 wpls25;", | |
| 139 "l_int32 wpls25, wpls26;", | |
| 140 "l_int32 wpls25, wpls26, wpls27;", | |
| 141 "l_int32 wpls25, wpls26, wpls27, wpls28;", | |
| 142 "l_int32 wpls29;", | |
| 143 "l_int32 wpls29, wpls30;", | |
| 144 "l_int32 wpls29, wpls30, wpls31;"}; | |
| 145 | |
| 146 static char wpldefs[][24] = { | |
| 147 " wpls2 = 2 * wpls;", | |
| 148 " wpls3 = 3 * wpls;", | |
| 149 " wpls4 = 4 * wpls;", | |
| 150 " wpls5 = 5 * wpls;", | |
| 151 " wpls6 = 6 * wpls;", | |
| 152 " wpls7 = 7 * wpls;", | |
| 153 " wpls8 = 8 * wpls;", | |
| 154 " wpls9 = 9 * wpls;", | |
| 155 " wpls10 = 10 * wpls;", | |
| 156 " wpls11 = 11 * wpls;", | |
| 157 " wpls12 = 12 * wpls;", | |
| 158 " wpls13 = 13 * wpls;", | |
| 159 " wpls14 = 14 * wpls;", | |
| 160 " wpls15 = 15 * wpls;", | |
| 161 " wpls16 = 16 * wpls;", | |
| 162 " wpls17 = 17 * wpls;", | |
| 163 " wpls18 = 18 * wpls;", | |
| 164 " wpls19 = 19 * wpls;", | |
| 165 " wpls20 = 20 * wpls;", | |
| 166 " wpls21 = 21 * wpls;", | |
| 167 " wpls22 = 22 * wpls;", | |
| 168 " wpls23 = 23 * wpls;", | |
| 169 " wpls24 = 24 * wpls;", | |
| 170 " wpls25 = 25 * wpls;", | |
| 171 " wpls26 = 26 * wpls;", | |
| 172 " wpls27 = 27 * wpls;", | |
| 173 " wpls28 = 28 * wpls;", | |
| 174 " wpls29 = 29 * wpls;", | |
| 175 " wpls30 = 30 * wpls;", | |
| 176 " wpls31 = 31 * wpls;"}; | |
| 177 | |
| 178 static char wplstrp[][10] = {"+ wpls", "+ wpls2", "+ wpls3", "+ wpls4", | |
| 179 "+ wpls5", "+ wpls6", "+ wpls7", "+ wpls8", | |
| 180 "+ wpls9", "+ wpls10", "+ wpls11", "+ wpls12", | |
| 181 "+ wpls13", "+ wpls14", "+ wpls15", "+ wpls16", | |
| 182 "+ wpls17", "+ wpls18", "+ wpls19", "+ wpls20", | |
| 183 "+ wpls21", "+ wpls22", "+ wpls23", "+ wpls24", | |
| 184 "+ wpls25", "+ wpls26", "+ wpls27", "+ wpls28", | |
| 185 "+ wpls29", "+ wpls30", "+ wpls31"}; | |
| 186 | |
| 187 static char wplstrm[][10] = {"- wpls", "- wpls2", "- wpls3", "- wpls4", | |
| 188 "- wpls5", "- wpls6", "- wpls7", "- wpls8", | |
| 189 "- wpls9", "- wpls10", "- wpls11", "- wpls12", | |
| 190 "- wpls13", "- wpls14", "- wpls15", "- wpls16", | |
| 191 "- wpls17", "- wpls18", "- wpls19", "- wpls20", | |
| 192 "- wpls21", "- wpls22", "- wpls23", "- wpls24", | |
| 193 "- wpls25", "- wpls26", "- wpls27", "- wpls28", | |
| 194 "- wpls29", "- wpls30", "- wpls31"}; | |
| 195 | |
| 196 | |
| 197 /*! | |
| 198 * \brief fhmtautogen() | |
| 199 * | |
| 200 * \param[in] sela | |
| 201 * \param[in] fileindex | |
| 202 * \param[in] filename [optional]; can be null | |
| 203 * \return 0 if OK; 1 on error | |
| 204 * | |
| 205 * <pre> | |
| 206 * Notes: | |
| 207 * (1) This function generates all the code for implementing | |
| 208 * dwa morphological operations using all the sels in the sela. | |
| 209 * (2) See fhmtautogen1() and fhmtautogen2() for details. | |
| 210 * </pre> | |
| 211 */ | |
| 212 l_ok | |
| 213 fhmtautogen(SELA *sela, | |
| 214 l_int32 fileindex, | |
| 215 const char *filename) | |
| 216 { | |
| 217 l_int32 ret1, ret2; | |
| 218 | |
| 219 if (!sela) | |
| 220 return ERROR_INT("sela not defined", __func__, 1); | |
| 221 ret1 = fhmtautogen1(sela, fileindex, filename); | |
| 222 ret2 = fhmtautogen2(sela, fileindex, filename); | |
| 223 if (ret1 || ret2) | |
| 224 return ERROR_INT("code generation problem", __func__, 1); | |
| 225 return 0; | |
| 226 } | |
| 227 | |
| 228 | |
| 229 /*! | |
| 230 * \brief fhmtautogen1() | |
| 231 * | |
| 232 * \param[in] sela array | |
| 233 * \param[in] fileindex | |
| 234 * \param[in] filename [optional]; can be null | |
| 235 * \return 0 if OK; 1 on error | |
| 236 * | |
| 237 * <pre> | |
| 238 * Notes: | |
| 239 * (1) This function uses hmttemplate1.txt to create a | |
| 240 * top-level file that contains two functions that carry | |
| 241 * out the hit-miss transform for any of the sels in | |
| 242 * the input sela. | |
| 243 * (2) The fileindex parameter is inserted into the output | |
| 244 * filename, as described below. | |
| 245 * (3) If filename == NULL, the output file is fhmtgen.[n].c, | |
| 246 * where [n] is equal to the 'fileindex' parameter. | |
| 247 * (4) If filename != NULL, the output file is [filename].[n].c. | |
| 248 * (5) Each sel must have at least one hit. A sel with only misses | |
| 249 * generates code that will abort the operation if it is called. | |
| 250 * </pre> | |
| 251 */ | |
| 252 l_ok | |
| 253 fhmtautogen1(SELA *sela, | |
| 254 l_int32 fileindex, | |
| 255 const char *filename) | |
| 256 { | |
| 257 char *filestr; | |
| 258 char *str_proto1, *str_proto2, *str_proto3; | |
| 259 char *str_doc1, *str_doc2, *str_doc3, *str_doc4; | |
| 260 char *str_def1, *str_def2, *str_proc1, *str_proc2; | |
| 261 char *str_dwa1, *str_low_dt, *str_low_ds; | |
| 262 char bigbuf[L_BUF_SIZE]; | |
| 263 l_int32 i, nsels, nbytes, actstart, end, newstart; | |
| 264 size_t size; | |
| 265 SARRAY *sa1, *sa2, *sa3; | |
| 266 | |
| 267 if (!sela) | |
| 268 return ERROR_INT("sela not defined", __func__, 1); | |
| 269 if (fileindex < 0) | |
| 270 fileindex = 0; | |
| 271 if ((nsels = selaGetCount(sela)) == 0) | |
| 272 return ERROR_INT("no sels in sela", __func__, 1); | |
| 273 | |
| 274 /* Make array of textlines from from hmttemplate1.txt */ | |
| 275 if ((filestr = (char *)l_binaryRead(TEMPLATE1, &size)) == NULL) | |
| 276 return ERROR_INT("filestr not made", __func__, 1); | |
| 277 sa2 = sarrayCreateLinesFromString(filestr, 1); | |
| 278 LEPT_FREE(filestr); | |
| 279 if (!sa2) | |
| 280 return ERROR_INT("sa2 not made", __func__, 1); | |
| 281 | |
| 282 /* Make array of sel names */ | |
| 283 sa1 = selaGetSelnames(sela); | |
| 284 | |
| 285 /* Make strings containing function call names */ | |
| 286 sprintf(bigbuf, "PIX *pixHMTDwa_%d(PIX *pixd, PIX *pixs, " | |
| 287 "const char *selname);", fileindex); | |
| 288 str_proto1 = stringNew(bigbuf); | |
| 289 sprintf(bigbuf, "PIX *pixFHMTGen_%d(PIX *pixd, PIX *pixs, " | |
| 290 "const char *selname);", fileindex); | |
| 291 str_proto2 = stringNew(bigbuf); | |
| 292 sprintf(bigbuf, "l_int32 fhmtgen_low_%d(l_uint32 *datad, l_int32 w,\n" | |
| 293 " l_int32 h, l_int32 wpld,\n" | |
| 294 " l_uint32 *datas, l_int32 wpls,\n" | |
| 295 " l_int32 index);", fileindex); | |
| 296 str_proto3 = stringNew(bigbuf); | |
| 297 sprintf(bigbuf, " * PIX *pixHMTDwa_%d()", fileindex); | |
| 298 str_doc1 = stringNew(bigbuf); | |
| 299 sprintf(bigbuf, " * PIX *pixFHMTGen_%d()", fileindex); | |
| 300 str_doc2 = stringNew(bigbuf); | |
| 301 sprintf(bigbuf, " * \\brief pixHMTDwa_%d()", fileindex); | |
| 302 str_doc3 = stringNew(bigbuf); | |
| 303 sprintf(bigbuf, " * \\brief pixFHMTGen_%d()", fileindex); | |
| 304 str_doc4 = stringNew(bigbuf); | |
| 305 sprintf(bigbuf, "pixHMTDwa_%d(PIX *pixd,", fileindex); | |
| 306 str_def1 = stringNew(bigbuf); | |
| 307 sprintf(bigbuf, "pixFHMTGen_%d(PIX *pixd,", fileindex); | |
| 308 str_def2 = stringNew(bigbuf); | |
| 309 sprintf(bigbuf, " PROCNAME(\"pixHMTDwa_%d\");", fileindex); | |
| 310 str_proc1 = stringNew(bigbuf); | |
| 311 sprintf(bigbuf, " PROCNAME(\"pixFHMTGen_%d\");", fileindex); | |
| 312 str_proc2 = stringNew(bigbuf); | |
| 313 sprintf(bigbuf, " pixt2 = pixFHMTGen_%d(NULL, pixt1, selname);", | |
| 314 fileindex); | |
| 315 str_dwa1 = stringNew(bigbuf); | |
| 316 sprintf(bigbuf, | |
| 317 " fhmtgen_low_%d(datad, w, h, wpld, datat, wpls, index);", | |
| 318 fileindex); | |
| 319 str_low_dt = stringNew(bigbuf); | |
| 320 sprintf(bigbuf, | |
| 321 " fhmtgen_low_%d(datad, w, h, wpld, datas, wpls, index);", | |
| 322 fileindex); | |
| 323 str_low_ds = stringNew(bigbuf); | |
| 324 | |
| 325 /* Make the output sa */ | |
| 326 sa3 = sarrayCreate(0); | |
| 327 | |
| 328 /* Copyright notice and info header */ | |
| 329 sarrayParseRange(sa2, 0, &actstart, &end, &newstart, "--", 0); | |
| 330 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 331 | |
| 332 /* Insert function names as documentation */ | |
| 333 sarrayAddString(sa3, str_doc1, L_INSERT); | |
| 334 sarrayAddString(sa3, str_doc2, L_INSERT); | |
| 335 | |
| 336 /* Add '#include's */ | |
| 337 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 338 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 339 | |
| 340 /* Insert function prototypes */ | |
| 341 sarrayAddString(sa3, str_proto1, L_INSERT); | |
| 342 sarrayAddString(sa3, str_proto2, L_INSERT); | |
| 343 sarrayAddString(sa3, str_proto3, L_INSERT); | |
| 344 | |
| 345 /* Add static globals */ | |
| 346 sprintf(bigbuf, "\nstatic l_int32 NUM_SELS_GENERATED = %d;", nsels); | |
| 347 sarrayAddString(sa3, bigbuf, L_COPY); | |
| 348 sprintf(bigbuf, "static char SEL_NAMES[][80] = {"); | |
| 349 sarrayAddString(sa3, bigbuf, L_COPY); | |
| 350 for (i = 0; i < nsels - 1; i++) { | |
| 351 sprintf(bigbuf, " \"%s\",", | |
| 352 sarrayGetString(sa1, i, L_NOCOPY)); | |
| 353 sarrayAddString(sa3, bigbuf, L_COPY); | |
| 354 } | |
| 355 sprintf(bigbuf, " \"%s\"};", | |
| 356 sarrayGetString(sa1, i, L_NOCOPY)); | |
| 357 sarrayAddString(sa3, bigbuf, L_COPY); | |
| 358 | |
| 359 /* Start pixHMTDwa_*() function description */ | |
| 360 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 361 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 362 sarrayAddString(sa3, str_doc3, L_INSERT); | |
| 363 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 364 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 365 | |
| 366 /* Finish pixHMTDwa_*() function definition */ | |
| 367 sarrayAddString(sa3, str_def1, L_INSERT); | |
| 368 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 369 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 370 sarrayAddString(sa3, str_proc1, L_INSERT); | |
| 371 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 372 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 373 sarrayAddString(sa3, str_dwa1, L_INSERT); | |
| 374 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 375 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 376 | |
| 377 /* Start pixFHMTGen_*() function description */ | |
| 378 sarrayAddString(sa3, str_doc4, L_INSERT); | |
| 379 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 380 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 381 | |
| 382 /* Finish pixFHMTGen_*() function description */ | |
| 383 sarrayAddString(sa3, str_def2, L_INSERT); | |
| 384 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 385 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 386 sarrayAddString(sa3, str_proc2, L_INSERT); | |
| 387 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 388 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 389 sarrayAddString(sa3, str_low_dt, L_INSERT); | |
| 390 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 391 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 392 sarrayAddString(sa3, str_low_ds, L_INSERT); | |
| 393 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); | |
| 394 sarrayAppendRange(sa3, sa2, actstart, end); | |
| 395 | |
| 396 filestr = sarrayToString(sa3, 1); | |
| 397 nbytes = strlen(filestr); | |
| 398 if (filename) | |
| 399 snprintf(bigbuf, L_BUF_SIZE, "%s.%d.c", filename, fileindex); | |
| 400 else | |
| 401 sprintf(bigbuf, "%s.%d.c", OUTROOT, fileindex); | |
| 402 l_binaryWrite(bigbuf, "w", filestr, nbytes); | |
| 403 sarrayDestroy(&sa1); | |
| 404 sarrayDestroy(&sa2); | |
| 405 sarrayDestroy(&sa3); | |
| 406 LEPT_FREE(filestr); | |
| 407 return 0; | |
| 408 } | |
| 409 | |
| 410 | |
| 411 /*! | |
| 412 * \brief fhmtautogen2() | |
| 413 * | |
| 414 * \param[in] sela array | |
| 415 * \param[in] fileindex | |
| 416 * \param[in] filename [optional]; can be null | |
| 417 * \return 0 if OK; 1 on error | |
| 418 * | |
| 419 * <pre> | |
| 420 * Notes: | |
| 421 * (1) This function uses hmttemplate2.txt to create a | |
| 422 * low-level file that contains the low-level functions for | |
| 423 * implementing the hit-miss transform for every sel | |
| 424 * in the input sela. | |
| 425 * (2) The fileindex parameter is inserted into the output | |
| 426 * filename, as described below. | |
| 427 * (3) If filename == NULL, the output file is fhmtgenlow.[n].c, | |
| 428 * where [n] is equal to the %fileindex parameter. | |
| 429 * (4) If filename != NULL, the output file is [filename]low.[n].c. | |
| 430 * </pre> | |
| 431 */ | |
| 432 l_ok | |
| 433 fhmtautogen2(SELA *sela, | |
| 434 l_int32 fileindex, | |
| 435 const char *filename) | |
| 436 { | |
| 437 char *filestr, *fname, *linestr; | |
| 438 char *str_doc1, *str_doc2, *str_doc3, *str_def1; | |
| 439 char bigbuf[L_BUF_SIZE]; | |
| 440 char breakstring[] = " break;"; | |
| 441 char staticstring[] = "static void"; | |
| 442 l_int32 i, k, l, nsels, nbytes, nhits, nmisses; | |
| 443 l_int32 actstart, end, newstart; | |
| 444 l_int32 argstart, argend, loopstart, loopend, finalstart, finalend; | |
| 445 size_t size; | |
| 446 SARRAY *sa1, *sa2, *sa3, *sa4, *sa5, *sa6; | |
| 447 SEL *sel; | |
| 448 | |
| 449 if (!sela) | |
| 450 return ERROR_INT("sela not defined", __func__, 1); | |
| 451 if (fileindex < 0) | |
| 452 fileindex = 0; | |
| 453 if ((nsels = selaGetCount(sela)) == 0) | |
| 454 return ERROR_INT("no sels in sela", __func__, 1); | |
| 455 | |
| 456 /* Make the array of textlines from hmttemplate2.txt */ | |
| 457 if ((filestr = (char *)l_binaryRead(TEMPLATE2, &size)) == NULL) | |
| 458 return ERROR_INT("filestr not made", __func__, 1); | |
| 459 sa1 = sarrayCreateLinesFromString(filestr, 1); | |
| 460 LEPT_FREE(filestr); | |
| 461 if (!sa1) | |
| 462 return ERROR_INT("sa1 not made", __func__, 1); | |
| 463 | |
| 464 /* Make the array of static function names */ | |
| 465 if ((sa2 = sarrayCreate(nsels)) == NULL) { | |
| 466 sarrayDestroy(&sa1); | |
| 467 return ERROR_INT("sa2 not made", __func__, 1); | |
| 468 } | |
| 469 for (i = 0; i < nsels; i++) { | |
| 470 sprintf(bigbuf, "fhmt_%d_%d", fileindex, i); | |
| 471 sarrayAddString(sa2, bigbuf, L_COPY); | |
| 472 } | |
| 473 | |
| 474 /* Make the static prototype strings */ | |
| 475 sa3 = sarrayCreate(2 * nsels); /* should be ok */ | |
| 476 for (i = 0; i < nsels; i++) { | |
| 477 fname = sarrayGetString(sa2, i, L_NOCOPY); | |
| 478 sprintf(bigbuf, "static void %s%s", fname, PROTOARGS); | |
| 479 sarrayAddString(sa3, bigbuf, L_COPY); | |
| 480 } | |
| 481 | |
| 482 /* Make strings containing function names */ | |
| 483 sprintf(bigbuf, " * l_int32 fhmtgen_low_%d()", | |
| 484 fileindex); | |
| 485 str_doc1 = stringNew(bigbuf); | |
| 486 sprintf(bigbuf, " * void fhmt_%d_*()", fileindex); | |
| 487 str_doc2 = stringNew(bigbuf); | |
| 488 | |
| 489 /* Output to this sa */ | |
| 490 sa4 = sarrayCreate(0); | |
| 491 | |
| 492 /* Copyright notice and info header */ | |
| 493 sarrayParseRange(sa1, 0, &actstart, &end, &newstart, "--", 0); | |
| 494 sarrayAppendRange(sa4, sa1, actstart, end); | |
| 495 | |
| 496 /* Insert function names as documentation */ | |
| 497 sarrayAddString(sa4, str_doc1, L_INSERT); | |
| 498 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); | |
| 499 sarrayAppendRange(sa4, sa1, actstart, end); | |
| 500 sarrayAddString(sa4, str_doc2, L_INSERT); | |
| 501 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); | |
| 502 sarrayAppendRange(sa4, sa1, actstart, end); | |
| 503 | |
| 504 /* Insert static protos */ | |
| 505 for (i = 0; i < nsels; i++) { | |
| 506 if ((linestr = sarrayGetString(sa3, i, L_COPY)) == NULL) { | |
| 507 sarrayDestroy(&sa1); | |
| 508 sarrayDestroy(&sa2); | |
| 509 sarrayDestroy(&sa3); | |
| 510 sarrayDestroy(&sa4); | |
| 511 return ERROR_INT("linestr not retrieved", __func__, 1); | |
| 512 } | |
| 513 sarrayAddString(sa4, linestr, L_INSERT); | |
| 514 } | |
| 515 | |
| 516 /* Make more strings containing function names */ | |
| 517 sprintf(bigbuf, " * fhmtgen_low_%d()", fileindex); | |
| 518 str_doc3 = stringNew(bigbuf); | |
| 519 sprintf(bigbuf, "fhmtgen_low_%d(l_uint32 *datad,", fileindex); | |
| 520 str_def1 = stringNew(bigbuf); | |
| 521 | |
| 522 /* Insert function header */ | |
| 523 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); | |
| 524 sarrayAppendRange(sa4, sa1, actstart, end); | |
| 525 sarrayAddString(sa4, str_doc3, L_INSERT); | |
| 526 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); | |
| 527 sarrayAppendRange(sa4, sa1, actstart, end); | |
| 528 sarrayAddString(sa4, str_def1, L_INSERT); | |
| 529 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); | |
| 530 sarrayAppendRange(sa4, sa1, actstart, end); | |
| 531 | |
| 532 /* Generate and insert the dispatcher code */ | |
| 533 for (i = 0; i < nsels; i++) { | |
| 534 sprintf(bigbuf, " case %d:", i); | |
| 535 sarrayAddString(sa4, bigbuf, L_COPY); | |
| 536 sprintf(bigbuf, " %s(datad, w, h, wpld, datas, wpls);", | |
| 537 sarrayGetString(sa2, i, L_NOCOPY)); | |
| 538 sarrayAddString(sa4, bigbuf, L_COPY); | |
| 539 sarrayAddString(sa4, breakstring, L_COPY); | |
| 540 } | |
| 541 | |
| 542 /* Finish the dispatcher and introduce the low-level code */ | |
| 543 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); | |
| 544 sarrayAppendRange(sa4, sa1, actstart, end); | |
| 545 | |
| 546 /* Get the range for the args common to all functions */ | |
| 547 sarrayParseRange(sa1, newstart, &argstart, &argend, &newstart, "--", 0); | |
| 548 | |
| 549 /* Get the range for the loop code common to all functions */ | |
| 550 sarrayParseRange(sa1, newstart, &loopstart, &loopend, &newstart, "--", 0); | |
| 551 | |
| 552 /* Get the range for the ending code common to all functions */ | |
| 553 sarrayParseRange(sa1, newstart, &finalstart, &finalend, &newstart, "--", 0); | |
| 554 | |
| 555 /* Do all the static functions */ | |
| 556 for (i = 0; i < nsels; i++) { | |
| 557 /* Generate the function header and add the common args */ | |
| 558 sarrayAddString(sa4, staticstring, L_COPY); | |
| 559 fname = sarrayGetString(sa2, i, L_NOCOPY); | |
| 560 sprintf(bigbuf, "%s(l_uint32 *datad,", fname); | |
| 561 sarrayAddString(sa4, bigbuf, L_COPY); | |
| 562 sarrayAppendRange(sa4, sa1, argstart, argend); | |
| 563 | |
| 564 /* Declare and define wplsN args, as necessary */ | |
| 565 if ((sel = selaGetSel(sela, i)) == NULL) { | |
| 566 sarrayDestroy(&sa1); | |
| 567 sarrayDestroy(&sa2); | |
| 568 sarrayDestroy(&sa3); | |
| 569 sarrayDestroy(&sa4); | |
| 570 return ERROR_INT("sel not returned", __func__, 1); | |
| 571 } | |
| 572 sa5 = sarrayMakeWplsCode(sel); | |
| 573 sarrayJoin(sa4, sa5); | |
| 574 sarrayDestroy(&sa5); | |
| 575 | |
| 576 /* Make sure sel has at least one hit */ | |
| 577 nhits = 0; | |
| 578 nmisses = 0; | |
| 579 for (k = 0; k < sel->sy; k++) { | |
| 580 for (l = 0; l < sel->sx; l++) { | |
| 581 if (sel->data[k][l] == 1) | |
| 582 nhits++; | |
| 583 else if (sel->data[k][l] == 2) | |
| 584 nmisses++; | |
| 585 } | |
| 586 } | |
| 587 if (nhits == 0) { | |
| 588 linestr = stringNew(" " | |
| 589 "lept_stderr(\"Error in HMT: no hits in sel!\\n\");\n}\n\n"); | |
| 590 sarrayAddString(sa4, linestr, L_INSERT); | |
| 591 continue; | |
| 592 } | |
| 593 | |
| 594 /* Add the function loop code */ | |
| 595 sarrayAppendRange(sa4, sa1, loopstart, loopend); | |
| 596 | |
| 597 /* Insert barrel-op code for *dptr */ | |
| 598 if ((sa6 = sarrayMakeInnerLoopDWACode(sel, nhits, nmisses)) == NULL) { | |
| 599 sarrayDestroy(&sa1); | |
| 600 sarrayDestroy(&sa2); | |
| 601 sarrayDestroy(&sa3); | |
| 602 sarrayDestroy(&sa4); | |
| 603 return ERROR_INT("sa6 not made", __func__, 1); | |
| 604 } | |
| 605 sarrayJoin(sa4, sa6); | |
| 606 sarrayDestroy(&sa6); | |
| 607 | |
| 608 /* Finish the function code */ | |
| 609 sarrayAppendRange(sa4, sa1, finalstart, finalend); | |
| 610 } | |
| 611 | |
| 612 /* Output to file */ | |
| 613 filestr = sarrayToString(sa4, 1); | |
| 614 nbytes = strlen(filestr); | |
| 615 if (filename) | |
| 616 snprintf(bigbuf, L_BUF_SIZE, "%slow.%d.c", filename, fileindex); | |
| 617 else | |
| 618 sprintf(bigbuf, "%slow.%d.c", OUTROOT, fileindex); | |
| 619 l_binaryWrite(bigbuf, "w", filestr, nbytes); | |
| 620 sarrayDestroy(&sa1); | |
| 621 sarrayDestroy(&sa2); | |
| 622 sarrayDestroy(&sa3); | |
| 623 sarrayDestroy(&sa4); | |
| 624 LEPT_FREE(filestr); | |
| 625 return 0; | |
| 626 } | |
| 627 | |
| 628 | |
| 629 | |
| 630 /*--------------------------------------------------------------------------* | |
| 631 * Helper code for sel * | |
| 632 *--------------------------------------------------------------------------*/ | |
| 633 /*! | |
| 634 * \brief sarrayMakeWplsCode() | |
| 635 */ | |
| 636 static SARRAY * | |
| 637 sarrayMakeWplsCode(SEL *sel) | |
| 638 { | |
| 639 char emptystring[] = ""; | |
| 640 l_int32 i, j, ymax, dely; | |
| 641 SARRAY *sa; | |
| 642 | |
| 643 if (!sel) | |
| 644 return (SARRAY *)ERROR_PTR("sel not defined", __func__, NULL); | |
| 645 | |
| 646 ymax = 0; | |
| 647 for (i = 0; i < sel->sy; i++) { | |
| 648 for (j = 0; j < sel->sx; j++) { | |
| 649 if (sel->data[i][j] == 1 || sel->data[i][j] == 2) { | |
| 650 dely = L_ABS(i - sel->cy); | |
| 651 ymax = L_MAX(ymax, dely); | |
| 652 } | |
| 653 } | |
| 654 } | |
| 655 if (ymax > 31) { | |
| 656 L_WARNING("ymax > 31; truncating to 31\n", __func__); | |
| 657 ymax = 31; | |
| 658 } | |
| 659 | |
| 660 sa = sarrayCreate(0); | |
| 661 | |
| 662 /* Declarations */ | |
| 663 if (ymax > 4) | |
| 664 sarrayAddString(sa, wpldecls[2], L_COPY); | |
| 665 if (ymax > 8) | |
| 666 sarrayAddString(sa, wpldecls[6], L_COPY); | |
| 667 if (ymax > 12) | |
| 668 sarrayAddString(sa, wpldecls[10], L_COPY); | |
| 669 if (ymax > 16) | |
| 670 sarrayAddString(sa, wpldecls[14], L_COPY); | |
| 671 if (ymax > 20) | |
| 672 sarrayAddString(sa, wpldecls[18], L_COPY); | |
| 673 if (ymax > 24) | |
| 674 sarrayAddString(sa, wpldecls[22], L_COPY); | |
| 675 if (ymax > 28) | |
| 676 sarrayAddString(sa, wpldecls[26], L_COPY); | |
| 677 if (ymax > 1) | |
| 678 sarrayAddString(sa, wpldecls[ymax - 2], L_COPY); | |
| 679 | |
| 680 sarrayAddString(sa, emptystring, L_COPY); | |
| 681 | |
| 682 /* Definitions */ | |
| 683 for (i = 2; i <= ymax; i++) | |
| 684 sarrayAddString(sa, wpldefs[i - 2], L_COPY); | |
| 685 | |
| 686 return sa; | |
| 687 } | |
| 688 | |
| 689 | |
| 690 /*! | |
| 691 * \brief sarrayMakeInnerLoopDWACode() | |
| 692 */ | |
| 693 static SARRAY * | |
| 694 sarrayMakeInnerLoopDWACode(SEL *sel, | |
| 695 l_int32 nhits, | |
| 696 l_int32 nmisses) | |
| 697 { | |
| 698 char *string; | |
| 699 char land[] = "&"; | |
| 700 char bigbuf[L_BUF_SIZE]; | |
| 701 l_int32 i, j, ntot, nfound, type, delx, dely; | |
| 702 SARRAY *sa; | |
| 703 | |
| 704 if (!sel) | |
| 705 return (SARRAY *)ERROR_PTR("sel not defined", __func__, NULL); | |
| 706 | |
| 707 sa = sarrayCreate(0); | |
| 708 ntot = nhits + nmisses; | |
| 709 nfound = 0; | |
| 710 for (i = 0; i < sel->sy; i++) { | |
| 711 for (j = 0; j < sel->sx; j++) { | |
| 712 type = sel->data[i][j]; | |
| 713 if (type == SEL_HIT || type == SEL_MISS) { | |
| 714 nfound++; | |
| 715 dely = i - sel->cy; | |
| 716 delx = j - sel->cx; | |
| 717 if ((string = makeBarrelshiftString(delx, dely, type)) | |
| 718 == NULL) { | |
| 719 L_WARNING("barrel shift string not made\n", __func__); | |
| 720 continue; | |
| 721 } | |
| 722 if (ntot == 1) /* just one item */ | |
| 723 sprintf(bigbuf, " *dptr = %s;", string); | |
| 724 else if (nfound == 1) | |
| 725 sprintf(bigbuf, " *dptr = %s %s", string, land); | |
| 726 else if (nfound < ntot) | |
| 727 sprintf(bigbuf, " %s %s", string, land); | |
| 728 else /* nfound == ntot */ | |
| 729 sprintf(bigbuf, " %s;", string); | |
| 730 sarrayAddString(sa, bigbuf, L_COPY); | |
| 731 LEPT_FREE(string); | |
| 732 } | |
| 733 } | |
| 734 } | |
| 735 | |
| 736 return sa; | |
| 737 } | |
| 738 | |
| 739 | |
| 740 /*! | |
| 741 * \brief makeBarrelshiftString() | |
| 742 */ | |
| 743 static char * | |
| 744 makeBarrelshiftString(l_int32 delx, /* j - cx */ | |
| 745 l_int32 dely, /* i - cy */ | |
| 746 l_int32 type) /* SEL_HIT or SEL_MISS */ | |
| 747 { | |
| 748 l_int32 absx, absy; | |
| 749 char bigbuf[L_BUF_SIZE]; | |
| 750 | |
| 751 if (delx < -31 || delx > 31) | |
| 752 return (char *)ERROR_PTR("delx out of bounds", __func__, NULL); | |
| 753 if (dely < -31 || dely > 31) | |
| 754 return (char *)ERROR_PTR("dely out of bounds", __func__, NULL); | |
| 755 absx = L_ABS(delx); | |
| 756 absy = L_ABS(dely); | |
| 757 | |
| 758 if (type == SEL_HIT) { | |
| 759 if ((delx == 0) && (dely == 0)) | |
| 760 sprintf(bigbuf, "(*sptr)"); | |
| 761 else if ((delx == 0) && (dely < 0)) | |
| 762 sprintf(bigbuf, "(*(sptr %s))", wplstrm[absy - 1]); | |
| 763 else if ((delx == 0) && (dely > 0)) | |
| 764 sprintf(bigbuf, "(*(sptr %s))", wplstrp[absy - 1]); | |
| 765 else if ((delx < 0) && (dely == 0)) | |
| 766 sprintf(bigbuf, "((*(sptr) >> %d) | (*(sptr - 1) << %d))", | |
| 767 absx, 32 - absx); | |
| 768 else if ((delx > 0) && (dely == 0)) | |
| 769 sprintf(bigbuf, "((*(sptr) << %d) | (*(sptr + 1) >> %d))", | |
| 770 absx, 32 - absx); | |
| 771 else if ((delx < 0) && (dely < 0)) | |
| 772 sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))", | |
| 773 wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); | |
| 774 else if ((delx > 0) && (dely < 0)) | |
| 775 sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))", | |
| 776 wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); | |
| 777 else if ((delx < 0) && (dely > 0)) | |
| 778 sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))", | |
| 779 wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); | |
| 780 else /* ((delx > 0) && (dely > 0)) */ | |
| 781 sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))", | |
| 782 wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); | |
| 783 } else { /* type == SEL_MISS */ | |
| 784 if ((delx == 0) && (dely == 0)) | |
| 785 sprintf(bigbuf, "(~*sptr)"); | |
| 786 else if ((delx == 0) && (dely < 0)) | |
| 787 sprintf(bigbuf, "(~*(sptr %s))", wplstrm[absy - 1]); | |
| 788 else if ((delx == 0) && (dely > 0)) | |
| 789 sprintf(bigbuf, "(~*(sptr %s))", wplstrp[absy - 1]); | |
| 790 else if ((delx < 0) && (dely == 0)) | |
| 791 sprintf(bigbuf, "((~*(sptr) >> %d) | (~*(sptr - 1) << %d))", | |
| 792 absx, 32 - absx); | |
| 793 else if ((delx > 0) && (dely == 0)) | |
| 794 sprintf(bigbuf, "((~*(sptr) << %d) | (~*(sptr + 1) >> %d))", | |
| 795 absx, 32 - absx); | |
| 796 else if ((delx < 0) && (dely < 0)) | |
| 797 sprintf(bigbuf, "((~*(sptr %s) >> %d) | (~*(sptr %s - 1) << %d))", | |
| 798 wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); | |
| 799 else if ((delx > 0) && (dely < 0)) | |
| 800 sprintf(bigbuf, "((~*(sptr %s) << %d) | (~*(sptr %s + 1) >> %d))", | |
| 801 wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); | |
| 802 else if ((delx < 0) && (dely > 0)) | |
| 803 sprintf(bigbuf, "((~*(sptr %s) >> %d) | (~*(sptr %s - 1) << %d))", | |
| 804 wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); | |
| 805 else /* ((delx > 0) && (dely > 0)) */ | |
| 806 sprintf(bigbuf, "((~*(sptr %s) << %d) | (~*(sptr %s + 1) >> %d))", | |
| 807 wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); | |
| 808 } | |
| 809 | |
| 810 return stringNew(bigbuf); | |
| 811 } |
