summaryrefslogtreecommitdiff
path: root/imdi/imdi_make.c
diff options
context:
space:
mode:
Diffstat (limited to 'imdi/imdi_make.c')
-rw-r--r--imdi/imdi_make.c514
1 files changed, 514 insertions, 0 deletions
diff --git a/imdi/imdi_make.c b/imdi/imdi_make.c
new file mode 100644
index 0000000..7990f53
--- /dev/null
+++ b/imdi/imdi_make.c
@@ -0,0 +1,514 @@
+
+/* Integer Multi-Dimensional Interpolation */
+
+/*
+ * Copyright 2000 - 2007 Graeme W. Gill
+ * All rights reserved.
+ *
+ * This material is licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
+ * see the License.txt file for licencing details.
+ */
+
+/*
+ * Top level kernel code generator
+ *
+ * This module is invoked from the make system,
+ * and generates all the versions and configurations of
+ * the IMDI kernel code. It includes all the generated
+ * files in imdi_k.h, which also contains a table
+ * so that the run time code knows what kernels
+ * are available.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdarg.h>
+#include <string.h>
+#include "copyright.h"
+#include "aconfig.h"
+
+#include "imdi.h"
+#include "imdi_tab.h"
+
+#ifndef MAXNAMEL
+# define MAXNAMEL 512 /* Maximum command line filename lengths */
+#endif
+
+#undef VERBOSE
+#undef TEST1 /* Generate one test case */
+
+/*
+ Ideal grid resolutions for 8 bit precision calculations.
+ See imdi_gen.c for a more detailed list.
+
+ Grid Jumps
+ 4 0
+ 6 0
+ 16 0
+ 18 0
+ 52 0
+ 86 0
+ 256 0
+
+ 3 1
+ 5 1
+ 9 1
+ 17 1
+ 33 1
+ 65 1
+ 128 1
+ 129 1
+ 255 1
+
+ */
+
+/* The following structure initialisations define what kernel routines should be built */
+static
+gendesc descs[] = {
+#ifdef TEST1
+ {
+ { 3, 0 }, /* * Input dimension combinations */
+ { 33, 0 }, /* + Interpolation table resolutions */
+ { 8, 0 }, /* + Min Simplex table resolutions */
+ { 4, 0 }, /* * Output dimension combinations */
+ {OOPT(oopts_check,3), oopts_none}, /* + Output channel options */
+ {pixint8, 0 }, /* * Input pixel representation */
+ {prec_p16, 0}, /* + Internal precision */
+ {pixint8, 0}, /* + Output pixel representation */
+ {opts_sort_splx, opts_end} /* * Direction & stride combinations */
+// {opts_splx_sort, opts_end} /* * Direction & stride combinations */
+ }
+#else
+ /* A reasonably full set of combinations */
+ /* * means multiplies combination */
+ /* + means lockstep with previous line */
+ {
+ { 1, 3, 4, 5, 6, 7, 8, 9, 10, 0 }, /* * Input dimension combinations */
+ { 256, 33, 18, 16, 12, 8, 7, 6, 5, 0 }, /* + Min Interpolation table resolutions */
+ { 1, 8, 17, 1, 1, 1, 1, 1, 1, 0 }, /* + Min Simplex table resolutions */
+
+ { 1, 3, 4, 5, 6, 7, 8, 9, 10, 0 }, /* * Output dimension combinations */
+ {oopts_none, oopts_none, oopts_none, oopts_none, oopts_none, oopts_none,
+ oopts_none, oopts_none, oopts_none, oopts_none, oopts_none, oopts_none},
+ /* + Output channel options */
+
+ {pixint8, pixint16, pixint8, pixint16, pixint16, 0 }, /* * Input pixel representation */
+ {prec_p8, prec_p8, prec_p8, prec_p16, prec_p16, 0 }, /* + Internal precision */
+ {pixint8, pixint8, pixint16, pixint16, pixint16, 0 }, /* + Output pixel representation */
+
+ {
+ opts_splx_sort, /* (both, but default to simple alg, no stride) */
+ opts_istride | opts_ostride, /* + (Sort only with stride) */
+ opts_end } /* * Direction & stride combinations */
+ }
+#endif /* !TEST1 */
+};
+
+void set_architecture(mach_arch *ar, int use64);
+
+struct _knamestr {
+ char name[100];
+ char desc[100];
+ struct _knamestr *next;
+}; typedef struct _knamestr knamestr;
+
+knamestr *
+new_knamestr(char *name, char *desc) {
+ knamestr *kn;
+
+ if ((kn = (knamestr *)malloc(sizeof(knamestr))) == NULL) {
+ fprintf(stderr,"new_knamestr malloc failed\n");
+ exit(-1);
+ }
+ strcpy(kn->name, name);
+ strcpy(kn->desc, desc);
+ kn->next = NULL;
+ return kn;
+}
+
+void usage(void) {
+ fprintf(stderr,"Make imdi kernel code Version %s\n",ARGYLL_VERSION_STR);
+ fprintf(stderr,"usage: imdi_make [-i]\n");
+ fprintf(stderr," -d dir Directory to create them in (default .)\n");
+ fprintf(stderr," -i Individial Files\n");
+ fprintf(stderr," -f Force 64 bit\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[]) {
+ int fa,nfa; /* argument we're looking at */
+ int indiv = 0; /* Individual files */
+ int rv;
+ int dn, tnd;
+ genspec gs, ogs;
+ tabspec ts, ots;
+ mach_arch ar;
+ int ix = 1; /* kernel index */
+ knamestr *list = NULL, *lp = NULL;
+#if defined(ALLOW64) && defined(USE64)
+ int use64 = 1;
+#else
+ int use64 = 0;
+#endif
+ char dirname[MAXNAMEL+1+1] = ""; /* Output directory name */
+ char temp[MAXNAMEL+100+1]; /* Buffer to compose filenames in */
+ FILE *kcode = NULL; /* Kernel routine code file */
+ FILE *kheader; /* Kernel routine header file */
+
+ /* Zero out the gen and tabspecs, to give diff a place to start */
+ memset((void *)&ogs, 0, sizeof(genspec));
+ memset((void *)&gs, 0, sizeof(genspec));
+ memset((void *)&ots, 0, sizeof(tabspec));
+ memset((void *)&ts, 0, sizeof(tabspec));
+
+ /* Process the arguments */
+ for(fa = 1;fa < argc;fa++) {
+ nfa = fa; /* skip to nfa if next argument is used */
+ if (argv[fa][0] == '-') { /* Look for any flags */
+ char *na = NULL; /* next argument after flag, null if none */
+
+ if (argv[fa][2] != '\000')
+ na = &argv[fa][2]; /* next is directly after flag */
+ else {
+ if ((fa+1) < argc) {
+ if (argv[fa+1][0] != '-') {
+ nfa = fa + 1;
+ na = argv[nfa]; /* next is seperate non-flag argument */
+ }
+ }
+ }
+
+ if (argv[fa][1] == '?') {
+ usage();
+
+ }
+ /* Destination directory */
+ else if (argv[fa][1] == 'd' || argv[fa][1] == 'D') {
+ int len;
+ fa = nfa;
+ if (na == NULL) usage();
+ strncpy(dirname,na,MAXNAMEL); dirname[MAXNAMEL] = '\000';
+ len = strlen(dirname);
+ if (len > 0) {
+ if (dirname[len-1] != '/' && dirname[len-1] != '\\')
+ strcat(dirname, "/");
+ }
+ }
+ /* Individual files */
+ else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
+ indiv = 1;
+ }
+ /* Force 64 bit */
+ else if (argv[fa][1] == 'f' || argv[fa][1] == 'F') {
+#ifdef ALLOW64
+ use64 = 1;
+#else
+ fprintf(stderr,"ALLOW64 bits is undefined\n");
+ usage();
+#endif
+ }
+ else {
+ usage();
+ }
+ } else
+ break;
+ }
+
+ set_architecture(&ar, use64);
+
+ /* Open the file for kernel routine declaration header */
+ sprintf(temp, "%simdi_k.h",dirname);
+ if ((kheader = fopen(temp, "w")) == NULL) {
+ fprintf(stderr,"imdi_make: unable to open file '%s'\n",temp);
+ exit(-1);
+ }
+
+ if (!indiv) {
+ sprintf(temp, "%simdi_k.c",dirname);
+ if ((kcode = fopen(temp, "w")) == NULL) {
+ fprintf(stderr,"imdi_make: unable to open file '%s'\n",temp);
+ exit(-1);
+ }
+ }
+
+ tnd = sizeof(descs)/sizeof(gendesc); /* Total number of descriptions */
+#ifdef VERBOSE
+ printf("Number of descriptions = %d\n",tnd);
+#endif /* VERBOSE */
+
+ fprintf(kheader,"/* Integer Multi-Dimensional Interpolation */\n");
+ fprintf(kheader,"/* Declarations for all the generated kernel functions */\n");
+ fprintf(kheader,"/* This file is generated by imdi_make */\n\n");
+ fprintf(kheader,"/* Copyright 2000 - 2007 Graeme W. Gill */\n");
+ fprintf(kheader,"/* All rights reserved. */\n");
+ fprintf(kheader,"/* This material is licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- */\n");
+ fprintf(kheader,"/* see the License.txt file for licensing details.*/\n");
+
+ fprintf(kheader,"\n");
+
+ /* For all the descriptions */
+ for (dn = 0; dn < tnd; dn++) {
+ int cb, ncb;
+
+ /* Do all combinations for that description */
+ for (cb = 0, ncb = 1; cb < ncb; cb++) {
+ int nalg, alg;
+ char ofname[100];
+
+ /* Compute generate spec. and number of combinations */
+ ncb = set_genspec(&gs, &descs[dn], cb, &ar);
+
+ if (indiv) {
+ sprintf(temp, "%s%s.c",dirname,ofname);
+ if ((kcode = fopen(temp, "w")) == NULL) {
+ fprintf(stderr,"imdi_make: unable to open file '%s'\n",temp);
+ exit(-1);
+ }
+ }
+
+ nalg = 2; /* By default generate just sort algorithm */
+ alg = 1;
+
+ if ((gs.opt & opts_splx_sort)
+ || (gs.opt & opts_sort_splx)) {
+ alg = 0; /* Generate both simplex and sort algorithms */
+ }
+ if (gs.opt & opts_splx) {
+ nalg = 1; /* Generate just simplex algorithm */
+ alg = 0;
+ }
+
+ for (; alg < nalg; alg++) {
+
+ if (alg == 0)
+ gs.opt |= opts_splx;
+ else
+ gs.opt &= ~opts_splx;
+
+ /* Generate it */
+ rv = gen_c_kernel(&gs, &ts, &ar, kcode, ix, &ogs, &ots);
+ if (rv != 0 && rv != 1) {
+ fprintf(stderr,"imdi_make: gen_c_kernel returned a err %d\n",rv);
+ exit(-1);
+ }
+
+ /* Add the name to the list */
+ if (list == NULL)
+ lp = list = new_knamestr(gs.kname, gs.kdesc);
+ else {
+ lp->next = new_knamestr(gs.kname, gs.kdesc);
+ lp = lp->next;
+ }
+ if (indiv) {
+ if (fclose(kcode) != 0) {
+ fprintf(stderr,"imdi_make: unable to close file '%s'\n",ofname);
+ exit(-1);
+ }
+ }
+ ogs = gs; /* Structure copy */
+ ots = ts;
+ ix++;
+
+ if (rv == 0)
+ break; /* there was only sort available */
+ }
+ }
+ }
+
+ /* Include the kernel functions in the header file */
+ if (indiv) {
+ for(lp = list; lp != NULL; lp = lp->next) {
+ fprintf(kheader,"#include \"%s_%s.c\"\n",lp->name,lp->desc);
+ }
+ } else {
+ fprintf(kheader,"#include \"imdi_k.c\" /* All the kernel code */\n");
+ }
+ fprintf(kheader,"\n");
+
+ /* Output function table */
+
+ fprintf(kheader,
+ "struct {\n"
+ " void (*interp)(imdi *s, void **outp, int ostride, void **inp, int istride, unsigned int npix);\n"
+ " void (*gentab)(genspec *g, tabspec *t);\n"
+ "} ktable[%d] = {\n",ix-1);
+
+ for(lp = list; lp != NULL; lp = lp->next) {
+ fprintf(kheader,"\t{ %s, %s_gentab }%s\n", lp->name, lp->name,
+ lp->next != NULL ? "," : "");
+ }
+ fprintf(kheader,"};\n");
+ fprintf(kheader,"\n");
+ fprintf(kheader,"int no_kfuncs = %d;\n",ix-1);
+ fprintf(kheader,"\n");
+
+ if (!indiv) {
+ if (fclose(kcode) != 0) {
+ fprintf(stderr,"imdi_make: unable to close file 'imdi_k.c'\n");
+ exit(-1);
+ }
+ }
+
+ if (fclose(kheader) != 0) {
+ fprintf(stderr,"imdi_make: unable to close file 'imdi_k.h'\n");
+ exit(-1);
+ }
+
+ /* Free the kname list */
+ for(lp = list; lp != NULL;) {
+ char *p = (char *)lp;
+ lp = lp->next;
+ free(p);
+ }
+
+ return 0;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - */
+/* Initialse the architecture structure properly. */
+/* We're doing this purely at run time, on the assumption */
+/* that the target machine is the one we're running on. */
+/* We would have to do this differently in a cross development */
+/* environment. */
+void
+set_architecture(
+mach_arch *ar,
+int use64
+) {
+ unsigned long etest = 0xff;
+ char *machtype; /* Environment value */
+
+ if (*((unsigned char *)&etest) == 0xff) {
+ ar->bigend = 0; /* Little endian */
+ } else {
+ ar->bigend = 1; /* Big endian endian */
+ }
+
+ machtype = getenv("MACHTYPE");
+
+ /* Unfortunetaly many environments don't export MACHTYPE :-( */
+ /* so we implement a fall back */
+ if (machtype == NULL) {
+#ifdef __ppc__
+ machtype = "powerpc";
+#endif
+ }
+
+ if (machtype != NULL && strcmp(machtype, "powerpc") == 0) {
+
+ /* Section tunable for PowerPC */
+
+ ar->uwa = 0; /* Use wide memory access */
+ ar->shfm = 0; /* Use shifts to mask values */
+ ar->oscale = 8; /* Has scaled indexing up to * 8 */
+ ar->smmul = 0; /* Doesn't have fast small multiply for index scaling */
+ if (use64) {
+ ar->nords = 4; /* Number of ord types */
+ ar->nints = 4; /* Number of int types */
+ } else {
+ ar->nords = 3; /* Number of ord types */
+ ar->nints = 3; /* Number of int types */
+ }
+ ar->natord = 2; /* Most natural type (assume unsigned int) */
+ ar->natint = 2; /* Most natural type (assume int) */
+
+ ar->pbits = sizeof(void *) * 8; /* Number of bits in a pointer */
+
+ ar->ords[0].bits = 8 * sizeof(unsigned char);
+ ar->ords[0].name = "unsigned char";
+ ar->ords[0].align = 1;
+
+ ar->ords[1].bits = 8 * sizeof(unsigned short);
+ ar->ords[1].name = "unsigned short";
+ ar->ords[1].align = 1;
+
+ ar->ords[2].bits = 8 * sizeof(unsigned int);
+ ar->ords[2].name = "unsigned int";
+ ar->ords[2].align = 1;
+
+#ifdef ALLOW64
+ ar->ords[3].bits = 8 * sizeof(unsigned longlong);
+ ar->ords[3].name = "unsigned " str_longlong ;
+ ar->ords[3].align = 0;
+#endif /* ALLOW64 */
+
+ ar->ints[0].bits = 8 * sizeof(signed char);
+ ar->ints[0].name = "signed char";
+ ar->ints[0].align = 1;
+
+ ar->ints[1].bits = 8 * sizeof(short);
+ ar->ints[1].name = "short";
+ ar->ints[1].align = 1;
+
+ ar->ints[2].bits = 8 * sizeof(int);
+ ar->ints[2].name = "int";
+ ar->ints[2].align = 1;
+
+#ifdef ALLOW64
+ ar->ints[3].bits = 8 * sizeof(longlong);
+ ar->ints[3].name = str_longlong ;
+ ar->ints[3].align = 0;
+#endif /* ALLOW64 */
+
+ } else {
+
+ /* Currently assume x86 type */
+
+ ar->uwa = 0; /* Use wide memory access */
+ ar->shfm = 0; /* Use shifts to mask values */
+ ar->oscale = 8; /* Has scaled indexing up to * 8 */
+ ar->smmul = 0; /* Doesn't have fast small multiply for index scaling */
+ if (use64) {
+ ar->nords = 4; /* Number of ord types */
+ ar->nints = 4; /* Number of int types */
+ } else {
+ ar->nords = 3; /* Number of ord types */
+ ar->nints = 3; /* Number of int types */
+ }
+ ar->natord = 2; /* Most natural type (assume unsigned int) */
+ ar->natint = 2; /* Most natural type (assume int) */
+
+ ar->pbits = sizeof(void *) * 8; /* Number of bits in a pointer */
+
+ ar->ords[0].bits = 8 * sizeof(unsigned char);
+ ar->ords[0].name = "unsigned char";
+ ar->ords[0].align = 1;
+
+ ar->ords[1].bits = 8 * sizeof(unsigned short);
+ ar->ords[1].name = "unsigned short";
+ ar->ords[1].align = 1;
+
+ ar->ords[2].bits = 8 * sizeof(unsigned int);
+ ar->ords[2].name = "unsigned int";
+ ar->ords[2].align = 1;
+
+#ifdef ALLOW64
+ ar->ords[3].bits = 8 * sizeof(unsigned longlong);
+ ar->ords[3].name = "unsigned " str_longlong ;
+ ar->ords[3].align = 0;
+#endif /* ALLOW64 */
+
+ ar->ints[0].bits = 8 * sizeof(signed char);
+ ar->ints[0].name = "signed char";
+ ar->ints[0].align = 1;
+
+ ar->ints[1].bits = 8 * sizeof(short);
+ ar->ints[1].name = "short";
+ ar->ints[1].align = 1;
+
+ ar->ints[2].bits = 8 * sizeof(int);
+ ar->ints[2].name = "int";
+ ar->ints[2].align = 1;
+
+#ifdef ALLOW64
+ ar->ints[3].bits = 8 * sizeof(longlong);
+ ar->ints[3].name = str_longlong ;
+ ar->ints[3].align = 0;
+#endif /* ALLOW64 */
+ }
+}
+
+