problem_util.c

Go to the documentation of this file.
00001 
00008 /* $Id: problem_util.c,v 1.67 2008/10/27 19:04:45 seymour Exp $ */
00009 /* $UTK_Copyright: $ */
00010 
00011 
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <time.h>
00015 #include <string.h>
00016 #include <sys/types.h>
00017 #include <sys/stat.h>
00018 #include <fcntl.h>
00019 
00020 #include "portability.h"
00021 #include "problem.h"
00022 #include "comm_encode.h"
00023 #include "utility.h"
00024 #include "proxylib.h"
00025 
00026 static int
00027   gs_free_problem_common(gs_problem_t *, int);
00028 
00030 char *gs_inout[] = {
00031   "in",
00032   "inout",
00033   "out",
00034   "workspace",
00035   "varout",
00036   "bad inout"
00037 };
00038 
00040 char *gs_c_datatype[] = {
00041   "int",
00042   "float",
00043   "double",
00044   "gs_scomplex",
00045   "gs_dcomplex",
00046   "char",
00047   "bad data type"
00048 };
00049 
00051 char *gs_objecttype[] = {
00052   "scalar",
00053   "vector",
00054   "matrix",
00055   "sparsematrix",
00056   "file",
00057   "packedfile",
00058   "bad object type"
00059 };
00060 
00062 char *gs_probtype[] = {
00063   "subroutine",
00064   "function",
00065   "bad prob type"
00066 };
00067 
00069 char *gs_const[] = {
00070   "10",
00071   "5.0",
00072   "10.0",
00073   "__scval",
00074   "__dcval",
00075   "'n'",
00076   "bad const"
00077 };
00078 
00079 char *gs_service_error[] = {
00080   "Unused error code",                          /*   not defined in enum      */
00081   "No error",                                   /*   not defined in enum      */
00082   "Unused error code",                          /*   not defined in enum      */
00083   "malloc failed",                              /* GS_SVC_ERR_MALLOC          */
00084   "Error loading service XML file",             /* GS_SVC_ERR_MISSING_XML     */
00085   "Error loading server info XML file",         /* GS_SVC_ERR_MISSING_SV_XML  */
00086   "Error creating problem XML for request",     /* GS_SVC_ERR_CREATE_XML      */
00087   "Could not open data file obtain output",     /* GS_SVC_ERR_OPEN_DATA_FILE  */
00088   "Could not create data file to save output",  /* GS_SVC_ERR_CREAT_DATA_FILE */
00089   "Could not create completion file",           /* GS_SVC_ERR_COMPLETION_FILE */
00090   "Could not encode problem into XML",          /* GS_SVC_ERR_PROBLEM_ENC     */
00091   "Could not get current working directory",    /* GS_SVC_ERR_GETCWD          */
00092   "Error creating request id",                  /* GS_SVC_ERR_REQID           */
00093   "Could not create request subdirectory",      /* GS_SVC_ERR_MKDIR           */
00094   "Could not chdir to request subdirectory",    /* GS_SVC_ERR_CHDIR           */
00095   "Failed to set up signal handler",            /* GS_SVC_ERR_SIGNALS         */
00096   "Failed to fork service process",             /* GS_SVC_ERR_FORK            */
00097   "Failed to wait for service process",         /* GS_SVC_ERR_WAITPID         */
00098   "Service process did not terminate properly", /* GS_SVC_ERR_ABNORMAL_EXIT   */
00099   "I/O Error transferring args",                /* GS_SVC_ERR_IO              */
00100   "Error executing service (likely missing)",   /* GS_SVC_ERR_EXEC            */
00101   "Error reading problem file from disk",       /* GS_SVC_ERR_READ_PROBLEM    */
00102   "Error restoring arg structures from disk",   /* GS_SVC_ERR_RESTORE_ARGS    */
00103   "Specified request ID not found on server",   /* GS_SVC_ERR_UNKNOWN_REQ     */
00104   "Request subdirectory removed while waiting", /* GS_SVC_ERR_REQ_DIR_GONE    */
00105   "Request not finished yet",                   /* GS_SVC_ERR_NOT_FINISHED    */
00106   "Invalid request ID (can't parse pid)",       /* GS_SVC_ERR_INVALID_PID     */
00107   "Could not kill service process",             /* GS_SVC_ERR_CANT_KILL       */
00108   "Invalid blocking/nonblocking specifier tag", /* GS_SVC_ERR_BAD_NB_TAG      */
00109   "Server has too many jobs running now",       /* GS_SVC_ERR_RESTRICT_JOBS   */
00110   "Only accepts jobs during a restricted time", /* GS_SVC_ERR_RESTRICT_TIME   */
00111   "Unsupported batch mode",                     /* GS_SVC_ERR_BAD_BATCH_MODE  */
00112   "Could not obtain lock on file",              /* GS_SVC_ERR_FILE_LOCK       */
00113   "Could not release lock on file",             /* GS_SVC_ERR_FILE_UNLOCK     */
00114   "Unspecified server error"                    /* GS_SVC_ERR_UNSPECIFIED     */
00115 };
00116 
00128 enum inout
00129 gs_parse_inout(const char *str)
00130 {
00131   if(!str)
00132     return GS_BAD_INOUT;
00133 
00134   if(!strcasecmp(str, gs_inout[GS_IN]))
00135     return GS_IN;
00136   if(!strcasecmp(str, gs_inout[GS_INOUT]))
00137     return GS_INOUT;
00138   if(!strcasecmp(str, gs_inout[GS_OUT]))
00139     return GS_OUT;
00140   if(!strcasecmp(str, gs_inout[GS_VAROUT]))
00141     return GS_VAROUT;
00142   if(!strcasecmp(str, gs_inout[GS_WORKSPACE]))
00143     return GS_WORKSPACE;
00144 
00145   return GS_BAD_INOUT;
00146 }
00147 
00158 enum datatype
00159 gs_parse_datatype(const char *str)
00160 {
00161   if(!str)
00162     return GS_BAD_DTYPE;
00163 
00164   if(!strcasecmp(str, gs_c_datatype[GS_INT]))
00165     return GS_INT;
00166   if(!strcasecmp(str, gs_c_datatype[GS_FLOAT]))
00167     return GS_FLOAT;
00168   if(!strcasecmp(str, gs_c_datatype[GS_DOUBLE]))
00169     return GS_DOUBLE;
00170   if(!strcasecmp(str, gs_c_datatype[GS_SCOMPLEX]))
00171     return GS_SCOMPLEX;
00172   if(!strcasecmp(str, gs_c_datatype[GS_DCOMPLEX]))
00173     return GS_DCOMPLEX;
00174   if(!strcasecmp(str, gs_c_datatype[GS_CHAR]))
00175     return GS_CHAR;
00176 
00177   return GS_BAD_DTYPE;
00178 }
00179 
00190 enum objecttype
00191 gs_parse_objecttype(const char *str)
00192 {
00193   if(!str)
00194     return GS_BAD_OTYPE;
00195 
00196   if(!strcasecmp(str, gs_objecttype[GS_SCALAR]))
00197     return GS_SCALAR;
00198   if(!strcasecmp(str, gs_objecttype[GS_VECTOR]))
00199     return GS_VECTOR;
00200   if(!strcasecmp(str, gs_objecttype[GS_MATRIX]))
00201     return GS_MATRIX;
00202   if(!strcasecmp(str, gs_objecttype[GS_SPARSEMATRIX]))
00203     return GS_SPARSEMATRIX;
00204   if(!strcasecmp(str, gs_objecttype[GS_FILE]))
00205     return GS_FILE;
00206   if(!strcasecmp(str, gs_objecttype[GS_PACKEDFILE]))
00207     return GS_PACKEDFILE;
00208 
00209   return GS_BAD_OTYPE;
00210 }
00211 
00221 enum probtype
00222 gs_parse_probtype(const char *str)
00223 {
00224   if(!str)
00225     return GS_BAD_PTYPE;
00226 
00227   if(!strcasecmp(str, gs_probtype[GS_SUBROUTINE]))
00228     return GS_SUBROUTINE;
00229   if(!strcasecmp(str, gs_probtype[GS_FUNCTION]))
00230     return GS_FUNCTION;
00231 
00232   return GS_BAD_PTYPE;
00233 }
00234 
00250 char *
00251 gs_problem_getinfo(gs_problem_t * problem, char *type, char *defaultvalue)
00252 {
00253   gs_info_t *info;
00254 
00255   if(!problem || !type)
00256     return NULL;
00257 
00258   for(info = problem->infolist; info != NULL; info = info->next)
00259     if(!strcmp(info->type, type))
00260       return info->value;
00261 
00262   return defaultvalue;
00263 }
00264 
00271 void
00272 gs_infolist_dump(gs_info_t * infolist)
00273 {
00274   gs_info_t *p;
00275 
00276   if(!infolist)
00277     return;
00278 
00279   printf("Problem attributes:\n");
00280   for(p = infolist; p != NULL; p = p->next)
00281     printf("  %s: %s\n", p->type, p->value);
00282 }
00283 
00290 void
00291 gs_arg_dump(gs_argument_t * arg)
00292 {
00293   if(!arg) {
00294     printf("NULL arg\n");
00295     return;
00296   }
00297 
00298   printf("  Argument Name:     %s\n", arg->name);
00299   printf("  Description:       %s\n", arg->description);
00300   printf("  In/out mode:       %s\n", gs_inout[arg->inout]);
00301   printf("  Data type:         %s\n", gs_c_datatype[arg->datatype]);
00302   printf("  Object type:       %s\n", gs_objecttype[arg->objecttype]);
00303   printf("  Row size expr:     %s\n", arg->rowexp);
00304   printf("  Column size expr:  %s\n", arg->colexp);
00305 }
00306 
00313 void
00314 gs_arglist_dump(gs_argument_t * arglist)
00315 {
00316   gs_argument_t *p;
00317   int i=0;
00318 
00319   for(p = arglist; p != NULL; p = p->next) {
00320     printf("Argument %d:\n", i++);
00321     gs_arg_dump(p);
00322     printf("\n");
00323   }
00324 }
00325 
00332 void
00333 gs_problem_dump(gs_problem_t * problem)
00334 {
00335   if(!problem) {
00336     printf("NULL problem\n");
00337     return;
00338   }
00339 
00340   printf("\n");
00341   printf("Problem Name: %s\n", problem->name);
00342   printf("\n");
00343   printf("Problem Description:\n  %s\n", problem->description);
00344   printf("\n");
00345   gs_arglist_dump(problem->arglist);
00346   gs_infolist_dump(problem->infolist);
00347 }
00348 
00355 void
00356 gs_problemlist_dump(gs_problem_t * problem)
00357 {
00358   gs_problem_t *p;
00359 
00360   printf("<problemlist>\n");
00361   for(p = problem; p != NULL; p = p->next)
00362     gs_problem_dump(p);
00363   printf("</problemlist>\n");
00364 }
00365 
00380 char *
00381 gs_problem_prototype(gs_problem_t * problem)
00382 {
00383   char *s, *stmp = NULL;
00384   gs_argument_t *arg = NULL;
00385 
00386   if(!problem) return NULL;
00387 
00388   s = strdup("");
00389   for(arg = problem->arglist; arg != NULL; arg = arg->next) {
00390     stmp = dstring_sprintf("inout=\"%s\" datatype=\"%s\" \
00391       objecttype=\"%s\" rowexp=\"%s\" colexp=\"%s\" \n",
00392       gs_inout[arg->inout], gs_c_datatype[arg->datatype],
00393       gs_objecttype[arg->objecttype], arg->rowexp, arg->colexp);
00394     s = dstring_append_free(s, stmp);
00395   }
00396 
00397   return s;
00398 }
00399 
00412 int
00413 gs_dup_problem(gs_problem_t * dest, gs_problem_t * src)
00414 {
00415   gs_argument_t *src_arg, *dest_arg;
00416   char *msg = NULL;
00417 
00418   if(!dest || !src)
00419     return -1;
00420 
00421   /* first copy most of the stuff the easy way - just encode the src and
00422      decode to the dest.  this won't copy everything however. */
00423 
00424   if(gs_encode_problem(&msg, src) < 0)
00425     return -1;
00426 
00427   if(gs_decode_problem(msg, dest) < 0) {
00428     if(msg)
00429       free(msg);
00430     return -1;
00431   }
00432 
00433   free(msg);
00434 
00435   /* now copy the remaining relevant information not contained in the
00436      encoding. */
00437 
00438   src_arg = src->arglist;
00439   dest_arg = dest->arglist;
00440 
00441   while(src_arg) {
00442     dest_arg->rows = src_arg->rows;
00443     dest_arg->cols = src_arg->cols;
00444     dest_arg->data = src_arg->data;
00445 
00446     src_arg = src_arg->next;
00447     dest_arg = dest_arg->next;
00448   }
00449 
00450   dest->major = src->major;
00451   dest->work = NULL;
00452   dest->worksize = 0;
00453 
00454   return 0;
00455 }
00456 
00470 int
00471 gs_create_request_id(char *template)
00472 {
00473   static char alphabet[] =
00474       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00475   char *p;
00476   unsigned int seed;
00477 
00478   if(!template)
00479     return -1;
00480 
00481 #ifdef WIN32
00482   seed = (unsigned)time(NULL);
00483 #else
00484   {
00485     struct timeval tv;
00486     gettimeofday(&tv, NULL);
00487     seed = tv.tv_usec;
00488   }
00489 #endif
00490   srand(seed);
00491 
00492   p = template;
00493 
00494   while(*p) {
00495     if(*p == 'X')
00496       *p = alphabet[rand() % 62];
00497     p++;
00498   }
00499 
00500   return 0;
00501 }
00502 
00515 int
00516 gs_read_problem_from_file(char *fname, gs_problem_t * problem)
00517 {
00518   char *problemstring = NULL;
00519 
00520   if(!fname || !problem)
00521     return -1;
00522 
00523   if(gs_get_contents_of_file(fname, &problemstring) < 0)
00524     return -1;
00525 
00526   /* parse buffer into problem structure */
00527   if(gs_decode_problem(problemstring, problem) < 0) {
00528     free(problemstring);
00529     return -1;
00530   }
00531 
00532   free(problemstring);
00533 
00534   return 0;
00535 }
00536 
00549 int
00550 gs_read_server_from_file(char *fname, gs_server_t * server)
00551 {
00552   char *serverstring = NULL;
00553 
00554   if(!fname || !server)
00555     return -1;
00556 
00557   if(gs_get_contents_of_file(fname, &serverstring) < 0)
00558     return -1;
00559 
00560   /* parse buffer into server structure */
00561   if(gs_decode_server(serverstring, server) < 0) {
00562     free(serverstring);
00563     return -1;
00564   }
00565 
00566   free(serverstring);
00567 
00568   return 0;
00569 }
00570 
00580 int
00581 gs_free_problem(gs_problem_t *problem)
00582 {
00583   return gs_free_problem_common(problem, FALSE);
00584 }
00585 
00597 int
00598 gs_free_problem_and_data(gs_problem_t *problem)
00599 {
00600   return gs_free_problem_common(problem, TRUE);
00601 }
00602 
00614 static int
00615 gs_free_problem_common(gs_problem_t *problem, int free_data)
00616 {
00617   gs_problem_t *tmpp, *prev;
00618 
00619   if(!problem)
00620     return -1;
00621 
00622   tmpp = problem;
00623   while(tmpp) {
00624     if(tmpp->name)
00625       free(tmpp->name);
00626     if(tmpp->description)
00627       free(tmpp->description);
00628     if(tmpp->callsig)
00629       free(tmpp->callsig);
00630     if(tmpp->work)
00631       free(tmpp->work);
00632 
00633     gs_free_arglist(tmpp->arglist, free_data);
00634     gs_free_infolist(tmpp->infolist);
00635     prev = tmpp;
00636     tmpp = tmpp->next;
00637     free(prev);
00638   }
00639   return 0;
00640 }
00641 
00642 int
00643 gs_free_enumlist(gs_arg_enum_t *elist)
00644 {
00645   gs_arg_enum_t *tmpe;
00646 
00647   if(!elist)
00648     return -1;
00649 
00650   tmpe = elist;
00651   while(tmpe) {
00652     if(tmpe->val)
00653       free(tmpe->val);
00654     tmpe = tmpe->next;
00655   }
00656 
00657   /* the enum list is built a bit differently, so we don't need
00658    * to free each element, just the head.
00659    */
00660 
00661   free(elist);
00662 
00663   return 0;
00664 }
00665 
00676 int
00677 gs_free_arglist(gs_argument_t * arg, int free_data)
00678 {
00679   gs_argument_t *tmpa, *prev;
00680 
00681   if(!arg)
00682     return -1;
00683 
00684   tmpa = arg;
00685   while(tmpa) {
00686     if(tmpa->name)
00687       free(tmpa->name);
00688     if(tmpa->description)
00689       free(tmpa->description);
00690     if(tmpa->rowexp)
00691       free(tmpa->rowexp);
00692     if(tmpa->colexp)
00693       free(tmpa->colexp);
00694     if(tmpa->sparse_attr.nnzexp)
00695       free(tmpa->sparse_attr.nnzexp);
00696     if(tmpa->sparse_attr.indices)
00697       free(tmpa->sparse_attr.indices);
00698     if(tmpa->sparse_attr.pointer)
00699       free(tmpa->sparse_attr.pointer);
00700 
00701     if(free_data && tmpa->data)
00702       free(tmpa->data);
00703 
00704     gs_free_enumlist(tmpa->arg_enum);
00705 
00706     prev = tmpa;
00707     tmpa = tmpa->next;
00708     free(prev);
00709   }
00710 
00711   return 0;
00712 }
00713 
00714 
00715 #ifdef GS_SMART_GRIDSOLVE
00716 
00717 int
00718 gs_smart_free_arg(gs_argument_t * arg, int free_data)
00719 {
00720   int i;
00721   if(!arg)
00722     return -1;
00723 
00724   if(arg->name)
00725     free(arg->name);
00726   if(arg->description)
00727     free(arg->description);
00728   if(arg->rowexp)
00729     free(arg->rowexp);
00730   if(arg->colexp)
00731     free(arg->colexp);
00732   if(arg->sparse_attr.nnzexp)
00733     free(arg->sparse_attr.nnzexp);
00734   if(arg->sparse_attr.indices)
00735     free(arg->sparse_attr.indices);
00736   if(arg->sparse_attr.pointer)
00737     free(arg->sparse_attr.pointer);
00738   if(arg->input_arg_file)
00739     free(arg->input_arg_file);
00740   if(arg->output_arg_file)
00741     free(arg->output_arg_file);
00742      
00743   for(i=0;i<arg->input_nb_dest_servers;i++){
00744     if(arg->enc_input_dest_servers[i])
00745       free(arg->enc_input_dest_servers[i]);
00746   }
00747   if(arg->enc_input_dest_servers)
00748     free(arg->enc_input_dest_servers);
00749 
00750   for(i=0;i<arg->output_nb_dest_servers;i++){
00751     if(arg->enc_output_dest_servers[i])
00752       free(arg->enc_output_dest_servers[i]);
00753   }
00754   if(arg->enc_output_dest_servers)
00755     free(arg->enc_output_dest_servers);
00756 
00757   if(free_data && arg->data)
00758     free(arg->data);
00759 
00760   gs_free_enumlist(arg->arg_enum);
00761 
00762   free(arg);
00763 
00764   return 0;
00765 }
00766 
00767 #endif
00768 
00769 
00770 
00780 int
00781 gs_free_infolist(gs_info_t * info)
00782 {
00783   gs_info_t *tmpi, *prev;
00784 
00785   if(!info)
00786     return -1;
00787 
00788   tmpi = info;
00789   while(tmpi) {
00790     if(tmpi->type)
00791       free(tmpi->type);
00792     if(tmpi->value)
00793       free(tmpi->value);
00794     prev = tmpi;
00795     tmpi = tmpi->next;
00796     free(prev);
00797   }
00798 
00799   return 0;
00800 }
00801 
00812 int
00813 gs_create_error_file(char *req, int err)
00814 {
00815   char *filename;
00816   FILE *error_file;
00817 
00818   if(!req) return -1;
00819 
00820   /* allocate enough for reqid + "/error" */
00821   filename = malloc(strlen(req) + 7);
00822 
00823   if(!filename)
00824     return -1;
00825 
00826   sprintf(filename, "%s/error", req);
00827 
00828   error_file = fopen(filename, "w");
00829 
00830   free(filename);
00831 
00832   if(error_file) {
00833     fprintf(error_file, "%d\n", err);
00834     fclose(error_file);
00835   }
00836   else
00837     return -1;
00838 
00839   return 0;
00840 }
00841 
00857 int
00858 gs_create_timestamp_file(char *req, char *fname, double run_time)
00859 {
00860   char *filename;
00861   FILE *timestamp_file;
00862 
00863   if(!req || !fname)
00864     return -1;
00865 
00866   filename = malloc(strlen(req) + strlen(fname) + 2);
00867 
00868   if(!filename)
00869     return -1;
00870 
00871   sprintf(filename, "%s/%s", req, fname);
00872 
00873   timestamp_file = fopen(filename, "w");
00874 
00875   free(filename);
00876 
00877   if(timestamp_file) {
00878     char timestr[100];
00879     struct tm *ptr;
00880     time_t tm;
00881 
00882     tm = time(NULL);
00883     ptr = localtime(&tm);
00884     strftime(timestr, 100, "%a %b %d %H:%M:%S %Z %Y", ptr);
00885 
00886     fprintf(timestamp_file, "%s\n", timestr);
00887     fprintf(timestamp_file, "%lf\n", run_time);
00888 
00889     fclose(timestamp_file);
00890   }
00891   else
00892     return -1;
00893 
00894   return 0;
00895 }
00896 
00897 
00913 int
00914 gs_gen_sparse_mat_common(int datatype, size_t el_size, int m, int rmin, int rmax,
00915   void **a, int **ip, int **p)
00916 {
00917   int i, ii, j, idx, nnz, *ptr, *ind;
00918   void *mat;
00919 
00920   nnz = 0;
00921 
00922   ptr = (int *) malloc((m+1) * sizeof(int));
00923   if(!ptr) return -1;
00924 
00925   ptr[0] = 0;
00926   for(i=1;i<=m;i++) {
00927     int colsize = random() % (rmax-rmin+1) + rmin;
00928 
00929     ptr[i] = ptr[i-1] + colsize;
00930 
00931     nnz += colsize;
00932   }
00933 
00934   ind = (int *)malloc(nnz * sizeof(int));
00935   if(!ind) return -1;
00936   mat = (void *) malloc(sizeof(double) * nnz * el_size);
00937   if(!mat) return -1;
00938 
00939   ii = idx = 0;
00940   for(i=0;i<m;i++) {
00941     int up, lo, remain, l = ptr[i+1]-ptr[i];
00942 
00943     remain = l;
00944     lo = -1;
00945 
00946     for(j=0;j<l;j++) {
00947       up = m - remain;
00948       lo = lo + 1;
00949 
00950       switch(datatype) {
00951         case GS_DOUBLE:
00952           ((double *)mat)[ii] = drand48();
00953           break;
00954         case GS_FLOAT:
00955           ((float *)mat)[ii] = (float)drand48();
00956           break;
00957         case GS_INT:
00958           ((int *)mat)[ii] = random();
00959           break;
00960         case GS_CHAR:
00961           ((int *)mat)[ii] = (random() % 26) + 'a';
00962           break;
00963         default:
00964           ERRPRINTF("Bad data type\n");
00965       }
00966 
00967       if(up != 0) {
00968         idx = random() % (up-lo) + lo;
00969 
00970         remain--;
00971       }
00972       else
00973         idx = lo;
00974 
00975       ind[ii] = idx;
00976       lo = idx;
00977       ii++;
00978     }
00979   }
00980 
00981   *p = ptr;
00982   *ip = ind;
00983   *a = mat;
00984   return nnz;
00985 }
00986 
01000 int
01001 gs_gen_sparse_mat_double(int m, int rmin, int rmax,
01002   double **a, int **ip, int **p)
01003 {
01004   return gs_gen_sparse_mat_common(GS_DOUBLE, sizeof(double), m, rmin, rmax,
01005     (void *)a, ip, p);
01006 }
01007 
01021 int
01022 gs_gen_sparse_mat_float(int m, int rmin, int rmax,
01023   float **a, int **ip, int **p)
01024 {
01025   return gs_gen_sparse_mat_common(GS_FLOAT, sizeof(float), m, rmin, rmax,
01026     (void *)a, ip, p);
01027 }
01028 
01042 int
01043 gs_gen_sparse_mat_int(int m, int rmin, int rmax,
01044   int **a, int **ip, int **p)
01045 {
01046   return gs_gen_sparse_mat_common(GS_INT, sizeof(int), m, rmin, rmax,
01047     (void *)a, ip, p);
01048 }
01049 
01063 int
01064 gs_gen_sparse_mat_char(int m, int rmin, int rmax,
01065   char **a, int **ip, int **p)
01066 {
01067   return gs_gen_sparse_mat_common(GS_CHAR, sizeof(char), m, rmin, rmax,
01068     (void *)a, ip, p);
01069 }
01070 
01084 gs_sparse_dup_t *
01085 gs_dup_sparse_mat(int nnz, int dim, size_t el_size,
01086   void *m, int *ind, int *ptr)
01087 {
01088   gs_sparse_dup_t *new_sp;
01089 
01090   new_sp = (gs_sparse_dup_t *) malloc(sizeof(gs_sparse_dup_t));
01091 
01092   if(!new_sp) return NULL;
01093 
01094   new_sp->m = (void *)malloc(sizeof(double) * el_size * nnz);
01095   new_sp->ind = (int *)malloc(nnz * sizeof(int));
01096   new_sp->ptr = (int *)malloc(dim * sizeof(int));
01097 
01098   if(!new_sp->m || !new_sp->ind || !new_sp->ptr) {
01099     if(new_sp->m) free(new_sp->m);
01100     if(new_sp->ind) free(new_sp->ind);
01101     if(new_sp->ptr) free(new_sp->ptr);
01102     if(new_sp) free(new_sp);
01103     ERRPRINTF("malloc failed.\n");
01104     return NULL;
01105   }
01106 
01107   memcpy(new_sp->m, m, nnz * el_size);
01108   memcpy(new_sp->ind, ind, nnz * sizeof(int));
01109   memcpy(new_sp->ptr, ptr, dim * sizeof(int));
01110 
01111   return new_sp;
01112 }
01113 
01123 gs_argument_t *
01124 gs_arg_lookup_by_name(char *name, gs_argument_t *arglist) 
01125 {
01126   gs_argument_t *arg;
01127   for (arg = arglist; arg != NULL; arg = arg->next) 
01128     if (!strcmp(name, arg->name) )
01129       return(arg);
01130   return NULL;
01131 }
01132 
01133 
01145 int
01146 gs_arg_is_sparse_attr(char *name, gs_argument_t *arglist)
01147 {
01148   gs_argument_t *arg;
01149 
01150   for(arg = arglist; arg != NULL; arg = arg->next) {
01151     if(arg->objecttype == GS_SPARSEMATRIX) {
01152       if(!strcmp(name, arg->sparse_attr.nnzexp) ||
01153          !strcmp(name, arg->sparse_attr.indices) ||
01154          !strcmp(name, arg->sparse_attr.pointer))
01155         return TRUE;
01156     }
01157   }
01158 
01159   return FALSE;
01160 }
01161 
01162 
01163 
01172 int gs_datatype_sizeof(int datatype) 
01173 {
01174   switch(datatype) {
01175   case GS_INT:
01176     return sizeof(int);
01177     break;
01178   case GS_FLOAT:
01179     return sizeof(float);
01180     break;
01181   case GS_DOUBLE:
01182     return sizeof(double);
01183     break;
01184   case GS_SCOMPLEX:
01185     return sizeof(gs_scomplex);
01186     break;
01187   case GS_DCOMPLEX:
01188     return sizeof(gs_dcomplex);
01189     break;
01190   case GS_CHAR:
01191     return sizeof(char);
01192     break;
01193   default:
01194     return -1;
01195     break;
01196   }
01197 }