You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Move the storage of rank and order from `ast.basic.TypedAstNode` to an
internal property of `ast.datatypes.PyccelType` objects (the properties
are still exposed via `ast.basic.TypedAstNode`). This allows mixed
ordered objects to be described and therefore created (e.g.
`list[float[:,:](order=F)]`). A test is added for this case. This change
should make pyccel#1583 simple to implement.
Making the rank and order part of the type fixespyccel#1821 . This provides
enough information to allow lists of arrays. Fixespyccel#1721.
In order to correctly index types such as `list[float[:,:](order=F)]`
the creation of an `IndexedElement` in the syntactic stage is modified.
Instead of collapsing all the indices into one `IndexedElement` an
`IndexedElement` is created for each `ast.Subscript`. In the semantic
stage this is collapsed into one `IndexedElement` for each container.
E.g. for the following code:
```python
import numpy as np
a = (np.ones((3,4)), np.zeros((3,4)))
a[0][1][2]
```
On the devel branch after the syntactic stage the last line is described
as `IndexedElement('a', (0, 1, 2))`. This persists to the codegen stage.
On this branch after the syntactic stage the last line is described as
`IndexedElement(IndexedElement(IndexedElement('a', (0,)), (1,)), (2,))`.
After the semantic stage it becomes `IndexedElement(IndexedElement('a',
(0,)), (1,2))`. The printers are modified to handle this. The generated
code is not changed (as support for lists has not yet been added) so the
indices are still used together to index a 3D array.
**Commit Summary**
- Update documentation
- Add missing `if __name__ == '__main__'` on old documentation examples.
- Remove `static_rank` and `static_order` properties from
`pyccel.ast.basic`. These properties are now contained in `static_type`.
- Remove `_rank` and `_order` properties from `TypedAstNode`s.
- Change `PyccelOperator.set_shape_rank` functions to
`PyccelOperator.set_shape` functions (the rank must now be determined at
the same time as the type).
- Remove `PyccelOperator._set_order` functions.
- Simplify homogeneity checks for tuples, lists and sets
- Ensure the shape of an empty list/tuple literal is set correctly.
- Correct the class type of `CmathPolar`
- Remove the `order` argument from the `Allocate` constructor (the
information is now retrieved from the order of the allocated variable).
- Add the properties `rank` and `order` to
`pyccel.ast.datatypes.PyccelType`.
- Add a `switch_rank` function to
`pyccel.ast.datatypes.HomogeneousContainerType`.
- Add a `container_rank` property to
`pyccel.ast.datatypes.HomogeneousContainerType`.
- Parameterise `NumpyNDArrayType` by the rank and the order
- Change the argument of `NumpyNewArray` from `dtype` to `class_type`
(to set the rank/order in the subclass).
- Allow `NumpyArray` to handle mixed rank objects (e.g. list of
F-ordered arrays).
- Rename `NumpyUfuncBase._set_shape_rank` to
`NumpyUfuncBase._get_shape_rank` and return the shape and rank to avoid
saving the rank unnecessarily.
- Rename `NumpyUfuncBase._set_order` to `NumpyUfuncBase._get_order` and
pass the rank and return the order to avoid saving unnecessarily.
- Add docstrings.
- Add a `NumpyNDArrayType.__new__` function which redirects rank 0
arrays to scalar types.
- Augment `NumpyNDArrayType.__add__` to handle rank and ordering.
- Add a `NumpyNDArrayType.swap_order` function to change between C and F
ordered equivalent types.
- Add `__str__` or `__repr__` functions to `PyccelType`s such that
printing them gives a valid type annotation.
- Add a `NumpyInt` object to easily find the NumPy integer which has the
same precision as Python integers.
- Remove `rank` and `order` arguments from
`pyccel.ast.type_annotations.VariableTypeAnnotation` constructor
(information now available in `class_type`).
- Remove `order` property from
`pyccel.ast.type_annotations.VariableTypeAnnotation` (`rank` is retained
for now).
- Update vector expression unravelling functions to handle multiple
levels of `IndexedElement`s.
- Improve docstrings in `pyccel.ast.utilities`.
- Remove `rank` and `order` arguments from
`pyccel.ast.variable.Variable` constructor (the information is now
retrieved from the `class_type`).
- Remove unused property `is_stack_scalar`.
- Simplify `is_ndarray` method.
- Add `_is_slice` attribute to `IndexedElement` to indicate if an
element or a slice of the base is represented.
- Add `allows_negative_indexes` property to `IndexedElement`.
- Update `_print_IndexedElement` to handle multi-level
`IndexedElement`s.
- Correct `abs` call in `_print_NumpyNorm`
- Improve error message for wrong arguments.
- Allocate strings on the stack to avoid calling `Allocate` (to be
improved with pyccel#459 ).
- Remove `get_type_description` (this is now handled by
`PyccelType.__str__`).
- Provide a traceback to `errors.report` to allow the location of a
`TypeError` raised during a `FunctionCall` to be more easily located.
- Stop collapsing `ast.Subscript` into one `IndexedElement` object.
- Add some mixed ordered tests.
- Disable tests with ambiguous interfaces (see pyccel#1821).
Copy file name to clipboardExpand all lines: developer_docs/ast_nodes.md
-8Lines changed: 0 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -54,14 +54,6 @@ The order indicates how an array is laid out in memory. This can either be row-m
54
54
55
55
The static type is the class type that would be assigned to an object created using an instance of this class as a type annotation.
56
56
57
-
### Static rank
58
-
59
-
The static rank is the rank that would be assigned to an object created using an instance of this class as a type annotation.
60
-
61
-
### Static order
62
-
63
-
The static order is the order that would be assigned to an object created using an instance of this class as a type annotation.
64
-
65
57
## Pyccel Internal Function
66
58
67
59
The class `pyccel.ast.internals.PyccelInternalFunction` is a super class. This class should never be used directly but provides functionalities which are common to certain AST objects. These AST nodes are those which describe functions which are supported by Pyccel. For example it is used for functions from the `math` library, the `cmath` library, the `numpy` library, etc. `PyccelInternalFunction` inherits from `TypedAstNode`. The type information for the sub-class describes the type of the result of the function.
Copy file name to clipboardExpand all lines: developer_docs/type_inference.md
+5-1Lines changed: 5 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -68,7 +68,7 @@ The and operator describes what happens when two numeric types are combined in a
68
68
When using these operators on an unknown number of arguments it can be useful to use `NativeGeneric()` as a starting point for the sum.
69
69
70
70
#### Container Type
71
-
A `ContainerType` is an object which is comprised of `FixedSizeType` objects (e.g. `ndarray`,`list`,`tuple`, custom class). The sub-class `HomogeneousContainerType` describes containers which contain homogeneous data. These objects are characterised by an `element_type`. The elements of a `HomogeneousContainerType` are instances of `PyccelType`, but they can be either `FixedSizeType`s or `ContainerType`s.
71
+
A `ContainerType` is an object which is comprised of `FixedSizeType` objects (e.g. `ndarray`,`list`,`tuple`, custom class). The sub-class `HomogeneousContainerType` describes containers which contain homogeneous data. These objects are characterised by an `element_type`, a `rank` (and associated `container_rank`) and an `order`. The elements of a `HomogeneousContainerType` are instances of `PyccelType`, but they can be either `FixedSizeType`s or `ContainerType`s. The `container_rank` is an integer equal to the number of indices necessary to index the container and get an element of type `element_type`. As these elements may also be indexable the `rank` property allows us to get the number of indices necessary to obtain a scalar element. It is the sum of all the `container_rank`s in the nested types. The `order` specifies the order in which the indices should be used to index the object. This is discussed in detail in the [order docs](./order_docs.md).
72
72
73
73
`HomogeneousContainerType`s also contain some utility functions. They implement `primitive_type` and `precision` to get the properties of the internal `FixedSizeType` (even if that type is inside another `HomogeneousContainerType`). They also implement `switch_basic_type` which creates a new `HomogeneousContainerType` which is similar to the current `HomogeneousContainerType`. The only difference is that the `FixedSizeType` is exchanged. This is useful when we want to preserve information about the container but need to change the type. For example, when we divide an integer by another we get a floating point type. When we divide a NumPy array or a CuPy array of integers by an integer (or array of integers) we get a NumPy/CuPy array of floating point numbers (with default Python precision). In order to preserve the container type we therefore call `switch_basic_type`. So for the division in the case of NumPy arrays, we want to change the type from `np.ndarray[int]` to `np.ndarray[float]`. This is done in one line:
74
74
```python
@@ -89,4 +89,8 @@ for container in new_container_types:
89
89
90
90
The `switch_basic_type` cannot be implemented generally in `PyccelType` as there is no logical interpretation for an inhomogeneous `ContainerType`, however the function is also implemented (as the identity function) for `FixedSizeType`s so `switch_basic_type` can be used without the need for type checks (generally inhomogeneous containers will not be valid arguments to classes which may need to use the `switch_basic_type` function).
91
91
92
+
`HomogeneousContainerType`s also contain a `switch_rank` function. This function is similar to `switch_basic_type` in that it is used to obtain a type which is similar in all but one characteristic. It is usually used to reduce the rank of an object, for example when calculating the type of a slice, however in the future it can also be used to increase the size of the type (e.g. to implement `np.newaxis`), in this case an order may need to be provided to add additional context. Increasing the rank is only possible for multi-dimensional types (e.g. `NumpyNDArrayType`) however the rank can be decreased for any `ContainerType`. If the rank is reduced by more than the `container_rank`, this function is called recursively.
93
+
94
+
For multi-dimensional `HomogeneousContainerType`s (e.g. `NumpyNDArrayType`) the function `swap_order` is also implemented. This inverts the ordering, changing from 'C' to 'F' or 'F' to 'C' if the rank is greater than 1.
95
+
92
96
In order to access the internal `FixedSizeType`, `PyccelType` also implements a `datatype` property. This makes more sense in the case of a `HomogeneousContainerType` however it is also implemented (as the identity function) for `FixedSizeType`s so the low-level type can be obtained without the need for type checks.
Copy file name to clipboardExpand all lines: docs/ndarrays.md
+88-22Lines changed: 88 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,9 +22,10 @@ Generally a variable in Pyccel should always keep its initial type, this also tr
22
22
```Python
23
23
import numpy as np
24
24
25
-
a = np.array([1, 2, 3], dtype=float)
26
-
#(some code...)
27
-
a = np.array([1, 2, 3], dtype=int)
25
+
if__name__=='__main__':
26
+
a = np.array([1, 2, 3], dtype=float)
27
+
#(some code...)
28
+
a = np.array([1, 2, 3], dtype=int)
28
29
```
29
30
30
31
_OUTPUT_ :
@@ -46,9 +47,10 @@ Pyccel calls its own garbage collector when needed, but has a set of rules to do
46
47
```Python
47
48
import numpy as np
48
49
49
-
a = np.ones((10, 20))
50
-
#(some code...)
51
-
a = np.ones(10)
50
+
if__name__=='__main__':
51
+
a = np.ones((10, 20))
52
+
#(some code...)
53
+
a = np.ones(10)
52
54
```
53
55
54
56
_OUTPUT_ :
@@ -66,9 +68,10 @@ This limitation is due to the fact that the rank of Fortran allocatable objects
66
68
```Python
67
69
import numpy as np
68
70
69
-
a = np.array([1, 2, 3, 4, 5])
70
-
b = np.array([1, 2, 3])
71
-
a = b
71
+
if__name__=='__main__':
72
+
a = np.array([1, 2, 3, 4, 5])
73
+
b = np.array([1, 2, 3])
74
+
a = b
72
75
```
73
76
74
77
_OUTPUT_ :
@@ -139,10 +142,11 @@ This limitation is due to the fact that the rank of Fortran allocatable objects
139
142
```Python
140
143
import numpy as np
141
144
142
-
a = np.ones(10)
143
-
b = a[:5]
144
-
#(some code...)
145
-
a = np.zeros(20)
145
+
if__name__=='__main__':
146
+
a = np.ones(10)
147
+
b = a[:5]
148
+
#(some code...)
149
+
a = np.zeros(20)
146
150
```
147
151
148
152
_OUTPUT_ :
@@ -157,7 +161,7 @@ This limitation is set since we need to free the previous data when we reallocat
157
161
158
162
### Slicing and indexing ###
159
163
160
-
The indexing and slicing in Pyccel handles only the basic indexing of [numpy arrays](https://numpy.org/doc/stable/user/basics.indexing.html).
164
+
The indexing and slicing in Pyccel handles only the basic indexing of [numpy arrays](https://numpy.org/doc/stable/user/basics.indexing.html). When multiple indexing expressions are used on the same variable Pyccel squashes them into one object. This means that we do not handle multiple slice indices applied to the same variable (e.g. `a[1::2][2:]`). This isnot recommended anyway as it makes code hard to read.
161
165
162
166
Some examples:
163
167
@@ -166,8 +170,9 @@ Some examples:
166
170
```Python
167
171
import numpy as np
168
172
169
-
a = np.array([1, 3, 4, 5])
170
-
a[0] =0
173
+
if__name__=='__main__':
174
+
a = np.array([1, 3, 4, 5])
175
+
a[0] =0
171
176
```
172
177
173
178
- C equivalent:
@@ -211,8 +216,9 @@ Some examples:
211
216
```Python
212
217
import numpy as np
213
218
214
-
a = np.ones((10, 20))
215
-
b = a[2:, :5]
219
+
if__name__=='__main__':
220
+
a = np.ones((10, 20))
221
+
b = a[2:, :5]
216
222
```
217
223
218
224
- C equivalent:
@@ -257,10 +263,11 @@ Some examples:
257
263
```Python
258
264
import numpy as np
259
265
260
-
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
261
-
b = a[1]
262
-
c = b[2]
263
-
print(c)
266
+
if__name__=='__main__':
267
+
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
268
+
b = a[1]
269
+
c = b[2]
270
+
print(c)
264
271
```
265
272
266
273
- C equivalent:
@@ -311,6 +318,65 @@ Some examples:
311
318
end program prog_ex
312
319
```
313
320
321
+
- Python code:
322
+
323
+
```Python
324
+
import numpy as np
325
+
326
+
if__name__=='__main__':
327
+
a = np.array([1, 2, 3, 4, 5, 6, 7, 8])
328
+
b = a[1::2][2]
329
+
print(b)
330
+
```
331
+
332
+
- C equivalent:
333
+
334
+
```C
335
+
#include <stdlib.h>
336
+
#include "ndarrays.h"
337
+
#include <stdint.h>
338
+
#include <string.h>
339
+
#include <stdio.h>
340
+
#include <inttypes.h>
341
+
int main()
342
+
{
343
+
t_ndarray a = {.shape = NULL};
344
+
int64_t b;
345
+
a = array_create(1, (int64_t[]){INT64_C(8)}, nd_int64, false, order_c);
0 commit comments