38 #include <D4Sequence.h>
43 #include <ServerFunctionsList.h>
58 static void read_array_values(Array *a)
72 TabularFunction::Shape TabularFunction::array_shape(Array *a)
76 for (Array::Dim_iter i = a->dim_begin(), e = a->dim_end(); i != e; ++i) {
77 shape.push_back(a->dimension_size(i));
91 bool TabularFunction::shape_matches(Array *a,
const Shape &shape)
94 if (shape.size() != a->dimensions())
return false;
97 Array::Dim_iter i = a->dim_begin(), e = a->dim_end();
98 Shape::const_iterator si = shape.begin(), se = shape.end();
99 while (i != e && si != se) {
100 assert(a->dimension_size(i) >= 0);
101 if (*si != (
unsigned long) a->dimension_size(i))
return false;
122 bool TabularFunction::dep_indep_match(
const Shape &dep_shape,
const Shape &indep_shape)
126 Shape::const_reverse_iterator di = dep_shape.rbegin();
127 for (Shape::const_reverse_iterator i = indep_shape.rbegin(), e = indep_shape.rend(); i != e; ++i) {
128 assert(di != dep_shape.rend());
129 if (*i != *di++)
return false;
142 unsigned long TabularFunction::number_of_values(
const Shape &shape)
144 unsigned long size = 1;
145 Shape::const_iterator si = shape.begin(), se = shape.end();
172 void TabularFunction::build_columns(
unsigned long n, BaseType* btp, vector<Array*>& the_arrays,
175 if (btp->type() != dods_array_c)
176 throw Error(
"In tabular(): Expected argument '" + btp->name() +
"' to be an Array.");
179 Array *a =
static_cast<Array*
>(btp);
183 shape = array_shape(a);
184 else if (!shape_matches(a, shape))
185 throw Error(
"In tabular: Array '" + a->name() +
"' does not match the shape of the initial Array.");
187 read_array_values(a);
189 the_arrays.at(n) = a;
200 void TabularFunction::read_values(
const vector<Array*> &arrays)
203 for_each(arrays.begin(), arrays.end(), read_array_values);
222 void TabularFunction::build_sequence_values(
const vector<Array*> &the_arrays, SequenceValues &sv)
229 for (SequenceValues::size_type i = 0; i < sv.size(); ++i) {
231 BaseTypeRow *row =
new BaseTypeRow(the_arrays.size());
233 for (BaseTypeRow::size_type j = 0; j < the_arrays.size(); ++j) {
234 DBG(cerr <<
"the_arrays.at(" << j <<
") " << the_arrays.at(j) << endl);
236 (*row)[j]= the_arrays[j]->var(i)->ptr_duplicate();
238 (*row)[j]->set_send_p(
true);
239 (*row)[j]->set_read_p(
true);
265 void TabularFunction::combine_sequence_values(SequenceValues &dep,
const SequenceValues &indep)
267 SequenceValues::const_iterator ii = indep.begin(), ie = indep.end();
268 for (SequenceValues::iterator i = dep.begin(), e = dep.end(); i != e; ++i) {
271 if (ii == ie) ii = indep.begin();
276 for (BaseTypeRow::iterator btr_i = (*ii)->begin(), btr_e = (*ii)->end(); btr_i != btr_e; ++btr_i) {
277 (*i)->push_back((*btr_i)->ptr_duplicate());
310 void TabularFunction::add_index_column(
const Shape &indep_shape,
const Shape &dep_shape,
311 vector<Array*> &dep_vars)
313 assert(dep_vars.size() > 0);
314 assert(dep_shape.size() == indep_shape.size() + 1);
317 unsigned long num_indep_values = number_of_values(indep_shape);
318 unsigned long num_dep_values = number_of_values(dep_shape);
319 vector<dods_uint32> index_vals(num_dep_values);
321 assert(num_dep_values == num_indep_values * dep_shape.at(0));
324 vector<dods_uint32>::iterator iv = index_vals.begin();
325 for (Shape::size_type i = 0; i < dep_shape.at(0); ++i) {
326 assert(iv != index_vals.end());
327 fill(iv, iv + num_indep_values, i);
328 iv += num_indep_values;
332 string new_column_name = dep_vars.at(0)->dimension_name(dep_vars.at(0)->dim_begin());
333 if (new_column_name.empty())
334 new_column_name =
"index";
337 Array *a =
new Array(new_column_name,
new UInt32(new_column_name));
338 a->append_dim(num_dep_values, new_column_name);
339 a->set_value(index_vals, (
int)index_vals.size());
342 dep_vars.insert(dep_vars.begin(), a);
364 void TabularFunction::function_dap2_tabular_2(
int argc, BaseType *argv[], DDS &, BaseType **btpp)
368 auto_ptr<TabularSequence> response(
new TabularSequence(
"table"));
370 int num_arrays = argc;
372 vector<Array*> the_arrays(num_arrays);
377 for (
int n = 0; n < num_arrays; ++n) {
378 build_columns(n, argv[n], the_arrays, shape);
381 DBG(cerr <<
"the_arrays.size(): " << the_arrays.size() << endl);
385 for (
unsigned long n = 0; n < the_arrays.size(); ++n) {
386 response->add_var(the_arrays[n]->var());
389 unsigned long num_values = number_of_values(shape);
390 SequenceValues sv(num_values);
394 build_sequence_values(the_arrays, sv);
396 response->set_value(sv);
397 response->set_read_p(
true);
399 *btpp = response.release();
429 void TabularFunction::function_dap2_tabular(
int argc, BaseType *argv[], DDS &, BaseType **btpp)
431 vector<Array*> the_arrays;
433 for (
int n = 0; n < argc; ++n) {
434 if (argv[n]->type() != dods_array_c)
435 throw Error(
"In function tabular(): Expected an array, but argument " + argv[n]->name()
436 +
" is a " + argv[n]->type_name() +
".");
437 the_arrays.push_back(static_cast<Array*>(argv[n]));
440 if (the_arrays.size() < 1)
441 throw Error(
"In function tabular(): Expected at least one Array variable.");
444 unsigned long min_dim_size = ULONG_MAX;
445 for (vector<Array*>::iterator i = the_arrays.begin(), e = the_arrays.end(); i != e; ++i) {
446 min_dim_size =
min((
unsigned long) (*i)->dimensions(), min_dim_size);
450 vector<Array*> indep_vars, dep_vars;
451 for (vector<Array*>::iterator i = the_arrays.begin(), e = the_arrays.end(); i != e; ++i) {
452 if ((*i)->dimensions() == min_dim_size) {
453 indep_vars.push_back(*i);
456 dep_vars.push_back(*i);
460 Shape indep_shape = array_shape(indep_vars.at(0));
462 for (vector<Array*>::iterator i = indep_vars.begin()+1, e = indep_vars.end(); i != e; ++i) {
463 if (!shape_matches(*i, indep_shape))
464 throw Error(
"In function tabular(): Expected all of the 'independent' variables to have the same shape.");
468 read_values(indep_vars);
469 unsigned long num_indep_values = number_of_values(indep_shape);
470 SequenceValues indep_sv(num_indep_values);
471 build_sequence_values(indep_vars, indep_sv);
476 SequenceValues &result = indep_sv;
479 if (dep_vars.size() > 0) {
480 Shape dep_shape = array_shape(dep_vars.at(0));
482 for (vector<Array*>::iterator i = dep_vars.begin()+1, e = dep_vars.end(); i != e; ++i) {
483 if (!shape_matches(*i, dep_shape))
484 throw Error(
"In function tabular(): Expected all of the 'dependent' variables to have the same shape.");
490 if (dep_shape.size() > indep_shape.size() + 1)
491 throw Error(
"In function tabular(): The rank of the dependent variables may be at most one more than the rank of the independent variables");
492 if (dep_shape.size() < indep_shape.size())
493 throw Error(
"In function tabular(): The rank of the dependent variables cannot be less than the rank of the independent variables");
495 if (!dep_indep_match(dep_shape, indep_shape))
496 throw Error(
"In function tabular(): The 'independent' array shapes must match the right-most dimensions of the 'dependent' variables.");
498 read_values(dep_vars);
499 unsigned long num_dep_values = number_of_values(dep_shape);
500 SequenceValues dep_sv(num_dep_values);
503 add_index_column(indep_shape, dep_shape, dep_vars);
505 build_sequence_values(dep_vars, dep_sv);
510 combine_sequence_values(dep_sv, indep_sv);
514 auto_ptr<TabularSequence> response(
new TabularSequence(
"table"));
516 if (dep_vars.size() > 0) {
518 for (SequenceValues::size_type n = 0; n < dep_vars.size(); ++n) {
519 response->add_var(dep_vars[n]->var());
523 for (SequenceValues::size_type n = 0; n < indep_vars.size(); ++n) {
524 response->add_var(indep_vars[n]->var());
528 response->set_value(result);
529 response->set_read_p(
true);
531 *btpp = response.release();
550 BaseType *TabularFunction::function_dap4_tabular(D4RValueList *args, DMR &dmr)
554 auto_ptr<D4Sequence> response(
new D4Sequence(
"table"));
556 int num_arrays = args->size();
557 vector<unsigned long> shape;
558 vector<Array*> the_arrays(num_arrays);
560 for (
int n = 0; n < num_arrays; ++n) {
561 TabularFunction::build_columns(n, args->get_rvalue(n)->value(dmr), the_arrays, shape);
564 DBG(cerr <<
"the_arrays.size(): " << the_arrays.size() << endl);
566 for (
unsigned long n = 0; n < the_arrays.size(); ++n) {
567 response->add_var(the_arrays[n]->var());
570 unsigned long num_values = TabularFunction::number_of_values(shape);
571 D4SeqValues sv(num_values);
573 TabularFunction::build_sequence_values(the_arrays, sv);
575 response->set_value(sv);
576 response->set_read_p(
true);
578 return response.release();
static class NCMLUtil overview