| 304 | |
| 305 | template<af_op_t op> |
| 306 | static af_err reduce_promote(af_array *out, const af_array in, const int dim, |
| 307 | bool change_nan = false, double nanval = 0.0) { |
| 308 | try { |
| 309 | ARG_ASSERT(2, dim >= 0); |
| 310 | ARG_ASSERT(2, dim < 4); |
| 311 | |
| 312 | const ArrayInfo &in_info = getInfo(in); |
| 313 | |
| 314 | if (dim >= static_cast<int>(in_info.ndims())) { |
| 315 | *out = retain(in); |
| 316 | return AF_SUCCESS; |
| 317 | } |
| 318 | |
| 319 | af_dtype type = in_info.getType(); |
| 320 | af_array res; |
| 321 | |
| 322 | switch (type) { |
| 323 | case f32: |
| 324 | res = reduce<op, float, float>(in, dim, change_nan, nanval); |
| 325 | break; |
| 326 | case f64: |
| 327 | res = reduce<op, double, double>(in, dim, change_nan, nanval); |
| 328 | break; |
| 329 | case c32: |
| 330 | res = reduce<op, cfloat, cfloat>(in, dim, change_nan, nanval); |
| 331 | break; |
| 332 | case c64: |
| 333 | res = reduce<op, cdouble, cdouble>(in, dim, change_nan, nanval); |
| 334 | break; |
| 335 | case u32: |
| 336 | res = reduce<op, uint, uint>(in, dim, change_nan, nanval); |
| 337 | break; |
| 338 | case s32: |
| 339 | res = reduce<op, int, int>(in, dim, change_nan, nanval); |
| 340 | break; |
| 341 | case u64: |
| 342 | res = reduce<op, uintl, uintl>(in, dim, change_nan, nanval); |
| 343 | break; |
| 344 | case s64: |
| 345 | res = reduce<op, intl, intl>(in, dim, change_nan, nanval); |
| 346 | break; |
| 347 | case u16: |
| 348 | res = reduce<op, ushort, uint>(in, dim, change_nan, nanval); |
| 349 | break; |
| 350 | case s16: |
| 351 | res = reduce<op, short, int>(in, dim, change_nan, nanval); |
| 352 | break; |
| 353 | case u8: |
| 354 | res = reduce<op, uchar, uint>(in, dim, change_nan, nanval); |
| 355 | break; |
| 356 | case s8: |
| 357 | res = reduce<op, schar, int>(in, dim, change_nan, nanval); |
| 358 | break; |
| 359 | case b8: { |
| 360 | if (op == af_mul_t) { |
| 361 | res = reduce<af_and_t, char, char>(in, dim, change_nan, |
| 362 | nanval); |
| 363 | } else { |