⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplify.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Simplify intrinsic functions at compile-time.   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software   Foundation, Inc.   Contributed by Andy Vaught & Katherine HolcombThis file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING.  If not, write to the FreeSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA02110-1301, USA.  */#include "config.h"#include "system.h"#include "flags.h"#include "gfortran.h"#include "arith.h"#include "intrinsic.h"gfc_expr gfc_bad_expr;/* Note that 'simplification' is not just transforming expressions.   For functions that are not simplified at compile time, range   checking is done if possible.   The return convention is that each simplification function returns:     A new expression node corresponding to the simplified arguments.     The original arguments are destroyed by the caller, and must not     be a part of the new expression.     NULL pointer indicating that no simplification was possible and     the original expression should remain intact.  If the     simplification function sets the type and/or the function name     via the pointer gfc_simple_expression, then this type is     retained.     An expression pointer to gfc_bad_expr (a static placeholder)     indicating that some error has prevented simplification.  For     example, sqrt(-1.0).  The error is generated within the function     and should be propagated upwards   By the time a simplification function gets control, it has been   decided that the function call is really supposed to be the   intrinsic.  No type checking is strictly necessary, since only   valid types will be passed on.  On the other hand, a simplification   subroutine may have to look at the type of an argument as part of   its processing.   Array arguments are never passed to these subroutines.   The functions in this file don't have much comment with them, but   everything is reasonably straight-forward.  The Standard, chapter 13   is the best comment you'll find for this file anyway.  *//* Static table for converting non-ascii character sets to ascii.   The xascii_table[] is the inverse table.  */static int ascii_table[256] = {  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',  '\b', '\t', '\n', '\v', '\0', '\r', '\0', '\0',  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',  ' ', '!', '\'', '#', '$', '%', '&', '\'',  '(', ')', '*', '+', ',', '-', '.', '/',  '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9', ':', ';', '<', '=', '>', '?',  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',  'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',  'X', 'Y', 'Z', '[', '\\', ']', '^', '_',  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z', '{', '|', '}', '~', '\?'};static int xascii_table[256];/* Range checks an expression node.  If all goes well, returns the   node, otherwise returns &gfc_bad_expr and frees the node.  */static gfc_expr *range_check (gfc_expr * result, const char *name){  if (gfc_range_check (result) == ARITH_OK)    return result;  gfc_error ("Result of %s overflows its kind at %L", name, &result->where);  gfc_free_expr (result);  return &gfc_bad_expr;}/* A helper function that gets an optional and possibly missing   kind parameter.  Returns the kind, -1 if something went wrong.  */static intget_kind (bt type, gfc_expr * k, const char *name, int default_kind){  int kind;  if (k == NULL)    return default_kind;  if (k->expr_type != EXPR_CONSTANT)    {      gfc_error ("KIND parameter of %s at %L must be an initialization "		 "expression", name, &k->where);      return -1;    }  if (gfc_extract_int (k, &kind) != NULL      || gfc_validate_kind (type, kind, true) < 0)    {      gfc_error ("Invalid KIND parameter of %s at %L", name, &k->where);      return -1;    }  return kind;}/* Checks if X, which is assumed to represent a two's complement   integer of binary width BITSIZE, has the signbit set.  If so, makes    X the corresponding negative number.  */static voidtwos_complement (mpz_t x, int bitsize){  mpz_t mask;  if (mpz_tstbit (x, bitsize - 1) == 1)    {      mpz_init_set_ui(mask, 1);      mpz_mul_2exp(mask, mask, bitsize);      mpz_sub_ui(mask, mask, 1);      /* We negate the number by hand, zeroing the high bits, that is        make it the corresponding positive number, and then have it        negated by GMP, giving the correct representation of the        negative number.  */      mpz_com (x, x);      mpz_add_ui (x, x, 1);      mpz_and (x, x, mask);      mpz_neg (x, x);      mpz_clear (mask);    }}/********************** Simplification functions *****************************/gfc_expr *gfc_simplify_abs (gfc_expr * e){  gfc_expr *result;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  switch (e->ts.type)    {    case BT_INTEGER:      result = gfc_constant_result (BT_INTEGER, e->ts.kind, &e->where);      mpz_abs (result->value.integer, e->value.integer);      result = range_check (result, "IABS");      break;    case BT_REAL:      result = gfc_constant_result (BT_REAL, e->ts.kind, &e->where);      mpfr_abs (result->value.real, e->value.real, GFC_RND_MODE);      result = range_check (result, "ABS");      break;    case BT_COMPLEX:      result = gfc_constant_result (BT_REAL, e->ts.kind, &e->where);      gfc_set_model_kind (e->ts.kind);      mpfr_hypot (result->value.real, e->value.complex.r, 		  e->value.complex.i, GFC_RND_MODE);      result = range_check (result, "CABS");      break;    default:      gfc_internal_error ("gfc_simplify_abs(): Bad type");    }  return result;}gfc_expr *gfc_simplify_achar (gfc_expr * e){  gfc_expr *result;  int index;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  /* We cannot assume that the native character set is ASCII in this     function.  */  if (gfc_extract_int (e, &index) != NULL || index < 0 || index > 127)    {      gfc_error ("Extended ASCII not implemented: argument of ACHAR at %L "		 "must be between 0 and 127", &e->where);      return &gfc_bad_expr;    }  result = gfc_constant_result (BT_CHARACTER, gfc_default_character_kind,				&e->where);  result->value.character.string = gfc_getmem (2);  result->value.character.length = 1;  result->value.character.string[0] = ascii_table[index];  result->value.character.string[1] = '\0';	/* For debugger */  return result;}gfc_expr *gfc_simplify_acos (gfc_expr * x){  gfc_expr *result;  if (x->expr_type != EXPR_CONSTANT)    return NULL;  if (mpfr_cmp_si (x->value.real, 1) > 0 || mpfr_cmp_si (x->value.real, -1) < 0)    {      gfc_error ("Argument of ACOS at %L must be between -1 and 1",		 &x->where);      return &gfc_bad_expr;    }  result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);  mpfr_acos (result->value.real, x->value.real, GFC_RND_MODE);  return range_check (result, "ACOS");}gfc_expr *gfc_simplify_acosh (gfc_expr * x){  gfc_expr *result;  if (x->expr_type != EXPR_CONSTANT)    return NULL;  if (mpfr_cmp_si (x->value.real, 1) < 0)    {      gfc_error ("Argument of ACOSH at %L must not be less than 1",		 &x->where);      return &gfc_bad_expr;    }  result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);  mpfr_acosh (result->value.real, x->value.real, GFC_RND_MODE);  return range_check (result, "ACOSH");}gfc_expr *gfc_simplify_adjustl (gfc_expr * e){  gfc_expr *result;  int count, i, len;  char ch;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  len = e->value.character.length;  result = gfc_constant_result (BT_CHARACTER, e->ts.kind, &e->where);  result->value.character.length = len;  result->value.character.string = gfc_getmem (len + 1);  for (count = 0, i = 0; i < len; ++i)    {      ch = e->value.character.string[i];      if (ch != ' ')	break;      ++count;    }  for (i = 0; i < len - count; ++i)    {      result->value.character.string[i] =	e->value.character.string[count + i];    }  for (i = len - count; i < len; ++i)    {      result->value.character.string[i] = ' ';    }  result->value.character.string[len] = '\0';	/* For debugger */  return result;}gfc_expr *gfc_simplify_adjustr (gfc_expr * e){  gfc_expr *result;  int count, i, len;  char ch;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  len = e->value.character.length;  result = gfc_constant_result (BT_CHARACTER, e->ts.kind, &e->where);  result->value.character.length = len;  result->value.character.string = gfc_getmem (len + 1);  for (count = 0, i = len - 1; i >= 0; --i)    {      ch = e->value.character.string[i];      if (ch != ' ')	break;      ++count;    }  for (i = 0; i < count; ++i)    {      result->value.character.string[i] = ' ';    }  for (i = count; i < len; ++i)    {      result->value.character.string[i] =	e->value.character.string[i - count];    }  result->value.character.string[len] = '\0';	/* For debugger */  return result;}gfc_expr *gfc_simplify_aimag (gfc_expr * e){  gfc_expr *result;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  result = gfc_constant_result (BT_REAL, e->ts.kind, &e->where);  mpfr_set (result->value.real, e->value.complex.i, GFC_RND_MODE);  return range_check (result, "AIMAG");}gfc_expr *gfc_simplify_aint (gfc_expr * e, gfc_expr * k){  gfc_expr *rtrunc, *result;  int kind;  kind = get_kind (BT_REAL, k, "AINT", e->ts.kind);  if (kind == -1)    return &gfc_bad_expr;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  rtrunc = gfc_copy_expr (e);  mpfr_trunc (rtrunc->value.real, e->value.real);  result = gfc_real2real (rtrunc, kind);  gfc_free_expr (rtrunc);  return range_check (result, "AINT");}gfc_expr *gfc_simplify_dint (gfc_expr * e){  gfc_expr *rtrunc, *result;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  rtrunc = gfc_copy_expr (e);  mpfr_trunc (rtrunc->value.real, e->value.real);  result = gfc_real2real (rtrunc, gfc_default_double_kind);  gfc_free_expr (rtrunc);  return range_check (result, "DINT");}gfc_expr *gfc_simplify_anint (gfc_expr * e, gfc_expr * k){  gfc_expr *result;  int kind;  kind = get_kind (BT_REAL, k, "ANINT", e->ts.kind);  if (kind == -1)    return &gfc_bad_expr;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  result = gfc_constant_result (e->ts.type, kind, &e->where);  mpfr_round (result->value.real, e->value.real);  return range_check (result, "ANINT");}gfc_expr *gfc_simplify_and (gfc_expr * x, gfc_expr * y){  gfc_expr *result;  int kind;  if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)    return NULL;  kind = x->ts.kind > y->ts.kind ? x->ts.kind : y->ts.kind;  if (x->ts.type == BT_INTEGER)    {      result = gfc_constant_result (BT_INTEGER, kind, &x->where);      mpz_and (result->value.integer, x->value.integer, y->value.integer);    }  else /* BT_LOGICAL */    {      result = gfc_constant_result (BT_LOGICAL, kind, &x->where);      result->value.logical = x->value.logical && y->value.logical;    }  return range_check (result, "AND");}gfc_expr *gfc_simplify_dnint (gfc_expr * e){  gfc_expr *result;  if (e->expr_type != EXPR_CONSTANT)    return NULL;  result = gfc_constant_result (BT_REAL, gfc_default_double_kind, &e->where);  mpfr_round (result->value.real, e->value.real);  return range_check (result, "DNINT");}gfc_expr *gfc_simplify_asin (gfc_expr * x){  gfc_expr *result;  if (x->expr_type != EXPR_CONSTANT)    return NULL;  if (mpfr_cmp_si (x->value.real, 1) > 0 || mpfr_cmp_si (x->value.real, -1) < 0)    {      gfc_error ("Argument of ASIN at %L must be between -1 and 1",		 &x->where);      return &gfc_bad_expr;    }  result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);  mpfr_asin(result->value.real, x->value.real, GFC_RND_MODE);  return range_check (result, "ASIN");}gfc_expr *gfc_simplify_asinh (gfc_expr * x){  gfc_expr *result;  if (x->expr_type != EXPR_CONSTANT)    return NULL;  result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);  mpfr_asinh(result->value.real, x->value.real, GFC_RND_MODE);  return range_check (result, "ASINH");}gfc_expr *gfc_simplify_atan (gfc_expr * x){  gfc_expr *result;  if (x->expr_type != EXPR_CONSTANT)    return NULL;      result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);  mpfr_atan(result->value.real, x->value.real, GFC_RND_MODE);  return range_check (result, "ATAN");}gfc_expr *gfc_simplify_atanh (gfc_expr * x){  gfc_expr *result;  if (x->expr_type != EXPR_CONSTANT)    return NULL;  if (mpfr_cmp_si (x->value.real, 1) >= 0 ||      mpfr_cmp_si (x->value.real, -1) <= 0)    {      gfc_error ("Argument of ATANH at %L must be inside the range -1 to 1",		 &x->where);      return &gfc_bad_expr;    }  result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);  mpfr_atanh(result->value.real, x->value.real, GFC_RND_MODE);  return range_check (result, "ATANH");}gfc_expr *gfc_simplify_atan2 (gfc_expr * y, gfc_expr * x){  gfc_expr *result;  if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)    return NULL;  result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);  if (mpfr_sgn (y->value.real) == 0 && mpfr_sgn (x->value.real) == 0)    {      gfc_error	("If first argument of ATAN2 %L is zero, then the second argument "	  "must not be zero", &x->where);      gfc_free_expr (result);      return &gfc_bad_expr;    }  arctangent2 (y->value.real, x->value.real, result->value.real);  return range_check (result, "ATAN2");}gfc_expr *gfc_simplify_bit_size (gfc_expr * e){  gfc_expr *result;  int i;  i = gfc_validate_kind (e->ts.type, e->ts.kind, false);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -