1 #include <vtestbed/config/real_type.hh> 2 #include <vtestbed/core/grid.hh> 3 #include <vtestbed/guile/base.hh> 4 #include <vtestbed/guile/grid.hh> 5 #include <vtestbed/guile/macros.hh> 9 SCM kw_min, kw_max, kw_npoints, kw_nsegments;
10 SCM kw_begin_index, kw_end_index;
11 const char* grid_goops = R
"( 12 (use-modules (oop goops)) 13 (define-method (write (grid <grid>) port) (display (grid->string grid) port)) 26 const int dimensions = N;
30 Grid_wrapper(SCM min, SCM max, SCM npoints, SCM nsegments, SCM begin, SCM end) {
33 if (is_bound(begin)) { this->begin(begin); }
34 else { grid.
begin() = VTB_REAL_TYPE{}; }
35 if (is_bound(end)) { this->end(end); }
36 else if (is_bound(npoints)) { this->num_points(npoints); }
37 else { this->num_segments(nsegments); }
42 for (
int i=N-1; i>=0; --i) {
43 ret = scm_cons(to_scm(grid.
lbound(i)), ret);
50 for (
int i=N-1; i>=0; --i) {
51 ret = scm_cons(to_scm(grid.
ubound(i)), ret);
58 for (
int i=N-1; i>=0; --i) {
59 ret = scm_cons(to_scm(grid.
begin(i)), ret);
66 for (
int i=N-1; i>=0; --i) {
67 ret = scm_cons(to_scm(grid.
end(i)), ret);
73 for (
int i=0; i<N; ++i) {
74 grid.
lbound(i) = scm_to_double(scm_car(min));
80 for (
int i=0; i<N; ++i) {
81 grid.
ubound(i) = scm_to_double(scm_car(max));
86 void begin(SCM begin) {
87 for (
int i=0; i<N; ++i) {
88 grid.
begin(i) = scm_to_int(scm_car(begin));
89 begin = scm_cdr(begin);
94 for (
int i=0; i<N; ++i) {
95 grid.
end(i) = scm_to_int(scm_car(end));
100 void num_points(SCM npoints) {
101 for (
int i=0; i<N; ++i) {
102 grid.
end(i) = grid.
begin(i) + scm_to_int(scm_car(npoints));
103 npoints = scm_cdr(npoints);
107 void num_segments(SCM nsegments) {
108 for (
int i=0; i<N; ++i) {
109 grid.
end(i) = grid.
begin(i) + 1+scm_to_int(scm_car(nsegments));
110 nsegments = scm_cdr(nsegments);
114 SCM select(SCM indices) {
119 while (indices != SCM_EOL) {
120 int i = scm_to_int(scm_car(indices));
121 min = scm_cons(to_scm(grid.
lbound(i)), min);
122 max = scm_cons(to_scm(grid.
ubound(i)), max);
123 begin = scm_cons(to_scm(grid.
begin(i)), begin);
124 end = scm_cons(to_scm(grid.
end(i)), end);
125 indices = scm_cdr(indices);
127 min = scm_reverse(min);
128 max = scm_reverse(max);
129 begin = scm_reverse(begin);
130 end = scm_reverse(end);
131 return scm_call(scm_variable_ref(scm_c_lookup(
"make-grid")),
132 kw_min, min, kw_max, max,
133 kw_begin_index, begin, kw_end_index, end,
137 SCM compact()
const {
138 auto* wrapper = allocate_pointerless<Grid_wrapper>(
"grid");
139 wrapper->grid = this->grid;
140 wrapper->grid.compact();
141 return scm_make_foreign_object_2(::type, wrapper,
142 reinterpret_cast<void*>(
size_t(dimensions)));
145 SCM to_string()
const {
148 return to_scm(tmp.str());
154 get_grid_wrapper(SCM
object) {
155 return reinterpret_cast<Grid_wrapper<N>*
>(scm_foreign_object_ref(
object, 0));
159 get_dimensions(SCM
object) {
160 return reinterpret_cast<size_t>(scm_foreign_object_ref(
object, 1));
170 SCM min = SCM_UNDEFINED, max = SCM_UNDEFINED, npoints = SCM_UNDEFINED,
171 nsegments = SCM_UNDEFINED, begin = SCM_UNDEFINED, end = SCM_UNDEFINED;
172 scm_c_bind_keyword_arguments(
"make-grid", rest,
173 scm_t_keyword_arguments_flags{},
174 kw_min, &min, kw_max, &max,
175 kw_npoints, &npoints, kw_nsegments, &nsegments,
176 kw_begin_index, &begin, kw_end_index, &end,
178 if (!is_bound(min) || !is_bound(max)) {
179 throw_error(
"missing min/max");
180 return SCM_UNSPECIFIED;
182 if (is_bound(npoints) && is_bound(nsegments)) {
183 throw_error(
"both num-points and num-segments defined");
184 return SCM_UNSPECIFIED;
186 if ((is_bound(end) && (is_bound(npoints) || is_bound(nsegments)))) {
187 throw_error(
"use either begin-index and end-index, " 188 "or begin-index and num-points/num-segments");
189 return SCM_UNSPECIFIED;
191 if (!is_list(min) || !is_list(max) ||
192 (is_bound(npoints) && !is_list(npoints)) ||
193 (is_bound(nsegments) && !is_list(nsegments))) {
194 throw_error(
"min/max/num-points/num-segments is not a list");
195 return SCM_UNSPECIFIED;
197 auto dimensions = length(min);
198 if (length(max) != dimensions ||
199 (is_bound(npoints) && length(npoints) != dimensions) ||
200 (is_bound(nsegments) && length(nsegments) != dimensions) ||
201 (is_bound(begin) && length(begin) != dimensions) ||
202 (is_bound(end) && length(end) != dimensions)) {
203 throw_error(
"min/max/num-points/num-segments/begin-index/end-index " 204 "have different length");
205 return SCM_UNSPECIFIED;
207 void* wrapper =
nullptr;
208 switch (dimensions) {
210 wrapper = construct_pointerless<Grid_wrapper<1>>(
211 "grid", min, max, npoints, nsegments, begin, end);
214 wrapper = construct_pointerless<Grid_wrapper<2>>(
215 "grid", min, max, npoints, nsegments, begin, end);
218 wrapper = construct_pointerless<Grid_wrapper<3>>(
219 "grid", min, max, npoints, nsegments, begin, end);
222 wrapper = construct_pointerless<Grid_wrapper<4>>(
223 "grid", min, max, npoints, nsegments, begin, end);
225 default: throw_error(
"bad no. of dimensions");
return SCM_UNSPECIFIED;
227 return scm_make_foreign_object_2(::type, wrapper,
228 reinterpret_cast<void*>(
size_t(dimensions)));
238 scm_assert_foreign_object_type(::type,
object);
239 switch (get_dimensions(
object)) {
240 case 1:
return get_grid_wrapper<1>(
object)->min();
241 case 2:
return get_grid_wrapper<2>(
object)->min();
242 case 3:
return get_grid_wrapper<3>(
object)->min();
243 case 4:
return get_grid_wrapper<4>(
object)->min();
245 return SCM_UNSPECIFIED;
255 scm_assert_foreign_object_type(::type,
object);
256 switch (get_dimensions(
object)) {
257 case 1:
return get_grid_wrapper<1>(
object)->max();
258 case 2:
return get_grid_wrapper<2>(
object)->max();
259 case 3:
return get_grid_wrapper<3>(
object)->max();
260 case 4:
return get_grid_wrapper<4>(
object)->max();
262 return SCM_UNSPECIFIED;
272 scm_assert_foreign_object_type(::type,
object);
273 switch (get_dimensions(
object)) {
274 case 1:
return get_grid_wrapper<1>(
object)->begin();
275 case 2:
return get_grid_wrapper<2>(
object)->begin();
276 case 3:
return get_grid_wrapper<3>(
object)->begin();
277 case 4:
return get_grid_wrapper<4>(
object)->begin();
279 return SCM_UNSPECIFIED;
289 scm_assert_foreign_object_type(::type,
object);
290 switch (get_dimensions(
object)) {
291 case 1:
return get_grid_wrapper<1>(
object)->end();
292 case 2:
return get_grid_wrapper<2>(
object)->end();
293 case 3:
return get_grid_wrapper<3>(
object)->end();
294 case 4:
return get_grid_wrapper<4>(
object)->end();
296 return SCM_UNSPECIFIED;
306 scm_assert_foreign_object_type(::type,
object);
307 switch (get_dimensions(
object)) {
308 case 1:
return get_grid_wrapper<1>(
object)->select(indices);
309 case 2:
return get_grid_wrapper<2>(
object)->select(indices);
310 case 3:
return get_grid_wrapper<3>(
object)->select(indices);
311 case 4:
return get_grid_wrapper<4>(
object)->select(indices);
313 return SCM_UNSPECIFIED;
323 scm_assert_foreign_object_type(::type,
object);
324 switch (get_dimensions(
object)) {
325 case 1:
return get_grid_wrapper<1>(
object)->compact();
326 case 2:
return get_grid_wrapper<2>(
object)->compact();
327 case 3:
return get_grid_wrapper<3>(
object)->compact();
328 case 4:
return get_grid_wrapper<4>(
object)->compact();
330 return SCM_UNSPECIFIED;
340 scm_assert_foreign_object_type(::type,
object);
341 switch (get_dimensions(
object)) {
342 case 1:
return get_grid_wrapper<1>(
object)->to_string();
343 case 2:
return get_grid_wrapper<2>(
object)->to_string();
344 case 3:
return get_grid_wrapper<3>(
object)->to_string();
345 case 4:
return get_grid_wrapper<4>(
object)->to_string();
347 return SCM_UNSPECIFIED;
351 kw_min = scm_from_utf8_keyword(
"min");
352 kw_max = scm_from_utf8_keyword(
"max");
353 kw_npoints = scm_from_utf8_keyword(
"num-points");
354 kw_nsegments = scm_from_utf8_keyword(
"num-segments");
355 kw_begin_index = scm_from_utf8_keyword(
"begin-index");
356 kw_end_index = scm_from_utf8_keyword(
"end-index");
357 ::type = scm_make_foreign_object_type(
358 scm_from_utf8_symbol(
"grid"),
359 scm_list_2(scm_from_utf8_symbol(
"grid"), scm_from_utf8_symbol(
"dimensions")),
361 scm_c_define(
"<grid>", ::type);
362 define_procedure(
"make-grid", 0, 0, 1, VTB_GUILE_1(
make_grid));
363 define_procedure(
"grid-min", 1, 0, 0, VTB_GUILE_1(
grid_min));
364 define_procedure(
"grid-max", 1, 0, 0, VTB_GUILE_1(
grid_max));
365 define_procedure(
"grid-begin-index", 1, 0, 0, VTB_GUILE_1(
grid_begin_index));
366 define_procedure(
"grid-end-index", 1, 0, 0, VTB_GUILE_1(
grid_end_index));
367 define_procedure(
"grid-select", 2, 0, 0, VTB_GUILE_2(
grid_select));
368 define_procedure(
"grid-compact!", 1, 0, 0, VTB_GUILE_1(
grid_compact));
369 define_procedure(
"grid->string", 1, 0, 0, VTB_GUILE_1(
grid_to_string));
370 scm_c_eval_string(grid_goops);
377 template <
class T,
int N> SCM
379 auto* wrapper = allocate_pointerless<Grid_wrapper<N>>(
"grid");
380 wrapper->grid = grid;
381 return scm_make_foreign_object_2(::type, wrapper, reinterpret_cast<void*>(
size_t(N)));
SCM grid_select(SCM object, SCM indices)
Construct new grid by selecting dimensions from the existing grid.
SCM make_grid(SCM rest)
Construct multidimensional rectangular grid.
SCM grid_end_index(SCM object)
Get grid end index (exclusive).
const int_n & end() const noexcept
End indices (exclusive).
SCM grid_begin_index(SCM object)
Get grid begin index (inclusive).
const vec & lbound() const noexcept
Lower bound of the region.
SCM grid_min(SCM object)
Get grid lower bound.
const int_n & begin() const noexcept
Start indices (inclusive).
SCM grid_to_string(SCM object)
Convert grid to human-readable string.
SCM grid_max(SCM object)
Get grid upper bound.
const vec & ubound() const noexcept
Upper bound of the region.
SCM grid_compact(SCM object)
Re-index the grid to make begin index equal nought.