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