arrays - vectores - Asignación de matrices de tamaño cero y uso en constructores de matrices




vectores y matrices matematicas (2)

1 Sí. Fortran es genial con matrices de 0 tamaños.

2 a(:) no es una matriz sino una sección de matriz (aunque una que comprende toda la matriz). La reasignación automática no está definida para trabajar en secciones de matriz, por lo que

allocate(a(0))
a(:) = [1 2 3]

no funciona En mi prueba el código compilado y ejecutado pero a se quedó con 0 tamaño.

En cuanto a si el código a = [a,1] debería funcionar si a no se ha asignado previamente (a 0- o cualquier otro tamaño), mi lectura del estándar es que esto no es estándar y que su compilador (el mío también ) es un error Espero que esto sea una lectura errónea del estándar de mi parte. Quizás alguien más vendrá y explicará correctamente.

3 Sí

allocate(a(0))
a = [a, 1]

está bien, se ajusta al estándar y funciona como es de esperar. Como habrás notado, un constructor de matriz vacío no está permitido en una asignación automática

En el siguiente código, estoy tratando de asignar una matriz vacía de tamaño 0 y agregar más elementos después mediante la reasignación automática:

integer, allocatable :: a(:)

allocate( a(0) )        ! Line 1
print *, size( a )
print *, "a(:) = ", a

a = [ a, 1 ]
print *, "a(:) = ", a

a = [ a, 2 ]
print *, "a(:) = ", a

!! Error
! a = []
! a = [ integer :: ]

Este código da el resultado esperado (por ejemplo, con gfortran o ifort -assume realloc_lhs)

           0
 a(:) = 
 a(:) =            1
 a(:) =            1           2

Aquí tengo tres preguntas:

  • En primer lugar, ¿está bien asignar matrices de tamaño cero como allocate( a( 0 ) ) ?
  • Si omitimos una asignación tan explícita, ¿ a(:) se inicializará automáticamente en una matriz de tamaño cero? (De hecho, el código parece funcionar incluso si comento la Línea 1.)
  • ¿No es un problema incluir matrices de tamaño cero en un constructor de matriz como a = [a, 1] ? (También traté de usar un constructor de matriz vacío como a = [] o a = [integer::] , pero no compilaron y parece que no está permitido).

Editar

Si descomiento a = [] en el código anterior, gfortran5.3 muestra el mensaje de error:

Error: Empty array constructor at (1) is not allowed

pero si eliminé solo la línea a = [ integer :: ] , ¡funcionó sin problemas! Debido a que inicialmente comenté las dos líneas al mismo tiempo, entendí mal que las dos vías son ilegales, pero en realidad esta última parece correcta (consulte la respuesta de @francescalus).


La respuesta de High Performance Mark cubre gran parte de esto, pero hay más para agregar (o replantear de una manera diferente). En cuanto a si a se "inicializó a una matriz de tamaño cero", no lo es y puede ver más detalles en otra pregunta . Tenga en cuenta, en particular, que a está inicialmente indefinido (y no asignado).

Como dice su otra respuesta, a(:) es una sección de matriz y no se puede asignar automáticamente en la asignación intrínseca. Quizás valga la pena señalar que esto se debe a(:) no tiene el atributo allocatable . Esto tiene otros efectos, como no permitir que se asocie con un argumento ficticio con ese atributo.

En un nivel alto, sí, las matrices de tamaño cero están bien (de nuevo, vea la pregunta vinculada donde hay una diferencia significativa entre cero y no asignado). Su enfoque con esa declaración de allocate y su uso en un constructor de matriz posterior son completamente razonables.

Sin embargo, en particular, para admitir la respuesta de High Performance Mark, no se permite el uso de una matriz no asignada en el constructor de la matriz: una variable no asignada no se puede referenciar.

Llegando a la construcción de una matriz de tamaño cero: pueden construirse matrices de tamaño cero, y no hay nada de especial en que se use una matriz de tamaño cero en la asignación intrínseca a una variable asignable.

Cuando se construye una matriz, se debe conocer el tipo (y los parámetros de tipo) de la matriz. Con un constructor de matriz como [a,1] (suponiendo que es a entero del tipo predeterminado) esta matriz es un entero del tipo predeterminado. ¿Cómo puede un compilador conocer el tipo / parámetros de [] ?

No puede, por lo que la sintaxis para un constructor de matriz para una matriz de tamaño cero es la que usted tiene: [integer::] es un constructor de matriz para una matriz (rango-1) de tamaño cero de entero predeterminado tipo.

En Fortran 2008 puede ver esta sintaxis como R468, R469 (4.8) y similares en Fortran 2003.

Finalmente, hay otra manera para un constructor de matriz de tamaño cero:

integer i
print*, [(i, i=1,0)]
end




allocation