}
+/* Similar to minloc/maxloc, the argument list might need to be
+ reordered for the MINVAL, MAXVAL, PRODUCT, and SUM intrinsics. The
+ difference is that MINLOC/MAXLOC take an additional KIND argument.
+ The possibilities are:
+
+ Arg #2 Arg #3
+ NULL NULL
+ DIM NULL
+ MASK NULL
+ NULL MASK minval(array, mask=m)
+ DIM MASK
+
+ I.e. in the case of minval(array,mask), mask will be in the second
+ position of the argument list and we'll have to fix that up. */
+
try
-gfc_check_minval_maxval (gfc_expr * array, gfc_expr * dim, gfc_expr * mask)
+gfc_check_reduction (gfc_actual_arglist * ap)
{
+ gfc_expr *a, *m, *d;
- if (array_check (array, 0) == FAILURE)
+ a = ap->expr;
+ if (int_or_real_check (a, 0) == FAILURE
+ || array_check (a, 0) == FAILURE)
return FAILURE;
- if (int_or_real_check (array, 0) == FAILURE)
- return FAILURE;
+ d = ap->next->expr;
+ m = ap->next->next->expr;
- if (dim_check (dim, 1, 1) == FAILURE)
+ if (m == NULL && d != NULL && d->ts.type == BT_LOGICAL
+ && ap->next->name[0] == '\0')
+ {
+ m = d;
+ d = NULL;
+
+ ap->next->expr = NULL;
+ ap->next->next->expr = m;
+ }
+
+ if (d != NULL
+ && (scalar_check (d, 1) == FAILURE
+ || type_check (d, 1, BT_INTEGER) == FAILURE))
return FAILURE;
- if (mask != NULL && logical_array_check (mask, 2) == FAILURE)
+ if (m != NULL && type_check (m, 2, BT_LOGICAL) == FAILURE)
return FAILURE;
return SUCCESS;
}
-try
-gfc_check_product (gfc_expr * array, gfc_expr * dim, gfc_expr * mask)
-{
-
- if (array_check (array, 0) == FAILURE)
- return FAILURE;
-
- if (numeric_check (array, 0) == FAILURE)
- return FAILURE;
-
- if (dim_check (dim, 1, 1) == FAILURE)
- return FAILURE;
-
- if (mask != NULL && logical_array_check (mask, 2) == FAILURE)
- return FAILURE;
-
- return SUCCESS;
-}
-
-
try
gfc_check_radix (gfc_expr * x)
{
}
-try
-gfc_check_sum (gfc_expr * array, gfc_expr * dim, gfc_expr * mask)
-{
-
- if (array_check (array, 0) == FAILURE)
- return FAILURE;
-
- if (numeric_check (array, 0) == FAILURE)
- return FAILURE;
-
- if (dim_check (dim, 1, 1) == FAILURE)
- return FAILURE;
-
- if (mask != NULL && logical_array_check (mask, 2) == FAILURE)
- return FAILURE;
-
- return SUCCESS;
-}
-
-
try
gfc_check_transfer (gfc_expr * source ATTRIBUTE_UNUSED,
gfc_expr * mold ATTRIBUTE_UNUSED,
try (*f2)(struct gfc_expr *, struct gfc_expr *);
try (*f3)(struct gfc_expr *, struct gfc_expr *, struct gfc_expr *);
try (*f3ml)(gfc_actual_arglist *);
+ try (*f3red)(gfc_actual_arglist *);
try (*f4)(struct gfc_expr *, struct gfc_expr *, struct gfc_expr *,
struct gfc_expr *);
try (*f5)(struct gfc_expr *, struct gfc_expr *, struct gfc_expr *,
(void*)0);
}
+/* MINVAL, MAXVAL, PRODUCT, and SUM also get special treatment because
+ their argument also might have to be reordered. */
+
+static void add_sym_3red (const char *name, int elemental,
+ int actual_ok, bt type, int kind,
+ try (*check)(gfc_actual_arglist *),
+ gfc_expr*(*simplify)(gfc_expr *,gfc_expr *,gfc_expr *),
+ void (*resolve)(gfc_expr *,gfc_expr *,gfc_expr *,gfc_expr *),
+ const char* a1, bt type1, int kind1, int optional1,
+ const char* a2, bt type2, int kind2, int optional2,
+ const char* a3, bt type3, int kind3, int optional3
+ ) {
+ gfc_check_f cf;
+ gfc_simplify_f sf;
+ gfc_resolve_f rf;
+
+ cf.f3red = check;
+ sf.f3 = simplify;
+ rf.f3 = resolve;
+
+ add_sym (name, elemental, actual_ok, type, kind, cf, sf, rf,
+ a1, type1, kind1, optional1,
+ a2, type2, kind2, optional2,
+ a3, type3, kind3, optional3,
+ (void*)0);
+}
+
/* Add the name of an intrinsic subroutine with three arguments to the list
of intrinsic names. */
make_generic ("maxloc", GFC_ISYM_MAXLOC);
- add_sym_3 ("maxval", 0, 1, BT_REAL, dr,
- gfc_check_minval_maxval, NULL, gfc_resolve_maxval,
- ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
- msk, BT_LOGICAL, dl, 1);
+ add_sym_3red ("maxval", 0, 1, BT_REAL, dr,
+ gfc_check_reduction, NULL, gfc_resolve_maxval,
+ ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
+ msk, BT_LOGICAL, dl, 1);
make_generic ("maxval", GFC_ISYM_MAXVAL);
make_generic ("minloc", GFC_ISYM_MINLOC);
- add_sym_3 ("minval", 0, 1, BT_REAL, dr,
- gfc_check_minval_maxval, NULL, gfc_resolve_minval,
- ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
- msk, BT_LOGICAL, dl, 1);
+ add_sym_3red ("minval", 0, 1, BT_REAL, dr,
+ gfc_check_reduction, NULL, gfc_resolve_minval,
+ ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
+ msk, BT_LOGICAL, dl, 1);
make_generic ("minval", GFC_ISYM_MINVAL);
make_generic ("present", GFC_ISYM_PRESENT);
- add_sym_3 ("product", 0, 1, BT_REAL, dr,
- gfc_check_product, NULL, gfc_resolve_product,
- ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
- msk, BT_LOGICAL, dl, 1);
+ add_sym_3red ("product", 0, 1, BT_REAL, dr,
+ gfc_check_reduction, NULL, gfc_resolve_product,
+ ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
+ msk, BT_LOGICAL, dl, 1);
make_generic ("product", GFC_ISYM_PRODUCT);
make_generic ("sqrt", GFC_ISYM_SQRT);
- add_sym_3 ("sum", 0, 1, BT_UNKNOWN, 0,
- gfc_check_sum, NULL, gfc_resolve_sum,
- ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
- msk, BT_LOGICAL, dl, 1);
+ add_sym_3red ("sum", 0, 1, BT_UNKNOWN, 0,
+ gfc_check_reduction, NULL, gfc_resolve_sum,
+ ar, BT_REAL, dr, 0, dm, BT_INTEGER, ii, 1,
+ msk, BT_LOGICAL, dl, 1);
make_generic ("sum", GFC_ISYM_SUM);
&expr->where) == FAILURE)
return FAILURE;
- if (specific->check.f3ml != gfc_check_minloc_maxloc)
+ if (specific->check.f3ml == gfc_check_minloc_maxloc)
+ /* This is special because we might have to reorder the argument
+ list. */
+ t = gfc_check_minloc_maxloc (*ap);
+ else if (specific->check.f3red == gfc_check_reduction)
+ /* This is also special because we also might have to reorder the
+ argument list. */
+ t = gfc_check_reduction (*ap);
+ else
{
if (specific->check.f1 == NULL)
{
else
t = do_check (specific, *ap);
}
- else
- /* This is special because we might have to reorder the argument
- list. */
- t = gfc_check_minloc_maxloc (*ap);
/* Check ranks for elemental intrinsics. */
if (t == SUCCESS && specific->elemental)
try gfc_check_matmul (gfc_expr *, gfc_expr *);
try gfc_check_merge (gfc_expr *, gfc_expr *, gfc_expr *);
try gfc_check_minloc_maxloc (gfc_actual_arglist *);
-try gfc_check_minval_maxval (gfc_expr *, gfc_expr *, gfc_expr *);
try gfc_check_nearest (gfc_expr *, gfc_expr *);
try gfc_check_null (gfc_expr *);
try gfc_check_pack (gfc_expr *, gfc_expr *, gfc_expr *);
try gfc_check_precision (gfc_expr *);
try gfc_check_present (gfc_expr *);
-try gfc_check_product (gfc_expr *, gfc_expr *, gfc_expr *);
try gfc_check_radix (gfc_expr *);
try gfc_check_rand (gfc_expr *);
try gfc_check_range (gfc_expr *);
try gfc_check_real (gfc_expr *, gfc_expr *);
+try gfc_check_reduction (gfc_actual_arglist *);
try gfc_check_repeat (gfc_expr *, gfc_expr *);
try gfc_check_reshape (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
try gfc_check_scale (gfc_expr *, gfc_expr *);
gfc_type_letter (array->ts.type), array->ts.kind);
}
+
void
gfc_resolve_minval (gfc_expr * f, gfc_expr * array, gfc_expr * dim,
gfc_expr * mask)
+2004-08-19 Erik Schnetter <schnetter@aei.mpg.de>
+
+ PR fortran/16946
+ * gfortran.dg/reduction.f90: New testcase.
+
2004-08-19 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
PR fortran/16520
--- /dev/null
+! { dg-do run }
+! PR 16946
+! Not all allowed combinations of arguments for MAXVAL, MINVAL,
+! PRODUCT and SUM were supported.
+program reduction_mask
+ implicit none
+ logical :: equal(3)
+
+ integer, parameter :: res(4*9) = (/ 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, &
+ 1, 1, 1, 1, 1, 6, 6, 6, 2, 2, 2, 2, 2, 2, 6, 6, 6, 3, 3, 3, 3, 3, 3 /)
+ integer :: val(4*9)
+
+ equal = (/ .true., .true., .false. /)
+
+ ! use all combinations of the dim and mask arguments for the
+ ! reduction intrinsics
+ val( 1) = maxval((/ 1, 2, 3 /))
+ val( 2) = maxval((/ 1, 2, 3 /), 1)
+ val( 3) = maxval((/ 1, 2, 3 /), dim=1)
+ val( 4) = maxval((/ 1, 2, 3 /), equal)
+ val( 5) = maxval((/ 1, 2, 3 /), mask=equal)
+ val( 6) = maxval((/ 1, 2, 3 /), 1, equal)
+ val( 7) = maxval((/ 1, 2, 3 /), 1, mask=equal)
+ val( 8) = maxval((/ 1, 2, 3 /), dim=1, mask=equal)
+ val( 9) = maxval((/ 1, 2, 3 /), mask=equal, dim=1)
+
+ val(10) = minval((/ 1, 2, 3 /))
+ val(11) = minval((/ 1, 2, 3 /), 1)
+ val(12) = minval((/ 1, 2, 3 /), dim=1)
+ val(13) = minval((/ 1, 2, 3 /), equal)
+ val(14) = minval((/ 1, 2, 3 /), mask=equal)
+ val(15) = minval((/ 1, 2, 3 /), 1, equal)
+ val(16) = minval((/ 1, 2, 3 /), 1, mask=equal)
+ val(17) = minval((/ 1, 2, 3 /), dim=1, mask=equal)
+ val(18) = minval((/ 1, 2, 3 /), mask=equal, dim=1)
+
+ val(19) = product((/ 1, 2, 3 /))
+ val(20) = product((/ 1, 2, 3 /), 1)
+ val(21) = product((/ 1, 2, 3 /), dim=1)
+ val(22) = product((/ 1, 2, 3 /), equal)
+ val(23) = product((/ 1, 2, 3 /), mask=equal)
+ val(24) = product((/ 1, 2, 3 /), 1, equal)
+ val(25) = product((/ 1, 2, 3 /), 1, mask=equal)
+ val(26) = product((/ 1, 2, 3 /), dim=1, mask=equal)
+ val(27) = product((/ 1, 2, 3 /), mask=equal, dim=1)
+
+ val(28) = sum((/ 1, 2, 3 /))
+ val(29) = sum((/ 1, 2, 3 /), 1)
+ val(30) = sum((/ 1, 2, 3 /), dim=1)
+ val(31) = sum((/ 1, 2, 3 /), equal)
+ val(32) = sum((/ 1, 2, 3 /), mask=equal)
+ val(33) = sum((/ 1, 2, 3 /), 1, equal)
+ val(34) = sum((/ 1, 2, 3 /), 1, mask=equal)
+ val(35) = sum((/ 1, 2, 3 /), dim=1, mask=equal)
+ val(36) = sum((/ 1, 2, 3 /), mask=equal, dim=1)
+
+ if (any (val /= res)) call abort
+end program reduction_mask