1
/* libctl: flexible Guile-based control files for scientific software
2
* Copyright (C) 1998, 1999, 2000, 2001, 2002, Steven G. Johnson
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
* Boston, MA 02111-1307, USA.
19
* Steven G. Johnson can be contacted at stevenj@alum.mit.edu.
26
/**************************************************************************/
28
/* Functions missing from Guile 1.2: */
30
#ifndef HAVE_GH_BOOL2SCM
31
/* Guile 1.2 is missing gh_bool2scm for some reason; redefine: */
32
SCM bool2scm(boolean b) { return (b ? SCM_BOOL_T : SCM_BOOL_F); }
35
#ifndef HAVE_GH_LENGTH
36
#define gh_length gh_list_length
39
#ifndef HAVE_GH_LIST_REF
40
/* Guile 1.2 doesn't have the gh_list_ref function. Sigh. */
41
/* Note: index must be in [0,list_length(l) - 1]. We don't check! */
42
static SCM list_ref(list l, int index)
44
SCM cur = SCM_UNSPECIFIED, rest = l;
54
#else /* HAVE_GH_LIST_REF */
55
#define list_ref(l,index) gh_list_ref(l,gh_int2scm(index))
58
#ifndef HAVE_GH_VECTOR_REF
59
#define gh_vector_ref gh_vref
62
/**************************************************************************/
64
/* Scheme file loading (don't use gh_load directly because subsequent
65
loads won't use the correct path name). Uses our "include" function
66
from include.scm, or defaults to gh_load if this function isn't
69
void ctl_include(char *filename)
71
SCM include_proc = gh_lookup("include");
72
if (include_proc == SCM_UNDEFINED)
75
gh_call1(include_proc, gh_str02scm(filename));
78
/* convert a pathname into one relative to the current include dir */
79
char *ctl_fix_path(const char *path)
83
SCM include_dir = gh_lookup("include-dir");
84
if (include_dir != SCM_UNDEFINED) {
85
char *dir = gh_scm2newstr(include_dir, NULL);
86
newpath = (char *) malloc(sizeof(char) * (strlen(dir) +
90
if (newpath[0] && newpath[strlen(newpath)-1] != '/')
92
strcat(newpath, path);
96
newpath = (char *) malloc(sizeof(char) * (strlen(path) + 1));
97
strcpy(newpath, path);
101
/**************************************************************************/
103
/* vector3 and matrix3x3 utilities: */
105
number vector3_dot(vector3 v1,vector3 v2)
107
return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
110
number vector3_norm(vector3 v)
112
return (sqrt(vector3_dot(v,v)));
115
vector3 vector3_scale(number s, vector3 v)
125
vector3 unit_vector3(vector3 v)
127
number norm = vector3_norm(v);
131
return vector3_scale(1.0/norm, v);
134
vector3 vector3_plus(vector3 v1,vector3 v2)
138
vnew.x = v1.x + v2.x;
139
vnew.y = v1.y + v2.y;
140
vnew.z = v1.z + v2.z;
144
vector3 vector3_minus(vector3 v1,vector3 v2)
148
vnew.x = v1.x - v2.x;
149
vnew.y = v1.y - v2.y;
150
vnew.z = v1.z - v2.z;
154
vector3 vector3_cross(vector3 v1,vector3 v2)
158
vnew.x = v1.y * v2.z - v2.y * v1.z;
159
vnew.y = v1.z * v2.x - v2.z * v1.x;
160
vnew.z = v1.x * v2.y - v2.x * v1.y;
164
vector3 matrix3x3_vector3_mult(matrix3x3 m, vector3 v)
168
vnew.x = m.c0.x * v.x + m.c1.x * v.y + m.c2.x * v.z;
169
vnew.y = m.c0.y * v.x + m.c1.y * v.y + m.c2.y * v.z;
170
vnew.z = m.c0.z * v.x + m.c1.z * v.y + m.c2.z * v.z;
174
matrix3x3 matrix3x3_mult(matrix3x3 m1, matrix3x3 m2)
178
m.c0.x = m1.c0.x * m2.c0.x + m1.c1.x * m2.c0.y + m1.c2.x * m2.c0.z;
179
m.c0.y = m1.c0.y * m2.c0.x + m1.c1.y * m2.c0.y + m1.c2.y * m2.c0.z;
180
m.c0.z = m1.c0.z * m2.c0.x + m1.c1.z * m2.c0.y + m1.c2.z * m2.c0.z;
182
m.c1.x = m1.c0.x * m2.c1.x + m1.c1.x * m2.c1.y + m1.c2.x * m2.c1.z;
183
m.c1.y = m1.c0.y * m2.c1.x + m1.c1.y * m2.c1.y + m1.c2.y * m2.c1.z;
184
m.c1.z = m1.c0.z * m2.c1.x + m1.c1.z * m2.c1.y + m1.c2.z * m2.c1.z;
186
m.c2.x = m1.c0.x * m2.c2.x + m1.c1.x * m2.c2.y + m1.c2.x * m2.c2.z;
187
m.c2.y = m1.c0.y * m2.c2.x + m1.c1.y * m2.c2.y + m1.c2.y * m2.c2.z;
188
m.c2.z = m1.c0.z * m2.c2.x + m1.c1.z * m2.c2.y + m1.c2.z * m2.c2.z;
193
matrix3x3 matrix3x3_transpose(matrix3x3 m)
209
number matrix3x3_determinant(matrix3x3 m)
211
return(m.c0.x*m.c1.y*m.c2.z - m.c2.x*m.c1.y*m.c0.z +
212
m.c1.x*m.c2.y*m.c0.z + m.c0.y*m.c1.z*m.c2.x -
213
m.c1.x*m.c0.y*m.c2.z - m.c2.y*m.c1.z*m.c0.x);
216
matrix3x3 matrix3x3_inverse(matrix3x3 m)
219
number detinv = matrix3x3_determinant(m);
222
fprintf(stderr, "error: singular matrix in matrix3x3_inverse!\n");
227
minv.c0.x = detinv * (m.c1.y * m.c2.z - m.c2.y * m.c1.z);
228
minv.c1.y = detinv * (m.c0.x * m.c2.z - m.c2.x * m.c0.z);
229
minv.c2.z = detinv * (m.c1.y * m.c0.x - m.c0.y * m.c1.x);
231
minv.c0.z = detinv * (m.c0.y * m.c1.z - m.c1.y * m.c0.z);
232
minv.c0.y = -detinv * (m.c0.y * m.c2.z - m.c2.y * m.c0.z);
233
minv.c1.z = -detinv * (m.c0.x * m.c1.z - m.c1.x * m.c0.z);
235
minv.c2.x = detinv * (m.c1.x * m.c2.y - m.c1.y * m.c2.x);
236
minv.c1.x = -detinv * (m.c1.x * m.c2.z - m.c1.z * m.c2.x);
237
minv.c2.y = -detinv * (m.c0.x * m.c2.y - m.c0.y * m.c2.x);
242
/**************************************************************************/
244
/* complex number utilities */
246
cnumber make_cnumber(number r, number i)
253
cnumber cnumber_conj(cnumber c)
255
return make_cnumber(c.re, -c.im);
258
vector3 cvector3_re(cvector3 cv)
261
v.x = cv.x.re; v.y = cv.y.re; v.z = cv.z.re;
265
vector3 cvector3_im(cvector3 cv)
268
v.x = cv.x.im; v.y = cv.y.im; v.z = cv.z.im;
272
cvector3 make_cvector3(vector3 vr, vector3 vi)
275
cv.x = make_cnumber(vr.x, vi.x);
276
cv.y = make_cnumber(vr.y, vi.y);
277
cv.z = make_cnumber(vr.z, vi.z);
281
matrix3x3 cmatrix3x3_re(cmatrix3x3 cm)
284
m.c0 = cvector3_re(cm.c0);
285
m.c1 = cvector3_re(cm.c1);
286
m.c2 = cvector3_re(cm.c2);
290
matrix3x3 cmatrix3x3_im(cmatrix3x3 cm)
293
m.c0 = cvector3_im(cm.c0);
294
m.c1 = cvector3_im(cm.c1);
295
m.c2 = cvector3_im(cm.c2);
299
cmatrix3x3 make_cmatrix3x3(matrix3x3 mr, matrix3x3 mi)
302
cm.c0 = make_cvector3(mr.c0, mi.c0);
303
cm.c1 = make_cvector3(mr.c1, mi.c1);
304
cm.c2 = make_cvector3(mr.c2, mi.c2);
308
cmatrix3x3 make_hermitian_cmatrix3x3(number m00, number m11, number m22,
309
cnumber m01, cnumber m02, cnumber m12)
312
cm.c0.x = make_cnumber(m00, 0);
313
cm.c1.y = make_cnumber(m11, 0);
314
cm.c2.y = make_cnumber(m22, 0);
315
cm.c1.x = m01; cm.c0.y = cnumber_conj(m01);
316
cm.c2.x = m02; cm.c0.z = cnumber_conj(m02);
317
cm.c2.y = m12; cm.c1.z = cnumber_conj(m12);
321
/**************************************************************************/
323
/* type conversion */
325
vector3 scm2vector3(SCM sv)
329
v.x = gh_scm2double(gh_vector_ref(sv,gh_int2scm(0)));
330
v.y = gh_scm2double(gh_vector_ref(sv,gh_int2scm(1)));
331
v.z = gh_scm2double(gh_vector_ref(sv,gh_int2scm(2)));
335
matrix3x3 scm2matrix3x3(SCM sm)
339
m.c0 = scm2vector3(gh_vector_ref(sm,gh_int2scm(0)));
340
m.c1 = scm2vector3(gh_vector_ref(sm,gh_int2scm(1)));
341
m.c2 = scm2vector3(gh_vector_ref(sm,gh_int2scm(2)));
345
SCM vector32scm(vector3 v)
347
return(gh_call3(gh_lookup("vector3"),
350
gh_double2scm(v.z)));
353
SCM matrix3x32scm(matrix3x3 m)
355
return(gh_call3(gh_lookup("matrix3x3"),
361
cnumber scm2cnumber(SCM sx)
363
if (scm_real_p(sx) && !(SCM_NIMP(sx) && SCM_INEXP(sx) && SCM_CPLXP(sx)))
364
return make_cnumber(gh_scm2double(sx), 0.0);
366
return make_cnumber(SCM_REALPART(sx), SCM_IMAG(sx));
369
SCM cnumber2scm(cnumber x)
372
return gh_double2scm(x.re);
374
return scm_makdbl(x.re, x.im);
377
cvector3 scm2cvector3(SCM sv)
381
v.x = scm2cnumber(gh_vector_ref(sv,gh_int2scm(0)));
382
v.y = scm2cnumber(gh_vector_ref(sv,gh_int2scm(1)));
383
v.z = scm2cnumber(gh_vector_ref(sv,gh_int2scm(2)));
387
cmatrix3x3 scm2cmatrix3x3(SCM sm)
391
m.c0 = scm2cvector3(gh_vector_ref(sm,gh_int2scm(0)));
392
m.c1 = scm2cvector3(gh_vector_ref(sm,gh_int2scm(1)));
393
m.c2 = scm2cvector3(gh_vector_ref(sm,gh_int2scm(2)));
397
SCM cvector32scm(cvector3 v)
399
return(gh_call3(gh_lookup("vector3"),
405
SCM cmatrix3x32scm(cmatrix3x3 m)
407
return(gh_call3(gh_lookup("matrix3x3"),
410
cvector32scm(m.c2)));
413
/**************************************************************************/
415
/* variable get/set functions */
419
integer ctl_get_integer(char *identifier)
421
return(gh_scm2int(gh_lookup(identifier)));
424
number ctl_get_number(char *identifier)
426
return(gh_scm2double(gh_lookup(identifier)));
429
cnumber ctl_get_cnumber(char *identifier)
431
return(scm2cnumber(gh_lookup(identifier)));
434
boolean ctl_get_boolean(char *identifier)
436
return(gh_scm2bool(gh_lookup(identifier)));
439
char* ctl_get_string(char *identifier)
441
return(gh_scm2newstr(gh_lookup(identifier), NULL));
444
vector3 ctl_get_vector3(char *identifier)
446
return(scm2vector3(gh_lookup(identifier)));
449
matrix3x3 ctl_get_matrix3x3(char *identifier)
451
return(scm2matrix3x3(gh_lookup(identifier)));
454
cvector3 ctl_get_cvector3(char *identifier)
456
return(scm2cvector3(gh_lookup(identifier)));
459
cmatrix3x3 ctl_get_cmatrix3x3(char *identifier)
461
return(scm2cmatrix3x3(gh_lookup(identifier)));
464
list ctl_get_list(char *identifier)
466
return(gh_lookup(identifier));
469
object ctl_get_object(char *identifier)
471
return(gh_lookup(identifier));
474
function ctl_get_function(char *identifier)
476
return(gh_lookup(identifier));
481
/* UGLY hack alert! There doesn't seem to be any clean way of setting
482
Scheme variables from C in Guile (e.g. no gh_* interface).
484
One option is to use scm_symbol_set_x (symbol-set! in Scheme), but
485
I'm not sure how to get this to work in Guile 1.3 because of the
486
%&*@^-ing module system (I need to pass some module for the first
487
parameter, but I don't know what to pass).
489
Instead, I hacked together the following my_symbol_set_x routine,
490
using the functions scm_symbol_value0 and scm_symbol_set_x from the
491
Guile 1.3 sources. (scm_symbol_value0 has the virtue of looking in
492
the correct module somehow; I also used this function to replace
493
gh_lookup, which broke in Guile 1.3 as well...sigh.)
495
Note that I can't call "set!" because it is really a macro.
497
All the ugliness is confined to the set_value() routine, though. */
499
#define USE_MY_SYMBOL_SET_X 1 /* use the hack */
501
#ifdef USE_MY_SYMBOL_SET_X
502
static SCM my_symbol_set_x(char *name, SCM v)
504
/* code swiped from scm_symbol_value0 and scm_symbol_set_x */
505
SCM symbol = scm_intern_obarray_soft(name, strlen (name), scm_symhash, 0);
506
SCM vcell = scm_sym2vcell (SCM_CAR (symbol),
507
SCM_CDR (scm_top_level_lookup_closure_var),
509
if (SCM_FALSEP (vcell))
510
return SCM_UNDEFINED;
511
SCM_SETCDR (vcell, v);
512
return SCM_UNSPECIFIED;
516
static void set_value(char *identifier, SCM value)
518
#if defined(USE_SCM_SYMBOL_SET_X) /* worked in Guile 1.1, 1.2 */
519
scm_symbol_set_x(SCM_BOOL_F, gh_symbol2scm(identifier), value);
520
#elif defined(USE_MY_SYMBOL_SET_X)
521
my_symbol_set_x(identifier, value);
525
void ctl_set_integer(char *identifier, integer value)
527
set_value(identifier, gh_int2scm(value));
530
void ctl_set_number(char *identifier, number value)
532
set_value(identifier, gh_double2scm(value));
535
void ctl_set_cnumber(char *identifier, cnumber value)
537
set_value(identifier, cnumber2scm(value));
540
void ctl_set_boolean(char *identifier, boolean value)
542
set_value(identifier, gh_bool2scm(value));
545
void ctl_set_string(char *identifier, char *value)
547
set_value(identifier, gh_str02scm(value));
550
void ctl_set_vector3(char *identifier, vector3 value)
552
set_value(identifier, vector32scm(value));
555
void ctl_set_matrix3x3(char *identifier, matrix3x3 value)
557
set_value(identifier, matrix3x32scm(value));
560
void ctl_set_cvector3(char *identifier, cvector3 value)
562
set_value(identifier, cvector32scm(value));
565
void ctl_set_cmatrix3x3(char *identifier, cmatrix3x3 value)
567
set_value(identifier, cmatrix3x32scm(value));
570
void ctl_set_list(char *identifier, list value)
572
set_value(identifier, value);
575
void ctl_set_object(char *identifier, object value)
577
set_value(identifier, value);
580
void ctl_set_function(char *identifier, function value)
582
set_value(identifier, value);
585
/**************************************************************************/
589
int list_length(list l)
591
return(gh_length(l));
594
integer integer_list_ref(list l, int index)
596
return(gh_scm2int(list_ref(l,index)));
599
number number_list_ref(list l, int index)
601
return(gh_scm2double(list_ref(l,index)));
604
cnumber cnumber_list_ref(list l, int index)
606
return(scm2cnumber(list_ref(l,index)));
609
boolean boolean_list_ref(list l, int index)
611
return(SCM_BOOL_F != list_ref(l,index));
614
char* string_list_ref(list l, int index)
616
return(gh_scm2newstr(list_ref(l,index),NULL));
619
vector3 vector3_list_ref(list l, int index)
621
return(scm2vector3(list_ref(l,index)));
624
matrix3x3 matrix3x3_list_ref(list l, int index)
626
return(scm2matrix3x3(list_ref(l,index)));
629
cvector3 cvector3_list_ref(list l, int index)
631
return(scm2cvector3(list_ref(l,index)));
634
cmatrix3x3 cmatrix3x3_list_ref(list l, int index)
636
return(scm2cmatrix3x3(list_ref(l,index)));
639
list list_list_ref(list l, int index)
641
return(list_ref(l,index));
644
object object_list_ref(list l, int index)
646
return(list_ref(l,index));
649
object function_list_ref(list l, int index)
651
return(list_ref(l,index));
654
/**************************************************************************/
658
#define MAKE_LIST(conv) \
661
list cur_list = SCM_EOL; \
662
for (i = num_items - 1; i >= 0; --i) \
663
cur_list = gh_cons(conv (items[i]), cur_list); \
667
list make_integer_list(int num_items, integer *items)
668
MAKE_LIST(gh_int2scm)
670
list make_number_list(int num_items, number *items)
671
MAKE_LIST(gh_double2scm)
673
list make_cnumber_list(int num_items, cnumber *items)
674
MAKE_LIST(cnumber2scm)
676
list make_boolean_list(int num_items, boolean *items)
677
MAKE_LIST(gh_bool2scm)
679
list make_string_list(int num_items, char **items)
680
MAKE_LIST(gh_str02scm)
682
list make_vector3_list(int num_items, vector3 *items)
683
MAKE_LIST(vector32scm)
685
list make_matrix3x3_list(int num_items, matrix3x3 *items)
686
MAKE_LIST(matrix3x32scm)
688
list make_cvector3_list(int num_items, cvector3 *items)
689
MAKE_LIST(cvector32scm)
691
list make_cmatrix3x3_list(int num_items, cmatrix3x3 *items)
692
MAKE_LIST(cmatrix3x32scm)
694
#define NO_CONVERSION
696
list make_list_list(int num_items, list *items)
697
MAKE_LIST(NO_CONVERSION)
699
list make_object_list(int num_items, object *items)
700
MAKE_LIST(NO_CONVERSION)
702
list make_function_list(int num_items, object *items)
703
MAKE_LIST(NO_CONVERSION)
706
/**************************************************************************/
708
/* object properties */
710
boolean object_is_member(char *type_name, object o)
712
return(SCM_BOOL_F != gh_call2(gh_lookup("object-member?"),
713
gh_symbol2scm(type_name),
717
static SCM object_property_value(object o, char *property_name)
719
return(gh_call2(gh_lookup("object-property-value"),
721
gh_symbol2scm(property_name)));
724
integer integer_object_property(object o, char *property_name)
726
return(gh_scm2int(object_property_value(o,property_name)));
729
number number_object_property(object o, char *property_name)
731
return(gh_scm2double(object_property_value(o,property_name)));
734
cnumber cnumber_object_property(object o, char *property_name)
736
return(scm2cnumber(object_property_value(o,property_name)));
739
boolean boolean_object_property(object o, char *property_name)
741
return(SCM_BOOL_F != object_property_value(o,property_name));
744
char* string_object_property(object o, char *property_name)
746
return(gh_scm2newstr(object_property_value(o,property_name),NULL));
749
vector3 vector3_object_property(object o, char *property_name)
751
return(scm2vector3(object_property_value(o,property_name)));
754
matrix3x3 matrix3x3_object_property(object o, char *property_name)
756
return(scm2matrix3x3(object_property_value(o,property_name)));
759
cvector3 cvector3_object_property(object o, char *property_name)
761
return(scm2cvector3(object_property_value(o,property_name)));
764
cmatrix3x3 cmatrix3x3_object_property(object o, char *property_name)
766
return(scm2cmatrix3x3(object_property_value(o,property_name)));
769
list list_object_property(object o, char *property_name)
771
return(object_property_value(o,property_name));
774
object object_object_property(object o, char *property_name)
776
return(object_property_value(o,property_name));
779
function function_object_property(object o, char *property_name)
781
return(object_property_value(o,property_name));