diff options
author | Tobias Burnus <burnus@net-b.de> | 2010-08-27 21:17:45 +0200 |
---|---|---|
committer | Tobias Burnus <burnus@gcc.gnu.org> | 2010-08-27 21:17:45 +0200 |
commit | 0cd0559e8ceb1764a41c8964f30a7de025956e8a (patch) | |
tree | def889db72c25844667547e301395013df023b00 /gcc/fortran/trans-intrinsic.c | |
parent | cbadd64af4764fe75658a20c229050453379841d (diff) | |
download | gcc-0cd0559e8ceb1764a41c8964f30a7de025956e8a.zip gcc-0cd0559e8ceb1764a41c8964f30a7de025956e8a.tar.gz gcc-0cd0559e8ceb1764a41c8964f30a7de025956e8a.tar.bz2 |
re PR fortran/33197 (Fortran 2008: math functions)
gcc/fortran/
2010-08-27 Tobias Burnus <burnus@net-b.de>
PR fortran/33197
* gcc/fortran/intrinsic.c (add_functions): Add norm2 and parity.
* gcc/fortran/intrinsic.h (gfc_check_norm2, gfc_check_parity):
gfc_simplify_norm2, gfc_simplify_parity, gfc_resolve_norm2,
gfc_resolve_parity): New prototypes.
* gcc/fortran/gfortran.h (gfc_isym_id): New enum items
GFC_ISYM_NORM2 and GFC_ISYM_PARITY.
* gcc/fortran/iresolve.c (gfc_resolve_norm2,
gfc_resolve_parity): New functions.
* gcc/fortran/check.c (gfc_check_norm2, gfc_check_parity):
New functions.
* gcc/fortran/trans-intrinsic.c (gfc_conv_intrinsic_arith,
gfc_conv_intrinsic_function): Handle NORM2 and PARITY.
* gcc/fortran/intrinsic.texi (NORM2, PARITY): Add.
* gcc/fortran/simplify.c (simplify_transformation_to_array):
Add post-processing opterator.
(gfc_simplify_all, gfc_simplify_any, gfc_simplify_count,
gfc_simplify_product, gfc_simplify_sum): Update call.
(add_squared, do_sqrt, gfc_simplify_norm2, do_xor,
gfc_simplify_parity): New functions.
gcc/testsuite/
2010-08-27 Tobias Burnus <burnus@net-b.de>
PR fortran/33197
* gcc/testsuite/gfortran.dg/norm2_1.f90: New.
* gcc/testsuite/gfortran.dg/norm2_2.f90: New.
* gcc/testsuite/gfortran.dg/norm2_3.f90: New.
* gcc/testsuite/gfortran.dg/norm2_4.f90: New.
* gcc/testsuite/gfortran.dg/parity_1.f90: New.
* gcc/testsuite/gfortran.dg/parity_2.f90: New.
* gcc/testsuite/gfortran.dg/parity_3.f90: New.
libgfortran/
2010-08-27 Tobias Burnus <burnus@net-b.de>
PR fortran/33197
* libgfortran/m4/ifunction.m4 (FINISH_ARRAY_FUNCTION,
ARRAY_FUNCTION): Allow expression after loop.
* libgfortran/m4/norm2.m4: New for _gfortran_norm2_r{4,8,10,16}.
* libgfortran/m4/parity.m4: New for
* _gfortran_parity_l{1,2,4,8,16}.
* libgfortran/gfortran.map: Add new functions.
* libgfortran/Makefile.am: Ditto.
* libgfortran/m4/minloc1.m4: Add empty argument for
* ARRAY_FUNCTION.
* libgfortran/m4/maxloc1.m4: Ditto.
* libgfortran/m4/all.m4: Ditto.
* libgfortran/m4/minval.m4: Ditto.
* libgfortran/m4/maxval.m4: Ditto.
* libgfortran/m4/count.m4: Ditto.
* libgfortran/m4/product.m4: Ditto.
* libgfortran/m4/any.m4: Ditto.
* Makefile.in: Regenerated.
* generated/minval_r8.c: Regenerated.
* generated/maxloc1_4_r8.c: Regenerated.
* generated/minloc1_16_r16.c: Regenerated.
* generated/norm2_r4.c: Regenerated.
* generated/sum_i8.c: Regenerated.
* generated/parity_l2.c: Regenerated.
* generated/any_l16.c: Regenerated.
* generated/maxval_i2.c: Regenerated.
* generated/any_l2.c: Regenerated.
* generated/product_r4.c: Regenerated.
* generated/maxloc1_8_i4.c: Regenerated.
* generated/parity_l16.c: Regenerated.
* generated/all_l1.c: Regenerated.
* generated/product_i2.c: Regenerated.
* generated/minloc1_8_r16.c: Regenerated.
* generated/maxloc1_8_r16.c: Regenerated.
* generated/sum_r16.c: Regenerated.
* generated/sum_i1.c: Regenerated.
* generated/minloc1_4_r8.c: Regenerated.
* generated/maxloc1_16_r16.c: Regenerated.
* generated/minloc1_16_i4.c: Regenerated.
* generated/maxloc1_16_i4.c: Regenerated.
* generated/maxval_r16.c: Regenerated.
* generated/product_c10.c: Regenerated.
* generated/minloc1_8_i4.c: Regenerated.
* generated/all_l2.c: Regenerated.
* generated/product_c4.c: Regenerated.
* generated/sum_r4.c: Regenerated.
* generated/all_l16.c: Regenerated.
* generated/minloc1_16_r10.c: Regenerated.
* generated/sum_i2.c: Regenerated.
* generated/maxloc1_8_r8.c: Regenerated.
* generated/minval_i16.c: Regenerated.
* generated/parity_l4.c: Regenerated.
* generated/maxval_i4.c: Regenerated.
* generated/any_l4.c: Regenerated.
* generated/minval_i8.c: Regenerated.
* generated/maxloc1_4_i8.c: Regenerated.
* generated/minloc1_4_i16.c: Regenerated.
* generated/maxloc1_4_i16.c: Regenerated.
* generated/minloc1_8_r10.c: Regenerated.
* generated/product_i4.c: Regenerated.
* generated/maxloc1_8_r10.c: Regenerated.
* generated/sum_c16.c: Regenerated.
* generated/minloc1_16_r8.c: Regenerated.
* generated/maxloc1_16_r8.c: Regenerated.
* generated/count_4_l.c: Regenerated.
* generated/sum_r10.c: Regenerated.
* generated/count_8_l.c: Regenerated.
* generated/sum_c4.c: Regenerated.
* generated/maxloc1_16_r10.c: Regenerated.
* generated/minloc1_8_r8.c: Regenerated.
* generated/maxval_r10.c: Regenerated.
* generated/minval_i1.c: Regenerated.
* generated/maxloc1_4_i1.c: Regenerated.
* generated/minloc1_4_i8.c: Regenerated.
* generated/product_i16.c: Regenerated.
* generated/all_l4.c: Regenerated.
* generated/norm2_r16.c: Regenerated.
* generated/minval_r4.c: Regenerated.
* generated/maxloc1_4_r4.c: Regenerated.
* generated/sum_i4.c: Regenerated.
* generated/maxval_r8.c: Regenerated.
* generated/norm2_r8.c: Regenerated.
* generated/minloc1_4_i1.c: Regenerated.
* generated/minval_r16.c: Regenerated.
* generated/minval_i2.c: Regenerated.
* generated/maxloc1_4_i2.c: Regenerated.
* generated/product_r8.c: Regenerated.
* generated/maxloc1_8_i8.c: Regenerated.
* generated/sum_c10.c: Regenerated.
* generated/minloc1_4_r16.c: Regenerated.
* generated/maxloc1_4_r16.c: Regenerated.
* generated/count_1_l.c: Regenerated.
* generated/minloc1_4_r4.c: Regenerated.
* generated/minloc1_16_i8.c: Regenerated.
* generated/maxloc1_16_i8.c: Regenerated.
* generated/minloc1_4_i2.c: Regenerated.
* generated/maxloc1_8_i1.c: Regenerated.
* generated/minloc1_8_i8.c: Regenerated.
* generated/product_r16.c: Regenerated.
* generated/product_c8.c: Regenerated.
* generated/sum_r8.c: Regenerated.
* generated/norm2_r10.c: Regenerated.
* generated/minloc1_16_i16.c: Regenerated.
* generated/maxloc1_8_r4.c: Regenerated.
* generated/minloc1_16_i1.c: Regenerated.
* generated/maxloc1_16_i1.c: Regenerated.
* generated/minval_r10.c: Regenerated.
* generated/count_16_l.c: Regenerated.
* generated/parity_l8.c: Regenerated.
* generated/minloc1_8_i1.c: Regenerated.
* generated/minval_i4.c: Regenerated.
* generated/maxloc1_4_i4.c: Regenerated.
* generated/maxloc1_8_i2.c: Regenerated.
* generated/maxval_i8.c: Regenerated.
* generated/any_l8.c: Regenerated.
* generated/minloc1_4_r10.c: Regenerated.
* generated/minloc1_8_i16.c: Regenerated.
* generated/maxloc1_4_r10.c: Regenerated.
* generated/maxloc1_8_i16.c: Regenerated.
* generated/minloc1_16_r4.c: Regenerated.
* generated/maxloc1_16_r4.c: Regenerated.
* generated/product_i8.c: Regenerated.
* generated/sum_i16.c: Regenerated.
* generated/count_2_l.c: Regenerated.
* generated/maxloc1_16_i16.c: Regenerated.
* generated/minloc1_8_r4.c: Regenerated.
* generated/sum_c8.c: Regenerated.
* generated/minloc1_16_i2.c: Regenerated.
* generated/maxloc1_16_i2.c: Regenerated.
* generated/parity_l1.c: Regenerated.
* generated/maxval_i16.c: Regenerated.
* generated/maxval_i1.c: Regenerated.
* generated/minloc1_4_i4.c: Regenerated.
* generated/any_l1.c: Regenerated.
* generated/minloc1_8_i2.c: Regenerated.
* generated/product_c16.c: Regenerated.
* generated/product_r10.c: Regenerated.
* generated/product_i1.c: Regenerated.
* generated/all_l8.c: Regenerated.
* generated/maxval_r4.c: Regenerated.
From-SVN: r163595
Diffstat (limited to 'gcc/fortran/trans-intrinsic.c')
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 123 |
1 files changed, 113 insertions, 10 deletions
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 373770f..e0805d0 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -1810,9 +1810,11 @@ gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr) /* Inline implementation of the sum and product intrinsics. */ static void -gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op) +gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op, + bool norm2) { tree resvar; + tree scale = NULL_TREE; tree type; stmtblock_t body; stmtblock_t block; @@ -1835,8 +1837,20 @@ gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op) type = gfc_typenode_for_spec (&expr->ts); /* Initialize the result. */ resvar = gfc_create_var (type, "val"); - if (op == PLUS_EXPR) + if (norm2) + { + /* result = 0.0; + scale = 1.0. */ + scale = gfc_create_var (type, "scale"); + gfc_add_modify (&se->pre, scale, + gfc_build_const (type, integer_one_node)); + tmp = gfc_build_const (type, integer_zero_node); + } + else if (op == PLUS_EXPR) tmp = gfc_build_const (type, integer_zero_node); + else if (op == NE_EXPR) + /* PARITY. */ + tmp = convert (type, boolean_false_node); else tmp = gfc_build_const (type, integer_one_node); @@ -1848,9 +1862,16 @@ gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op) arrayss = gfc_walk_expr (arrayexpr); gcc_assert (arrayss != gfc_ss_terminator); - actual = actual->next->next; - gcc_assert (actual); - maskexpr = actual->expr; + if (op == NE_EXPR || norm2) + /* PARITY and NORM2. */ + maskexpr = NULL; + else + { + actual = actual->next->next; + gcc_assert (actual); + maskexpr = actual->expr; + } + if (maskexpr && maskexpr->rank != 0) { maskss = gfc_walk_expr (maskexpr); @@ -1896,15 +1917,77 @@ gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op) gfc_conv_expr_val (&arrayse, arrayexpr); gfc_add_block_to_block (&block, &arrayse.pre); - tmp = fold_build2 (op, type, resvar, arrayse.expr); - gfc_add_modify (&block, resvar, tmp); + if (norm2) + { + /* if (x(i) != 0.0) + { + absX = abs(x(i)) + if (absX > scale) + { + val = scale/absX; + result = 1.0 + result * val * val; + scale = absX; + } + else + { + val = absX/scale; + result += val * val; + } + } */ + tree res1, res2, cond, absX, val; + stmtblock_t ifblock1, ifblock2, ifblock3; + + gfc_init_block (&ifblock1); + + absX = gfc_create_var (type, "absX"); + gfc_add_modify (&ifblock1, absX, + fold_build1 (ABS_EXPR, type, arrayse.expr)); + val = gfc_create_var (type, "val"); + gfc_add_expr_to_block (&ifblock1, val); + + gfc_init_block (&ifblock2); + gfc_add_modify (&ifblock2, val, + fold_build2 (RDIV_EXPR, type, scale, absX)); + res1 = fold_build2 (MULT_EXPR, type, val, val); + res1 = fold_build2 (MULT_EXPR, type, resvar, res1); + res1 = fold_build2 (PLUS_EXPR, type, res1, + gfc_build_const (type, integer_one_node)); + gfc_add_modify (&ifblock2, resvar, res1); + gfc_add_modify (&ifblock2, scale, absX); + res1 = gfc_finish_block (&ifblock2); + + gfc_init_block (&ifblock3); + gfc_add_modify (&ifblock3, val, + fold_build2 (RDIV_EXPR, type, absX, scale)); + res2 = fold_build2 (MULT_EXPR, type, val, val); + res2 = fold_build2 (PLUS_EXPR, type, resvar, res2); + gfc_add_modify (&ifblock3, resvar, res2); + res2 = gfc_finish_block (&ifblock3); + + cond = fold_build2 (GT_EXPR, boolean_type_node, absX, scale); + tmp = build3_v (COND_EXPR, cond, res1, res2); + gfc_add_expr_to_block (&ifblock1, tmp); + tmp = gfc_finish_block (&ifblock1); + + cond = fold_build2 (NE_EXPR, boolean_type_node, arrayse.expr, + gfc_build_const (type, integer_zero_node)); + + tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location)); + gfc_add_expr_to_block (&block, tmp); + } + else + { + tmp = fold_build2 (op, type, resvar, arrayse.expr); + gfc_add_modify (&block, resvar, tmp); + } + gfc_add_block_to_block (&block, &arrayse.post); if (maskss) { /* We enclose the above in if (mask) {...} . */ - tmp = gfc_finish_block (&block); + tmp = gfc_finish_block (&block); tmp = build3_v (COND_EXPR, maskse.expr, tmp, build_empty_stmt (input_location)); } @@ -1937,6 +2020,16 @@ gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op) gfc_cleanup_loop (&loop); + if (norm2) + { + /* result = scale * sqrt(result). */ + tree sqrt; + sqrt = builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind); + resvar = build_call_expr_loc (input_location, + sqrt, 1, resvar); + resvar = fold_build2 (MULT_EXPR, type, scale, resvar); + } + se->expr = resvar; } @@ -5288,6 +5381,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_nearest (se, expr); break; + case GFC_ISYM_NORM2: + gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true); + break; + case GFC_ISYM_NOT: gfc_conv_intrinsic_not (se, expr); break; @@ -5296,12 +5393,16 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR); break; + case GFC_ISYM_PARITY: + gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false); + break; + case GFC_ISYM_PRESENT: gfc_conv_intrinsic_present (se, expr); break; case GFC_ISYM_PRODUCT: - gfc_conv_intrinsic_arith (se, expr, MULT_EXPR); + gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false); break; case GFC_ISYM_RRSPACING: @@ -5338,7 +5439,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) break; case GFC_ISYM_SUM: - gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR); + gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false); break; case GFC_ISYM_TRANSFER: @@ -5508,6 +5609,8 @@ gfc_is_intrinsic_libcall (gfc_expr * expr) case GFC_ISYM_MAXVAL: case GFC_ISYM_MINLOC: case GFC_ISYM_MINVAL: + case GFC_ISYM_NORM2: + case GFC_ISYM_PARITY: case GFC_ISYM_PRODUCT: case GFC_ISYM_SUM: case GFC_ISYM_SHAPE: |