samer@0
|
1 /*
|
samer@0
|
2 * Prolog-C utilities
|
samer@0
|
3 * Samer Abdallah (2009)
|
samer@0
|
4 */
|
samer@0
|
5
|
samer@0
|
6 //#define _USE_MATH_DEFINES 1
|
samer@0
|
7 //#include "plutils.h"
|
samer@0
|
8
|
samer@0
|
9 //#include <math.h>
|
samer@0
|
10 //#include <float.h>
|
samer@0
|
11
|
samer@0
|
12 // throws a Prolog exception to signal type error
|
samer@0
|
13 int type_error(term_t actual, const char *expected)
|
samer@0
|
14 {
|
samer@0
|
15 term_t ex = PL_new_term_ref();
|
samer@0
|
16 int rc = PL_unify_term(ex, PL_FUNCTOR_CHARS, "error", 2,
|
samer@0
|
17 PL_FUNCTOR_CHARS, "type_error", 2,
|
samer@0
|
18 PL_CHARS, expected,
|
samer@0
|
19 PL_TERM, actual,
|
samer@0
|
20 PL_VARIABLE);
|
samer@0
|
21
|
samer@0
|
22 return rc && PL_raise_exception(ex);
|
samer@0
|
23 }
|
samer@0
|
24
|
samer@0
|
25 double sum_array(double *p, int n) {
|
samer@0
|
26 double tot=0;
|
samer@0
|
27 int i;
|
samer@0
|
28 for (i=0; i<n; i++) tot+=*p++;
|
samer@0
|
29 return tot;
|
samer@0
|
30 }
|
samer@0
|
31
|
samer@0
|
32 int memory_error(size_t amount)
|
samer@0
|
33 {
|
samer@0
|
34 term_t ex = PL_new_term_ref();
|
samer@0
|
35 int rc = PL_unify_term(ex, PL_FUNCTOR_CHARS, "error", 2,
|
samer@0
|
36 PL_FUNCTOR_CHARS, "memory_error", 1,
|
samer@0
|
37 PL_INTEGER, amount,
|
samer@0
|
38 PL_VARIABLE);
|
samer@0
|
39
|
samer@0
|
40 return rc && PL_raise_exception(ex);
|
samer@0
|
41 }
|
samer@0
|
42
|
samer@0
|
43 // extract double from Prolog float
|
samer@0
|
44 int get_double(term_t term, double *p)
|
samer@0
|
45 {
|
samer@0
|
46 if (PL_get_float(term, p)) return TRUE;
|
samer@0
|
47 else return type_error(term, "float");
|
samer@0
|
48 }
|
samer@0
|
49
|
samer@0
|
50 // extract long from Prolog integer
|
samer@0
|
51 int get_long(term_t term, long *p)
|
samer@0
|
52 {
|
samer@0
|
53 if (PL_get_long(term, p)) return TRUE;
|
samer@0
|
54 else return type_error(term, "integer");
|
samer@0
|
55 }
|
samer@0
|
56
|
samer@0
|
57
|
samer@0
|
58 // unify Prolog list of floats with array of doubles
|
samer@0
|
59 int unify_list_doubles(term_t list, double *x, int n)
|
samer@0
|
60 {
|
samer@0
|
61 int i;
|
samer@0
|
62 list=PL_copy_term_ref(list);
|
samer@0
|
63
|
samer@0
|
64 for (i=0; i<n; i++) {
|
samer@0
|
65 term_t head=PL_new_term_ref();
|
samer@0
|
66 term_t tail=PL_new_term_ref();
|
samer@0
|
67 if (!PL_unify_list(list,head,tail)) PL_fail;
|
samer@0
|
68 if (!PL_unify_float(head,x[i])) PL_fail;
|
samer@0
|
69 list=tail;
|
samer@0
|
70 }
|
samer@0
|
71 return PL_unify_nil(list);
|
samer@0
|
72 }
|
samer@0
|
73
|
samer@0
|
74 // read list of floats from term and write to double array
|
samer@0
|
75 int get_list_doubles(term_t list, double *vals, int len)
|
samer@0
|
76 {
|
samer@0
|
77 term_t head=PL_new_term_ref();
|
samer@0
|
78 int n;
|
samer@0
|
79
|
samer@0
|
80 // copy term ref so as not to modify original
|
samer@0
|
81 list=PL_copy_term_ref(list);
|
samer@0
|
82 for (n=0; n<len && PL_get_list(list,head,list);n++) {
|
samer@0
|
83 if (!PL_get_float(head,&vals[n])) return FALSE;
|
samer@0
|
84 }
|
samer@0
|
85 if (!PL_get_nil(list)) return FALSE;
|
samer@0
|
86 return TRUE;
|
samer@0
|
87 }
|
samer@0
|
88
|
samer@0
|
89 int unify_args_doubles(term_t state, double *p, int n)
|
samer@0
|
90 {
|
samer@0
|
91 term_t arg = PL_new_term_ref();
|
samer@0
|
92 int i;
|
samer@0
|
93
|
samer@0
|
94 for (i=0; i<n; i++) {
|
samer@0
|
95 if (!PL_put_float(arg,p[i])) PL_fail;
|
samer@0
|
96 if (!PL_unify_arg(i+1,state,arg)) PL_fail;
|
samer@0
|
97 }
|
samer@0
|
98 return TRUE;
|
samer@0
|
99 }
|
samer@0
|
100
|
samer@0
|
101 int get_args_doubles(term_t state, double *p, int n)
|
samer@0
|
102 {
|
samer@0
|
103 term_t arg = PL_new_term_ref();
|
samer@0
|
104 int i;
|
samer@0
|
105
|
samer@0
|
106 for (i=0; i<n; i++) {
|
samer@0
|
107 _PL_get_arg(i+1, state, arg);
|
samer@0
|
108 if (!get_double(arg, p+i)) return FALSE;
|
samer@0
|
109 }
|
samer@0
|
110 return TRUE;
|
samer@0
|
111 }
|
samer@0
|
112
|
samer@0
|
113 int alloc_array(size_t N, size_t SZ, void **PP) {
|
samer@0
|
114 *PP=calloc(N,SZ);
|
samer@0
|
115 if (*PP) return TRUE;
|
samer@0
|
116 else return memory_error(N*SZ);
|
samer@0
|
117 }
|
samer@0
|
118
|