1/* 2 * gvec - vectorize any single-input function or trailing operator 3 * 4 * This version accepts arbitrary number of arguments, but of course 5 * they must all be same length vectors. 6 * 7 * The gvec function is for use in either a two-arg function or a two-arg 8 * operation "function" must be first; calc doesn't care how many more 9 * arguments there actually are. 10 * 11 * Under source code control: 2011/03/31 17:54:55 12 * File existed as early as: 2010 13 * 14 * By Carl Witthoft carl at witthoft dot com 15 */ 16 17define gvec(function, vector) 18{ 19 local xlen,y,foo; 20 local precx = 1e-50; /* default for now */ 21 local argc = param(0)-1; 22 local old_tilde; /* previous config("tilde") */ 23 24 /* 25 * parse args 26 */ 27 local plist = mat[argc]; 28 if (config("resource_debug") & 8) { 29 print "plist=", plist; 30 print "argc=", argc; 31 } 32 for(local i = 0; i< argc; i++) { 33 local ii = i + 2; 34 if (config("resource_debug") & 8) { 35 print "ii=", ii; 36 print "param(" : ii : "}=", param(ii); 37 print "size(param(" : ii : ")=", size(param(ii)); 38 } 39 plist[i] = size(param(ii)); 40 } 41 local slist=sort(plist); 42 if (config("resource_debug") & 8) { 43 print "plist=", plist; 44 } 45 local argm = argc-1; 46 if (config("resource_debug") & 8) { 47 print "argm=", argm; 48 } 49 if (slist[0] != slist[argm]) { 50 quit "lengths don't match"; 51 } 52 xlen = size(vector); 53 y = mat[xlen]; 54 55 /* 56 * We can't do str(vector[j]) outside loop, eval() petulantly refuses to 57 * look at local variables. 58 * 59 * Also we need to config("tilde",0) to turn off lead tilde 60 * (so str(vector[j]) looks like a number. 61 */ 62 old_tilde = config("tilde",0); 63 64 /* 65 * Ok, now check to see if "function" is a function. If not, it's an 66 * operation and it's up to user to make it valid 67 */ 68 if (isdefined(function)) { 69 70 /* yep, it's a function, either builtin or user-defined */ 71 for (local j=0; j<xlen; j++) { 72 73 /* build the function call */ 74 foo = strcat(function, "("); 75 for (local jj = 0; jj<argc; jj++) { 76 foo = strcat(foo , str(param(jj+2)[j]), ","); 77 } 78 foo = strcat(foo, str(precx), ")"); 79 if (config("resource_debug") & 8) { 80 print "foo=", foo; 81 } 82 y[j] = eval(foo); 83 } 84 85 /* 86 * it is an operator -- multi-argument operator makes no sense 87 */ 88 } else { 89 if (argc > 1) { 90 quit "Error: operator can accept only one argument"; 91 } 92 for (j=0; j<xlen; j++) { 93 foo = strcat(str(vector[j]), function); 94 y[j] = eval(foo); 95 } 96 } 97 98 /* restore tilde mode if needed */ 99 config("tilde", old_tilde); 100 101 /* return result */ 102 return y; 103} 104