File: matheval.c

package info (click to toggle)
libmatheval 1.1.11%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 2,396 kB
  • sloc: sh: 15,152; ansic: 2,391; lex: 142; makefile: 85; yacc: 68
file content (342 lines) | stat: -rw-r--r-- 11,478 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/* 
 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012,
 * 2013 Free Software Foundation, Inc.
 * 
 * This file is part of GNU libmatheval
 * 
 * GNU libmatheval is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * GNU libmatheval is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU libmatheval.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <libguile.h>
#include <matheval.h>
#include "config.h"

static scm_t_bits evaluator_tag;	/* Unique identifier for Guile
					 * objects of evaluator type.  */

/* Guile interface for libmatheval library.  Procedures below are simple
 * wrappers for corresponding libmatheval procedures. */
static size_t evaluator_destroy_scm(SCM evaluator_smob);
static SCM      evaluator_create_scm(SCM string);
static SCM      evaluator_evaluate_scm(SCM evaluator_smob, SCM count,
				       SCM names, SCM values);
static SCM      evaluator_get_string_scm(SCM evaluator_smob);
static SCM      evaluator_get_variables_scm(SCM evaluator_smob);
static SCM      evaluator_derivative_scm(SCM evaluator_smob, SCM name);
static SCM      evaluator_evaluate_x_scm(SCM evaluator_smob, SCM x);
static SCM      evaluator_evaluate_x_y_scm(SCM evaluator_smob, SCM x,
					   SCM y);
static SCM      evaluator_evaluate_x_y_z_scm(SCM evaluator_smob, SCM x,
					     SCM y, SCM z);
static SCM      evaluator_derivative_x_scm(SCM evaluator_smob);
static SCM      evaluator_derivative_y_scm(SCM evaluator_smob);
static SCM      evaluator_derivative_z_scm(SCM evaluator_smob);

static void
inner_main(void *closure, int argc, char **argv)
{
	/* Extend Guile with evaluator type and register procedure to free 
	 * objects of this type. */
	evaluator_tag = scm_make_smob_type("evaluator", sizeof(void *));
	scm_set_smob_free(evaluator_tag, evaluator_destroy_scm);

	/* Register other procedures working on evaluator type. */
	scm_c_define_gsubr("evaluator-create", 1, 0, 0,
			   (SCM(*)())evaluator_create_scm);
	scm_c_define_gsubr("evaluator-evaluate", 4, 0, 0,
			   (SCM(*)())evaluator_evaluate_scm);
	scm_c_define_gsubr("evaluator-get-string", 1, 0, 0,
			   (SCM(*)())evaluator_get_string_scm);
	scm_c_define_gsubr("evaluator-get-variables", 1, 0, 0,
			   (SCM(*)())evaluator_get_variables_scm);
	scm_c_define_gsubr("evaluator-derivative", 2, 0, 0,
			   (SCM(*)())evaluator_derivative_scm);
	scm_c_define_gsubr("evaluator-evaluate-x", 2, 0, 0,
			   (SCM(*)())evaluator_evaluate_x_scm);
	scm_c_define_gsubr("evaluator-evaluate-x-y", 3, 0, 0,
			   (SCM(*)())evaluator_evaluate_x_y_scm);
	scm_c_define_gsubr("evaluator-evaluate-x-y-z", 4, 0, 0,
			   (SCM(*)())evaluator_evaluate_x_y_z_scm);
	scm_c_define_gsubr("evaluator-derivative-x", 1, 0, 0,
			   (SCM(*)())evaluator_derivative_x_scm);
	scm_c_define_gsubr("evaluator-derivative-y", 1, 0, 0,
			   (SCM(*)())evaluator_derivative_y_scm);
	scm_c_define_gsubr("evaluator-derivative-z", 1, 0, 0,
			   (SCM(*)())evaluator_derivative_z_scm);

	/* Check is there exactly one argument left in command line. */
	assert(argc == 2);

	/* Interpret Guile code from file with name given through above
	 * argument.  */
	scm_primitive_load(scm_from_locale_string(argv[1]));
}

/* Program is demonstrating use of libmatheval library of procedures for
 * evaluating mathematical functions.  Program expects single argument
 * from command line and interpret Guile code (extended with procedures
 * from libmatheval Guile interface) from this file. */
int
main(int argc, char **argv)
{
	/* Initialize Guile library; inner_main() procedure gets called in 
	 * turn. */
	scm_boot_guile(argc, argv, inner_main, 0);

	exit(EXIT_SUCCESS);
}

/* Wrapper for evaluator_destroy() procedure from libmatheval library. */
static          size_t
evaluator_destroy_scm(SCM evaluator_smob)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-destroy");

	evaluator_destroy((void *) SCM_CDR(evaluator_smob));

	return sizeof(void *);
}

/* Wrapper for evaluator_create() procedure from libmatheval library. */
static          SCM
evaluator_create_scm(SCM string)
{
	char           *stringz;
	void           *evaluator;

	SCM_ASSERT(SCM_NIMP(string) &&
		   scm_is_string(string), string, SCM_ARG1,
		   "evaluator-create");
        
	stringz = scm_to_locale_string(string);

	evaluator = evaluator_create(stringz);

	free(stringz);

	SCM_RETURN_NEWSMOB(evaluator_tag, evaluator);
}

/* Wrapper for evaluator_evaluate() procedure from libmatheval library.
 * Variable names and values are passed as lists from Guile, so copies of
 * these argument have to be created in order to be able to call
 * evaluator_evaluate() procedure. */
static          SCM
evaluator_evaluate_scm(SCM evaluator_smob, SCM count, SCM names,
		       SCM values)
{
	SCM             name;
	char          **names_copy;
	SCM             value;
	double         *values_copy;
	double          result;
	int             i;

	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-evaluate");
	SCM_ASSERT(scm_is_integer(count), count, SCM_ARG2,
		   "evaluator-evaluate");

	names_copy = (char **) malloc(scm_to_int(count) * sizeof(char *));
	for (i = 0, name = names; i < scm_to_int(count);
	     i++, name = SCM_CDR(name)) {
		SCM_ASSERT(SCM_NIMP(name) && SCM_CONSP(name)
			   && scm_is_string(SCM_CAR(name)), names, SCM_ARG3,
			   "evaluator-evaluate");
		names_copy[i] = scm_to_locale_string(SCM_CAR(name));
	}

	values_copy = (double *) malloc(scm_to_int(count) * sizeof(double));
	for (i = 0, value = values; i < scm_to_int(count);
	     i++, value = SCM_CDR(value)) {
		SCM_ASSERT(SCM_NIMP(value) && SCM_CONSP(value)
			   && SCM_NUMBERP(SCM_CAR(value)), values,
			   SCM_ARG4, "evaluator-evaluate");
		values_copy[i] =
		    scm_to_double(SCM_CAR(value));
	}

	result =
	    evaluator_evaluate((void *) SCM_CDR(evaluator_smob),
			       scm_to_int(count), names_copy, values_copy);

	for (i = 0; i < scm_to_int(count); i++)
		free(names_copy[i]);
	free(names_copy);
	free(values_copy);

	return scm_from_double(result);
}

/* Wrapper for evaluator_get_string() procedure from libmatheval library. */
static          SCM
evaluator_get_string_scm(SCM evaluator_smob)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-get-string");

	return
	    scm_from_locale_string(evaluator_get_string
			    ((void *) SCM_CDR(evaluator_smob)));
}

/* Wrapper for evaluator_get_variables() procedure from libmatheval
 * library. */
static          SCM
evaluator_get_variables_scm(SCM evaluator_smob)
{
	char          **names;
	int             count;
	SCM             list;
	int             i;

	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-get-string");

	evaluator_get_variables((void *) SCM_CDR(evaluator_smob), &names,
				&count);
	list = SCM_EOL;
	for (i = 0; i < count; i++)
		list =
		    scm_append_x(scm_list_n
				 (list,
				  scm_list_n(scm_from_locale_string(names[i]),
					      SCM_UNDEFINED),
				  SCM_UNDEFINED));

	return list;
}

/* Wrapper for evaluator_derivative() procedure from libmatheval library. */
static          SCM
evaluator_derivative_scm(SCM evaluator_smob, SCM name)
{
	char * stringz;
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-derivative");
	SCM_ASSERT(SCM_NIMP(name)
		   && scm_is_string(name), name, SCM_ARG2,
		   "evaluator-derivative");
	stringz = scm_to_locale_string(name);
	SCM_RETURN_NEWSMOB(evaluator_tag,
			   evaluator_derivative((void *)
						SCM_CDR(evaluator_smob),
						stringz));
	free(stringz);
}

/* Wrapper for evaluator_evaluate_x() procedure from libmatheval library. */
static          SCM
evaluator_evaluate_x_scm(SCM evaluator_smob, SCM x)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-evaluate-x");
	SCM_ASSERT(SCM_NUMBERP(x), x, SCM_ARG2, "evaluator-evaluate-x");
	return
	    scm_from_double(evaluator_evaluate_x
			  ((void *) SCM_CDR(evaluator_smob),
			   scm_to_double(x)));
}

/* Wrapper for evaluator_evaluate_x_y() procedure from libmatheval
 * library. */
static          SCM
evaluator_evaluate_x_y_scm(SCM evaluator_smob, SCM x, SCM y)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-evaluate-x-y");
	SCM_ASSERT(SCM_NUMBERP(x), x, SCM_ARG2, "evaluator-evaluate-x-y");
	SCM_ASSERT(SCM_NUMBERP(y), y, SCM_ARG3, "evaluator-evaluate-x-y");
	return
	    scm_from_double(evaluator_evaluate_x_y
			  ((void *) SCM_CDR(evaluator_smob),
			   scm_to_double(x),
			   scm_to_double(y)));
}

/* Wrapper for evaluator_evaluate_x_y_z() procedure from libmatheval
 * library. */
static          SCM
evaluator_evaluate_x_y_z_scm(SCM evaluator_smob, SCM x, SCM y, SCM z)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-evaluate-x-y-z");
	SCM_ASSERT(SCM_NUMBERP(x), x, SCM_ARG2,
		   "evaluator-evaluate-x-y-z");
	SCM_ASSERT(SCM_NUMBERP(y), y, SCM_ARG3,
		   "evaluator-evaluate-x-y-z");
	SCM_ASSERT(SCM_NUMBERP(z), z, SCM_ARG4,
		   "evaluator-evaluate-x-y-z");
	return
	    scm_from_double(evaluator_evaluate_x_y_z
			  ((void *) SCM_CDR(evaluator_smob),
			   scm_to_double(x),
			   scm_to_double(y),
			   scm_to_double(z)));
}

/* Wrapper for evaluator_derivative_x() procedure from libmatheval
 * library. */
static          SCM
evaluator_derivative_x_scm(SCM evaluator_smob)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-derivative-x");
	SCM_RETURN_NEWSMOB(evaluator_tag,
			   evaluator_derivative((void *)
						SCM_CDR(evaluator_smob),
						"x"));
}

/* Wrapper for evaluator_derivative_y() procedure from libmatheval
 * library. */
static          SCM
evaluator_derivative_y_scm(SCM evaluator_smob)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-derivative-y");
	SCM_RETURN_NEWSMOB(evaluator_tag,
			   evaluator_derivative((void *)
						SCM_CDR(evaluator_smob),
						"y"));
}

/* Wrapper for evaluator_derivative_z() procedure from libmatheval
 * library. */
static          SCM
evaluator_derivative_z_scm(SCM evaluator_smob)
{
	SCM_ASSERT((SCM_NIMP(evaluator_smob)
		    && SCM_SMOB_PREDICATE(evaluator_tag, evaluator_smob)),
		   evaluator_smob, SCM_ARG1, "evaluator-derivative-z");
	SCM_RETURN_NEWSMOB(evaluator_tag,
			   evaluator_derivative((void *)
						SCM_CDR(evaluator_smob),
						"z"));
}