OmniSciDB  b28c0d5765
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GeoRasterTableFunctions.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #ifndef __CUDACC__
20 
21 #include <vector>
23 
24 // Note that GAUSS_AVG and AVG only valid in context of fill pass
26 
27 RasterAggType get_raster_agg_type(const std::string& agg_type_str,
28  const bool is_fill_agg) {
29  const auto upper_agg_type_str = to_upper(agg_type_str);
30  const static std::map<std::string, RasterAggType> agg_type_map = {
31  {"COUNT", RasterAggType::COUNT},
32  {"MIN", RasterAggType::MIN},
33  {"MAX", RasterAggType::MAX},
34  {"SUM", RasterAggType::SUM},
35  {"AVG", RasterAggType::AVG},
36  {"GAUSS_AVG", RasterAggType::GAUSS_AVG},
37  {"BOX_AVG", RasterAggType::BOX_AVG}};
38  const auto itr = agg_type_map.find(upper_agg_type_str);
39  if (itr == agg_type_map.end()) {
41  }
42  if (is_fill_agg && itr->second == RasterAggType::AVG) {
44  } else if (!is_fill_agg && (itr->second == RasterAggType::BOX_AVG ||
45  itr->second == RasterAggType::GAUSS_AVG)) {
46  // GAUSS_AVG and BOX_AVG are fill-only aggregates
48  }
49  return itr->second;
50 }
51 
52 template <RasterAggType AggType>
53 struct ComputeAgg {};
54 
55 template <>
57  template <typename Z, typename Z2>
58  void operator()(const Z2& input_z, Z& output_z, const Z2 input_sentinel) const {
59  if (input_z != input_sentinel) {
60  output_z = output_z == std::numeric_limits<Z>::lowest() ? 1 : output_z + 1;
61  }
62  }
63 };
64 
65 template <>
67  template <typename Z, typename Z2>
68  void operator()(const Z2& input_z, Z& output_z, const Z2 input_sentinel) const {
69  if (input_z != input_sentinel && input_z > output_z) {
70  output_z = input_z;
71  }
72  }
73 };
74 
75 template <>
77  template <typename Z, typename Z2>
78  void operator()(const Z2& input_z, Z& output_z, const Z2 input_sentinel) const {
79  if (input_z != input_sentinel && input_z < output_z) {
80  output_z = input_z;
81  }
82  }
83 };
84 
85 template <>
87  template <typename Z, typename Z2>
88  void operator()(const Z2& input_z, Z& output_z, const Z2 input_sentinel) const {
89  if (input_z != input_sentinel) {
90  output_z =
91  output_z == std::numeric_limits<Z>::lowest() ? input_z : output_z + input_z;
92  }
93  }
94 };
95 
96 // Just instansiating so don't have to work conditionally around AVG
97 template <>
99 
100 template <typename T, typename Z>
101 struct GeoRaster {
104  const bool geographic_coords_;
105  const Z null_sentinel_;
106  std::vector<Z> z_;
107  std::vector<Z> counts_;
108  T x_min_{0};
109  T x_max_{0};
110  T y_min_{0};
111  T y_max_{0};
116  int64_t num_x_bins_{0};
117  int64_t num_y_bins_{0};
118  int64_t num_bins_{0};
123 
124  constexpr static int64_t BIN_OUT_OF_BOUNDS{-1};
125 
126  template <typename T2, typename Z2>
127  GeoRaster(const Column<T2>& input_x,
128  const Column<T2>& input_y,
129  const Column<Z2>& input_z,
130  const RasterAggType raster_agg_type,
131  const double bin_dim_meters,
132  const bool geographic_coords,
133  const bool align_bins_to_zero_based_grid);
134 
135  template <typename T2, typename Z2>
136  GeoRaster(const Column<T2>& input_x,
137  const Column<T2>& input_y,
138  const Column<Z2>& input_z,
139  const RasterAggType raster_agg_type,
140  const double bin_dim_meters,
141  const bool geographic_coords,
142  const bool align_bins_to_zero_based_grid,
143  const T x_min,
144  const T x_max,
145  const T y_min,
146  const T y_max);
147 
148  inline T get_x_bin(const T input) const {
149  return (input - x_min_) * x_scale_input_to_bin_;
150  }
151 
152  inline T get_y_bin(const T input) const {
153  return (input - y_min_) * y_scale_input_to_bin_;
154  }
155 
156  inline bool is_null(const Z value) const { return value == null_sentinel_; }
157 
158  inline bool is_bin_out_of_bounds(const int64_t x_bin, const int64_t y_bin) const {
159  return (x_bin < 0 || x_bin >= num_x_bins_ || y_bin < 0 || y_bin >= num_y_bins_);
160  }
161 
162  inline std::pair<int64_t, Z> get_bin_idx_and_z_val_for_xy_bin(
163  const int64_t x_bin,
164  const int64_t y_bin) const {
165  if (is_bin_out_of_bounds(x_bin, y_bin)) {
166  return std::make_pair(BIN_OUT_OF_BOUNDS, null_sentinel_);
167  }
168  const int64_t bin_idx = x_y_bin_to_bin_index(x_bin, y_bin, num_x_bins_);
169  return std::make_pair(bin_idx, z_[bin_idx]);
170  }
171 
172  inline int64_t get_bin_idx_for_xy_coords(const T x, const T y) const {
173  if (x < x_min_ || x > x_max_ || y < y_min_ || y > y_max_) {
174  return BIN_OUT_OF_BOUNDS;
175  }
177  }
178 
179  inline std::pair<T, T> get_xy_coords_for_bin_idx(const int64_t bin_idx) const {
180  const auto [x_bin, y_bin] = bin_to_x_y_bin_indexes(bin_idx, num_x_bins_);
181  const T x = x_min_ + (x_bin + 0.5) * x_scale_bin_to_input_;
182  const T y = y_min_ + (y_bin + 0.5) * y_scale_bin_to_input_;
183  return std::make_pair(x, y);
184  }
185 
186  inline Z offset_source_z_from_raster_z(const int64_t source_x_bin,
187  const int64_t source_y_bin,
188  const Z source_z_offset) const;
190 
192 
194 
195  template <typename T2, typename Z2>
196  void compute(const Column<T2>& input_x,
197  const Column<T2>& input_y,
198  const Column<Z2>& input_z,
199  const size_t max_inputs_per_thread);
200 
202  const int64_t neighborhood_fill_radius,
203  const bool fill_only_nulls,
204  const RasterAggType raster_agg_type = RasterAggType::GAUSS_AVG);
205 
206  bool get_nxn_neighbors_if_not_null(const int64_t x_bin,
207  const int64_t y_bin,
208  const int64_t num_bins_radius,
209  std::vector<Z>& neighboring_bins) const;
210  inline std::pair<Z, Z> calculate_slope_and_aspect_of_cell(
211  const std::vector<Z>& neighboring_cells,
212  const bool compute_slope_in_degrees) const;
214  Column<Z>& aspect,
215  const bool compute_slope_in_degrees) const;
216 
218  Column<T>& output_x,
219  Column<T>& output_y,
220  Column<Z>& output_z) const;
221 
223  Column<T>& output_x,
224  Column<T>& output_y,
225  Column<Z>& output_z,
226  const int64_t neighborhood_null_fill_radius) const;
227 
228  void setMetadata(TableFunctionManager& mgr) const;
229 
230  private:
231  template <RasterAggType AggType, typename T2, typename Z2>
232  void computeSerialImpl(const Column<T2>& input_x,
233  const Column<T2>& input_y,
234  const Column<Z2>& input_z,
235  std::vector<Z>& output_z);
236 
237  template <RasterAggType AggType>
238  void computeParallelReductionAggImpl(const std::vector<std::vector<Z>>& z_inputs,
239  std::vector<Z>& output_z,
240  const Z agg_sentinel);
241 
242  template <RasterAggType AggType, typename T2, typename Z2>
243  void computeParallelImpl(const Column<T2>& input_x,
244  const Column<T2>& input_y,
245  const Column<Z2>& input_z,
246  std::vector<Z>& output_z,
247  const size_t max_inputs_per_thread);
248 
249  inline Z fill_bin_from_avg_box_neighborhood(const int64_t x_centroid_bin,
250  const int64_t y_centroid_bin,
251  const int64_t bins_radius) const;
252 
253  template <RasterAggType AggType>
254  inline Z fill_bin_from_box_neighborhood(const int64_t x_centroid_bin,
255  const int64_t y_centroid_bin,
256  const int64_t bins_radius,
257  const ComputeAgg<AggType>& compute_agg) const;
258 
259  template <RasterAggType AggType>
260  void fill_bins_from_box_neighborhood(const int64_t neighborhood_fill_radius,
261  const bool fill_only_nulls);
262  void fill_bins_from_gaussian_neighborhood(const int64_t neighborhood_fill_radius,
263  const bool fill_only_nulls);
264 };
265 
266 template <typename T, typename Z>
268  const Column<T>& input_x,
269  const Column<T>& input_y,
270  const Column<Z>& input_z,
271  const RasterAggType raster_agg_type,
272  const RasterAggType raster_fill_agg_type,
273  const T bin_dim_meters,
274  const bool geographic_coords,
275  const int64_t neighborhood_fill_radius,
276  const bool fill_only_nulls,
277  Column<T>& output_x,
278  Column<T>& output_y,
279  Column<Z>& output_z) {
280  GeoRaster<T, Z> geo_raster(input_x,
281  input_y,
282  input_z,
283  raster_agg_type,
284  bin_dim_meters,
285  geographic_coords,
286  true);
287 
288  geo_raster.setMetadata(mgr);
289 
290  if (neighborhood_fill_radius > 0) {
291  geo_raster.fill_bins_from_neighbors(
292  neighborhood_fill_radius, fill_only_nulls, raster_fill_agg_type);
293  }
294 
295  return geo_raster.outputDenseColumns(mgr, output_x, output_y, output_z);
296 }
297 
298 // clang-format off
299 /*
300  UDTF: tf_geo_rasterize__cpu_template(TableFunctionManager,
301  Cursor<Column<T> x, Column<T> y, Column<Z> z> raster, TextEncodingNone agg_type,
302  T bin_dim_meters | require="bin_dim_meters > 0", bool geographic_coords,
303  int64_t neighborhood_fill_radius | require="neighborhood_fill_radius >= 0",
304  bool fill_only_nulls) | filter_table_function_transpose=on ->
305  Column<T> x, Column<T> y, Column<Z> z, T=[float, double], Z=[float, double]
306  */
307 // clang-format on
308 
309 template <typename T, typename Z>
310 TEMPLATE_NOINLINE int32_t
312  const Column<T>& input_x,
313  const Column<T>& input_y,
314  const Column<Z>& input_z,
315  const TextEncodingNone& agg_type_str,
316  const T bin_dim_meters,
317  const bool geographic_coords,
318  const int64_t neighborhood_fill_radius,
319  const bool fill_only_nulls,
320  Column<T>& output_x,
321  Column<T>& output_y,
322  Column<Z>& output_z) {
323  const auto raster_agg_type = get_raster_agg_type(agg_type_str, false);
324  if (raster_agg_type == RasterAggType::INVALID) {
325  const std::string error_msg =
326  "Invalid Raster Aggregate Type: " + agg_type_str.getString();
327  return mgr.ERROR_MESSAGE(error_msg);
328  }
329  return geo_rasterize_impl(mgr,
330  input_x,
331  input_y,
332  input_z,
333  raster_agg_type,
335  bin_dim_meters,
336  geographic_coords,
337  neighborhood_fill_radius,
338  fill_only_nulls,
339  output_x,
340  output_y,
341  output_z);
342 }
343 
344 // clang-format off
345 /*
346  UDTF: tf_geo_rasterize__cpu_template(TableFunctionManager,
347  Cursor<Column<T> x, Column<T> y, Column<Z> z> raster, TextEncodingNone agg_type,
348  TextEncodingNone fill_agg_type, T bin_dim_meters | require="bin_dim_meters > 0", bool geographic_coords,
349  int64_t neighborhood_fill_radius | require="neighborhood_fill_radius >= 0",
350  bool fill_only_nulls) | filter_table_function_transpose=on ->
351  Column<T> x, Column<T> y, Column<Z> z, T=[float, double], Z=[float, double]
352  */
353 // clang-format on
354 
355 template <typename T, typename Z>
356 TEMPLATE_NOINLINE int32_t
358  const Column<T>& input_x,
359  const Column<T>& input_y,
360  const Column<Z>& input_z,
361  const TextEncodingNone& agg_type_str,
362  const TextEncodingNone& fill_agg_type_str,
363  const T bin_dim_meters,
364  const bool geographic_coords,
365  const int64_t neighborhood_fill_radius,
366  const bool fill_only_nulls,
367  Column<T>& output_x,
368  Column<T>& output_y,
369  Column<Z>& output_z) {
370  const auto raster_agg_type = get_raster_agg_type(agg_type_str, false);
371  if (raster_agg_type == RasterAggType::INVALID) {
372  const std::string error_msg =
373  "Invalid Raster Aggregate Type: " + agg_type_str.getString();
374  return mgr.ERROR_MESSAGE(error_msg);
375  }
376  const auto raster_fill_agg_type = get_raster_agg_type(fill_agg_type_str, true);
377  if (raster_fill_agg_type == RasterAggType::INVALID) {
378  const std::string error_msg =
379  "Invalid Raster Fill Aggregate Type: " + fill_agg_type_str.getString();
380  return mgr.ERROR_MESSAGE(error_msg);
381  }
382  return geo_rasterize_impl(mgr,
383  input_x,
384  input_y,
385  input_z,
386  raster_agg_type,
387  raster_fill_agg_type,
388  bin_dim_meters,
389  geographic_coords,
390  neighborhood_fill_radius,
391  fill_only_nulls,
392  output_x,
393  output_y,
394  output_z);
395 }
396 
397 // clang-format off
398 /*
399  UDTF: tf_geo_rasterize__cpu_template(TableFunctionManager,
400  Cursor<Column<T> x, Column<T> y, Column<Z> z> raster,
401  TextEncodingNone agg_type, TextEncodingNone fill_agg_type,
402  T bin_dim_meters | require="bin_dim_meters > 0",
403  bool geographic_coords, int64_t neighborhood_fill_radius | require="neighborhood_fill_radius >= 0", bool fill_only_nulls,
404  T x_min, T x_max | require="x_max > x_min", T y_min, T y_max | require="y_max > y_min") ->
405  Column<T> x, Column<T> y, Column<Z> z, T=[float, double], Z=[float, double]
406  */
407 // clang-format on
408 
409 template <typename T, typename Z>
410 TEMPLATE_NOINLINE int32_t
412  const Column<T>& input_x,
413  const Column<T>& input_y,
414  const Column<Z>& input_z,
415  const TextEncodingNone& agg_type_str,
416  const TextEncodingNone& fill_agg_type_str,
417  const T bin_dim_meters,
418  const bool geographic_coords,
419  const int64_t neighborhood_fill_radius,
420  const bool fill_only_nulls,
421  const T x_min,
422  const T x_max,
423  const T y_min,
424  const T y_max,
425  Column<T>& output_x,
426  Column<T>& output_y,
427  Column<Z>& output_z) {
428  const auto raster_agg_type = get_raster_agg_type(agg_type_str, false);
429  if (raster_agg_type == RasterAggType::INVALID) {
430  const std::string error_msg =
431  "Invalid Raster Aggregate Type: " + agg_type_str.getString();
432  return mgr.ERROR_MESSAGE(error_msg);
433  }
434  const auto raster_fill_agg_type = get_raster_agg_type(fill_agg_type_str, true);
435  if (raster_fill_agg_type == RasterAggType::INVALID) {
436  const std::string error_msg =
437  "Invalid Raster Fill Aggregate Type: " + fill_agg_type_str.getString();
438  return mgr.ERROR_MESSAGE(error_msg);
439  }
440 
441  GeoRaster<T, Z> geo_raster(input_x,
442  input_y,
443  input_z,
444  raster_agg_type,
445  bin_dim_meters,
446  geographic_coords,
447  true,
448  x_min,
449  x_max,
450  y_min,
451  y_max);
452 
453  geo_raster.setMetadata(mgr);
454 
455  if (neighborhood_fill_radius > 0) {
456  geo_raster.fill_bins_from_neighbors(
457  neighborhood_fill_radius, fill_only_nulls, raster_fill_agg_type);
458  }
459 
460  return geo_raster.outputDenseColumns(mgr, output_x, output_y, output_z);
461 }
462 // clang-format off
463 /*
464  UDTF: tf_geo_rasterize_slope__cpu_template(TableFunctionManager,
465  Cursor<Column<T> x, Column<T> y, Column<Z> z> raster,
466  TextEncodingNone agg_type, T bin_dim_meters | require="bin_dim_meters > 0",
467  bool geographic_coords, int64_t neighborhood_fill_radius | require="neighborhood_fill_radius >= 0", bool fill_only_nulls,
468  bool compute_slope_in_degrees) | filter_table_function_transpose=on ->
469  Column<T> x, Column<T> y, Column<Z> z, Column<Z> slope, Column<Z> aspect, T=[float, double], Z=[float, double]
470  */
471 // clang-format on
472 
473 template <typename T, typename Z>
474 TEMPLATE_NOINLINE int32_t
476  const Column<T>& input_x,
477  const Column<T>& input_y,
478  const Column<Z>& input_z,
479  const TextEncodingNone& agg_type_str,
480  const T bin_dim_meters,
481  const bool geographic_coords,
482  const int64_t neighborhood_fill_radius,
483  const bool fill_only_nulls,
484  const bool compute_slope_in_degrees,
485  Column<T>& output_x,
486  Column<T>& output_y,
487  Column<Z>& output_z,
488  Column<Z>& output_slope,
489  Column<Z>& output_aspect) {
490  const auto raster_agg_type = get_raster_agg_type(agg_type_str, false);
491  if (raster_agg_type == RasterAggType::INVALID) {
492  const std::string error_msg =
493  "Invalid Raster Aggregate Type: " + agg_type_str.getString();
494  return mgr.ERROR_MESSAGE(error_msg);
495  }
496 
497  GeoRaster<T, Z> geo_raster(input_x,
498  input_y,
499  input_z,
500  raster_agg_type,
501  bin_dim_meters,
502  geographic_coords,
503  true);
504  geo_raster.setMetadata(mgr);
505 
506  if (neighborhood_fill_radius > 0) {
507  geo_raster.fill_bins_from_neighbors(
508  neighborhood_fill_radius, fill_only_nulls, RasterAggType::GAUSS_AVG);
509  }
510 
511  const size_t output_rows =
512  geo_raster.outputDenseColumns(mgr, output_x, output_y, output_z);
513  geo_raster.calculate_slope_and_aspect(
514  output_slope, output_aspect, compute_slope_in_degrees);
515  return output_rows;
516 }
517 
519 
520 #endif // __CUDACC__
Z offset_source_z_from_raster_z(const int64_t source_x_bin, const int64_t source_y_bin, const Z source_z_offset) const
bool get_nxn_neighbors_if_not_null(const int64_t x_bin, const int64_t y_bin, const int64_t num_bins_radius, std::vector< Z > &neighboring_bins) const
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
int64_t get_bin_idx_for_xy_coords(const T x, const T y) const
void setMetadata(TableFunctionManager &mgr) const
std::pair< Z, Z > calculate_slope_and_aspect_of_cell(const std::vector< Z > &neighboring_cells, const bool compute_slope_in_degrees) const
std::pair< T, T > get_xy_coords_for_bin_idx(const int64_t bin_idx) const
std::string getString() const
Definition: heavydbTypes.h:276
GeoRaster(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, const RasterAggType raster_agg_type, const double bin_dim_meters, const bool geographic_coords, const bool align_bins_to_zero_based_grid)
int64_t outputDenseColumns(TableFunctionManager &mgr, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z) const
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
void fill_bins_from_neighbors(const int64_t neighborhood_fill_radius, const bool fill_only_nulls, const RasterAggType raster_agg_type=RasterAggType::GAUSS_AVG)
void computeParallelReductionAggImpl(const std::vector< std::vector< Z >> &z_inputs, std::vector< Z > &output_z, const Z agg_sentinel)
const size_t max_inputs_per_thread
T get_y_bin(const T input) const
T get_x_bin(const T input) const
bool is_bin_out_of_bounds(const int64_t x_bin, const int64_t y_bin) const
static constexpr int64_t BIN_OUT_OF_BOUNDS
TEMPLATE_NOINLINE int32_t geo_rasterize_impl(TableFunctionManager &mgr, const Column< T > &input_x, const Column< T > &input_y, const Column< Z > &input_z, const RasterAggType raster_agg_type, const RasterAggType raster_fill_agg_type, const T bin_dim_meters, const bool geographic_coords, const int64_t neighborhood_fill_radius, const bool fill_only_nulls, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z)
int64_t x_y_bin_to_bin_index(const int64_t x_bin, const int64_t y_bin, const int64_t num_x_bins)
void fill_bins_from_gaussian_neighborhood(const int64_t neighborhood_fill_radius, const bool fill_only_nulls)
const bool geographic_coords_
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
void calculate_slope_and_aspect(Column< Z > &slope, Column< Z > &aspect, const bool compute_slope_in_degrees) const
std::string to_upper(const std::string &str)
const RasterAggType raster_agg_type_
void computeParallelImpl(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, std::vector< Z > &output_z, const size_t max_inputs_per_thread)
std::pair< int64_t, Z > get_bin_idx_and_z_val_for_xy_bin(const int64_t x_bin, const int64_t y_bin) const
Z fill_bin_from_box_neighborhood(const int64_t x_centroid_bin, const int64_t y_centroid_bin, const int64_t bins_radius, const ComputeAgg< AggType > &compute_agg) const
TEMPLATE_NOINLINE int32_t tf_geo_rasterize_slope__cpu_template(TableFunctionManager &mgr, const Column< T > &input_x, const Column< T > &input_y, const Column< Z > &input_z, const TextEncodingNone &agg_type_str, const T bin_dim_meters, const bool geographic_coords, const int64_t neighborhood_fill_radius, const bool fill_only_nulls, const bool compute_slope_in_degrees, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z, Column< Z > &output_slope, Column< Z > &output_aspect)
TEMPLATE_NOINLINE int32_t tf_geo_rasterize__cpu_template(TableFunctionManager &mgr, const Column< T > &input_x, const Column< T > &input_y, const Column< Z > &input_z, const TextEncodingNone &agg_type_str, const T bin_dim_meters, const bool geographic_coords, const int64_t neighborhood_fill_radius, const bool fill_only_nulls, Column< T > &output_x, Column< T > &output_y, Column< Z > &output_z)
void fill_bins_from_box_neighborhood(const int64_t neighborhood_fill_radius, const bool fill_only_nulls)
bool is_null(const Z value) const
void compute(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, const size_t max_inputs_per_thread)
Z fill_bin_from_avg_box_neighborhood(const int64_t x_centroid_bin, const int64_t y_centroid_bin, const int64_t bins_radius) const
std::pair< int64_t, int64_t > bin_to_x_y_bin_indexes(const int64_t bin, const int64_t num_x_bins)
std::vector< Z > counts_
std::vector< Z > z_
RasterAggType get_raster_agg_type(const std::string &agg_type_str, const bool is_fill_agg)
void operator()(const Z2 &input_z, Z &output_z, const Z2 input_sentinel) const
void computeSerialImpl(const Column< T2 > &input_x, const Column< T2 > &input_y, const Column< Z2 > &input_z, std::vector< Z > &output_z)
#define TEMPLATE_NOINLINE
Definition: heavydbTypes.h:54