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

📄 array.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 3 页
字号:
	    return FAILURE;	  continue;	}      e = gfc_copy_expr (e);      if (gfc_simplify_expr (e, 1) == FAILURE)	{	  gfc_free_expr (e);	  return FAILURE;	}      current_expand.offset = &c->n.offset;      current_expand.component = c->n.component;      current_expand.repeat = &c->repeat;      if (current_expand.expand_work_function (e) == FAILURE)	return FAILURE;    }  return SUCCESS;}/* Top level subroutine for expanding constructors.  We only expand   constructor if they are small enough.  */trygfc_expand_constructor (gfc_expr * e){  expand_info expand_save;  gfc_expr *f;  try rc;  f = gfc_get_array_element (e, GFC_MAX_AC_EXPAND);  if (f != NULL)    {      gfc_free_expr (f);      return SUCCESS;    }  expand_save = current_expand;  current_expand.new_head = current_expand.new_tail = NULL;  iter_stack = NULL;  current_expand.expand_work_function = expand;  if (expand_constructor (e->value.constructor) == FAILURE)    {      gfc_free_constructor (current_expand.new_head);      rc = FAILURE;      goto done;    }  gfc_free_constructor (e->value.constructor);  e->value.constructor = current_expand.new_head;  rc = SUCCESS;done:  current_expand = expand_save;  return rc;}/* Work function for checking that an element of a constructor is a   constant, after removal of any iteration variables.  We return   FAILURE if not so.  */static tryconstant_element (gfc_expr * e){  int rv;  rv = gfc_is_constant_expr (e);  gfc_free_expr (e);  return rv ? SUCCESS : FAILURE;}/* Given an array constructor, determine if the constructor is   constant or not by expanding it and making sure that all elements   are constants.  This is a bit of a hack since something like (/ (i,   i=1,100000000) /) will take a while as* opposed to a more clever   function that traverses the expression tree. FIXME.  */intgfc_constant_ac (gfc_expr * e){  expand_info expand_save;  try rc;  iter_stack = NULL;  expand_save = current_expand;  current_expand.expand_work_function = constant_element;  rc = expand_constructor (e->value.constructor);  current_expand = expand_save;  if (rc == FAILURE)    return 0;  return 1;}/* Returns nonzero if an array constructor has been completely   expanded (no iterators) and zero if iterators are present.  */intgfc_expanded_ac (gfc_expr * e){  gfc_constructor *p;  if (e->expr_type == EXPR_ARRAY)    for (p = e->value.constructor; p; p = p->next)      if (p->iterator != NULL || !gfc_expanded_ac (p->expr))	return 0;  return 1;}/*************** Type resolution of array constructors ***************//* Recursive array list resolution function.  All of the elements must   be of the same type.  */static tryresolve_array_list (gfc_constructor * p){  try t;  t = SUCCESS;  for (; p; p = p->next)    {      if (p->iterator != NULL	  && gfc_resolve_iterator (p->iterator, false) == FAILURE)	t = FAILURE;      if (gfc_resolve_expr (p->expr) == FAILURE)	t = FAILURE;    }  return t;}/* Resolve character array constructor. If it is a constant character array and   not specified character length, update character length to the maximum of   its element constructors' length.  */static voidresolve_character_array_constructor (gfc_expr * expr){  gfc_constructor * p;  int max_length;  gcc_assert (expr->expr_type == EXPR_ARRAY);  gcc_assert (expr->ts.type == BT_CHARACTER);  max_length = -1;  if (expr->ts.cl == NULL)    {      expr->ts.cl = gfc_get_charlen ();      expr->ts.cl->next = gfc_current_ns->cl_list;      gfc_current_ns->cl_list = expr->ts.cl;    }  if (expr->ts.cl->length == NULL)    {      /* Find the maximum length of the elements. Do nothing for variable array	 constructor.  */      for (p = expr->value.constructor; p; p = p->next)	if (p->expr->expr_type == EXPR_CONSTANT)	  max_length = MAX (p->expr->value.character.length, max_length);	else	  return;      if (max_length != -1)	{	  /* Update the character length of the array constructor.  */	  expr->ts.cl->length = gfc_int_expr (max_length);	  /* Update the element constructors.  */	  for (p = expr->value.constructor; p; p = p->next)	    gfc_set_constant_character_len (max_length, p->expr);	}    }}/* Resolve all of the expressions in an array list.  */trygfc_resolve_array_constructor (gfc_expr * expr){  try t;  t = resolve_array_list (expr->value.constructor);  if (t == SUCCESS)    t = gfc_check_constructor_type (expr);  if (t == SUCCESS && expr->ts.type == BT_CHARACTER)    resolve_character_array_constructor (expr);  return t;}/* Copy an iterator structure.  */static gfc_iterator *copy_iterator (gfc_iterator * src){  gfc_iterator *dest;  if (src == NULL)    return NULL;  dest = gfc_get_iterator ();  dest->var = gfc_copy_expr (src->var);  dest->start = gfc_copy_expr (src->start);  dest->end = gfc_copy_expr (src->end);  dest->step = gfc_copy_expr (src->step);  return dest;}/* Copy a constructor structure.  */gfc_constructor *gfc_copy_constructor (gfc_constructor * src){  gfc_constructor *dest;  gfc_constructor *tail;  if (src == NULL)    return NULL;  dest = tail = NULL;  while (src)    {      if (dest == NULL)	dest = tail = gfc_get_constructor ();      else	{	  tail->next = gfc_get_constructor ();	  tail = tail->next;	}      tail->where = src->where;      tail->expr = gfc_copy_expr (src->expr);      tail->iterator = copy_iterator (src->iterator);      mpz_set (tail->n.offset, src->n.offset);      tail->n.component = src->n.component;      mpz_set (tail->repeat, src->repeat);      src = src->next;    }  return dest;}/* Given an array expression and an element number (starting at zero),   return a pointer to the array element.  NULL is returned if the   size of the array has been exceeded.  The expression node returned   remains a part of the array and should not be freed.  Access is not   efficient at all, but this is another place where things do not   have to be particularly fast.  */gfc_expr *gfc_get_array_element (gfc_expr * array, int element){  expand_info expand_save;  gfc_expr *e;  try rc;  expand_save = current_expand;  current_expand.extract_n = element;  current_expand.expand_work_function = extract_element;  current_expand.extracted = NULL;  current_expand.extract_count = 0;  iter_stack = NULL;  rc = expand_constructor (array->value.constructor);  e = current_expand.extracted;  current_expand = expand_save;  if (rc == FAILURE)    return NULL;  return e;}/********* Subroutines for determining the size of an array *********//* These are needed just to accommodate RESHAPE().  There are no   diagnostics here, we just return a negative number if something   goes wrong.  *//* Get the size of single dimension of an array specification.  The   array is guaranteed to be one dimensional.  */static tryspec_dimen_size (gfc_array_spec * as, int dimen, mpz_t * result){  if (as == NULL)    return FAILURE;  if (dimen < 0 || dimen > as->rank - 1)    gfc_internal_error ("spec_dimen_size(): Bad dimension");  if (as->type != AS_EXPLICIT      || as->lower[dimen]->expr_type != EXPR_CONSTANT      || as->upper[dimen]->expr_type != EXPR_CONSTANT)    return FAILURE;  mpz_init (*result);  mpz_sub (*result, as->upper[dimen]->value.integer,	   as->lower[dimen]->value.integer);  mpz_add_ui (*result, *result, 1);  return SUCCESS;}tryspec_size (gfc_array_spec * as, mpz_t * result){  mpz_t size;  int d;  mpz_init_set_ui (*result, 1);  for (d = 0; d < as->rank; d++)    {      if (spec_dimen_size (as, d, &size) == FAILURE)	{	  mpz_clear (*result);	  return FAILURE;	}      mpz_mul (*result, *result, size);      mpz_clear (size);    }  return SUCCESS;}/* Get the number of elements in an array section.  */static tryref_dimen_size (gfc_array_ref * ar, int dimen, mpz_t * result){  mpz_t upper, lower, stride;  try t;  if (dimen < 0 || ar == NULL || dimen > ar->dimen - 1)    gfc_internal_error ("ref_dimen_size(): Bad dimension");  switch (ar->dimen_type[dimen])    {    case DIMEN_ELEMENT:      mpz_init (*result);      mpz_set_ui (*result, 1);      t = SUCCESS;      break;    case DIMEN_VECTOR:      t = gfc_array_size (ar->start[dimen], result);	/* Recurse! */      break;    case DIMEN_RANGE:      mpz_init (upper);      mpz_init (lower);      mpz_init (stride);      t = FAILURE;      if (ar->start[dimen] == NULL)	{	  if (ar->as->lower[dimen] == NULL	      || ar->as->lower[dimen]->expr_type != EXPR_CONSTANT)	    goto cleanup;	  mpz_set (lower, ar->as->lower[dimen]->value.integer);	}      else	{	  if (ar->start[dimen]->expr_type != EXPR_CONSTANT)	    goto cleanup;	  mpz_set (lower, ar->start[dimen]->value.integer);	}      if (ar->end[dimen] == NULL)	{	  if (ar->as->upper[dimen] == NULL	      || ar->as->upper[dimen]->expr_type != EXPR_CONSTANT)	    goto cleanup;	  mpz_set (upper, ar->as->upper[dimen]->value.integer);	}      else	{	  if (ar->end[dimen]->expr_type != EXPR_CONSTANT)	    goto cleanup;	  mpz_set (upper, ar->end[dimen]->value.integer);	}      if (ar->stride[dimen] == NULL)	mpz_set_ui (stride, 1);      else	{	  if (ar->stride[dimen]->expr_type != EXPR_CONSTANT)	    goto cleanup;	  mpz_set (stride, ar->stride[dimen]->value.integer);	}      mpz_init (*result);      mpz_sub (*result, upper, lower);      mpz_add (*result, *result, stride);      mpz_div (*result, *result, stride);      /* Zero stride caught earlier.  */      if (mpz_cmp_ui (*result, 0) < 0)	mpz_set_ui (*result, 0);      t = SUCCESS;    cleanup:      mpz_clear (upper);      mpz_clear (lower);      mpz_clear (stride);      return t;    default:      gfc_internal_error ("ref_dimen_size(): Bad dimen_type");    }  return t;}static tryref_size (gfc_array_ref * ar, mpz_t * result){  mpz_t size;  int d;  mpz_init_set_ui (*result, 1);  for (d = 0; d < ar->dimen; d++)    {      if (ref_dimen_size (ar, d, &size) == FAILURE)	{	  mpz_clear (*result);	  return FAILURE;	}      mpz_mul (*result, *result, size);      mpz_clear (size);    }  return SUCCESS;}/* Given an array expression and a dimension, figure out how many   elements it has along that dimension.  Returns SUCCESS if we were   able to return a result in the 'result' variable, FAILURE   otherwise.  */trygfc_array_dimen_size (gfc_expr * array, int dimen, mpz_t * result){  gfc_ref *ref;  int i;  if (dimen < 0 || array == NULL || dimen > array->rank - 1)    gfc_internal_error ("gfc_array_dimen_size(): Bad dimension");  switch (array->expr_type)    {    case EXPR_VARIABLE:    case EXPR_FUNCTION:      for (ref = array->ref; ref; ref = ref->next)	{	  if (ref->type != REF_ARRAY)	    continue;	  if (ref->u.ar.type == AR_FULL)	    return spec_dimen_size (ref->u.ar.as, dimen, result);	  if (ref->u.ar.type == AR_SECTION)	    {	      for (i = 0; dimen >= 0; i++)		if (ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)		  dimen--;	      return ref_dimen_size (&ref->u.ar, i - 1, result);	    }	}      if (spec_dimen_size (array->symtree->n.sym->as, dimen, result) == FAILURE)	return FAILURE;      break;    case EXPR_ARRAY:      if (array->shape == NULL) {	/* Expressions with rank > 1 should have "shape" properly set */	if ( array->rank != 1 )	  gfc_internal_error ("gfc_array_dimen_size(): Bad EXPR_ARRAY expr");	return gfc_array_size(array, result);      }      /* Fall through */    default:      if (array->shape == NULL)	return FAILURE;      mpz_init_set (*result, array->shape[dimen]);      break;    }  return SUCCESS;}/* Given an array expression, figure out how many elements are in the   array.  Returns SUCCESS if this is possible, and sets the 'result'   variable.  Otherwise returns FAILURE.  */trygfc_array_size (gfc_expr * array, mpz_t * result){  expand_info expand_save;  gfc_ref *ref;  int i, flag;  try t;  switch (array->expr_type)    {    case EXPR_ARRAY:      flag = gfc_suppress_error;      gfc_suppress_error = 1;      expand_save = current_expand;      current_expand.count = result;      mpz_init_set_ui (*result, 0);      current_expand.expand_work_function = count_elements;      iter_stack = NULL;      t = expand_constructor (array->value.constructor);      gfc_suppress_error = flag;      if (t == FAILURE)	mpz_clear (*result);      current_expand = expand_save;      return t;    case EXPR_VARIABLE:      for (ref = array->ref; ref; ref = ref->next)	{	  if (ref->type != REF_ARRAY)	    continue;	  if (ref->u.ar.type == AR_FULL)	    return spec_size (ref->u.ar.as, result);	  if (ref->u.ar.type == AR_SECTION)	    return ref_size (&ref->u.ar, result);	}      return spec_size (array->symtree->n.sym->as, result);    default:      if (array->rank == 0 || array->shape == NULL)	return FAILURE;      mpz_init_set_ui (*result, 1);      for (i = 0; i < array->rank; i++)	mpz_mul (*result, *result, array->shape[i]);      break;    }  return SUCCESS;}/* Given an array reference, return the shape of the reference in an   array of mpz_t integers.  */trygfc_array_ref_shape (gfc_array_ref * ar, mpz_t * shape){  int d;  int i;  d = 0;  switch (ar->type)    {    case AR_FULL:      for (; d < ar->as->rank; d++)	if (spec_dimen_size (ar->as, d, &shape[d]) == FAILURE)	  goto cleanup;      return SUCCESS;    case AR_SECTION:      for (i = 0; i < ar->dimen; i++)	{	  if (ar->dimen_type[i] != DIMEN_ELEMENT)	    {	      if (ref_dimen_size (ar, i, &shape[d]) == FAILURE)		goto cleanup;	      d++;	    }	}      return SUCCESS;    default:      break;    }cleanup:  for (d--; d >= 0; d--)    mpz_clear (shape[d]);  return FAILURE;}/* Given an array expression, find the array reference structure that   characterizes the reference.  */gfc_array_ref *gfc_find_array_ref (gfc_expr * e){  gfc_ref *ref;  for (ref = e->ref; ref; ref = ref->next)    if (ref->type == REF_ARRAY	&& (ref->u.ar.type == AR_FULL	    || ref->u.ar.type == AR_SECTION))      break;  if (ref == NULL)    gfc_internal_error ("gfc_find_array_ref(): No ref found");  return &ref->u.ar;}/* Find out if an array shape is known at compile time.  */intgfc_is_compile_time_shape (gfc_array_spec *as){  int i;  if (as->type != AS_EXPLICIT)    return 0;  for (i = 0; i < as->rank; i++)    if (!gfc_is_constant_expr (as->lower[i])	|| !gfc_is_constant_expr (as->upper[i]))      return 0;  return 1;}

⌨️ 快捷键说明

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