Virtual Testbed
Ship dynamics simulator for extreme conditions
base.hh
1 #ifndef VTESTBED_GUILE_BASE_HH
2 #define VTESTBED_GUILE_BASE_HH
3 
4 #include <blitz/array.h>
5 #include <libguile.h>
6 
7 #include <cstdint>
8 #include <memory>
9 #include <string>
10 
11 namespace vtb {
12 
14  namespace guile {
15 
16  template <class Pointer>
17  inline void
18  define_procedure(const char *name, int req, int opt, int rest, Pointer ptr,
19  const char* documentation=nullptr) {
20  SCM proc = scm_c_define_gsubr(name, req, opt, rest,
21  reinterpret_cast<scm_t_subr>(ptr));
22  if (documentation) {
23  scm_set_procedure_property_x(proc, scm_from_utf8_symbol("documentation"),
24  scm_from_utf8_string(documentation));
25  }
26  }
27 
28  inline void
29  throw_error(const char* message) {
30  scm_throw(scm_from_utf8_symbol("vtb-error"),
31  scm_list_1(scm_from_utf8_string(message)));
32  }
33 
34  inline bool
35  symbol_equal(SCM a, SCM b) {
36  return scm_is_true(scm_eq_p(a, b));
37  }
38 
45  inline SCM vtestbed_gc() {
46  scm_gc();
47  scm_run_finalizers();
48  return SCM_UNSPECIFIED;
49  }
50 
51  template <class T> inline T*
52  allocate(const char* name) {
53  return reinterpret_cast<T*>(scm_gc_malloc(sizeof(T), name));
54  }
55 
56  template <class T> inline T*
57  allocate_pointerless(const char* name) {
58  return reinterpret_cast<T*>(scm_gc_malloc_pointerless(sizeof(T), name));
59  }
60 
61  template <class T, class ... Args> inline T*
62  construct_pointerless(const char* name, Args ... args) {
63  auto* ptr = allocate_pointerless<T>(name);
64  new (ptr) T(std::forward<Args>(args)...);
65  return ptr;
66  }
67 
68  inline bool is_bound(SCM s) { return !SCM_UNBNDP(s); }
69  inline int length(SCM s) { return scm_to_int(scm_length(s)); }
70  inline bool is_list(SCM s) { return scm_is_true(scm_list_p(s)); }
71 
72  template <int N>
73  inline SCM to_scm(const blitz::TinyVector<float,N>& x) {
74  auto *ptr = reinterpret_cast<float*>(std::malloc(sizeof(float)*N));
75  for (int i=0; i<N; ++i) { ptr[i] = x[i]; }
76  return scm_take_f32vector(ptr, N);
77  }
78 
79  template <int N>
80  inline SCM to_scm(const blitz::TinyVector<double,N>& x) {
81  auto *ptr = reinterpret_cast<double*>(std::malloc(sizeof(double)*N));
82  for (int i=0; i<N; ++i) { ptr[i] = x[i]; }
83  return scm_take_f64vector(ptr, N);
84  }
85 
86  template <class T> struct Uniform_vector_traits;
87 
88  template <> struct Uniform_vector_traits<int> {
89  using scalar_type = int;
90  static constexpr const auto elements = scm_s32vector_elements;
91  };
92 
93  template <> struct Uniform_vector_traits<float> {
94  using scalar_type = float;
95  static constexpr const auto elements = scm_f32vector_elements;
96  };
97 
98  template <> struct Uniform_vector_traits<double> {
99  using scalar_type = double;
100  static constexpr const auto elements = scm_f64vector_elements;
101  };
102 
103  template <class T, int N>
104  inline blitz::TinyVector<T,N> to_vector(SCM x) {
105  scm_t_array_handle handle;
106  size_t n = 0;
107  ssize_t dn = 1;
108  const T* ptr = Uniform_vector_traits<T>::elements(x, &handle, &n, &dn);
109  blitz::TinyVector<T,N> y;
110  for (size_t i=0; i<n; ++i, ptr += dn) { y[i] = *ptr; }
111  return y;
112  }
113 
114  struct c_deleter {
115  inline void operator()(void* ptr) { std::free(ptr); }
116  };
117 
118  template <class T> using c_string = std::unique_ptr<T,c_deleter>;
119 
120  inline c_string<char>
121  to_c_string(SCM s) {
122  return c_string<char>(scm_to_utf8_string(s));
123  }
124 
125  inline std::string to_string(SCM s) { return std::string(to_c_string(s).get()); }
126 
127  inline SCM to_scm(int32_t x) { return scm_from_int32(x); }
128  inline SCM to_scm(uint32_t x) { return scm_from_uint32(x); }
129  inline SCM to_scm(int64_t x) { return scm_from_int64(x); }
130  inline SCM to_scm(uint64_t x) { return scm_from_uint64(x); }
131  inline SCM to_scm(float x) { return scm_from_double(x); }
132  inline SCM to_scm(double x) { return scm_from_double(x); }
133  inline SCM to_scm(const char* x) { return scm_from_utf8_string(x); }
134  inline SCM to_scm(const std::string& x) { return to_scm(x.data()); }
135 
136  template <class T> T from_scm(SCM x);
137  template <> inline bool from_scm<bool>(SCM x) { return scm_is_true(x); }
138  template <> inline int from_scm<int>(SCM x) { return scm_to_int(x); }
139  template <> inline float from_scm<float>(SCM x) { return scm_to_double(x); }
140  template <> inline double from_scm<double>(SCM x) { return scm_to_double(x); }
141 
142  }
143 
144 }
145 
146 #endif // vim:filetype=cpp
SCM vtestbed_gc()
Run garbage collection and all object destructors.
Definition: base.hh:45
T length(const blitz::TinyVector< T, N > &x)
Computes vector length without overflow.
Definition: blitz.hh:471
Main namespace.
Definition: convert.hh:9