Repository: pyccel/pyccel (language: python)

Issue:
Hide traceback for `epyccel` errors
When an error is raised from within a call to `epyccel`, a traceback is printed which is not informative to the user (nor to the developer).

This may be due to a missing `except` block, which is present for `pyccel` instead.

The problem does not depend on the language.
Correct wrong array order and several bugs returning fortran ordered arrays
Correct wrong array order when initialising from a fortran ordered array (fixes #1171). Implemtation of tests showed several bugs when returning fortran ordered arrays. These are also fixed.

**Commit Summary**
- Update version patch number
- Add a test for `np.array` which returns an array and checks flags
- [BUGFIX] Ensure numpy is aware that it owns the data returned by a function to ensure that this memory is freed
- [BUGFIX] Only transpose 2d arrays saved to Fortran ordered objects if the transpose is required
- [BUGFIX] pyccel and numpy handle slicing differently which requires a more complicated `_ndarray_to_numpy_strides` function to return a fortran ordered array
- [BUGFIX] Correct numpy type when returning an array with rank>1
Ci_tools are installed
### Description

On my computer the `ci_tools` directory is installed into `site-packages`. This file is not intended to be packaged.

### Environment information

Python version : 3.10

OS version : Ubuntu 22.04
Fix Interface returning 1 scalar or array in Fortran
### Relevant Discussion

https://github.com/pyccel/pyccel/pull/1278#discussion_r1127502147

### Describe the feature
Interfaces which return one result which can be either a scalar or an array work in C but not in Fortran. We would like this to work correctly for all languages.

### Test Code
Provide code which does not currently work but which should do when this issue is fixed:
```python
@types('int')
@types('int[:]')
def f(a):
    return a+3
```
Since PR #1278 this code leads to the following Fortran code being generated:
```fortran
module foo


  use, intrinsic :: ISO_C_Binding, only : i64 => C_INT64_T
  implicit none

  interface f
    module procedure f_00
    module procedure f_01
  end interface

  contains

  !........................................
  function f_00(a) result(Out_0001)

    implicit none

    integer(i64) :: Out_0001
    integer(i64), value :: a

    Out_0001 = a + 3_i64
    return

  end function f_00
  !........................................

  !........................................
  subroutine f_01(a, Out_0001)

    implicit none

    integer(i64), allocatable, intent(out) :: Out_0001(:)
    integer(i64), intent(in) :: a(0:)

    allocate(Out_0001(0:size(a, kind=i64) - 1_i64))
    Out_0001 = a + 3_i64
    return

  end subroutine f_01
  !........................................

end module foo
```
which raises the following compiler error:
```
/home/emily/Code/test/__pyccel__/foo.f90:15:2:

   15 |   function f_00(a) result(Out_0001)
      |  1
Error: In generic interface 'f' at (1) procedures must be either all SUBROUTINEs or all FUNCTIONs
```

### Proposed Solution
As seen in the discussion there are a few possible solutions. The simplest involves creating a separate interface for subroutines and functions. So the following code:
```python
@types('int')
@types('int[:]')
@types('float')
@types('float[:]')
def f(a):
    return a+3
```
would lead to the following interfaces being printed:
```fortran

  interface f_f
    module procedure f_00
    module procedure f_02
  end interface

  interface s_f
    module procedure f_01
    module procedure f_03
  end interface
```
As this solution involves renaming the interface as compared to the original Fortran code it may be a good idea to wait for issue #297 to be fixed before tackling it.
Fix Interface returning 1 scalar or array in Fortran
### Relevant Discussion

https://github.com/pyccel/pyccel/pull/1278#discussion_r1127502147

### Describe the feature
Interfaces which return one result which can be either a scalar or an array work in C but not in Fortran. We would like this to work correctly for all languages.

### Test Code
Provide code which does not currently work but which should do when this issue is fixed:
```python
@types('int')
@types('int[:]')
def f(a):
    return a+3
```
Since PR #1278 this code leads to the following Fortran code being generated:
```fortran
module foo


  use, intrinsic :: ISO_C_Binding, only : i64 => C_INT64_T
  implicit none

  interface f
    module procedure f_00
    module procedure f_01
  end interface

  contains

  !........................................
  function f_00(a) result(Out_0001)

    implicit none

    integer(i64) :: Out_0001
    integer(i64), value :: a

    Out_0001 = a + 3_i64
    return

  end function f_00
  !........................................

  !........................................
  subroutine f_01(a, Out_0001)

    implicit none

    integer(i64), allocatable, intent(out) :: Out_0001(:)
    integer(i64), intent(in) :: a(0:)

    allocate(Out_0001(0:size(a, kind=i64) - 1_i64))
    Out_0001 = a + 3_i64
    return

  end subroutine f_01
  !........................................

end module foo
```
which raises the following compiler error:
```
/home/emily/Code/test/__pyccel__/foo.f90:15:2:

   15 |   function f_00(a) result(Out_0001)
      |  1
Error: In generic interface 'f' at (1) procedures must be either all SUBROUTINEs or all FUNCTIONs
```

### Proposed Solution
As seen in the discussion there are a few possible solutions. The simplest involves creating a separate interface for subroutines and functions. So the following code:
```python
@types('int')
@types('int[:]')
@types('float')
@types('float[:]')
def f(a):
    return a+3
```
would lead to the following interfaces being printed:
```fortran

  interface f_f
    module procedure f_00
    module procedure f_02
  end interface

  interface s_f
    module procedure f_01
    module procedure f_03
  end interface
```
As this solution involves renaming the interface as compared to the original Fortran code it may be a good idea to wait for issue #297 to be fixed before tackling it.
Version 1.12.0
TODO:
- [X] Prepare commits
- [x] Update workflows to manage `main` (#1860)
- [x] Update version (#1859)
- [x] Update `devel` CHANGELOG (#1859)
- [x] Add workflow to deploy to PyPi


Discussion / hints:

Hi @EmilyBourne, what's the status of this PR?
This PR is supposed to fix a memory leak (I think some of the other bug fixes have been fixed in other branches since). It works perfectly for linux and mac but on Windows it is raising "double free". I need someone with a windows machine to run the test with a tool such as drmemory. I haven't been able to find anyone who has a windows machine and would be able to debug this. I managed to install pyccel on a very old Windows machine, but so far I haven't convinced it to run without getting stuck so I haven't been able to test myself. I can "fix" the problem with an `ifdef` macro but I am not sure that there wouldn't be a windows memory leak





Fix patch:
diff --git a/.dict_custom.txt b/.dict_custom.txt
index b25b47f277..f5b89328e5 100644
--- a/.dict_custom.txt
+++ b/.dict_custom.txt
@@ -3,6 +3,10 @@ Pythran
 numba
 NumPy
 NumPy's
+CuPy
+CuPy's
+SymPy
+SymPy's
 BLAS
 LAPACK
 MPI
diff --git a/.docstr.yaml b/.docstr.yaml
new file mode 100644
index 0000000000..f89d0b5e5d
--- /dev/null
+++ b/.docstr.yaml
@@ -0,0 +1,10 @@
+skip_magic: True
+skip_init: True
+fail_under: 0
+ignore_patterns:
+  "syntactic":
+    - "_visit_.*"
+  "semantic":
+    - "_visit_.*"
+  ".*code":
+    - "_print_.*"
diff --git a/.docstr_coverage b/.docstr_coverage
deleted file mode 100644
index 8007a6bb25..0000000000
--- a/.docstr_coverage
+++ /dev/null
@@ -1,3 +0,0 @@
-.*code _print_.*
-semantic _visit_.*
-syntactic _visit_.*
diff --git a/.github/actions/macos_install/action.yml b/.github/actions/macos_install/action.yml
index 212c79d24c..5f166c9f4d 100644
--- a/.github/actions/macos_install/action.yml
+++ b/.github/actions/macos_install/action.yml
@@ -7,9 +7,14 @@ runs:
       run: |
         brew install open-mpi
         brew install libomp
-        if [[ ! -f "/usr/local/bin/gfortran" ]]; then
-          gfort=$(ls /usr/local/bin/gfortran-* | tail -n 1)
-          ln -s ${gfort} /usr/local/bin/gfortran
+        GFORTRAN_HOME=$(which gfortran || true)
+        echo "GFORTRAN_HOME : $GFORTRAN_HOME"
+        if [[ ! -f "$GFORTRAN_HOME" ]]; then
+          gfort=$(find ${PATH//:/\/ } -name 'gfortran-*' -exec basename {} \; | sort | tail -n 1 || true)
+          echo "Found $gfort"
+          gfort_path=$(which ${gfort})
+          folder=$(dirname ${gfort_path})
+          ln -s ${gfort_path} ${folder}/gfortran
         fi
         echo "MPI_OPTS=--oversubscribe" >> $GITHUB_ENV
       shell: bash
diff --git a/.github/actions/windows_install/action.yml b/.github/actions/windows_install/action.yml
index d5a902a9c7..7d0b630de7 100644
--- a/.github/actions/windows_install/action.yml
+++ b/.github/actions/windows_install/action.yml
@@ -52,10 +52,8 @@ runs:
         curl https://github.com/microsoft/Microsoft-MPI/releases/download/v10.1.1/msmpisdk.msi -o msmpisdk.msi
         #
         # Install MS MPI
-        ./msmpisetup.exe -unattend -verbose
-        sleep 30
-        msiexec /quiet /i msmpisdk.msi
-        sleep 1
+        Start-Process msmpisetup.exe -Wait -ArgumentList '-unattend -verbose'
+        Start-Process msiexec -Wait -ArgumentList '/quiet /i msmpisdk.msi'
         echo "MS MPI runtime and SDK installed"
       shell: powershell
     - name: Setup MPI
diff --git a/.github/workflows/anaconda_linux.yml b/.github/workflows/anaconda_linux.yml
index c7e04a37da..f6b21e8391 100644
--- a/.github/workflows/anaconda_linux.yml
+++ b/.github/workflows/anaconda_linux.yml
@@ -16,7 +16,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -52,7 +52,7 @@ jobs:
     needs: Python_version_picker
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
@@ -68,6 +68,7 @@ jobs:
         with:
           mpi_type: openmpi
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           pip install jwt requests
@@ -107,7 +108,7 @@ jobs:
           path: .coverage
           retention-days: 1
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run:
           python ci_tools/complete_check_run.py ${{ steps.f_c_pytest.outcome }} ${{ steps.python_pytest.outcome }} ${{ steps.parallel.outcome }}
         shell: bash -l {0}
diff --git a/.github/workflows/anaconda_windows.yml b/.github/workflows/anaconda_windows.yml
index 70bf150b1a..e965f0b25b 100644
--- a/.github/workflows/anaconda_windows.yml
+++ b/.github/workflows/anaconda_windows.yml
@@ -16,7 +16,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -52,7 +52,7 @@ jobs:
     needs: Python_version_picker
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
@@ -68,6 +68,7 @@ jobs:
         with:
           mpi_type: msmpi
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           python -m pip install jwt requests
@@ -87,7 +88,7 @@ jobs:
         with:
           shell_cmd: 'bash -l -eo pipefail {0}'
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run: |
           which python
           python --version
diff --git a/.github/workflows/clean_up.yml b/.github/workflows/clean_up.yml
index 4093bc0bda..8828aeb9b1 100644
--- a/.github/workflows/clean_up.yml
+++ b/.github/workflows/clean_up.yml
@@ -10,7 +10,7 @@ jobs:
     name: Report result
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - name: Clean up
diff --git a/.github/workflows/comment_bot.yml b/.github/workflows/comment_bot.yml
index 3a2b65ef5b..9e33193464 100644
--- a/.github/workflows/comment_bot.yml
+++ b/.github/workflows/comment_bot.yml
@@ -9,14 +9,14 @@ jobs:
     if: ${{ startsWith( github.event.comment.body, '/bot ' ) }}
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - uses: ./.github/actions/add_remote
         with:
           pr_id: ${{ github.event.issue.number }}
       - name: Set up Python 3.9
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: 3.9
       - name: Install python dependencies
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index e7ae1652ce..a46a258d57 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -40,12 +40,12 @@ jobs:
     name: Unit tests
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ inputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ inputs.python_version }}
       - name: "Setup"
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000000..9111b47d52
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,69 @@
+name: Deploy new version to PyPi
+
+on:
+  workflow_run:
+    workflows: [Anaconda-Windows]
+    types:
+      - completed
+
+jobs:
+  waitForWorklows:
+    name: Wait for workflows
+    runs-on: ubuntu-latest
+    if: github.event.workflow_run.head_branch == 'main'
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: 3.9
+      - name: Install python dependencies
+        run: |
+          python -m pip install requests jwt
+      - name: Wait for workflows
+        run: |
+          python3 wait_for_main_workflows.py
+        working-directory: ./ci_tools
+        shell: bash
+        env:
+          COMMIT: ${{ github.event.workflow_run.head_sha }}
+
+  deployVersion:
+    runs-on: ubuntu-latest
+    needs: [waitForWorklows]
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+        with:
+          submodules: true
+      - name: Install dependencies
+        uses: ./.github/actions/linux_install
+      - name: Update build
+        run: |
+          python -m pip install --upgrade pip
+          python -m pip install --upgrade build
+          python -m pip install --upgrade twine
+      - name: Build and deploy
+        run: |
+          echo ${{ github.event.workflow_run.head_branch }}
+          python3 -m build
+          ls dist/*
+          python3 -m twine upload --repository pypi dist/* --non-interactive
+        shell: bash
+        env:
+          TWINE_USERNAME: '__token__'
+          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
+      - name: Install Pyccel without tests
+        run: |
+          python -m pip install .
+      - name: "Get tag name"
+        id: tag_name
+        run: |
+          version=$(python -c "from pyccel import __version__; print(__version__)")
+          echo "TAG_NAME=v${version}" >> $GITHUB_OUTPUT
+      - name: "Update repo tags"
+        uses: EndBug/latest-tag@latest
+        with:
+          ref: ${{ steps.tag_name.outputs.TAG_NAME }}
+
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index efccbe8152..32fcf1493e 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -34,18 +34,18 @@ jobs:
     name: Documentation Format
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ inputs.base }}
           path: base
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           path: compare
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
           fetch-depth: 0
       - name: Set up Python ${{ inputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ inputs.python_version }}
       - name: "Setup check run"
@@ -74,9 +74,8 @@ jobs:
       - name: Check doc coverage
         id: doc_coverage
         run: |
-          echo "${{ github.event.pull_request.base.sha }}"
-          docstr-coverage --skip-magic --skip-init --fail-under=0 --docstr-ignore-file=base/.docstr_coverage base/pyccel base/ci_tools 2>&1 | tee base_cov
-          docstr-coverage --skip-magic --skip-init --fail-under=0 --docstr-ignore-file=compare/.docstr_coverage compare/pyccel compare/ci_tools 2>&1 | tee compare_cov
+          docstr-coverage --config=base/.docstr.yaml base/pyccel base/ci_tools 2>&1 | tee base_cov
+          docstr-coverage --config=compare/.docstr.yaml compare/pyccel compare/ci_tools 2>&1 | tee compare_cov
           export PYTHONPATH=compare
           python compare/ci_tools/summarise_doccoverage.py compare_cov base_cov $GITHUB_STEP_SUMMARY
         shell: bash
diff --git a/.github/workflows/intel.yml b/.github/workflows/intel.yml
index d45beb3d8b..8ba9599246 100644
--- a/.github/workflows/intel.yml
+++ b/.github/workflows/intel.yml
@@ -16,7 +16,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -54,15 +54,16 @@ jobs:
     needs: Python_version_picker
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ needs.Python_version_picker.outputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ needs.Python_version_picker.outputs.python_version }}
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           pip install jwt requests
@@ -101,6 +102,6 @@ jobs:
           path: .coverage
           retention-days: 1
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run:
           python ci_tools/complete_check_run.py ${{ steps.f_c_pytest.outcome }} ${{ steps.python_pytest.outcome }} ${{ steps.parallel.outcome }} ${{ steps.valgrind.outcome }}
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 29239db9b6..bd2d42c699 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -16,7 +16,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -57,15 +57,16 @@ jobs:
       matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}}
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ matrix.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python_version }}
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           pip install jwt requests
@@ -104,6 +105,6 @@ jobs:
           path: .coverage
           retention-days: 1
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run:
           python ci_tools/complete_check_run.py ${{ steps.f_c_pytest.outcome }} ${{ steps.python_pytest.outcome }} ${{ steps.parallel.outcome }} ${{ steps.valgrind.outcome }}
diff --git a/.github/workflows/macosx.yml b/.github/workflows/macosx.yml
index 1d4d4fd562..43731d469a 100644
--- a/.github/workflows/macosx.yml
+++ b/.github/workflows/macosx.yml
@@ -16,7 +16,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -53,15 +53,16 @@ jobs:
     needs: Python_version_picker
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ needs.Python_version_picker.outputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ needs.Python_version_picker.outputs.python_version }}
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           pip install jwt requests
@@ -86,6 +87,6 @@ jobs:
         timeout-minutes: 20
         uses: ./.github/actions/pytest_parallel
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run:
           python ci_tools/complete_check_run.py ${{ steps.f_c_pytest.outcome }} ${{ steps.python_pytest.outcome }} ${{ steps.parallel.outcome }}
diff --git a/.github/workflows/pickle.yml b/.github/workflows/pickle.yml
index b20fe1a93f..1c940dfbe9 100644
--- a/.github/workflows/pickle.yml
+++ b/.github/workflows/pickle.yml
@@ -19,7 +19,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -62,15 +62,16 @@ jobs:
       matrix: ${{fromJson(needs.Python_version_picker.outputs.matrix)}}
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ needs.Python_version_picker.outputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ needs.Python_version_picker.outputs.python_version }}
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           pip install jwt requests
@@ -88,7 +89,7 @@ jobs:
         id: pickle_check
         uses: ./.github/actions/check_for_pickled
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run: |
           python ci_tools/basic_json_check_output.py --statuses ${{ steps.pickle.outcome }} ${{ steps.pickle_check.outcome }} --reasons "Installation failed." "Pickled files were not found in installaion."
           python ci_tools/complete_check_run.py ${{ steps.pickle.outcome }} ${{ steps.pickle_check.outcome }}
diff --git a/.github/workflows/pickle_wheel.yml b/.github/workflows/pickle_wheel.yml
index ce530a238f..d5b7c14192 100644
--- a/.github/workflows/pickle_wheel.yml
+++ b/.github/workflows/pickle_wheel.yml
@@ -16,7 +16,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -52,15 +52,16 @@ jobs:
     needs: Python_version_picker
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ needs.Python_version_picker.outputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ needs.Python_version_picker.outputs.python_version }}
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           pip install jwt requests
@@ -79,7 +80,7 @@ jobs:
         id: pickle_check
         uses: ./.github/actions/check_for_pickled
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run: |
           python ci_tools/basic_json_check_output.py --statuses ${{ steps.pickle.outcome }} ${{ steps.pickle_check.outcome }} --reasons "Installation failed." "Pickled files were not found in installaion."
           python ci_tools/complete_check_run.py ${{ steps.pickle.outcome }} ${{ steps.pickle_check.outcome }}
diff --git a/.github/workflows/prepare_review_stage.yml b/.github/workflows/prepare_review_stage.yml
index 7eac2d1956..298b934bea 100644
--- a/.github/workflows/prepare_review_stage.yml
+++ b/.github/workflows/prepare_review_stage.yml
@@ -10,14 +10,14 @@ jobs:
     name: Preparing Pull Request for review stage
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - uses: ./.github/actions/add_remote
         with:
           pr_id: ${{ github.event.number }}
       - name: Set up Python 3.9
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: 3.9
       - name: Install python dependencies
diff --git a/.github/workflows/pyccel_lint.yml b/.github/workflows/pyccel_lint.yml
index c36bbf929f..7e5df21268 100644
--- a/.github/workflows/pyccel_lint.yml
+++ b/.github/workflows/pyccel_lint.yml
@@ -32,13 +32,13 @@ jobs:
     name: Best practices
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
           fetch-depth: 0
       - name: Set up Python ${{ inputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ inputs.python_version }}
       - name: "Setup"
diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml
index df4e2b42ac..d034b1144b 100644
--- a/.github/workflows/pylint.yml
+++ b/.github/workflows/pylint.yml
@@ -32,13 +32,13 @@ jobs:
     name: Python best practices
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
           fetch-depth: 0
       - name: Set up Python ${{ inputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ inputs.python_version }}
       - name: "Setup"
diff --git a/.github/workflows/review_bot.yml b/.github/workflows/review_bot.yml
index d212234235..00fb2d8bb8 100644
--- a/.github/workflows/review_bot.yml
+++ b/.github/workflows/review_bot.yml
@@ -10,9 +10,9 @@ jobs:
     if: ((! github.event.pull_request.draft) && (github.event.review.user.type != 'Bot' ))
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up Python ${{ inputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: 3.9
       - name: Install python dependencies
diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml
index c24c2cd13a..5a308ed05a 100644
--- a/.github/workflows/spelling.yml
+++ b/.github/workflows/spelling.yml
@@ -29,12 +29,12 @@ jobs:
     name: Documentation spellcheck
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ inputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ inputs.python_version }}
       - name: "Setup"
diff --git a/.github/workflows/welcome.yml b/.github/workflows/welcome.yml
index 69aac1a6b8..7ac944d579 100644
--- a/.github/workflows/welcome.yml
+++ b/.github/workflows/welcome.yml
@@ -9,9 +9,9 @@ jobs:
     name: Thanks for the Pull Request!
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up Python 3.9
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: 3.9
       - name: Install python dependencies
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 03cecaab64..93d595694d 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -16,7 +16,7 @@ on:
         required: false
         type: string
   push:
-    branches: devel
+    branches: [devel, main]
 
 env:
   COMMIT: ${{ inputs.ref || github.event.ref }}
@@ -53,15 +53,16 @@ jobs:
     needs: Python_version_picker
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           ref: ${{ env.COMMIT }}
           repository: ${{ env.PR_REPO }}
       - name: Set up Python ${{ needs.Python_version_picker.outputs.python_version }}
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ needs.Python_version_picker.outputs.python_version }}
       - name: "Setup"
+        if: github.event_name != 'push'
         id: token
         run: |
           pip install jwt requests
@@ -89,6 +90,6 @@ jobs:
         timeout-minutes: 20
         uses: ./.github/actions/pytest_parallel
       - name: "Post completed"
-        if: always()
+        if: always() && github.event_name != 'push'
         run:
           python ci_tools/complete_check_run.py ${{ steps.f_c_pytest.outcome }} ${{ steps.python_pytest.outcome }} ${{ steps.parallel.outcome }}
diff --git a/AUTHORS b/AUTHORS
index 8416d06035..6c30ce5830 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -30,3 +30,4 @@ Contributors
 * Priyabrata Mondal
 * Farouk Ech-Charef
 * Mustapha Belbiad
+* Varadarajan Rengaraj
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 322d037c61..a2168bbd74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,16 +1,39 @@
 # Change Log
 All notable changes to this project will be documented in this file.
 
-## \[UNRELEASED\]
+## \[1.12.0\] - 2024-05-08
 
 ### Added
 
+-   #1830 : Add a `pyccel.lambdify` function to accelerate SymPy expressions.
+-   #1867 : Add a `use_out` parameter to `pyccel.lambdify` to avoid unnecessary memory allocation.
+-   #1867 : Auto-generate a docstring for functions generated via calls to `pyccel.lambdify`.
+-   #1868 : Hide traceback for `epyccel` and `lambdify` errors.
+
 ### Fixed
 
+-   #1762 : Fix array copy between different data types.
+-   #1792 : Fix array unpacking.
+-   #1795 : Fix bug when returning slices in C.
+-   #1218 : Fix bug when assigning an array to a slice in Fortran.
+-   #1830 : Fix missing allocation when returning an annotated array expression.
+-   #1853 : Fix translation of a file whose name conflicts with Fortran keywords.
+-   Link and mention `devel` branch, not `master`.
+
 ### Changed
 
+-   #1866 : Raise a more informative error when mixing scalar and array return types.
+-   \[TESTS\] Filter out cast warnings in cast tests.
+-   \[INTERNALS\] Removed unused `fcode`, `ccode`, `cwrappercode`, `luacode`, and `pycode` functions from printers.
+-   \[INTERNALS\] Removed unused arguments from methods in `pyccel.codegen.codegen.Codegen`.
+
 ### Deprecated
 
+-   #1820 : Deprecated unused decorator `@lambdify`
+-   \[INTERNALS\] Removed unused and undocumented function `get_function_from_ast`.
+-   \[INTERNALS\] Remove function `Module.set_name`.
+-   \[INTERNALS\] Remove unused `assign_to` argument of `CodePrinter.doprint`.
+
 ## \[1.11.2\] - 2024-03-05
 
 ### Added
diff --git a/ci_tools/bot_messages/welcome_newcomer.txt b/ci_tools/bot_messages/welcome_newcomer.txt
index ed8832c69b..e5dad51771 100644
--- a/ci_tools/bot_messages/welcome_newcomer.txt
+++ b/ci_tools/bot_messages/welcome_newcomer.txt
@@ -1,7 +1,7 @@
 Hello! Welcome to Pyccel! Thank you very much for your contribution :heart:.
 
-I am the GitHub bot. I will help guide you through the different stages necessary to validate a review in Pyccel. If you haven't yet seen our developer docs make sure you check them out [here](https://github.com/pyccel/pyccel/tree/master/developer_docs). Amongst other things they describe the [review process](https://github.com/pyccel/pyccel/blob/master/developer_docs/review_process.md) that we have just started. You can also get in touch with our other developers on our [Pyccel Discord Server](https://discord.gg/2Q6hwjfFVb).
+I am the GitHub bot. I will help guide you through the different stages necessary to validate a review in Pyccel. If you haven't yet seen our developer docs make sure you check them out [here](https://github.com/pyccel/pyccel/tree/devel/developer_docs). Amongst other things they describe the [review process](https://github.com/pyccel/pyccel/blob/devel/developer_docs/review_process.md) that we have just started. You can also get in touch with our other developers on our [Pyccel Discord Server](https://discord.gg/2Q6hwjfFVb).
 
 To begin with I will give you a short checklist to make sure your pull request is complete. Please tick items off when you have completed them or determined that they are not necessary for this pull request. If you want me to run any specific tests to check out corner cases that you can't easily check on your computer, you can request this using the command `/bot run X`. Use the command `/bot show tests` to see a full list of the tests I can run. Once you have finished preparing your pull request and are ready to request reviews just take your PR out of draft, or let me know with the command `/bot mark as ready`. I will then run the full suite of tests to check that everything is as neat as you think before asking other contributors for reviews. Tests will not run automatically before this point to avoid wasting resources. You can get a full list of commands that I understand using `/bot commands`.
 
-Please begin by requesting your checklist using the command `/bot checklist`
+Please begin by requesting your checklist using the command `/bot checklist`.
diff --git a/ci_tools/bot_tools/github_api_interactions.py b/ci_tools/bot_tools/github_api_interactions.py
index 47129d2ef4..b8ca4cd9de 100644
--- a/ci_tools/bot_tools/github_api_interactions.py
+++ b/ci_tools/bot_tools/github_api_interactions.py
@@ -69,11 +69,15 @@ def __init__(self):
         repo = os.environ["GITHUB_REPOSITORY"]
         self._org, self._repo = repo.split('/')
         if "installation_token" in os.environ:
+            self._authenticated = True
             self._install_token = os.environ["installation_token"]
             self._install_token_exp = time.strptime(os.environ["installation_token_exp"], "%Y-%m-%dT%H:%M:%SZ")
-        else:
+        elif "PEM" in os.environ:
+            self._authenticated = True
             self._install_token, expiry = get_authorization()
             self._install_token_exp = time.strptime(expiry, "%Y-%m-%dT%H:%M:%SZ")
+        else:
+            self._authenticated = False
 
     def _post_request(self, method, url, json=None, **kwargs):
         """
@@ -168,6 +172,7 @@ def create_run(self, commit, name):
         AssertionError
             An assertion error is raised if the check run was not successfully posted.
         """
+        assert self._authenticated
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/check-runs"
         workflow_url = f"https://github.com/{self._org}/{self._repo}/actions/runs/{os.environ['GITHUB_RUN_ID']}"
         print("create_run:", url)
@@ -204,6 +209,7 @@ def prepare_run(self, commit, name):
         AssertionError
             An assertion error is raised if the check run was not successfully posted.
         """
+        assert self._authenticated
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/check-runs"
         json = {"name": name,
                 "head_sha": commit,
@@ -238,6 +244,7 @@ def update_run(self, run_id, json):
         AssertionError
             An assertion error is raised if the check run was not successfully updated.
         """
+        assert self._authenticated
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/check-runs/{run_id}"
         run = self._post_request("PATCH", url, json)
         print(run.text)
@@ -266,6 +273,7 @@ def rerequest_run(self, run_id):
         AssertionError
             An assertion error is raised if the check run was not successfully rerequested.
         """
+        assert self._authenticated
         print("Rerequesting : ", run_id)
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/check-runs/{run_id}/rerequest"
         run = self._post_request("POST", url)
@@ -303,6 +311,7 @@ def create_run_from_old(self, commit, name, old_check_run):
         AssertionError
             An assertion error is raised if the check run was not successfully posted.
         """
+        assert self._authenticated
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/check-runs"
         print("create_run:", url)
         json = {"name": name,
@@ -356,6 +365,7 @@ def run_workflow(self, filename, inputs):
         AssertionError
             An assertion error is raised if the workflow was not successfully started.
         """
+        assert self._authenticated
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/actions/workflows/{filename}/dispatches"
         json = {"ref": "devel",
                 "inputs": inputs}
@@ -445,6 +455,7 @@ def create_comment(self, pr_id, comment, reply_to = None):
         requests.Response
             The response collected from the request.
         """
+        assert self._authenticated
         if reply_to:
             suffix = f"/{reply_to}/replies"
             issue_type = 'pulls'
@@ -473,6 +484,7 @@ def modify_comment(self, comment_url, new_body):
         requests.Response
             The response collected from the request.
         """
+        assert self._authenticated
         return self._post_request("PATCH", comment_url, json={"body":new_body})
 
     def create_review(self, pr_id, commit, comment, status, comments = ()):
@@ -510,6 +522,7 @@ def create_review(self, pr_id, commit, comment, status, comments = ()):
         AssertionError
             An assertion error is raised if the review was not successfully posted.
         """
+        assert self._authenticated
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/pulls/{pr_id}/reviews"
         review = {'commit_id':commit, 'body': comment, 'event': status, 'comments': comments}
         print(review)
@@ -539,6 +552,7 @@ def check_for_user_in_team(self, user, team):
         dict
             A dictionary describing the result.
         """
+        assert self._authenticated
         url = f'https://api.github.com/orgs/{self._org}/teams/{team}/memberships/{user}'
         return self._post_request("GET", url).json()
 
@@ -789,6 +803,7 @@ def request_reviewers(self, pr_id, request_team = False, reviewers = ()):
         reviewers : iterable
             A list of individual reviewers to be requested.
         """
+        assert self._authenticated
         assert request_team or reviewers
         url = f"https://api.github.com/repos/{self._org}/{self._repo}/pulls/{pr_id}/requested_reviewers"
         review_requests = {}
@@ -799,6 +814,67 @@ def request_reviewers(self, pr_id, request_team = False, reviewers = ()):
 
         self._post_request("POST", url, review_requests)
 
+    def wait_for_runs(self, commit_sha, run_names, max_time=15*60, wait_time=15):
+        """
+        Wait for the specified workflow runs associated with the commit.
+
+        Use the API to find workflow runs associated with a commit as described here:
+        https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository
+
+        If the workflows are not finished then wait before trying again. Keep trying until the
+        timeout is reached.
+
+        Parameters
+        ----------
+        commit_sha : str
+            The SHA of the commit for which the workflows are run.
+
+        run_names : tuple[str,...]
+            The names of the workflows which should finish before this method terminates.
+
+        max_time : int, default=15*60
+            The maximum number of seconds which should be spent in this method.
+
+        wait_time : int, default=15
+            The time in seconds that the method should wait for before rechecking the workflow
+            results.
+
+        Returns
+        -------
+        bool
+            True if all workflows succeeded, False otherwise.
+        """
+        url = f"https://api.github.com/repos/{self._org}/{self._repo}/actions/runs"
+        completed = False
+        # Run for 15 mins maximum
+        timeout = time.time() + max_time
+
+        request_result = self._post_request("GET", url, params={'head_sha': commit_sha}).json()
+        workflow_runs = [j for j in request_result['workflow_runs'] if j['name'] in run_names]
+        completed = all(j['status'] == 'completed' for j in workflow_runs)
+
+        print(commit_sha)
+        print(workflow_runs)
+        print([j['name'] for j in workflow_runs])
+        print([j['status'] for j in workflow_runs])
+        print([j['conclusion'] for j in workflow_runs])
+
+        while not completed and time.time() < timeout:
+            time.sleep(15)
+            request_result = self._post_request("GET", url, params={'head_sha': commit_sha}).json()
+            workflow_runs = [j for j in request_result['workflow_runs'] if j['name'] in run_names]
+            completed = all(j['status'] == 'completed' for j in workflow_runs)
+            print(workflow_runs)
+            print([j['name'] for j in workflow_runs])
+            print([j['status'] for j in workflow_runs])
+            print([j['conclusion'] for j in workflow_runs])
+
+        assert completed
+
+        success = all(j['conclusion'] == 'success' for j in workflow_runs)
+
+        return success
+
     def get_headers(self):
         """
         Get the header which is always passed to the API.
@@ -812,10 +888,14 @@ def get_headers(self):
         dict
             The header which should be used in requests.
         """
-        if self._install_token_exp < time.struct_time(time.gmtime()):
-            self._install_token, expiry = get_authorization()
-            self._install_token_exp = time.strptime(expiry, "%Y-%m-%dT%H:%M:%SZ")
+        if self._authenticated:
+            if self._install_token_exp < time.struct_time(time.gmtime()):
+                self._install_token, expiry = get_authorization()
+                self._install_token_exp = time.strptime(expiry, "%Y-%m-%dT%H:%M:%SZ")
 
-        return {"Accept": "application/vnd.github+json",
-                 "Authorization": f"Bearer {self._install_token}",
-                 "X-GitHub-Api-Version": "2022-11-28"}
+            return {"Accept": "application/vnd.github+json",
+                     "Authorization": f"Bearer {self._install_token}",
+                     "X-GitHub-Api-Version": "2022-11-28"}
+        else:
+            return {"Accept": "application/vnd.github+json",
+                     "X-GitHub-Api-Version": "2022-11-28"}
diff --git a/ci_tools/wait_for_main_workflows.py b/ci_tools/wait_for_main_workflows.py
new file mode 100644
index 0000000000..c12a8a9a09
--- /dev/null
+++ b/ci_tools/wait_for_main_workflows.py
@@ -0,0 +1,13 @@
+""" Module which waits for the workflows triggered on the main branch to finish and asserts
+that they pass. This is must succeed before the code can be deployed to PyPi.
+"""
+import os
+from bot_tools.github_api_interactions import GitHubAPIInteractions
+
+if __name__ == '__main__':
+    GAI = GitHubAPIInteractions()
+    required_workflows = ('Anaconda-Linux', 'Anaconda-Windows', 'Intel unit tests',
+                          'Linux unit tests', 'MacOSX unit tests', 'Windows unit tests',
+                          'Pickled-installation', 'Wheel-pickled-installation')
+    assert GAI.wait_for_runs(os.environ['COMMIT'], required_workflows)
+
diff --git a/developer_docs/codegen_stage.md b/developer_docs/codegen_stage.md
index f42d291e7c..faabb62052 100644
--- a/developer_docs/codegen_stage.md
+++ b/developer_docs/codegen_stage.md
@@ -20,8 +20,8 @@ def _print_ClassName(self, stmt):
     return Y
 ```
 where `Y` must be a string.
-Each of these `_print_X` functions should internally call the `_print` function on each of the elements of the object to obtain strings which can be combined to create a string describing the current object in the target language.
-It can be tempting to skip some of these `_print` calls, especially for basic types such as literals.
+Each of these `_print_X` functions should internally call the `_print` function on each of the `PyccelAstNode` elements of the object to obtain strings which can be combined to create a string describing the current object in the target language.
+It can be tempting to skip some of these `_print` calls, especially for basic types such as `Literal`s.
 However it is very important to use these functions as much as possible, for several reasons:
 1.  It ensures that the same conventions are used throughout the generated code
 2.  It ensures that code details are not forgotten
diff --git a/developer_docs/how_to_solve_an_issue.md b/developer_docs/how_to_solve_an_issue.md
index 8c6771cec1..2ad3c0ed24 100644
--- a/developer_docs/how_to_solve_an_issue.md
+++ b/developer_docs/how_to_solve_an_issue.md
@@ -15,6 +15,6 @@ To add a new function:
 ## Language Specific Bug Fixes
 
 -   Use the issue description to reproduce the bug
--   Add a test targeting this specific problem (which fails in the master branch but will pass after your fix)
+-   Add a test targeting this specific problem (which fails in the `devel` branch but will pass after your fix)
 -   By comparing the original Python code and the generated code, try to locate the problematic line and therefore the print function in the corresponding code generation file
 -   Try to fix the problem
diff --git a/developer_docs/review_process.md b/developer_docs/review_process.md
index adc4357f19..86e0257df0 100644
--- a/developer_docs/review_process.md
+++ b/developer_docs/review_process.md
@@ -1,8 +1,8 @@
 # Review Process
 
-The review process is the process through which a branch which solves an issue is merged into the master branch.
+The review process is the process through which a branch which solves an issue is merged into the `devel` branch.
 
-When you believe your branch is ready to merge you should create a pull request. Be sure to add a description which allows other developers to understand what your changes aim to do. You may also want to include a commit summary as the pull request description forms the basis of the commit message shown on the master branch. In addition you should make sure that your pull request links to the issue that it is solving so that issue is automatically closed when the pull request is merged.
+When you believe your branch is ready to merge you should create a pull request. Be sure to add a description which allows other developers to understand what your changes aim to do. You may also want to include a commit summary as the pull request description forms the basis of the commit message shown on the `devel` branch. In addition you should make sure that your pull request links to the issue that it is solving so that issue is automatically closed when the pull request is merged.
 
 Once the pull request is opened 9 tests should be triggered they are: 
 
@@ -52,4 +52,4 @@ Once the senior developer is happy with the branch they should accept the pull r
 
 Once the code has been accepted by both a junior and a senior developer it should be ready to merge. This flag therefore indicates that one of our developers with merge permissions can review the code. They will look for anything missed by the previous two reviews.
 
-Anyone can make silly mistakes so Pyccel aims to have all pull requests be reviewed by at least 2 developers before being merged to master.
+Anyone can make silly mistakes so Pyccel aims to have all pull requests be reviewed by at least 2 developers before being merged to `devel`.
diff --git a/developer_docs/wrapper_stage.md b/developer_docs/wrapper_stage.md
index 204e2aa7a2..8cc3e09ae8 100644
--- a/developer_docs/wrapper_stage.md
+++ b/developer_docs/wrapper_stage.md
@@ -20,7 +20,7 @@ The entry point for the class `Wrapper` is the function `wrap`.
 The `_wrap` function internally calls a function named `_wrap_X`, where `X` is the type of the object.
 These functions must have the form:
 ```python
-def _print_ClassName(self, stmt):
+def _wrap_ClassName(self, stmt):
     ...
     return Y
 ```
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 745eaea529..33020b43f2 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -38,14 +38,14 @@ Please open a pull request to add or change anything in the docs.
 
 ## Reviewing a pull request
 
-There are many pull requests and reviewing them is a great way to help things get to the master branch faster.
+There are many pull requests and reviewing them is a great way to help things get to the `devel` branch faster.
 This is also a really good way to get to grips with the code base as you will see examples of many different areas of the code.
 It's incredibly helpful to have pull requests go through as many reviews as possible, to make sure the code change makes sense, is documented, and is efficient and clear.
 As the clarity is subjective, more eyes can only improve the code base.
-The review process is described in the [developer docs](https://github.com/pyccel/pyccel/blob/master/developer_docs/review_process.md), keep an eye out for pull requests tagged `needs_initial_review`.
+The review process is described in the [developer docs](https://github.com/pyccel/pyccel/blob/devel/developer_docs/review_process.md), keep an eye out for pull requests tagged `needs_initial_review`.
 
 ## Contributing code
 
-Before contributing we strongly recommend you check out the [developer docs](https://github.com/pyccel/pyccel/tree/master/developer_docs).
+Before contributing we strongly recommend you check out the [developer docs](https://github.com/pyccel/pyccel/tree/devel/developer_docs).
 We try to flag `good-first-issue`s.
-These are either issues which can be fixed by following the example provided by a similar solution which is already implemented, or issues which only concern one of the Pyccel [stages](https://github.com/pyccel/pyccel/blob/master/developer_docs/overview.md).
+These are either issues which can be fixed by following the example provided by a similar solution which is already implemented, or issues which only concern one of the Pyccel [stages](https://github.com/pyccel/pyccel/blob/devel/developer_docs/overview.md).
diff --git a/docs/function-pointers-as-arguments.md b/docs/function-pointers-as-arguments.md
index b96d6d47dd..47e1208af2 100644
--- a/docs/function-pointers-as-arguments.md
+++ b/docs/function-pointers-as-arguments.md
@@ -1,6 +1,6 @@
 # Function-pointers as arguments
 
-Note: before reading this you should have read [Installation and Command Line Usage](https://github.com/pyccel/pyccel/blob/master/tutorial/quickstart.md#installation)
+Note: before reading this you should have read [Installation and Command Line Usage](https://github.com/pyccel/pyccel/blob/devel/docs/quickstart.md#installation)
 
 In order to support passing [function-pointers](https://en.wikipedia.org/wiki/Function_pointer) as arguments, Pyccel needs the user to define the type of the passed function-pointers. This can be done by using the syntax `def function_name(func1_name : '(func1_return_type)(func1_arguments_types)', func2_name : '(func2_return_type)(func2_arguments_types)', ..., arg1, arg2, ...)` or using a function-header `#$ header function function_name((func1_return_type)(func1_arguments), (func2_return_type)(func2_arguments), ..., var1_type, var2_type, ...)`. Here is how Pyccel converts that feature:
 
@@ -425,7 +425,7 @@ end program prog_prog_boo
 
 If you face problems with Pyccel, please take the following steps:
 
-1.  Consult our documentation in the tutorial directory;
+1.  Consult our documentation in the  [`docs/`](https://github.com/pyccel/pyccel/blob/devel/docs) directory;
 2.  Send an email message to pyccel@googlegroups.com;
 3.  Open an issue on GitHub.
 
diff --git a/docs/installation.md b/docs/installation.md
index 47236583e0..77d6d55e1c 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -242,7 +242,7 @@ Most of the unit tests can also be run in parallel.
 
 To test your Pyccel installation please run the script `tests/run\_tests\_py3.sh` (Unix), or `tests/run\_tests.bat` (Windows).
 
-Continuous testing runs on GitHub actions: <https://github.com/pyccel/pyccel/actions?query=branch%3Amaster>
+Continuous testing runs on GitHub actions: <https://github.com/pyccel/pyccel/actions?query=branch%3Adevel>
 
 ## Pyccel Container Images
 
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 0a283991cb..753d2b6e3f 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -124,8 +124,8 @@ Such type annotations are compatible with mypy and as such are recommended for u
 ### Installation
 
 Pyccel's official releases can be downloaded from PyPI (the Python Package Index) using `pip`.
-To get the latest (trunk) version of Pyccel, one can clone the `git` repository from GitHub and checkout the `master` branch.
-Detailed installation instructions are found in the [README](https://github.com/pyccel/pyccel/blob/master/README.rst) file.
+To get the latest (trunk) version of Pyccel, one can clone the `git` repository from GitHub and checkout the `devel` branch.
+Detailed installation instructions are found in the [README](https://github.com/pyccel/pyccel/blob/devel/README.md) file.
 
 ### Command Line Usage
 
@@ -453,9 +453,54 @@ Out[9]: 210.99245283018868
 ```
 After subtracting the amount of time required to create an array copy from the given times, we can conclude that the pyccelised function is approximately 210 times faster than the original Python function.
 
+### Interactive Usage with `lambdify`
+
+While Pyccel is usually used to accelerate Python code, it is also possible to accelerate other expressions. The Pyccel library provides the `lambdify` Python function. This function is similar to SymPy's [`lambdify`](https://docs.sympy.org/latest/modules/utilities/lambdify.html) function, given a SymPy expression `f` and type annotations, `lambdify` returns a "pyccelised" function `f_fast` that can be used in the same Python session.
+For example:
+```python
+import numpy as np
+import sympy as sp
+from pyccel import lambdify
+
+x = sp.Symbol('x')
+expr = x**2 + x*5
+f = lambdify(expr, {x : 'float'})
+print(f(3.0))
+
+expr2 = x-x
+f2 = lambdify(expr, {x : 'float'}, result_type = 'float')
+print(f2(3.0))
+
+expr = x**2 + x*5 + 4.5
+f3 = lambdify(expr, {x : 'T'}, templates = {'T': ['float[:]', 'float[:,:]']})
+x_1d = np.ones(4)
+x_2d = np.ones((4,2))
+print(f3(x_1d))
+print(f3(x_2d))
+```
+In practice `lambdify` uses SymPy's `NumPyPrinter` to generate code which is passed to the `epyccel` function. The `epyccel` function copies the code into a temporary Python file in the `__epyccel__` directory.
+Once the file has been copied, `epyccel` calls the `pyccel` command to generate a Python C extension module that contains a single pyccelised function.
+Then finally, it imports this function and returns it to the caller.
+
+In order to make functions even faster it may be desirable to avoid unnecessary allocations inside the function. This functionality is similar to using an `out` argument in NumPy. Pyccel makes this functionality possible through the use of the `use_out` argument.
+For example:
+```python
+import numpy as np
+import sympy as sp
+from pyccel import lambdify
+
+x = sp.Symbol('x')
+expr = x**2 + x*5
+f = lambdify(expr, {x : 'float[:,:]'}, result_type = 'float[:,:]')
+x_2d = np.ones((4,2))
+y_2d = np.empty_like(x_2d)
+f(x_2d, y_2d)
+print(y_2d)
+```
+
 ## Other Features
 
-Pyccel's generated code can use parallel multi-threading through [OpenMP](https://en.wikipedia.org/wiki/OpenMP); please read [our documentation](https://github.com/pyccel/pyccel/blob/master/tutorial/openmp.md) for more details.
+Pyccel's generated code can use parallel multi-threading through [OpenMP](https://en.wikipedia.org/wiki/OpenMP); please read [our documentation](https://github.com/pyccel/pyccel/blob/devel/docs/openmp.md) for more details.
 
 We are also working on supporting [MPI](https://en.wikipedia.org/wiki/Open_MPI), [LAPACK](https://en.wikipedia.org/wiki/LAPACK)/[BLAS](https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms), and [OpenACC](https://en.wikipedia.org/wiki/OpenACC).
 
@@ -470,7 +515,7 @@ This tool removes all folders whose name begins with `__pyccel__` or `__epyccel_
 
 If you face problems with Pyccel, please take the following steps:
 
-1.  Consult our documentation in the tutorial directory;
+1.  Consult our documentation in the  [`docs/`](https://github.com/pyccel/pyccel/blob/devel/docs) directory;
 2.  Send an email message to pyccel@googlegroups.com;
 3.  Open an issue on GitHub.
 
diff --git a/pyccel/__init__.py b/pyccel/__init__.py
index 58f3ace6c0..ecc56a0380 100644
--- a/pyccel/__init__.py
+++ b/pyccel/__init__.py
@@ -1,1 +1,2 @@
 from .version import __version__
+from .commands.lambdify import lambdify
diff --git a/pyccel/ast/basic.py b/pyccel/ast/basic.py
index fa38daac39..d138ef1d7f 100644
--- a/pyccel/ast/basic.py
+++ b/pyccel/ast/basic.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/ast/bind_c.py b/pyccel/ast/bind_c.py
index 2678a2d8cb..17d1ed5678 100644
--- a/pyccel/ast/bind_c.py
+++ b/pyccel/ast/bind_c.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module describing all elements of the AST needed to represent elements which appear in a Fortran-C binding
diff --git a/pyccel/ast/bitwise_operators.py b/pyccel/ast/bitwise_operators.py
index 2a867f9340..b182533854 100644
--- a/pyccel/ast/bitwise_operators.py
+++ b/pyccel/ast/bitwise_operators.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module handling all Python builtin operators
diff --git a/pyccel/ast/builtin_methods/list_methods.py b/pyccel/ast/builtin_methods/list_methods.py
index 43f07e8420..59f15b3173 100644
--- a/pyccel/ast/builtin_methods/list_methods.py
+++ b/pyccel/ast/builtin_methods/list_methods.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 The List container has a number of built-in methods that are 
diff --git a/pyccel/ast/builtin_methods/set_methods.py b/pyccel/ast/builtin_methods/set_methods.py
index b5b3a07665..e38757a59c 100644
--- a/pyccel/ast/builtin_methods/set_methods.py
+++ b/pyccel/ast/builtin_methods/set_methods.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 The Set container has a number of built-in methods that are 
diff --git a/pyccel/ast/builtins.py b/pyccel/ast/builtins.py
index 2dc1fc0ff5..cc9d4a7c96 100644
--- a/pyccel/ast/builtins.py
+++ b/pyccel/ast/builtins.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 The Python interpreter has a number of built-in functions and types that are
diff --git a/pyccel/ast/c_concepts.py b/pyccel/ast/c_concepts.py
index 3e78e805d4..4006f777ba 100644
--- a/pyccel/ast/c_concepts.py
+++ b/pyccel/ast/c_concepts.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/ast/class_defs.py b/pyccel/ast/class_defs.py
index 250d461870..bb22ee4b00 100644
--- a/pyccel/ast/class_defs.py
+++ b/pyccel/ast/class_defs.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 This module contains all types which define a python class which is automatically recognised by pyccel
diff --git a/pyccel/ast/cmathext.py b/pyccel/ast/cmathext.py
index 1d7585f656..f6e0027937 100644
--- a/pyccel/ast/cmathext.py
+++ b/pyccel/ast/cmathext.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing objects from the cmath module understood by pyccel
 """
diff --git a/pyccel/ast/core.py b/pyccel/ast/core.py
index a752bc7180..b78e732a1d 100644
--- a/pyccel/ast/core.py
+++ b/pyccel/ast/core.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 from itertools import chain
 
@@ -10,7 +10,6 @@
 from pyccel.errors.messages   import RECURSIVE_RESULTS_REQUIRED
 
 from pyccel.utilities.stage   import PyccelStage
-from pyccel.utilities.strings import create_incremented_string
 
 from .basic     import PyccelAstNode, TypedAstNode, iterable, ScopedAstNode
 from .builtins  import (PythonEnumerate, PythonLen, PythonMap, PythonTuple,
@@ -107,9 +106,18 @@
 
 
 class AsName(PyccelAstNode):
-
     """
-    Represents a renaming of a variable, used with Import.
+    Represents a renaming of an object, used with Import.
+
+    A class representing the renaming of an object such as a function or a
+    variable. This usually occurs during an Import.
+
+    Parameters
+    ----------
+    obj : PyccelAstNode or PyccelAstNodeType
+        The variable, function, or module being renamed.
+    target : str
+        Name of variable or function in this context.
 
     Examples
     --------
@@ -120,13 +128,6 @@ class AsName(PyccelAstNode):
     old as new
     >>> AsName(NumpyFull, 'fill_func')
     full as fill_func
-
-    Parameters
-    ==========
-    obj    : PyccelAstNode or PyccelAstNodeType
-             The variable, function, or module being renamed
-    target : str
-             name of variable or function in this context
     """
     __slots__ = ('_obj', '_target')
     _attribute_nodes = ()
@@ -163,10 +164,7 @@ def object(self):
         return self._obj
 
     def __repr__(self):
-        return '{0} as {1}'.format(str(self.name), str(self.target))
-
-    def __str__(self):
-        return '{0} as {1}'.format(str(self.name), str(self.target))
+        return f'{self.name} as {self.target}'
 
     def __eq__(self, string):
         if isinstance(string, str):
@@ -224,10 +222,10 @@ def length(self):
         return self._length
 
     def __str__(self):
-        return '{} * {}'.format(str(self.val), str(self.length))
+        return f'{self.val} * {self.length}'
 
     def __repr__(self):
-        return '{} * {}'.format(repr(self.val), repr(self.length))
+        return f'{repr(self.val)} * {repr(self.length)}'
 
 class Concatenate(TypedAstNode):
     """
@@ -335,10 +333,10 @@ def __init__(
             self.set_current_ast(python_ast)
 
     def __str__(self):
-        return '{0} := {1}'.format(str(self.lhs), str(self.rhs))
+        return f'{self.lhs} := {self.rhs}'
 
     def __repr__(self):
-        return '({0} := {1})'.format(repr(self.lhs), repr(self.rhs))
+        return f'{repr(self.lhs)} := {repr(self.rhs)}'
 
     @property
     def lhs(self):
@@ -437,14 +435,14 @@ class Allocate(PyccelAstNode):
     def __init__(self, variable, *, shape, order, status, like = None):
 
         if not isinstance(variable, (Variable, PointerCast)):
-            raise TypeError("Can only allocate a 'Variable' object, got {} instead".format(type(variable)))
+            raise TypeError(f"Can only allocate a 'Variable' object, got {type(variable)} instead")
 
         if variable.on_stack:
             # Variable may only be a pointer in the wrapper
             raise ValueError("Variable must be allocatable")
 
         if shape and not isinstance(shape, (int, tuple, list)):
-            raise TypeError("Cannot understand 'shape' parameter of type '{}'".format(type(shape)))
+            raise TypeError(f"Cannot understand 'shape' parameter of type '{type(shape)}'")
 
         if variable.rank != len(shape):
             raise ValueError("Incompatible rank in variable allocation")
@@ -454,10 +452,10 @@ def __init__(self, variable, *, shape, order, status, like = None):
             raise ValueError("Incompatible order in variable allocation")
 
         if not isinstance(status, str):
-            raise TypeError("Cannot understand 'status' parameter of type '{}'".format(type(status)))
+            raise TypeError(f"Cannot understand 'status' parameter of type '{type(status)}'")
 
         if status not in ('allocated', 'unallocated', 'unknown'):
-            raise ValueError("Value of 'status' not allowed: '{}'".format(status))
+            raise ValueError(f"Value of 'status' not allowed: '{status}'")
 
         self._variable = variable
         self._shape    = shape
@@ -516,8 +514,7 @@ def like(self):
         return self._like
 
     def __str__(self):
-        return 'Allocate({}, shape={}, order={}, status={})'.format(
-                str(self.variable), str(self.shape), str(self.order), str(self.status))
+        return f'Allocate({self.variable}, shape={self.shape}, order={self.order}, status={self.status})'
 
     def __eq__(self, other):
         if isinstance(other, Allocate):
@@ -534,6 +531,8 @@ def __hash__(self):
 #------------------------------------------------------------------------------
 class Deallocate(PyccelAstNode):
     """
+    Class representing memory deallocation.
+
     Represents memory deallocation (usually of an array) for code generation.
     This is relevant to low-level target languages, such as C or Fortran,
     where the programmer must take care of heap memory deallocation.
@@ -547,7 +546,6 @@ class Deallocate(PyccelAstNode):
     -----
     An object of this class is immutable, although it contains a reference to a
     mutable Variable object.
-
     """
     __slots__ = ('_variable',)
     _attribute_nodes = ('_variable',)
@@ -556,7 +554,7 @@ class Deallocate(PyccelAstNode):
     def __init__(self, variable):
 
         if not isinstance(variable, Variable):
-            raise TypeError("Can only allocate a 'Variable' object, got {} instead".format(type(variable)))
+            raise TypeError(f"Can only allocate a 'Variable' object, got {type(variable)} instead")
 
         self._variable = variable
         super().__init__()
@@ -638,7 +636,7 @@ def insert2body(self, *obj, back=True):
             self._body = tuple([*obj, *self.body])
 
     def __repr__(self):
-        return 'CodeBlock({})'.format(self.body)
+        return f'CodeBlock({self.body})'
 
     def __reduce_ex__(self, i):
         """ Used by pickle to create an object of this class.
@@ -729,7 +727,7 @@ def __init__(self, lhs, rhs):
         super().__init__()
 
     def __str__(self):
-        return '{0} := {1}'.format(str(self.lhs), str(self.rhs))
+        return f'{self.lhs} := {self.rhs}'
 
     @property
     def lhs(self):
@@ -849,10 +847,7 @@ def __init__(
         super().__init__(lhs, rhs, status, like, python_ast=python_ast)
 
     def __repr__(self):
-        return '{0} {1}= {2}'.format(str(self.lhs), self.op, str(self.rhs))
-
-    def __str__(self):
-        return '{0} {1}= {2}'.format(str(self.lhs), self.op, str(self.rhs))
+        return f'{self.lhs} {self.op}= {self.rhs}'
 
     @property
     def op(self):
@@ -1065,8 +1060,8 @@ def __init__(
         imports=(),
         scope = None
         ):
-        if not isinstance(name, (str, AsName)):
-            raise TypeError('name must be a string or an AsName')
+        if not isinstance(name, str):
+            raise TypeError('name must be a string')
 
         if not iterable(variables):
             raise TypeError('variables must be an iterable')
@@ -1220,11 +1215,6 @@ def body(self):
         """
         return self.interfaces + self.funcs + self.classes
 
-    def set_name(self, new_name):
-        """ Function for changing the name of a module
-        """
-        self._name = new_name
-
     def __getitem__(self, arg):
         assert isinstance(arg, str)
         args = arg.split('.')
@@ -1428,7 +1418,7 @@ def __init__(self, iterable):
         elif hasattr(iterable, 'n_indices') and hasattr(iterable, 'to_range'):
             self._num_indices_required = iterable.n_indices
         else:
-            raise TypeError("Unknown iterator type {}".format(type(iterable)))
+            raise TypeError(f"Unknown iterator type {type(iterable)}")
 
         super().__init__()
 
@@ -1675,15 +1665,15 @@ def has_keyword(self):
 
     def __repr__(self):
         if self.has_keyword:
-            return 'FunctionCallArgument({} = {})'.format(self.keyword, repr(self.value))
+            return f'FunctionCallArgument({self.keyword} = {repr(self.value)})'
         else:
-            return 'FunctionCallArgument({})'.format(repr(self.value))
+            return f'FunctionCallArgument({repr(self.value)})'
 
     def __str__(self):
         if self.has_keyword:
-            return '{} = {}'.format(self.keyword, str(self.value))
+            return f'{self.keyword} = {self.value}'
         else:
-            return '{}'.format(str(self.value))
+            return f'{self.value}'
 
 class FunctionDefArgument(TypedAstNode):
     """
@@ -1862,19 +1852,15 @@ def bound_argument(self, bound):
 
     def __str__(self):
         if self.has_default:
-            argument = str(self.name)
-            value = str(self.value)
-            return '{0}={1}'.format(argument, value)
+            return f'{self.name}={self.value}'
         else:
             return str(self.name)
 
     def __repr__(self):
         if self.has_default:
-            argument = str(self.name)
-            value = str(self.value)
-            return 'FunctionDefArgument({0}={1})'.format(argument, value)
+            return f'FunctionDefArgument({self.name}={self.value})'
         else:
-            return 'FunctionDefArgument({})'.format(repr(self.name))
+            return f'FunctionDefArgument({repr(self.name)})'
 
 class FunctionDefResult(TypedAstNode):
     """
@@ -1952,7 +1938,7 @@ def is_argument(self):
         return self._is_argument
 
     def __repr__(self):
-        return 'FunctionDefResult({})'.format(repr(self.var))
+        return f'FunctionDefResult({repr(self.var)})'
 
     def __str__(self):
         return str(self.var)
@@ -2110,7 +2096,8 @@ def interface_name(self):
         return self._interface_name
 
     def __repr__(self):
-        return '{}({})'.format(self.func_name, ', '.join(str(a) for a in self.args))
+        args = ', '.join(str(a) for a in self.args)
+        return f'{self.func_name}({args})'
 
     @classmethod
     def _ignore(cls, c):
@@ -2173,15 +2160,18 @@ def cls_variable(self):
 
 
 class Return(PyccelAstNode):
+    """
+    Represents a return statement in a function in the code.
 
-    """Represents a function return in the code.
+    Represents a return statement in a function in the code.
 
     Parameters
     ----------
     expr : TypedAstNode
         The expression to return.
 
-    stmts :represent assign stmts in the case of expression return
+    stmt : PyccelAstNode
+        Any assign statements in the case of expression return.
     """
     __slots__ = ('_expr', '_stmt')
     _attribute_nodes = ('_expr', '_stmt')
@@ -2215,7 +2205,8 @@ def __repr__(self):
             code = repr(self.stmt)+';'
         else:
             code = ''
-        return code+"Return({})".format(','.join([repr(e) for e in self.expr]))
+        exprs = ','.join(repr(e) for e in self.expr)
+        return code+f"Return({exprs})"
 
 class FunctionDef(ScopedAstNode):
 
@@ -2732,10 +2723,7 @@ def __str__(self):
         result = 'None' if len(self.results) == 0 else \
                     ', '.join(str(r) for r in self.results)
         args = ', '.join(str(a) for a in self.arguments)
-        return '{name}({args}) -> {result}'.format(
-                name   = self.name,
-                args   = args,
-                result = result)
+        return f'{self.name}({args}) -> {result}'
 
     @property
     def is_unused(self):
@@ -2911,6 +2899,20 @@ def argument_description(self):
         """
         return self._argument_description
 
+    def __getnewargs__(self):
+        """
+        This method returns the positional and keyword arguments
+        used to create an instance of this class.
+        """
+        args = (
+        self._name,
+        self._cls_name)
+
+        kwargs = {
+            'decorators':self._decorators,
+            'argument_description':self._argument_description}
+        return args, kwargs
+
 class Interface(PyccelAstNode):
     """
     Class representing an interface function.
@@ -3547,19 +3549,23 @@ def is_unused(self):
 
 
 class Import(PyccelAstNode):
+    """
+    Represents inclusion of dependencies in the code.
 
-    """Represents inclusion of dependencies in the code.
+    Represents the importation of targets from another source code. This is
+    usually used to represent an import statement in the original code but
+    it is also used to import language/library specific dependencies.
 
     Parameters
     ----------
     source : str, DottedName, AsName
-        the module from which we import
+        The module from which we import.
     target : str, AsName, list, tuple
-        targets to import
+        Targets to import.
     ignore_at_print : bool
-        indicates whether the import should be printed
+        Indicates whether the import should be printed.
     mod : Module
-        The module describing the source
+        The module describing the source.
 
     Examples
     --------
@@ -3587,6 +3593,10 @@ def __init__(self, source, target = None, ignore_at_print = False, mod = None):
         self._target = set()
         self._source_mod      = mod
         self._ignore_at_print = ignore_at_print
+
+        if mod is None and isinstance(target, Module):
+            self._source_mod = target
+
         if target is None:
             if pyccel_stage == "syntactic":
                 target = []
@@ -3608,6 +3618,28 @@ def __init__(self, source, target = None, ignore_at_print = False, mod = None):
 
     @staticmethod
     def _format(i):
+        """
+        Format a string passed to this file into a Pyccel object.
+
+        Format a string passed to this file into a Pyccel object or confirm
+        that it is already correctly formatted.
+
+        Parameters
+        ----------
+        i : Any
+            The object to be formatted.
+
+        Returns
+        -------
+        DottedName | PyccelSymbol | AsName
+            The formatted object.
+
+        Raises
+        ------
+        TypeError
+            Raised if the input is not a string or one of the acceptable
+            output types.
+        """
         if isinstance(i, str):
             if '.' in i:
                 return DottedName(*i.split('.'))
@@ -3616,7 +3648,7 @@ def _format(i):
         if isinstance(i, (DottedName, AsName, PyccelSymbol)):
             return i
         else:
-            raise TypeError('Expecting a string, PyccelSymbol DottedName, given {}'.format(type(i)))
+            raise TypeError(f'Expecting a string, PyccelSymbol DottedName, given {type(i)}')
 
     @property
     def target(self):
@@ -3639,11 +3671,10 @@ def ignore(self, to_ignore):
     def __str__(self):
         source = str(self.source)
         if len(self.target) == 0:
-            return 'import {source}'.format(source=source)
+            return f'import {source}'
         else:
             target = ', '.join([str(i) for i in self.target])
-            return 'from {source} import {target}'.format(source=source,
-                    target=target)
+            return f'from {source} import {target}'
 
     def define_target(self, new_target):
         """
@@ -3718,7 +3749,7 @@ def __init__(
         ):
 
         if not isinstance(variable, FunctionAddress):
-            raise TypeError('variable must be of type FunctionAddress, given {0}'.format(variable))
+            raise TypeError(f'variable must be of type FunctionAddress, given {variable}')
 
         if intent:
             if not intent in ['in', 'out', 'inout']:
@@ -3806,7 +3837,7 @@ def __init__(
         module_variable = False
         ):
         if not isinstance(variable, Variable):
-            raise TypeError('var must be of type Variable, given {0}'.format(variable))
+            raise TypeError(f'var must be of type Variable, given {variable}')
 
         if intent:
             if not intent in ['in', 'out', 'inout']:
@@ -3857,7 +3888,7 @@ def module_variable(self):
         return self._module_variable
 
     def __repr__(self):
-        return 'Declare({})'.format(repr(self.variable))
+        return f'Declare({repr(self.variable)})'
 
 class Break(PyccelAstNode):
 
@@ -4008,7 +4039,7 @@ def text(self):
         return self._text
 
     def __str__(self):
-        return '# {0}'.format(str(self.text))
+        return f'# {self.text}'
 
     def __reduce_ex__(self, i):
         """ Used by pickle to create an object of this class.
@@ -4222,16 +4253,18 @@ def __iter__(self):
         return iter((self.condition, self.body))
 
     def __str__(self):
-        return "IfSec({},{})".format(str(self.condition), str(self.body))
+        return f"IfSec({self.condition}, {self.body})"
 
 class If(PyccelAstNode):
+    """
+    Represents an if statement in the code.
 
-    """Represents a if statement in the code.
+    Represents an if statement in the code.
 
     Parameters
     ----------
-    args : IfSection
-           All arguments are sections of the complete If block
+    *args : IfSection
+        All arguments are sections of the complete If block.
 
     Examples
     --------
@@ -4266,7 +4299,8 @@ def bodies(self):
         return [b.body for b in self._blocks]
 
     def __str__(self):
-        return "If({})".format(','.join(str(b) for b in self.blocks))
+        blocks = ','.join(str(b) for b in self.blocks)
+        return f"If({blocks})"
 
 class StarredArguments(PyccelAstNode):
     __slots__ = ('_starred_obj',)
diff --git a/pyccel/ast/cwrapper.py b/pyccel/ast/cwrapper.py
index 2dfaf292c0..29e16d59bf 100644
--- a/pyccel/ast/cwrapper.py
+++ b/pyccel/ast/cwrapper.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py
index 054d2fa546..af1caa08f0 100644
--- a/pyccel/ast/datatypes.py
+++ b/pyccel/ast/datatypes.py
@@ -2,7 +2,7 @@
 
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/ast/functionalexpr.py b/pyccel/ast/functionalexpr.py
index b574305fb5..144cece4f6 100644
--- a/pyccel/ast/functionalexpr.py
+++ b/pyccel/ast/functionalexpr.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 from pyccel.utilities.stage import PyccelStage
diff --git a/pyccel/ast/headers.py b/pyccel/ast/headers.py
index f5498ef35c..b806484387 100644
--- a/pyccel/ast/headers.py
+++ b/pyccel/ast/headers.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 from ..errors.errors    import Errors
diff --git a/pyccel/ast/internals.py b/pyccel/ast/internals.py
index bdb65be485..095e4a2d6a 100644
--- a/pyccel/ast/internals.py
+++ b/pyccel/ast/internals.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 File containing basic classes which are used throughout pyccel.
@@ -281,7 +281,7 @@ def __str__(self):
             stop = ''
         else:
             stop = str(self.stop)
-        return '{0} : {1}'.format(start, stop)
+        return f'{start} : {stop}'
 
 
 class PyccelSymbol(str, Immutable):
diff --git a/pyccel/ast/itertoolsext.py b/pyccel/ast/itertoolsext.py
index 24c6914890..cdec9c9a70 100644
--- a/pyccel/ast/itertoolsext.py
+++ b/pyccel/ast/itertoolsext.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 This module represent a call to the itertools functions for code generation.
diff --git a/pyccel/ast/literals.py b/pyccel/ast/literals.py
index b81febba9e..389cd8676b 100644
--- a/pyccel/ast/literals.py
+++ b/pyccel/ast/literals.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ This module contains all literal types
 """
diff --git a/pyccel/ast/macros.py b/pyccel/ast/macros.py
index e360d3b0d3..810eb3c954 100644
--- a/pyccel/ast/macros.py
+++ b/pyccel/ast/macros.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/ast/mathext.py b/pyccel/ast/mathext.py
index e9b4446583..ec1f6e918c 100644
--- a/pyccel/ast/mathext.py
+++ b/pyccel/ast/mathext.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing objects from the math module understood by pyccel
 """
diff --git a/pyccel/ast/numpy_wrapper.py b/pyccel/ast/numpy_wrapper.py
index fce4170e8e..8462369479 100644
--- a/pyccel/ast/numpy_wrapper.py
+++ b/pyccel/ast/numpy_wrapper.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
@@ -64,17 +64,24 @@ class used to hold NumPy array objects in Python.
 
 def get_numpy_max_acceptable_version_file():
     """
-    Get the macro specifying the last acceptable numpy version. If numpy is more
-    recent than this then deprecation warnings are shown.
+    Get the macro specifying the most recent acceptable NumPy version.
 
-    The last acceptable numpy version is 1.19. If the current version is older
-    than this then the last acceptable numpy version is the current version
+    Get the macro specifying the most recent acceptable NumPy version.
+    If NumPy is more recent than this then deprecation warnings are shown.
+
+    The most recent acceptable NumPy version is 1.19. If the current version is older
+    than this then the last acceptable NumPy version is the current version.
+
+    Returns
+    -------
+    str
+        A string containing the code which defines the macro.
     """
     numpy_max_acceptable_version = [1, 19]
     numpy_current_version = [int(v) for v in np.version.version.split('.')[:2]]
     numpy_api_acceptable_version = min(numpy_max_acceptable_version, numpy_current_version)
-    numpy_api_macro = '# define NPY_NO_DEPRECATED_API NPY_{}_{}_API_VERSION\n'.format(
-        *numpy_api_acceptable_version)
+    major, minor = numpy_api_acceptable_version
+    numpy_api_macro = f'# define NPY_NO_DEPRECATED_API NPY_{major}_{minor}_API_VERSION\n'
 
     return '#ifndef NPY_NO_DEPRECATED_API\n'+ \
             numpy_api_macro+\
@@ -85,14 +92,14 @@ def get_numpy_max_acceptable_version_file():
                             arguments = [FunctionDefArgument(Variable(dtype=PyccelPyObject(), name = 'o'))],
                             results   = [FunctionDefResult(Variable(dtype=NativeBool(), name='b'))])
 
-# numpy array to c ndarray : function definition in pyccel/stdlib/cwrapper/cwrapper_ndarrays.c
+# NumPy array to c ndarray : function definition in pyccel/stdlib/cwrapper/cwrapper_ndarrays.c
 pyarray_to_ndarray = FunctionDef(
                 name      = 'pyarray_to_ndarray',
                 arguments = [FunctionDefArgument(Variable(name = 'a', dtype = PyccelPyObject(), memory_handling = 'alias'))],
                 body      = [],
                 results   = [FunctionDefResult(Variable(name = 'array', dtype = NativeGeneric()))])
 
-# numpy array check elements : function definition in pyccel/stdlib/cwrapper/cwrapper_ndarrays.c
+# NumPy array check elements : function definition in pyccel/stdlib/cwrapper/cwrapper_ndarrays.c
 pyarray_check = FunctionDef(
                 name      = 'pyarray_check',
                 arguments = [
diff --git a/pyccel/ast/numpyext.py b/pyccel/ast/numpyext.py
index 4fd28b584b..de673c4ab9 100644
--- a/pyccel/ast/numpyext.py
+++ b/pyccel/ast/numpyext.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing objects from the numpy module understood by pyccel
 """
@@ -613,13 +613,31 @@ def init_dtype(self):
     #--------------------------------------------------------------------------
     @staticmethod
     def _process_order(rank, order):
+        """
+        Treat the order to get an order in the format expected by Pyccel.
+
+        Process the order passed to the array creation function to get an order
+        in the format expected by Pyccel. The final format should be a string
+        containing either 'C' or 'F'.
+
+        Parameters
+        ----------
+        rank : int
+            The rank of the array being created.
+        order : str | LiteralString
+            The order of the array as specified by the user or the subclass.
+
+        Returns
+        -------
+        str | None
+            The order in the format expected by Pyccel.
+        """
 
         if rank < 2:
             return None
 
         order = str(order).strip('\'"')
-        if order not in ('C', 'F'):
-            raise ValueError('unrecognized order = {}'.format(order))
+        assert order in ('C', 'F')
         return order
 
 #==============================================================================
@@ -651,7 +669,7 @@ class NumpyArray(NumpyNewArray):
     def __init__(self, arg, dtype=None, order='K', ndmin=None):
 
         if not isinstance(arg, (PythonTuple, PythonList, Variable, IndexedElement)):
-            raise TypeError('Unknown type of  %s.' % type(arg))
+            raise TypeError(f'Unknown type of  {type(arg)}')
 
         is_homogeneous_tuple = isinstance(arg.class_type, NativeHomogeneousTuple)
         # Inhomogeneous tuples can contain homogeneous data if it is inhomogeneous due to pointers
@@ -711,8 +729,7 @@ def __init__(self, arg, dtype=None, order='K', ndmin=None):
             # ... Determine ordering
             order = str(order).strip("\'")
 
-            if order not in ('K', 'A', 'C', 'F'):
-                raise ValueError(f"Cannot recognize '{order}' order")
+            assert order in ('K', 'A', 'C', 'F')
 
             if order in ('K', 'A'):
                 order = arg.order or 'C'
@@ -823,7 +840,7 @@ class NumpySum(PyccelInternalFunction):
 
     def __init__(self, arg):
         if not isinstance(arg, TypedAstNode):
-            raise TypeError('Unknown type of  %s.' % type(arg))
+            raise TypeError(f'Unknown type of {type(arg)}.')
         super().__init__(arg)
         if isinstance(arg.dtype, NativeBool):
             self._dtype = NativeInteger()
@@ -856,7 +873,7 @@ class NumpyProduct(PyccelInternalFunction):
 
     def __init__(self, arg):
         if not isinstance(arg, TypedAstNode):
-            raise TypeError('Unknown type of  %s.' % type(arg))
+            raise TypeError(f'Unknown type of {type(arg)}.')
         super().__init__(arg)
         self._arg = PythonList(arg) if arg.rank == 0 else self._args[0]
         self._arg = NumpyInt(self._arg) if (isinstance(arg.dtype, NativeBool) or \
@@ -894,9 +911,9 @@ def __init__(self, a ,b):
             return
 
         if not isinstance(a, TypedAstNode):
-            raise TypeError('Unknown type of  %s.' % type(a))
+            raise TypeError(f'Unknown type of {type(a)}.')
         if not isinstance(b, TypedAstNode):
-            raise TypeError('Unknown type of  %s.' % type(a))
+            raise TypeError(f'Unknown type of {type(a)}.')
 
         args      = (a, b)
         type_info = NumpyResultType(*args)
diff --git a/pyccel/ast/omp.py b/pyccel/ast/omp.py
index 594283e843..293f2ed490 100644
--- a/pyccel/ast/omp.py
+++ b/pyccel/ast/omp.py
@@ -1,13 +1,13 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 OpenMP has several constructs and directives, and this file contains the OpenMP types that are supported.
 We represent some types with the OmpAnnotatedComment type.
 These types are detailed on our documentation:
-https://github.com/pyccel/pyccel/blob/master/tutorial/openmp.md
+https://github.com/pyccel/pyccel/blob/devel/docs/openmp.md
 """
 
 from .basic import PyccelAstNode
diff --git a/pyccel/ast/operators.py b/pyccel/ast/operators.py
index 463d50564f..be870b1d7d 100644
--- a/pyccel/ast/operators.py
+++ b/pyccel/ast/operators.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module handling all Python builtin operators
diff --git a/pyccel/ast/scipyext.py b/pyccel/ast/scipyext.py
index 8bbe7adf89..70da4cb406 100644
--- a/pyccel/ast/scipyext.py
+++ b/pyccel/ast/scipyext.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing objects from the scipy module understood by pyccel
 """
diff --git a/pyccel/ast/sympy_helper.py b/pyccel/ast/sympy_helper.py
index dd838cfdb7..52d5b38d49 100644
--- a/pyccel/ast/sympy_helper.py
+++ b/pyccel/ast/sympy_helper.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/ast/sysext.py b/pyccel/ast/sysext.py
index 58c0f1654f..c031b7df7f 100644
--- a/pyccel/ast/sysext.py
+++ b/pyccel/ast/sysext.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing objects from the sys module understood by pyccel
 """
diff --git a/pyccel/ast/type_annotations.py b/pyccel/ast/type_annotations.py
index 315e1a0391..a25fb1b103 100644
--- a/pyccel/ast/type_annotations.py
+++ b/pyccel/ast/type_annotations.py
@@ -2,7 +2,7 @@
 
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing all classes useful for type annotation.
 """
diff --git a/pyccel/ast/typingext.py b/pyccel/ast/typingext.py
index 42c373f33e..0669c0d449 100644
--- a/pyccel/ast/typingext.py
+++ b/pyccel/ast/typingext.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing objects from the typing module understood by pyccel
 """
diff --git a/pyccel/ast/utilities.py b/pyccel/ast/utilities.py
index 7876d5b196..c0e500e895 100644
--- a/pyccel/ast/utilities.py
+++ b/pyccel/ast/utilities.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 import sys
@@ -189,19 +189,6 @@ def builtin_import(expr):
 
     return []
 
-#==============================================================================
-def get_function_from_ast(ast, func_name):
-    node = None
-    for stmt in ast:
-        if isinstance(stmt, FunctionDef) and str(stmt.name) == func_name:
-            node = stmt
-            break
-
-    if node is None:
-        print('> could not find {}'.format(func_name))
-
-    return node
-
 #==============================================================================
 def split_positional_keyword_arguments(*args):
     """ Create a list of positional arguments and a dictionary of keyword arguments
@@ -345,7 +332,7 @@ def insert_index(expr, pos, index_var):
         return expr[index_var]
 
     else:
-        raise NotImplementedError("Expansion not implemented for type : {}".format(type(expr)))
+        raise NotImplementedError(f"Expansion not implemented for type : {type(expr)}")
 
 #==============================================================================
 
@@ -505,14 +492,14 @@ def collect_loops(block, indices, new_index, language_has_vectors = False, resul
             # Loop over indexes, inserting until the expression can be evaluated
             # in the desired language
             new_level = 0
-            for index in range(-rank,0):
+            for index_depth in range(-rank, 0):
                 new_level += 1
                 # If an index exists at the same depth, reuse it if not create one
-                if rank+index >= len(indices):
-                    indices.append(new_index('int','i'))
-                index_var = indices[rank+index]
-                new_vars = [insert_index(v, index, index_var) for v in new_vars]
-                handled_funcs = [insert_index(v, index, index_var) for v in handled_funcs]
+                if rank+index_depth >= len(indices):
+                    indices.append(new_index('int', 'i'))
+                index = indices[rank+index_depth]
+                new_vars = [insert_index(v, index_depth, index) for v in new_vars]
+                handled_funcs = [insert_index(v, index_depth, index) for v in handled_funcs]
                 if compatible_operation(*new_vars, *handled_funcs, language_has_vectors = language_has_vectors):
                     break
 
@@ -552,22 +539,34 @@ def collect_loops(block, indices, new_index, language_has_vectors = False, resul
             current_level = new_level
 
         elif isinstance(line, Assign) and isinstance(line.lhs, IndexedElement) \
-                and isinstance(line.rhs, (PythonTuple, NumpyArray)) and not language_has_vectors:
-
+                and isinstance(line.rhs, (PythonTuple, NumpyArray)):
             lhs = line.lhs
             rhs = line.rhs
-            if isinstance(rhs, NumpyArray):
-                rhs = rhs.arg
-
-            lhs_rank = lhs.rank
-
-            new_assigns = [Assign(
-                            insert_index(expr=lhs,
-                                pos       = -lhs_rank,
-                                index_var = LiteralInteger(j)),
-                            rj) # lhs[j] = rhs[j]
-                          for j, rj in enumerate(rhs)]
-            collect_loops(new_assigns, indices, new_index, language_has_vectors, result = result)
+            if lhs.rank > rhs.rank:
+                for index_depth in range(lhs.rank-rhs.rank):
+                    # If an index exists at the same depth, reuse it if not create one
+                    if index_depth >= len(indices):
+                        indices.append(new_index('int', 'i'))
+                    index = indices[index_depth]
+                    lhs = insert_index(lhs, index_depth, index)
+                collect_loops([Assign(lhs, rhs)], indices, new_index, language_has_vectors, result = result)
+
+            elif not language_has_vectors:
+                if isinstance(rhs, NumpyArray):
+                    rhs = rhs.arg
+
+                lhs_rank = lhs.rank
+
+                new_assigns = [Assign(
+                                insert_index(expr=lhs,
+                                    pos       = -lhs_rank,
+                                    index_var = LiteralInteger(j)),
+                                rj) # lhs[j] = rhs[j]
+                              for j, rj in enumerate(rhs)]
+                collect_loops(new_assigns, indices, new_index, language_has_vectors, result = result)
+
+            else:
+                result.append(line)
 
         elif isinstance(line, Assign) and isinstance(line.rhs, Concatenate):
             lhs = line.lhs
diff --git a/pyccel/ast/variable.py b/pyccel/ast/variable.py
index 3e48bd5eed..362caee0b6 100644
--- a/pyccel/ast/variable.py
+++ b/pyccel/ast/variable.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ This module contains all classes which are used to handle memory block labels at
 different stages of pyccel. Memory block labels are usually either Variables or Indexed
@@ -155,7 +155,7 @@ def __init__(
             raise ValueError("Variable name can't be empty")
 
         if not isinstance(name, (str, DottedName)):
-            raise TypeError('Expecting a string or DottedName, given {0}'.format(type(name)))
+            raise TypeError(f'Expecting a string or DottedName, given {type(name)}')
         self._name = name
 
         if memory_handling not in ('heap', 'stack', 'alias'):
@@ -821,9 +821,7 @@ def value(self):
         return self._value
 
     def __str__(self):
-        name = str(self.name)
-        value = str(self.value)
-        return '{0}={1}'.format(name, value)
+        return f'{self.name}={self.value}'
 
 
 
@@ -939,10 +937,12 @@ def indices(self):
         return self._indices
 
     def __str__(self):
-        return '{}[{}]'.format(self.base, ','.join(str(i) for i in self.indices))
+        indices = ','.join(str(i) for i in self.indices)
+        return f'{self.base}[{indices}]'
 
     def __repr__(self):
-        return '{}[{}]'.format(repr(self.base), ','.join(repr(i) for i in self.indices))
+        indices = ','.join(repr(i) for i in self.indices)
+        return f'{repr(self.base)}[{indices}]'
 
     def __getitem__(self, *args):
 
diff --git a/pyccel/codegen/codegen.py b/pyccel/codegen/codegen.py
index 01303cc393..a19f07a4ed 100644
--- a/pyccel/codegen/codegen.py
+++ b/pyccel/codegen/codegen.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 import os
 
@@ -11,7 +11,6 @@
 from pyccel.codegen.printing.pycode import PythonCodePrinter
 
 from pyccel.ast.core      import FunctionDef, Interface, ModuleHeader
-from pyccel.errors.errors import Errors
 from pyccel.utilities.stage import PyccelStage
 
 _extension_registry = {'fortran': 'f90', 'c':'c',  'python':'py'}
@@ -24,28 +23,31 @@
 
 pyccel_stage = PyccelStage()
 
-class Codegen(object):
-
-    """Abstract class for code generator."""
-
-    def __init__(self, parser, name):
-        """Constructor for Codegen.
-
-        parser: pyccel parser
-
-
-        name: str
-            name of the generated module or program.
-        """
+class Codegen:
+    """
+    Class which handles the generation of code.
+
+    The class which handles the generation of code. This is done by creating an appropriate
+    class inheriting from `CodePrinter` and using it to create strings describing the code
+    that should be printed. This class then takes care of creating the necessary files.
+
+    Parameters
+    ----------
+    parser : SemanticParser
+        The Pyccel semantic parser for a Python program or module. This contains the
+        annotated AST and additional information about the variables scope.
+    name : str
+        Name of the generated module or program.
+    language : str
+        The language which the printer should print to.
+    """
+    def __init__(self, parser, name, language):
         pyccel_stage.set_stage('codegen')
         self._parser   = parser
         self._ast      = parser.ast
         self._name     = name
         self._printer  = None
-        self._language = None
-
-        #TODO verify module name != function name
-        #it generates a compilation error
+        self._language = language
 
         self._stmts = {}
         _structs = [
@@ -63,11 +65,32 @@ def __init__(self, parser, name):
         self._collect_statements()
         self._is_program = self.ast.program is not None
 
+        # instantiate code_printer
+        try:
+            CodePrinterSubclass = printer_registry[language]
+        except KeyError as err:
+            raise ValueError(f'{language} language is not available') from err
+
+        self._printer = CodePrinterSubclass(self.parser.filename)
 
     @property
     def parser(self):
+        """
+        The parser which generated the AST printed by this class.
+
+        The parser which generated the AST printed by this class.
+        """
         return self._parser
 
+    @property
+    def printer(self):
+        """
+        The printer which is used to generate code.
+
+        The printer which is used by this class to generate code in the target language.
+        """
+        return self._printer
+
     @property
     def name(self):
         """Returns the name associated to the source code"""
@@ -134,22 +157,6 @@ def language(self):
 
         return self._language
 
-    def set_printer(self, **settings):
-        """ Set the current codeprinter instance"""
-        # Get language used (default language used is fortran)
-        language = settings.pop('language', 'fortran')
-
-        # Set language
-        if not language in ['fortran', 'c', 'python']:
-            raise ValueError('{} language is not available'.format(language))
-        self._language = language
-
-        # instantiate codePrinter
-        code_printer = printer_registry[language]
-        errors = Errors()
-        # set the code printer
-        self._printer = code_printer(self.parser.filename, **settings)
-
     def get_printer_imports(self):
         """return the imports of the current codeprinter"""
         return self._printer.get_additional_imports()
@@ -176,22 +183,38 @@ def _collect_statements(self):
         self._stmts['interfaces'] = interfaces
         self._stmts['body']       = self.ast
 
-    def doprint(self, **settings):
-        """Prints the code in the target language."""
-        if not self._printer:
-            self.set_printer(**settings)
-        return self._printer.doprint(self.ast)
 
-
-    def export(self, filename=None, **settings):
-        """Export code in filename"""
-        self.set_printer(**settings)
+    def export(self, filename):
+        """
+        Export code to a file with the requested name.
+
+        Generate the code in the target language from the AST and print this code
+        to file. Between 1 and 3 files are generated depending on the AST and the
+        target language. A source file is always generated. In languages with
+        header files, a header file is also generated. Finally if the AST includes
+        a program and the target language is not Python a program source file is
+        also generated. The source and header files are named by appending the
+        extension to the requested filename. The program source file is named by
+        additionally prepending 'prog_' to the requested filename.
+
+        Parameters
+        ----------
+        filename : str
+            The base (i.e. no extensions) of the filename of the file where the
+            code should be printed to.
+
+        Returns
+        -------
+        filename : str
+            The name of the file where the source code was printed.
+        prog_filename : str
+            The name of the file where the source code for the program was printed.
+        """
         ext = _extension_registry[self._language]
         header_ext = _header_extension_registry[self._language]
 
-        if filename is None: filename = self.name
-        header_filename = '{name}.{ext}'.format(name=filename, ext=header_ext)
-        filename = '{name}.{ext}'.format(name=filename, ext=ext)
+        header_filename = f'{filename}.{header_ext}'
+        filename = f'{filename}.{ext}'
 
         # print module header
         if header_ext is not None:
diff --git a/pyccel/codegen/compiling/basic.py b/pyccel/codegen/compiling/basic.py
index 8fb8bade1f..9e31b58cc0 100644
--- a/pyccel/codegen/compiling/basic.py
+++ b/pyccel/codegen/compiling/basic.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module handling classes for compiler information relevant to a given object
diff --git a/pyccel/codegen/compiling/compilers.py b/pyccel/codegen/compiling/compilers.py
index feafa4bea8..fca93c5624 100644
--- a/pyccel/codegen/compiling/compilers.py
+++ b/pyccel/codegen/compiling/compilers.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module handling everything related to the compilers used to compile the various generated files
diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py
index 4d4770a491..efff153aad 100644
--- a/pyccel/codegen/pipeline.py
+++ b/pyccel/codegen/pipeline.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Contains the execute_pyccel function which carries out the main steps required to execute pyccel
@@ -260,9 +260,9 @@ def handle_error(stage):
     start_codegen = time.time()
     # Generate .f90 file
     try:
-        codegen = Codegen(semantic_parser, module_name)
+        codegen = Codegen(semantic_parser, module_name, language)
         fname = os.path.join(pyccel_dirpath, module_name)
-        fname, prog_name = codegen.export(fname, language=language)
+        fname, prog_name = codegen.export(fname)
     except NotImplementedError as error:
         msg = str(error)
         errors.report(msg+'\n'+PYCCEL_RESTRICTION_TODO,
diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py
index e071b0f429..764ef7b4ce 100644
--- a/pyccel/codegen/printing/ccode.py
+++ b/pyccel/codegen/printing/ccode.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 import functools
 from itertools import chain
@@ -739,6 +739,7 @@ def _print_Header(self, expr):
 
     def _print_ModuleHeader(self, expr):
         self.set_scope(expr.module.scope)
+        self._current_module = expr.module
         self._in_header = True
         name = expr.module.name
         if isinstance(name, AsName):
@@ -772,6 +773,7 @@ def _print_ModuleHeader(self, expr):
 
         self._in_header = False
         self.exit_scope()
+        self._current_module = None
         return (f"#ifndef {name.upper()}_H\n \
                 #define {name.upper()}_H\n\n \
                 {imports}\n \
@@ -782,13 +784,13 @@ def _print_ModuleHeader(self, expr):
 
     def _print_Module(self, expr):
         self.set_scope(expr.scope)
-        self._current_module = expr.name
+        self._current_module = expr
         body    = ''.join(self._print(i) for i in expr.body)
 
         global_variables = ''.join([self._print(d) for d in expr.declarations])
 
         # Print imports last to be sure that all additional_imports have been collected
-        imports = [Import(expr.name, Module(expr.name,(),())), *self._additional_imports.values()]
+        imports = [Import(self.scope.get_python_name(expr.name), Module(expr.name,(),())), *self._additional_imports.values()]
         imports = ''.join(self._print(i) for i in imports)
 
         code = ('{imports}\n'
@@ -799,6 +801,7 @@ def _print_Module(self, expr):
                         body      = body)
 
         self.exit_scope()
+        self._current_module = None
         return code
 
     def _print_Break(self, expr):
@@ -935,7 +938,7 @@ def _print_Import(self, expr):
         if source in import_dict: # pylint: disable=consider-using-get
             source = import_dict[source]
 
-        if expr.source_module:
+        if expr.source_module and expr.source_module is not self._current_module:
             for classDef in expr.source_module.classes:
                 class_scope = classDef.scope
                 for method in classDef.methods:
@@ -2097,8 +2100,7 @@ def _print_AliasAssign(self, expr):
 
         # the below condition handles the case of reassinging a pointer to an array view.
         # setting the pointer's is_view attribute to false so it can be ignored by the free_pointer function.
-        if not self.is_c_pointer(lhs_var) and \
-                isinstance(lhs_var, Variable) and lhs_var.is_ndarray:
+        if isinstance(lhs_var, Variable) and lhs_var.is_ndarray and not lhs_var.is_optional:
             rhs = self._print(rhs_var)
 
             if isinstance(rhs_var, Variable) and rhs_var.is_ndarray:
@@ -2109,12 +2111,12 @@ def _print_AliasAssign(self, expr):
                     return 'transpose_alias_assign({}, {});\n'.format(lhs, rhs)
             else:
                 lhs = self._print(lhs_var)
-                return '{} = {};\n'.format(lhs, rhs)
+                return f'{lhs} = {rhs};\n'
         else:
             lhs = self._print(lhs_address)
             rhs = self._print(rhs_address)
 
-            return '{} = {};\n'.format(lhs, rhs)
+            return f'{lhs} = {rhs};\n'
 
     def _print_For(self, expr):
         self.set_scope(expr.scope)
@@ -2388,6 +2390,8 @@ def _print_Omp_End_Clause(self, expr):
     #=====================================
 
     def _print_Program(self, expr):
+        mod = expr.get_direct_user_nodes(lambda x: isinstance(x, Module))[0]
+        self._current_module = mod
         self.set_scope(expr.scope)
         body  = self._print(expr.body)
         variables = self.scope.variables.values()
@@ -2397,6 +2401,7 @@ def _print_Program(self, expr):
         imports = ''.join(self._print(i) for i in imports)
 
         self.exit_scope()
+        self._current_module = None
         return ('{imports}'
                 'int main()\n{{\n'
                 '{decs}'
@@ -2481,29 +2486,3 @@ def indent_code(self, code):
             level += increase[n]
         return pretty
 
-def ccode(expr, filename, assign_to=None, **settings):
-    """Converts an expr to a string of c code
-
-    expr : Expr
-        A pyccel expression to be converted.
-    filename : str
-        The name of the file being translated. Used in error printing
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    precision : integer, optional
-        The precision for numbers such as pi [default=15].
-    user_functions : dict, optional
-        A dictionary where keys are ``FunctionClass`` instances and values are
-        their string representations. Alternatively, the dictionary value can
-        be a list of tuples i.e. [(argument_test, cfunction_string)]. See below
-        for examples.
-    dereference : iterable, optional
-        An iterable of symbols that should be dereferenced in the printed code
-        expression. These would be values passed by address to the function.
-        For example, if ``dereference=[a]``, the resulting code would print
-        ``(*a)`` instead of ``a``.
-    """
-    return CCodePrinter(filename, **settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/printing/codeprinter.py b/pyccel/codegen/printing/codeprinter.py
index dcc97359b6..2dbcde1069 100644
--- a/pyccel/codegen/printing/codeprinter.py
+++ b/pyccel/codegen/printing/codeprinter.py
@@ -1,13 +1,13 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 
 from pyccel.ast.basic import PyccelAstNode
 
-from pyccel.ast.core      import Assign
+from pyccel.ast.core      import Module, ModuleHeader, Program
 from pyccel.ast.internals import PyccelSymbol
 
 from pyccel.errors.errors     import Errors
@@ -22,31 +22,31 @@
 class CodePrinter:
     """
     The base class for code-printing subclasses.
+
+    The base class from which code printers inherit. The sub-classes should define a language
+    and `_print_X` functions.
     """
     language = None
     def __init__(self):
         self._scope = None
 
-    def doprint(self, expr, assign_to=None):
+    def doprint(self, expr):
         """
         Print the expression as code.
 
+        Print the expression as code.
+
+        Parameters
+        ----------
         expr : Expression
             The expression to be printed.
 
-        assign_to : PyccelSymbol, MatrixSymbol, or string (optional)
-            If provided, the printed code will set the expression to a
-            variable with name ``assign_to``.
+        Returns
+        -------
+        str
+            The generated code.
         """
-
-        if isinstance(assign_to, str):
-            assign_to = PyccelSymbol(assign_to)
-        elif not isinstance(assign_to, (PyccelAstNode, type(None))):
-            raise TypeError("{0} cannot assign to object of type {1}".format(
-                    type(self).__name__, type(assign_to)))
-
-        if assign_to:
-            expr = Assign(assign_to, expr)
+        assert isinstance(expr, (Module, ModuleHeader, Program))
 
         # Do the actual printing
         lines = self._print(expr).splitlines(True)
diff --git a/pyccel/codegen/printing/cwrappercode.py b/pyccel/codegen/printing/cwrappercode.py
index 7289b51ac1..4b71f9ec3c 100644
--- a/pyccel/codegen/printing/cwrappercode.py
+++ b/pyccel/codegen/printing/cwrappercode.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 from pyccel.codegen.printing.ccode import CCodePrinter
@@ -260,6 +260,7 @@ def _print_PyModule_Create(self, expr):
 
     def _print_ModuleHeader(self, expr):
         mod = expr.module
+        self._current_module = expr.module
         name = mod.name
 
         # Print imports last to be sure that all additional_imports have been collected
@@ -293,6 +294,7 @@ def _print_ModuleHeader(self, expr):
         static_import_decs = self._print(Declare(API_var, static=True))
         import_func = self._print(mod.import_func)
 
+        self._current_module = None
         header_id = f'{name.upper()}_WRAPPER'
         header_guard = f'{header_id}_H'
         return (f"#ifndef {header_guard}\n \
@@ -311,6 +313,7 @@ def _print_ModuleHeader(self, expr):
     def _print_PyModule(self, expr):
         scope = expr.scope
         self.set_scope(scope)
+        self._current_module = expr
 
         # Insert declared objects into scope
         variables = expr.original_module.variables if isinstance(expr, BindCModule) else expr.variables
@@ -322,7 +325,7 @@ def _print_PyModule(self, expr):
 
         funcs = []
 
-        self._module_name  = self.get_python_name(scope, expr)
+        self._module_name  = expr.name
         sep = self._print(SeparatorComment(40))
 
         interface_funcs = [f.name for i in expr.interfaces for f in i.functions]
@@ -373,6 +376,7 @@ def _print_PyModule(self, expr):
         imports  = ''.join(self._print(i) for i in imports)
 
         self.exit_scope()
+        self._current_module = None
 
         return '\n'.join(['#define PY_ARRAY_UNIQUE_SYMBOL CWRAPPER_ARRAY_API',
                 f'#define {pymod_name.upper()}\n',
@@ -515,31 +519,3 @@ def _print_IndexedElement(self, expr):
             return f'{base}{idxs}'
         else:
             return CCodePrinter._print_IndexedElement(self, expr)
-
-def cwrappercode(expr, filename, target_language, assign_to=None, **settings):
-    """Converts an expr to a string of c wrapper code
-
-    expr : Expr
-        A pyccel expression to be converted.
-    filename : str
-        The name of the file being translated. Used in error printing
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    precision : integer, optional
-        The precision for numbers such as pi [default=15].
-    user_functions : dict, optional
-        A dictionary where keys are ``FunctionClass`` instances and values are
-        their string representations. Alternatively, the dictionary value can
-        be a list of tuples i.e. [(argument_test, cfunction_string)]. See below
-        for examples.
-    dereference : iterable, optional
-        An iterable of symbols that should be dereferenced in the printed code
-        expression. These would be values passed by address to the function.
-        For example, if ``dereference=[a]``, the resulting code would print
-        ``(*a)`` instead of ``a``.
-    """
-
-    return CWrapperCodePrinter(filename, target_language, **settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/printing/fcode.py b/pyccel/codegen/printing/fcode.py
index a0c2e9530f..b4c80812a0 100644
--- a/pyccel/codegen/printing/fcode.py
+++ b/pyccel/codegen/printing/fcode.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """Print to F90 standard. Trying to follow the information provided at
 www.fortran90.org as much as possible."""
@@ -602,7 +602,7 @@ def _print_Import(self, expr):
             return ''
 
         if expr.source_module:
-            source = expr.source_module.scope.get_expected_name(source)
+            source = expr.source_module.name
 
         if 'mpi4py' == str(getattr(expr.source,'name',expr.source)):
             return 'use mpi\n' + 'use mpiext\n'
@@ -1799,12 +1799,24 @@ def _print_LiteralString(self, expr):
         return ' // '.join(formatted_str)
 
     def _print_Interface(self, expr):
-        # ... we don't print 'hidden' functions
+        interface_funcs = expr.functions
+
+        example_func = interface_funcs[0]
+
+        if len(example_func.results) == 1:
+            if len(set(f.results[0].var.rank == 0 for f in interface_funcs)) != 1:
+                message = ("Fortran cannot yet handle a templated function returning either a scalar or an array. "
+                           "If you are using the terminal interface, please pass --language c, "
+                           "if you are using the interactive interfaces epyccel or lambdify, please pass language='c'. "
+                           "See https://github.com/pyccel/pyccel/issues/1339 to monitor the advancement of this issue.")
+                errors.report(message,
+                        severity='error', symbol=expr)
+
         name = self._print(expr.name)
-        if all(isinstance(f, FunctionAddress) for f in expr.functions):
-            funcs = expr.functions
+        if all(isinstance(f, FunctionAddress) for f in interface_funcs):
+            funcs = interface_funcs
         else:
-            funcs = [f for f in expr.functions if f is \
+            funcs = [f for f in interface_funcs if f is \
                     expr.point([FunctionCallArgument(a.var.clone('arg_'+str(i))) \
                         for i,a in enumerate(f.arguments)], use_final_precision = True)]
 
@@ -3198,27 +3210,3 @@ def _print_BindCClassDef(self, expr):
                  *[a.getter for a in expr.attributes], *[a.setter for a in expr.attributes]]
         sep = f'\n{self._print(SeparatorComment(40))}\n'
         return '', sep.join(self._print(f) for f in funcs)
-
-
-def fcode(expr, filename, assign_to=None, **settings):
-    """Converts an expr to a string of Fortran code
-
-    expr : Expr
-        A pyccel expression to be converted.
-    filename : str
-        The name of the file being translated. Used in error printing
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    precision : integer, optional
-        The precision for numbers such as pi [default=15].
-    user_functions : dict, optional
-        A dictionary where keys are ``FunctionClass`` instances and values are
-        their string representations. Alternatively, the dictionary value can
-        be a list of tuples i.e. [(argument_test, cfunction_string)]. See below
-        for examples.
-    """
-
-    return FCodePrinter(filename, **settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/printing/luacode.py b/pyccel/codegen/printing/luacode.py
index c3edbdb22e..556c854b2b 100644
--- a/pyccel/codegen/printing/luacode.py
+++ b/pyccel/codegen/printing/luacode.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Lua code printer
@@ -507,118 +507,3 @@ def indent_code(self, code):
             level += increase[n]
         return pretty
 
-
-def lua_code(expr, assign_to=None, **settings):
-    """Converts an expr to a string of Lua code
-
-    expr : Expr
-        A sympy expression to be converted.
-    assign_to : optional
-        When given, the argument is used as the name of the variable to which
-        the expression is assigned. Can be a string, ``Symbol``,
-        ``MatrixSymbol``, or ``Indexed`` type. This is helpful in case of
-        line-wrapping, or for expressions that generate multi-line statements.
-    precision : integer, optional
-        The precision for numbers such as pi [default=15].
-    user_functions : dict, optional
-        A dictionary where the keys are string representations of either
-        ``FunctionClass`` or ``UndefinedFunction`` instances and the values
-        are their desired C string representations. Alternatively, the
-        dictionary value can be a list of tuples i.e. [(argument_test,
-        cfunction_string)].  See below for examples.
-    dereference : iterable, optional
-        An iterable of symbols that should be dereferenced in the printed code
-        expression. These would be values passed by address to the function.
-        For example, if ``dereference=[a]``, the resulting code would print
-        ``(*a)`` instead of ``a``.
-    human : bool, optional
-        If True, the result is a single string that may contain some constant
-        declarations for the number symbols. If False, the same information is
-        returned in a tuple of (symbols_to_declare, not_supported_functions,
-        code_text). [default=True].
-    contract: bool, optional
-        If True, ``Indexed`` instances are assumed to obey tensor contraction
-        rules and the corresponding nested loops over indices are generated.
-        Setting contract=False will not generate loops, instead the user is
-        responsible to provide values for the indices in the code.
-        [default=True].
-    locals: dict
-        A dictionary that contains the list of local symbols. these symbols will
-        be preceeded by local for their first assignment.
-
-    Examples
-
-    >>> from sympy import lua_code, symbols, Rational, sin, ceiling, Abs, Function
-    >>> x, tau = symbols("x, tau")
-    >>> lua_code((2*tau)**Rational(7, 2))
-    '8*1.4142135623731*tau.powf(7_f64/2.0)'
-    >>> lua_code(sin(x), assign_to="s")
-    's = x.sin();'
-
-    Simple custom printing can be defined for certain types by passing a
-    dictionary of {"type" : "function"} to the ``user_functions`` kwarg.
-    Alternatively, the dictionary value can be a list of tuples i.e.
-    [(argument_test, cfunction_string)].
-
-    >>> custom_functions = {
-    ...   "ceiling": "CEIL",
-    ...   "Abs": [(lambda x: not x.is_integer, "fabs", 4),
-    ...           (lambda x: x.is_integer, "ABS", 4)],
-    ...   "func": "f"
-    ... }
-    >>> func = Function('func')
-    >>> lua_code(func(Abs(x) + ceiling(x)), user_functions=custom_functions)
-    '(fabs(x) + x.CEIL()).f()'
-
-    ``Piecewise`` expressions are converted into conditionals. If an
-    ``assign_to`` variable is provided an if statement is created, otherwise
-    the ternary operator is used. Note that if the ``Piecewise`` lacks a
-    default term, represented by ``(expr, True)`` then an error will be thrown.
-    This is to prevent generating an expression that may not evaluate to
-    anything.
-
-    >>> from sympy import Piecewise
-    >>> expr = Piecewise((x + 1, x > 0), (x, True))
-    >>> print(lua_code(expr, tau))
-    tau = if (x > 0) {
-        x + 1
-    } else {
-        x
-    };
-
-    Support for loops is provided through ``Indexed`` types. With
-    ``contract=True`` these expressions will be turned into loops, whereas
-    ``contract=False`` will just print the assignment expression that should be
-    looped over:
-
-    >>> from sympy import Eq, IndexedBase, Idx
-    >>> len_y = 5
-    >>> y = IndexedBase('y', shape=(len_y,))
-    >>> t = IndexedBase('t', shape=(len_y,))
-    >>> Dy = IndexedBase('Dy', shape=(len_y-1,))
-    >>> i = Idx('i', len_y-1)
-    >>> e=Eq(Dy[i], (y[i+1]-y[i])/(t[i+1]-t[i]))
-    >>> lua_code(e.rhs, assign_to=e.lhs, contract=False)
-    'Dy[i] = (y[i + 1] - y[i])/(t[i + 1] - t[i]);'
-
-    Matrices are also supported, but a ``MatrixSymbol`` of the same dimensions
-    must be provided to ``assign_to``. Note that any expression that can be
-    generated normally can also exist inside a Matrix:
-
-    >>> from sympy import Matrix, MatrixSymbol
-    >>> mat = Matrix([x**2, Piecewise((x + 1, x > 0), (x, True)), sin(x)])
-    >>> A = MatrixSymbol('A', 3, 1)
-    >>> print(lua_code(mat, A))
-    A = [x.powi(2), if (x > 0) {
-        x + 1
-    } else {
-        x
-    }, x.sin()];
-    """
-
-    return LuaCodePrinter(settings).doprint(expr, assign_to)
-
-
-def print_lua_code(expr, **settings):
-    """Prints Lua representation of the given expression."""
-    print((lua_code(expr, **settings)))
diff --git a/pyccel/codegen/printing/pycode.py b/pyccel/codegen/printing/pycode.py
index 8cfdef22c5..a0dfe548c3 100644
--- a/pyccel/codegen/printing/pycode.py
+++ b/pyccel/codegen/printing/pycode.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 import warnings
 
@@ -239,7 +239,7 @@ def _print_NativeComplex(self, expr):
         return 'complex'
 
     def _print_Variable(self, expr):
-        return self._print(expr.name)
+        return expr.name
 
     def _print_DottedVariable(self, expr):
         rhs_code = self._print_Variable(expr)
@@ -410,7 +410,10 @@ def _print_Return(self, expr):
     def _print_Program(self, expr):
         mod_scope = self.scope
         self.set_scope(expr.scope)
-        imports  = ''.join(self._print(i) for i in expr.imports)
+        modules = expr.get_direct_user_nodes(lambda m: isinstance(m, Module))
+        assert len(modules) == 1
+        module = modules[0]
+        imports = ''.join(self._print(i) for i in expr.imports if i.source_module is not module)
         body     = self._print(expr.body)
         imports += ''.join(self._print(i) for i in self.get_additional_imports())
 
@@ -1170,22 +1173,3 @@ def _print_FunctionTypeAnnotation(self, expr):
     def _print_TypingFinal(self, expr):
         annotation = self._print(expr.arg)
         return f'const {annotation}'
-
-#==============================================================================
-def pycode(expr, assign_to=None, **settings):
-    """ Converts an expr to a string of Python code
-    Parameters
-    ==========
-    expr : Expr
-        A SymPy expression.
-    fully_qualified_modules : bool
-        Whether or not to write out full module names of functions
-        (``math.sin`` vs. ``sin``). default: ``True``.
-    Examples
-    ========
-    >>> from sympy import tan, Symbol
-    >>> from sympy.printing.pycode import pycode
-    >>> pycode(tan(Symbol('x')) + 1)
-    'math.tan(x) + 1'
-    """
-    return PythonCodePrinter(settings).doprint(expr, assign_to)
diff --git a/pyccel/codegen/python_wrapper.py b/pyccel/codegen/python_wrapper.py
index cc1eef8446..9437727042 100644
--- a/pyccel/codegen/python_wrapper.py
+++ b/pyccel/codegen/python_wrapper.py
@@ -1,25 +1,25 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 import os
 import time
 
-from pyccel.ast.core                        import ModuleHeader
-from pyccel.ast.numpy_wrapper               import get_numpy_max_acceptable_version_file
-from pyccel.codegen.printing.fcode          import fcode
-from pyccel.codegen.printing.cwrappercode   import CWrapperCodePrinter
-from pyccel.codegen.wrapper.fortran_to_c_wrapper   import FortranToCWrapper
-from pyccel.codegen.wrapper.c_to_python_wrapper    import CToPythonWrapper
-from pyccel.codegen.utilities      import recompile_object
-from pyccel.codegen.utilities      import copy_internal_library
-from pyccel.codegen.utilities      import internal_libs
-from pyccel.naming                 import name_clash_checkers
-from pyccel.parser.scope           import Scope
-from pyccel.utilities.stage        import PyccelStage
-from .compiling.basic     import CompileObj
+from pyccel.ast.core                             import ModuleHeader
+from pyccel.ast.numpy_wrapper                    import get_numpy_max_acceptable_version_file
+from pyccel.codegen.printing.cwrappercode        import CWrapperCodePrinter
+from pyccel.codegen.printing.fcode               import FCodePrinter
+from pyccel.codegen.wrapper.fortran_to_c_wrapper import FortranToCWrapper
+from pyccel.codegen.wrapper.c_to_python_wrapper  import CToPythonWrapper
+from pyccel.codegen.utilities                    import recompile_object
+from pyccel.codegen.utilities                    import copy_internal_library
+from pyccel.codegen.utilities                    import internal_libs
+from pyccel.naming                               import name_clash_checkers
+from pyccel.parser.scope                         import Scope
+from pyccel.utilities.stage                      import PyccelStage
+from .compiling.basic                            import CompileObj
 
 from pyccel.errors.errors import Errors
 
@@ -126,7 +126,7 @@ def create_shared_library(codegen,
         timings['Bind C wrapping'] = time.time() - start_bind_c_wrapping
 
         start_bind_c_printing = time.time()
-        bind_c_code = fcode(bind_c_mod, bind_c_mod.name)
+        bind_c_code = FCodePrinter(bind_c_mod.name).doprint(bind_c_mod)
         bind_c_filename = f'{bind_c_mod.name}.f90'
 
         with open(bind_c_filename, 'w') as f:
@@ -170,7 +170,6 @@ def create_shared_library(codegen,
     #      Print code specific cwrapper
     #---------------------------------------
     module_old_name = codegen.ast.name
-    codegen.ast.set_name(sharedlib_modname)
     wrapper_codegen = CWrapperCodePrinter(codegen.parser.filename, language)
     Scope.name_clash_checker = name_clash_checkers['c']
     wrapper = CToPythonWrapper(base_dirpath)
@@ -185,8 +184,6 @@ def create_shared_library(codegen,
     if errors.has_errors():
         return
 
-    codegen.ast.set_name(module_old_name)
-
     with open(wrapper_filename, 'w', encoding="utf-8") as f:
         f.writelines(wrapper_code)
     timings['Wrapper printing'] = time.time() - start_print_cwrapper
diff --git a/pyccel/codegen/utilities.py b/pyccel/codegen/utilities.py
index b9b419390f..190044b5f0 100644
--- a/pyccel/codegen/utilities.py
+++ b/pyccel/codegen/utilities.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/codegen/wrapper/c_to_python_wrapper.py b/pyccel/codegen/wrapper/c_to_python_wrapper.py
index 18b64c8818..8e845388c8 100644
--- a/pyccel/codegen/wrapper/c_to_python_wrapper.py
+++ b/pyccel/codegen/wrapper/c_to_python_wrapper.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module describing the code-wrapping class : CToPythonWrapper
@@ -11,13 +11,13 @@
 from pyccel.ast.bind_c        import BindCFunctionDef, BindCPointer, BindCFunctionDefArgument
 from pyccel.ast.bind_c        import BindCModule, BindCVariable, BindCFunctionDefResult
 from pyccel.ast.bind_c        import BindCClassDef, BindCClassProperty
-from pyccel.ast.builtins      import PythonTuple, PythonRange
+from pyccel.ast.builtins      import PythonTuple
 from pyccel.ast.class_defs    import StackArrayClass
 from pyccel.ast.core          import Interface, If, IfSection, Return, FunctionCall
 from pyccel.ast.core          import FunctionDef, FunctionDefArgument, FunctionDefResult
 from pyccel.ast.core          import Assign, AliasAssign, Deallocate, Allocate
 from pyccel.ast.core          import Import, Module, AugAssign, CommentBlock
-from pyccel.ast.core          import FunctionAddress, Declare, ClassDef, For, AsName
+from pyccel.ast.core          import FunctionAddress, Declare, ClassDef, AsName
 from pyccel.ast.cwrapper      import PyModule, PyccelPyObject, PyArgKeywords, PyModule_Create
 from pyccel.ast.cwrapper      import PyArg_ParseTupleNode, Py_None, PyClassDef, PyModInitFunc
 from pyccel.ast.cwrapper      import py_to_c_registry, check_type_registry, PyBuildValueNode
@@ -26,7 +26,7 @@
 from pyccel.ast.cwrapper      import C_to_Python, PyFunctionDef, PyInterface
 from pyccel.ast.cwrapper      import PyModule_AddObject, Py_DECREF, PyObject_TypeCheck
 from pyccel.ast.cwrapper      import Py_INCREF, PyType_Ready, WrapperCustomDataType
-from pyccel.ast.cwrapper      import PyList_New, PyList_Append, PyList_Size, PyList_GetItem, PyList_SetItem
+from pyccel.ast.cwrapper      import PyList_New, PyList_Append, PyList_GetItem, PyList_SetItem
 from pyccel.ast.cwrapper      import PyccelPyTypeObject, PyCapsule_New, PyCapsule_Import
 from pyccel.ast.cwrapper      import PySys_GetObject, PyUnicode_FromString, PyGetSetDefElement
 from pyccel.ast.c_concepts    import ObjectAddress, PointerCast, CStackArray
@@ -601,7 +601,7 @@ def _build_module_init_function(self, expr, imports):
             The initialisation function.
         """
 
-        mod_name = getattr(expr, 'original_module', expr).name
+        mod_name = self.scope.get_python_name(getattr(expr, 'original_module', expr).name)
         # Initialise the scope
         func_name = self.scope.get_new_name(f'PyInit_{mod_name}')
         func_scope = self.scope.new_child_scope(func_name)
@@ -637,7 +637,7 @@ def _build_module_init_function(self, expr, imports):
         ok_code = LiteralInteger(0)
 
         # Save Capsule describing types (needed for dependent modules)
-        body.append(AliasAssign(capsule_obj, PyCapsule_New(API_var, self.scope.get_python_name(mod_name))))
+        body.append(AliasAssign(capsule_obj, PyCapsule_New(API_var, mod_name)))
         body.extend(self._add_object_to_mod(module_var, capsule_obj, '_C_API', initialised))
 
         body.append(FunctionCall(import_array, ()))
@@ -1056,9 +1056,10 @@ def _wrap_Module(self, expr):
 
         imports += cwrapper_ndarray_imports if self._wrapping_arrays else []
         if not isinstance(expr, BindCModule):
-            imports.append(Import(expr.name, expr))
+            imports.append(Import(mod_scope.get_python_name(expr.name), expr))
         original_mod = getattr(expr, 'original_module', expr)
-        return PyModule(original_mod.name, [API_var], funcs, imports = imports,
+        original_mod_name = mod_scope.get_python_name(original_mod.name)
+        return PyModule(original_mod_name, [API_var], funcs, imports = imports,
                         interfaces = interfaces, classes = classes, scope = mod_scope,
                         init_func = init_func, import_func = import_func)
 
@@ -2126,7 +2127,7 @@ def _wrap_Import(self, expr):
 
         if import_wrapper:
             wrapper_name = f'{expr.source}_wrapper'
-            mod_spoof = PyModule(expr.source_module.name.name, (), (), scope = Scope())
+            mod_spoof = PyModule(expr.source_module.name, (), (), scope = Scope())
             return Import(wrapper_name, AsName(mod_spoof, expr.source), mod = mod_spoof)
         else:
             return None
diff --git a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py
index 19e7eb9bf0..869f3f899e 100644
--- a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py
+++ b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module describing the code-wrapping class : FortranToCWrapper
@@ -188,10 +188,10 @@ def _wrap_Module(self, expr):
         classes = [self._wrap(f) for f in expr.classes]
         variables = [self._wrap(v) for v in expr.variables if not v.is_private]
         variable_getters = [v for v in variables if isinstance(v, BindCArrayVariable)]
-        imports = [Import(expr.name, target = expr, mod=expr)]
+        imports = [Import(self.scope.get_python_name(expr.name), target = expr, mod=expr)]
 
-        name = mod_scope.get_new_name(f'bind_c_{expr.name.target}')
-        self._wrapper_names_dict[expr.name.target] = name
+        name = mod_scope.get_new_name(f'bind_c_{expr.name}')
+        self._wrapper_names_dict[expr.name] = name
 
         self.exit_scope()
 
diff --git a/pyccel/codegen/wrapper/wrapper.py b/pyccel/codegen/wrapper/wrapper.py
index e4b4220455..f111d6ab2c 100644
--- a/pyccel/codegen/wrapper/wrapper.py
+++ b/pyccel/codegen/wrapper/wrapper.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module describing the base code-wrapping class : Wrapper.
diff --git a/pyccel/commands/console.py b/pyccel/commands/console.py
index aa9c1aadc5..596c440ec0 100644
--- a/pyccel/commands/console.py
+++ b/pyccel/commands/console.py
@@ -2,7 +2,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 import sys
@@ -286,50 +286,3 @@ def pyccel(files=None, mpi=None, openmp=None, openacc=None, output_dir=None, com
         sys.exit(1)
     finally:
         os.chdir(base_dirpath)
-
-#==============================================================================
-# NOTE: left here for later reference
-#
-#    group.add_argument('--prefix', type=str, default = '',\
-#                       help='add prefix to the generated file.')
-#    group.add_argument('--prefix-module', type=str, default = '',\
-#                       help='add prefix module name.')
-#    group.add_argument('--language', type=str, help='target language')
-#
-#    ...
-#
-#    prefix = args.prefix
-#    prefix_module = args.prefix_module
-#    language = args.language
-#
-#    output_folder = args.output
-#
-#    if (len(output_folder)>0 and output_folder[-1]!='/'):
-#        output_folder+='/'
-#
-#    ...
-#
-#    elif args.convert_only:
-#        pyccel = Parser(filename)
-#        ast = pyccel.parse()
-#        settings = {}
-#        if args.language:
-#            settings['language'] = args.language
-#        ast = pyccel.annotate(**settings)
-#        name = os.path.basename(filename)
-#        name = os.path.splitext(name)[0]
-#        codegen = Codegen(ast, name)
-#        settings['prefix_module'] = prefix_module
-#        code = codegen.doprint(**settings)
-#        if prefix:
-#            name = '{prefix}{name}'.format(prefix=prefix, name=name)
-#
-#        codegen.export(output_folder+name)
-#
-#        for son in pyccel.sons:
-#            if 'print' in son.metavars.keys():
-#                name = son.filename.split('/')[-1].strip('.py')
-#                name = 'mod_'+name
-#                codegen = Codegen(son.ast, name)
-#                code = codegen.doprint()
-#                codegen.export()
diff --git a/pyccel/commands/lambdify.py b/pyccel/commands/lambdify.py
new file mode 100644
index 0000000000..c3220b2865
--- /dev/null
+++ b/pyccel/commands/lambdify.py
@@ -0,0 +1,127 @@
+"""
+File describing commands associated with the lambdify function which converts a
+SymPy expression into a Pyccel-accelerated function.
+"""
+import sympy as sp
+from packaging import version
+
+from pyccel.epyccel           import epyccel
+from pyccel.utilities.strings import random_string
+from pyccel.errors.errors     import PyccelError
+
+if version.parse(sp.__version__) >= version.parse('1.8'):
+    from sympy.printing.numpy import NumPyPrinter
+else:
+    from sympy.printing.pycode import NumPyPrinter
+
+def lambdify(expr : sp.Expr, args : 'dict[sp.Symbol, str]', *, result_type : str = None,
+             templates : 'dict[str, list[str]]' = None, use_out = False,
+             **kwargs):
+    """
+    Convert a SymPy expression into a Pyccel-accelerated function.
+
+    Convert a SymPy expression into a function that allows for fast
+    numeric evaluation. This is done using SymPy's NumPyPrinter to
+    generate code that can be accelerated by Pyccel.
+
+    Parameters
+    ----------
+    expr : sp.Expr
+        The SymPy expression that should be returned from the function.
+    args : dict[sp.Symbol, str]
+        A dictionary of the arguments of the function being created.
+        The keys are variables representing the arguments that will be
+        passed to the function. The values are the the type annotations
+        for those functions.
+    result_type : str, optional
+        The type annotation for the result of the function. This argument
+        is optional but it is recommended to provide it as SymPy
+        expressions do not always evaluate to the expected type. For
+        example if the SymPy expression simplifies to 0 then the default
+        type will be int even if the arguments are floats.
+    templates : dict[str, list[str]], optional
+        A description of any templates that should be added to the
+        function. The keys are the symbols which can be used as type
+        specifiers, the values are a list of the type annotations which
+        are valid types for the symbol. See
+        <https://github.com/pyccel/pyccel/blob/devel/docs/templates.md>
+        for more details.
+    use_out : bool, default=False
+        If true the function will modify an argument called 'out' instead
+        of returning a newly allocated array. If this argument is set then
+        result_type must be provided. This only works if the result is an
+        array type.
+    **kwargs : dict
+        Additional arguments that are passed to epyccel.
+
+    Returns
+    -------
+    func
+        A Pyccel-accelerated function which allows the evaluation of
+        the SymPy expression.
+
+    See Also
+    --------
+    sympy.lambdify
+        <https://docs.sympy.org/latest/modules/utilities/lambdify.html>.
+    epyccel
+        The function that accelerates the generated code.
+    """
+    if not (isinstance(args, dict) and all(isinstance(k, sp.Symbol) and isinstance(v, str) for k,v in args.items())):
+        raise TypeError("Argument 'args': Expected a dictionary mapping SymPy symbols to string type annotations.")
+    if result_type is not None and not isinstance(result_type, str):
+        raise TypeError("Argument 'result_type': Expected a string type annotation.")
+
+    expr = NumPyPrinter().doprint(expr)
+    args_code = ', '.join(f'{a} : "{annot}"' for a, annot in args.items())
+    func_name = 'func_'+random_string(8)
+
+    docstring = " \n".join(('    """',
+            "    Expression evaluation created with `pyccel.lambdify`.",
+            "",
+            "    Function evaluating the expression:",
+           f"    {expr}",
+            "",
+            "    Parameters",
+            "    ----------\n"))
+    docstring += '\n'.join(f"    {a} : {type_annot}" for a, type_annot in args.items())
+
+    if use_out:
+        if not result_type:
+            raise TypeError("The result_type must be provided if use_out is true.")
+        else:
+            signature = f'def {func_name}({args_code}, out : "{result_type}"):'
+            docstring += f"\n    out : {result_type}"
+    elif result_type:
+        signature = f'def {func_name}({args_code}) -> "{result_type}":'
+        docstring += "\n".join(("\n",
+                    "     Returns",
+                    "     -------",
+                   f"     {result_type}"))
+    else:
+        signature = f'def {func_name}({args_code}):'
+    if templates:
+        if not (isinstance(templates, dict) and all(isinstance(k, str) and hasattr(v, '__iter__') for k,v in templates.items()) \
+                and all(all(isinstance(type_annot, str) for type_annot in v) for v in templates.values())):
+            raise TypeError("Argument 'templates': Expected a dictionary mapping strings describing type specifiers to lists of string type annotations.")
+
+        decorators = '\n'.join(f'@template("{key}", ['+', '.join(f'"{annot}"' for annot in annotations)+'])' \
+                for key, annotations in templates.items())
+    else:
+        decorators = ''
+    if use_out:
+        code = f'    out[:] = {expr}'
+    else:
+        code = f'    return {expr}'
+    numpy_import = 'import numpy\n'
+
+    docstring += '\n    """'
+
+    func = '\n'.join((numpy_import, decorators, signature, docstring, code))
+    try:
+        package = epyccel(func, **kwargs)
+    except PyccelError as e:
+        raise type(e)(str(e)) from None
+
+    return getattr(package, func_name)
+
diff --git a/pyccel/commands/pyccel_clean.py b/pyccel/commands/pyccel_clean.py
index 03ba45e506..c14c1191f7 100644
--- a/pyccel/commands/pyccel_clean.py
+++ b/pyccel/commands/pyccel_clean.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing scripts to remove pyccel generated objects
 """
diff --git a/pyccel/commands/pyccel_init.py b/pyccel/commands/pyccel_init.py
index 9c42da6d74..441e9de323 100644
--- a/pyccel/commands/pyccel_init.py
+++ b/pyccel/commands/pyccel_init.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing script to pyccelize internal files
 """
diff --git a/pyccel/complexity/arithmetic.py b/pyccel/complexity/arithmetic.py
index 2f08ef5143..dab6bb548c 100644
--- a/pyccel/complexity/arithmetic.py
+++ b/pyccel/complexity/arithmetic.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/complexity/basic.py b/pyccel/complexity/basic.py
index 51386f9194..dfff4bbadf 100644
--- a/pyccel/complexity/basic.py
+++ b/pyccel/complexity/basic.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 from pyccel.parser.parser import Parser
diff --git a/pyccel/complexity/memory.py b/pyccel/complexity/memory.py
index 5bf110c8aa..0ca5f481b1 100644
--- a/pyccel/complexity/memory.py
+++ b/pyccel/complexity/memory.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/decorators.py b/pyccel/decorators.py
index a12f13b36f..1f640043db 100644
--- a/pyccel/decorators.py
+++ b/pyccel/decorators.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
@@ -13,7 +13,6 @@
     'bypass',
     'elemental',
     'inline',
-    'lambdify',
     'private',
     'pure',
     'stack_array',
@@ -22,16 +21,6 @@
     'types',
 )
 
-def lambdify(f):
-
-    args = f.__code__.co_varnames
-    from sympy import symbols
-    args = symbols(args)
-    expr = f(*args)
-    def wrapper(*vals):
-        return  expr.subs(zip(args,vals)).doit()
-
-    return wrapper
 
 def sympy(f):
     return f
diff --git a/pyccel/epyccel.py b/pyccel/epyccel.py
index fe849c1b39..f4fc277ed2 100644
--- a/pyccel/epyccel.py
+++ b/pyccel/epyccel.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 
@@ -9,24 +9,18 @@
 import importlib
 import sys
 import os
-import string
-import random
+
 from filelock import FileLock, Timeout
 
 from types import ModuleType, FunctionType
 from importlib.machinery import ExtensionFileLoader
 
-from pyccel.codegen.pipeline import execute_pyccel
-from pyccel.errors.errors import ErrorsMode
-
-__all__ = ['random_string', 'get_source_function', 'epyccel_seq', 'epyccel']
+from pyccel.utilities.strings  import random_string
+from pyccel.codegen.pipeline   import execute_pyccel
+from pyccel.errors.errors      import ErrorsMode, PyccelError
 
-#==============================================================================
-random_selector = random.SystemRandom()
+__all__ = ['get_source_function', 'epyccel_seq', 'epyccel']
 
-def random_string( n ):
-    chars    = string.ascii_lowercase + string.digits
-    return ''.join( random_selector.choice( chars ) for _ in range(n) )
 
 #==============================================================================
 def get_source_function(func):
@@ -124,8 +118,11 @@ def epyccel_seq(function_or_module, *,
 
     Parameters
     ----------
-    function_or_module : function | module
+    function_or_module : function | module | str
         Python function or module to be accelerated.
+        If a string is passed then it is assumed to be the code from a module which
+        should be accelerated. The module must be capable of running as a standalone
+        file so it must include any necessary import statements.
     language : {'fortran', 'c', 'python'}
         Language of generated code (default: 'fortran').
     compiler : str, optional
@@ -173,7 +170,7 @@ def epyccel_seq(function_or_module, *,
     # Store current directory
     base_dirpath = os.getcwd()
 
-    if isinstance(function_or_module, (FunctionType, type)):
+    if isinstance(function_or_module, (FunctionType, type, str)):
         dirpath = os.getcwd()
 
     elif isinstance(function_or_module, ModuleType):
@@ -203,6 +200,11 @@ def epyccel_seq(function_or_module, *,
 
         module_name, module_lock = get_unique_name(pymod.__name__, epyccel_dirpath)
 
+    elif isinstance(function_or_module, str):
+        code = function_or_module
+
+        module_name, module_lock = get_unique_name('mod', epyccel_dirpath)
+
     else:
         raise TypeError('> Expecting a FunctionType, type or a ModuleType')
 
@@ -283,8 +285,10 @@ def epyccel( python_function_or_module, **kwargs ):
 
     Parameters
     ----------
-    python_function_or_module : function | module
+    python_function_or_module : function | module | str
         Python function or module to be accelerated.
+        If a string is passed then it is assumed to be the code from a module which
+        should be accelerated..
     **kwargs :
         Additional keyword arguments for configuring the compilation and acceleration process.
         Available options are defined in epyccel_seq.
@@ -306,7 +310,7 @@ def epyccel( python_function_or_module, **kwargs ):
     >>> one_f = epyccel(one, language='fortran')
     >>> one_c = epyccel(one, language='c')
     """
-    assert isinstance( python_function_or_module, (FunctionType, type, ModuleType) )
+    assert isinstance( python_function_or_module, (FunctionType, type, ModuleType, str) )
 
     comm  = kwargs.pop('comm', None)
     root  = kwargs.pop('root', 0)
@@ -340,6 +344,8 @@ def epyccel( python_function_or_module, **kwargs ):
                 fun_name = python_function_or_module.__name__ if fun else None
                 success  = True
             # error handling carried out after broadcast to prevent deadlocks
+            except PyccelError as e:
+                raise type(e)(str(e)) from None
             except BaseException as e: # pylint: disable=broad-except
                 exc_info = e
                 success  = False
@@ -377,7 +383,10 @@ def epyccel( python_function_or_module, **kwargs ):
 
     # Serial version
     else:
-        mod, fun = epyccel_seq( python_function_or_module, **kwargs )
+        try:
+            mod, fun = epyccel_seq( python_function_or_module, **kwargs )
+        except PyccelError as e:
+            raise type(e)(str(e)) from None
 
     # Return Fortran function (if any), otherwise module
     return fun or mod
diff --git a/pyccel/errors/errors.py b/pyccel/errors/errors.py
index 8ad82ed6a9..ca63233149 100644
--- a/pyccel/errors/errors.py
+++ b/pyccel/errors/errors.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/errors/messages.py b/pyccel/errors/messages.py
index 944b128751..9fe996a701 100644
--- a/pyccel/errors/messages.py
+++ b/pyccel/errors/messages.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 
@@ -27,8 +27,8 @@
 STACK_ARRAY_DEFINITION_IN_LOOP = 'Cannot create stack array in loop, because if does not support memory reallocation. Create array before loop, or use standard heap array.'
 STACK_ARRAY_UNKNOWN_SHAPE = 'Cannot create stack array from a shape which is unknown at function entry'
 STACK_ARRAY_SHAPE_UNPURE_FUNC = 'Cannot create stack array from a shape created with an impure function'
-INCOMPATIBLE_ARGUMENT = 'Argument {} : {}, passed to function {} is incompatible (expected {}). Please cast the argument explicitly or overload the function (see https://github.com/pyccel/pyccel/blob/master/tutorial/headers.md for details)'
-INCOMPATIBLE_ORDERING = "Argument {idx} : {arg}, passed to function {func} is incompatible as it has the wrong ordering (expected '{order}'). Please use an argument with '{order}' ordering, explicitly transpose {arg}, or overload the function (see https://github.com/pyccel/pyccel/blob/master/tutorial/headers.md for details)"
+INCOMPATIBLE_ARGUMENT = 'Argument {} : {}, passed to function {} is incompatible (expected {}). Please cast the argument explicitly or overload the function (see https://github.com/pyccel/pyccel/blob/devel/docs/type_annotations.md for details)'
+INCOMPATIBLE_ORDERING = "Argument {idx} : {arg}, passed to function {func} is incompatible as it has the wrong ordering (expected '{order}'). Please use an argument with '{order}' ordering, explicitly transpose {arg}, or overload the function (see https://github.com/pyccel/pyccel/blob/devel/docs/type_annotations.md for details)"
 UNRECOGNISED_FUNCTION_CALL = 'Function call cannot be processed. Please ensure that your code runs correctly in python. If this is the case then you may be using function arguments which are not currently supported by pyccel. Please create an issue at https://github.com/pyccel/pyccel/issues and provide a small example of your problem.'
 
 UNSUPPORTED_FEATURE_OOP_EMPTY_CLASS = "Empty classes are not supported"
diff --git a/pyccel/naming/__init__.py b/pyccel/naming/__init__.py
index a71d841c8e..72c318d3ad 100644
--- a/pyccel/naming/__init__.py
+++ b/pyccel/naming/__init__.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Module containing all classes which handle name collision rules
diff --git a/pyccel/naming/cnameclashchecker.py b/pyccel/naming/cnameclashchecker.py
index f1639f64d7..6485bcfdb3 100644
--- a/pyccel/naming/cnameclashchecker.py
+++ b/pyccel/naming/cnameclashchecker.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Handles name clash problems in C
diff --git a/pyccel/naming/fortrannameclashchecker.py b/pyccel/naming/fortrannameclashchecker.py
index b7873d10e3..a9070a7d3d 100644
--- a/pyccel/naming/fortrannameclashchecker.py
+++ b/pyccel/naming/fortrannameclashchecker.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Handles name clash problems in Fortran.
diff --git a/pyccel/naming/languagenameclashchecker.py b/pyccel/naming/languagenameclashchecker.py
index c8bec836d6..fa672a905b 100644
--- a/pyccel/naming/languagenameclashchecker.py
+++ b/pyccel/naming/languagenameclashchecker.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Superclass for handling name clash problems.
diff --git a/pyccel/naming/pythonnameclashchecker.py b/pyccel/naming/pythonnameclashchecker.py
index 319f14c72a..3fc08be600 100644
--- a/pyccel/naming/pythonnameclashchecker.py
+++ b/pyccel/naming/pythonnameclashchecker.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 Handles name clash problems in Python
diff --git a/pyccel/parser/base.py b/pyccel/parser/base.py
index 54b50bd3f3..1cafb753f8 100644
--- a/pyccel/parser/base.py
+++ b/pyccel/parser/base.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/parser/extend_tree.py b/pyccel/parser/extend_tree.py
index 515db1e2ec..d62d58ab5e 100644
--- a/pyccel/parser/extend_tree.py
+++ b/pyccel/parser/extend_tree.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """Extended AST with CommentLine nodes
diff --git a/pyccel/parser/parser.py b/pyccel/parser/parser.py
index 5f5b85a1ca..7808446260 100644
--- a/pyccel/parser/parser.py
+++ b/pyccel/parser/parser.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/parser/scope.py b/pyccel/parser/scope.py
index 1ce5037b8f..fdf3a2d066 100644
--- a/pyccel/parser/scope.py
+++ b/pyccel/parser/scope.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing the Scope class
 """
diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py
index 4d596d65bc..e987ec9b7f 100644
--- a/pyccel/parser/semantic.py
+++ b/pyccel/parser/semantic.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ File containing SemanticParser. This class handles the semantic stage of the translation.
 See the developer docs for more details
@@ -73,7 +73,7 @@
 from pyccel.ast.headers import FunctionHeader, MethodHeader, Header
 from pyccel.ast.headers import MacroFunction, MacroVariable
 
-from pyccel.ast.internals import PyccelInternalFunction, Slice, PyccelSymbol, get_final_precision
+from pyccel.ast.internals import PyccelInternalFunction, Slice, PyccelSymbol, get_final_precision, PyccelArrayShapeElement
 from pyccel.ast.itertoolsext import Product
 
 from pyccel.ast.literals import LiteralTrue, LiteralFalse
@@ -2168,6 +2168,9 @@ def _visit_Module(self, expr):
         container['imports'][mod_name] = Import(mod_name, mod)
 
         if program_body:
+            container = self._program_namespace.imports
+            container['imports'][mod_name] = Import(self.scope.get_python_name(mod_name), mod)
+
             if init_func:
                 import_init  = FunctionCall(init_func,[],[])
                 program_body = [import_init, *program_body]
@@ -3217,7 +3220,7 @@ def _visit_Assign(self, expr):
                         new_lhs.append( self._assign_lhs_variable(l, d_var[i].copy(), rhs, new_expressions, isinstance(expr, AugAssign)) )
                 lhs = PythonTuple(*new_lhs)
 
-            elif d_var['shape'][0]==n:
+            elif d_var['shape'][0]==n or isinstance(d_var['shape'][0], PyccelArrayShapeElement):
                 new_lhs = []
                 new_rhs = []
 
@@ -3226,7 +3229,7 @@ def _visit_Assign(self, expr):
                     new_rhs.append(r)
 
                 lhs = PythonTuple(*new_lhs)
-                rhs = new_rhs
+                rhs = PythonTuple(*new_rhs)
             else:
                 errors.report(WRONG_NUMBER_OUTPUT_ARGS, symbol=expr, severity='error')
                 return None
@@ -3749,6 +3752,9 @@ def _visit_Return(self, expr):
         for o,r in zip(return_objs, results):
             v = o.var
             if not (isinstance(r, PyccelSymbol) and r == (v.name if isinstance(v, Variable) else v)):
+                # Create a syntactic object to visit
+                if isinstance(v, Variable):
+                    v = PyccelSymbol(v.name)
                 a = self._visit(Assign(v, r, python_ast=expr.python_ast))
                 assigns.append(a)
                 if isinstance(a, ConstructorCall):
diff --git a/pyccel/parser/syntactic.py b/pyccel/parser/syntactic.py
index 7d10e88e69..f68179a99f 100644
--- a/pyccel/parser/syntactic.py
+++ b/pyccel/parser/syntactic.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 import os
@@ -344,7 +344,8 @@ def _visit_Module(self, stmt):
         # Define the name of the module
         # The module name allows it to be correctly referenced from an import command
         mod_name = os.path.splitext(os.path.basename(self._filename))[0]
-        name = AsName(mod_name, self.scope.get_new_name(mod_name))
+        name = self.scope.get_new_name(mod_name)
+        self.scope.python_names[name] = mod_name
 
         body = [b for i in body for b in (i.body if isinstance(i, CodeBlock) else [i])]
         return Module(name, [], [], program = CodeBlock(body), scope=self.scope)
diff --git a/pyccel/parser/syntax/basic.py b/pyccel/parser/syntax/basic.py
index 9bf5e19342..402354ed6f 100644
--- a/pyccel/parser/syntax/basic.py
+++ b/pyccel/parser/syntax/basic.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 __all__ = ["BasicStmt"]
diff --git a/pyccel/parser/syntax/headers.py b/pyccel/parser/syntax/headers.py
index aa4aad57a4..bcccbcb18a 100644
--- a/pyccel/parser/syntax/headers.py
+++ b/pyccel/parser/syntax/headers.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 """
diff --git a/pyccel/parser/syntax/openacc.py b/pyccel/parser/syntax/openacc.py
index d319f274a2..fa0c3523e6 100644
--- a/pyccel/parser/syntax/openacc.py
+++ b/pyccel/parser/syntax/openacc.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 """
diff --git a/pyccel/parser/syntax/openmp.py b/pyccel/parser/syntax/openmp.py
index e2ee4f1cdc..ed7a11e940 100644
--- a/pyccel/parser/syntax/openmp.py
+++ b/pyccel/parser/syntax/openmp.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 """
diff --git a/pyccel/parser/utilities.py b/pyccel/parser/utilities.py
index 9403e9b5f8..6d7b8ce032 100644
--- a/pyccel/parser/utilities.py
+++ b/pyccel/parser/utilities.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """This file contains different utilities for the Parser."""
diff --git a/pyccel/stdlib/cwrapper/cwrapper.c b/pyccel/stdlib/cwrapper/cwrapper.c
index 80de0d0d9f..257b2daaf6 100644
--- a/pyccel/stdlib/cwrapper/cwrapper.c
+++ b/pyccel/stdlib/cwrapper/cwrapper.c
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #include "cwrapper.h"
 
diff --git a/pyccel/stdlib/cwrapper/cwrapper.h b/pyccel/stdlib/cwrapper/cwrapper.h
index 48a9f0a2c1..b60e1888d2 100644
--- a/pyccel/stdlib/cwrapper/cwrapper.h
+++ b/pyccel/stdlib/cwrapper/cwrapper.h
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 /*
  * File containing functions useful for the cwrapper.
diff --git a/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.c b/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.c
index 3b95c21ea8..e2d43d95cb 100644
--- a/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.c
+++ b/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.c
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #include <string.h>
 #include "cwrapper_ndarrays.h"
diff --git a/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.h b/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.h
index 2e69532212..05799a249e 100644
--- a/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.h
+++ b/pyccel/stdlib/cwrapper_ndarrays/cwrapper_ndarrays.h
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 /*
  * File containing functions useful for the cwrapper which require ndarrays.
diff --git a/pyccel/stdlib/external/dfftpack.py b/pyccel/stdlib/external/dfftpack.py
index 2484bde90d..83964124ca 100644
--- a/pyccel/stdlib/external/dfftpack.py
+++ b/pyccel/stdlib/external/dfftpack.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/stdlib/external/fitpack.py b/pyccel/stdlib/external/fitpack.py
index f63762d45f..b005a2894e 100644
--- a/pyccel/stdlib/external/fitpack.py
+++ b/pyccel/stdlib/external/fitpack.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 
diff --git a/pyccel/stdlib/external/lapack.py b/pyccel/stdlib/external/lapack.py
index 0b158f3aac..180498c0e7 100644
--- a/pyccel/stdlib/external/lapack.py
+++ b/pyccel/stdlib/external/lapack.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/stdlib/external/mpi4py.py b/pyccel/stdlib/external/mpi4py.py
index ce27510adb..ed11ef9208 100644
--- a/pyccel/stdlib/external/mpi4py.py
+++ b/pyccel/stdlib/external/mpi4py.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/stdlib/internal/mpiext.py b/pyccel/stdlib/internal/mpiext.py
index a3a8fe4836..ae606d1cdf 100644
--- a/pyccel/stdlib/internal/mpiext.py
+++ b/pyccel/stdlib/internal/mpiext.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 """
diff --git a/pyccel/stdlib/internal/openmp.py b/pyccel/stdlib/internal/openmp.py
index 5559dd9894..caf43f0252 100644
--- a/pyccel/stdlib/internal/openmp.py
+++ b/pyccel/stdlib/internal/openmp.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """
 File providing functions to mimic OpenMP Runtime library routines to allow files to run
diff --git a/pyccel/stdlib/math/pyc_math_c.c b/pyccel/stdlib/math/pyc_math_c.c
index 640f8ed961..5dae9f14d8 100644
--- a/pyccel/stdlib/math/pyc_math_c.c
+++ b/pyccel/stdlib/math/pyc_math_c.c
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #include "pyc_math_c.h"
 #include <math.h>
diff --git a/pyccel/stdlib/math/pyc_math_c.h b/pyccel/stdlib/math/pyc_math_c.h
index 60c8cd361e..20dd1aca9c 100644
--- a/pyccel/stdlib/math/pyc_math_c.h
+++ b/pyccel/stdlib/math/pyc_math_c.h
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #ifndef         PYC_MATH_C_H
 #define         PYC_MATH_C_H
diff --git a/pyccel/stdlib/math/pyc_math_f90.f90 b/pyccel/stdlib/math/pyc_math_f90.f90
index 593cead82d..c38831ba73 100644
--- a/pyccel/stdlib/math/pyc_math_f90.f90
+++ b/pyccel/stdlib/math/pyc_math_f90.f90
@@ -1,7 +1,7 @@
-! --------------------------------------------------------------------------------------- !
-! This file is part of Pyccel which is released under MIT License. See the LICENSE file   !
-! or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. !
-! --------------------------------------------------------------------------------------- !
+! -------------------------------------------------------------------------------------- !
+! This file is part of Pyccel which is released under MIT License. See the LICENSE file  !
+! or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. !
+! -------------------------------------------------------------------------------------- !
 
 module pyc_math_f90
 
diff --git a/pyccel/stdlib/ndarrays/ndarrays.c b/pyccel/stdlib/ndarrays/ndarrays.c
index 98e9990132..bceaeea429 100644
--- a/pyccel/stdlib/ndarrays/ndarrays.c
+++ b/pyccel/stdlib/ndarrays/ndarrays.c
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 # include "ndarrays.h"
 # include <string.h>
@@ -490,6 +490,175 @@ bool is_same_shape(t_ndarray a, t_ndarray b)
     return (true);
 }
 
+#define COPY_DATA_FROM_(SRC_TYPE) \
+    void copy_data_from_##SRC_TYPE(t_ndarray **ds, t_ndarray src, uint32_t offset, bool elem_wise_cp) \
+    { \
+        t_ndarray *dest = *ds; \
+        switch(dest->type) \
+        { \
+            case nd_bool: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_bool[i + offset] = (bool)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_bool[element_index(*dest, i, dest->nd) + offset] = (bool)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_int8: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int8[i + offset] = (int8_t)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int8[element_index(*dest, i, dest->nd) + offset] = (int8_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_int16: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int16[i + offset] = (int16_t)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int16[element_index(*dest, i, dest->nd) + offset] = (int16_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_int32: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int32[i + offset] = (int32_t)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int32[element_index(*dest, i, dest->nd) + offset] = (int32_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_int64: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int64[i + offset] = (int64_t)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_int64[element_index(*dest, i, dest->nd) + offset] = (int64_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_float: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_float[i + offset] = (float)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_float[element_index(*dest, i, dest->nd) + offset] = (float)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_double: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_double[i + offset] = (double)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_double[element_index(*dest, i, dest->nd) + offset] = (double)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_cfloat: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_cfloat[i + offset] = (float complex)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_cfloat[element_index(*dest, i, dest->nd) + offset] = (float complex)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+            case nd_cdouble: \
+                if(elem_wise_cp == false)\
+                { \
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_cdouble[i + offset] = (double complex)src.nd_##SRC_TYPE[i]; \
+                }\
+                else \
+                {\
+                    for(int64_t i = 0; i < src.length; i++) \
+                        dest->nd_cdouble[element_index(*dest, i, dest->nd) + offset] = (double complex)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
+                }\
+                break; \
+        } \
+    }
+
+COPY_DATA_FROM_(bool)
+COPY_DATA_FROM_(int8)
+COPY_DATA_FROM_(int16)
+COPY_DATA_FROM_(int32)
+COPY_DATA_FROM_(int64)
+COPY_DATA_FROM_(float)
+COPY_DATA_FROM_(double)
+COPY_DATA_FROM_(cfloat)
+COPY_DATA_FROM_(cdouble)
+
+void copy_data(t_ndarray **ds, t_ndarray src, uint32_t offset, bool elem_wise_cp)
+{
+    switch(src.type)
+    {
+        case nd_bool:
+            copy_data_from_bool(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_int8:
+            copy_data_from_int8(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_int16:
+            copy_data_from_int16(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_int32:
+            copy_data_from_int32(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_int64:
+            copy_data_from_int64(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_float:
+            copy_data_from_float(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_double:
+            copy_data_from_double(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_cfloat:
+            copy_data_from_cfloat(ds, src, offset, elem_wise_cp);
+            break;
+
+        case nd_cdouble:
+            copy_data_from_cdouble(ds, src, offset, elem_wise_cp);
+            break;
+    }
+}
+
 void array_copy_data(t_ndarray *dest, t_ndarray src, uint32_t offset)
 {
     unsigned char *d = (unsigned char*)dest->raw_data;
@@ -499,15 +668,11 @@ void array_copy_data(t_ndarray *dest, t_ndarray src, uint32_t offset)
         && (src.order == order_c
             || (src.order == order_f && is_same_shape(*dest, src))))
     {
-        memcpy(d + offset * dest->type_size, s, src.buffer_size);
+        copy_data(&dest, src, offset, false);
     }
     else
     {
-        for (int64_t element_num = 0; element_num < src.length; ++element_num)
-        {
-            memcpy(d + ((element_index(*dest, element_num, dest->nd) + offset) * dest->type_size),
-                s + (element_index(src, element_num, src.nd) * src.type_size), src.type_size);
-        }
+        copy_data(&dest, src, offset, true);
     }
 }
 
@@ -654,3 +819,4 @@ NUMPY_AMIN_(float32, float, float)
 NUMPY_AMIN_(float64, double, double)
 NUMPY_AMIN_(complex64, float complex, cfloat)
 NUMPY_AMIN_(complex128, double complex, cdouble)
+
diff --git a/pyccel/stdlib/ndarrays/ndarrays.h b/pyccel/stdlib/ndarrays/ndarrays.h
index fa113c1811..11bbfbf455 100644
--- a/pyccel/stdlib/ndarrays/ndarrays.h
+++ b/pyccel/stdlib/ndarrays/ndarrays.h
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #ifndef NDARRAYS_H
 # define NDARRAYS_H
diff --git a/pyccel/stdlib/numpy/numpy_c.c b/pyccel/stdlib/numpy/numpy_c.c
index 36e4a205ec..7c9ecbbf6b 100644
--- a/pyccel/stdlib/numpy/numpy_c.c
+++ b/pyccel/stdlib/numpy/numpy_c.c
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #include "numpy_c.h"
 
diff --git a/pyccel/stdlib/numpy/numpy_c.h b/pyccel/stdlib/numpy/numpy_c.h
index 4133e9dbe9..e72cf3ad57 100644
--- a/pyccel/stdlib/numpy/numpy_c.h
+++ b/pyccel/stdlib/numpy/numpy_c.h
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #ifndef NUMPY_H
 # define NUMPY_H
diff --git a/pyccel/stdlib/numpy/numpy_f90.f90 b/pyccel/stdlib/numpy/numpy_f90.f90
index c9c1e14e62..bc2befd0b4 100644
--- a/pyccel/stdlib/numpy/numpy_f90.f90
+++ b/pyccel/stdlib/numpy/numpy_f90.f90
@@ -1,7 +1,7 @@
-! ! --------------------------------------------------------------------------------------- !
-! ! This file is part of Pyccel which is released under MIT License. See the LICENSE file   !
-! ! or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. !
-! ! --------------------------------------------------------------------------------------- !
+! -------------------------------------------------------------------------------------- !
+! This file is part of Pyccel which is released under MIT License. See the LICENSE file  !
+! or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. !
+! -------------------------------------------------------------------------------------- !
 
 module numpy_f90
 
diff --git a/pyccel/stdlib/parallel/mpi.py b/pyccel/stdlib/parallel/mpi.py
index abf818433b..a8f8c7392b 100644
--- a/pyccel/stdlib/parallel/mpi.py
+++ b/pyccel/stdlib/parallel/mpi.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 
 # TODO - improve communicate method
diff --git a/pyccel/utilities/metaclasses.py b/pyccel/utilities/metaclasses.py
index 8718da1f54..42320426bc 100644
--- a/pyccel/utilities/metaclasses.py
+++ b/pyccel/utilities/metaclasses.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing metaclasses which are useful for the rest of pyccel
 """
diff --git a/pyccel/utilities/stage.py b/pyccel/utilities/stage.py
index c7ff8e3da3..686ab2d6aa 100644
--- a/pyccel/utilities/stage.py
+++ b/pyccel/utilities/stage.py
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ File containing information about which treatment stage Pyccel is executing
 """
diff --git a/pyccel/utilities/strings.py b/pyccel/utilities/strings.py
index 13deff4ae3..3080ce5d1c 100644
--- a/pyccel/utilities/strings.py
+++ b/pyccel/utilities/strings.py
@@ -1,11 +1,37 @@
 # -*- coding: utf-8 -*-
 #------------------------------------------------------------------------------------------#
 # This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
-# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details.     #
+# go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details.      #
 #------------------------------------------------------------------------------------------#
 """ Module containing helper functions for managing strings
 """
+import string
+import random
 
+__all__ = ('random_string', 'create_incremented_string')
+#==============================================================================
+random_selector = random.SystemRandom()
+
+def random_string( n ):
+    """
+    Generate a random string.
+
+    Generate a random string with length n made of lower case characters and digits.
+
+    Parameters
+    ----------
+    n : int
+      The length of the random string.
+
+    Returns
+    -------
+    str
+       The random string.
+    """
+    chars    = string.ascii_lowercase + string.digits
+    return ''.join( random_selector.choice( chars ) for _ in range(n) )
+
+#==============================================================================
 def create_incremented_string(forbidden_exprs, prefix = 'Dummy', counter = 1, name_clash_checker = None):
     """
     Create a new unique string by incrementing a prefix.
diff --git a/pyccel/version.py b/pyccel/version.py
index b01a093893..30178ac57e 100644
--- a/pyccel/version.py
+++ b/pyccel/version.py
@@ -1,4 +1,4 @@
 """
 Module specifying the current version string for pyccel
 """
-__version__ = "1.11.2"
+__version__ = "1.12.0"
diff --git a/pyproject.toml b/pyproject.toml
index e77c3832cb..b9da4fe16b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,6 +20,7 @@ dependencies = [
     "sympy >= 1.2",
     "termcolor >= 1.0.0",
     "textx >= 2.2",
+    "packaging",
 ]
 
 [project.optional-dependencies]


Test patch:
diff --git a/.github/actions/pytest_run/action.yml b/.github/actions/pytest_run/action.yml
index 8d300bd87c..0b6f0f988d 100644
--- a/.github/actions/pytest_run/action.yml
+++ b/.github/actions/pytest_run/action.yml
@@ -28,7 +28,7 @@ runs:
       shell: ${{ inputs.shell_cmd }}
       working-directory: ./tests
     - name: Test C translation
-      run: python -m pytest -n auto -rX ${FLAGS} -m "not (parallel or xdist_incompatible) and c ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s1_outfile.out
+      run: python -m pytest -n auto -rX ${FLAGS} -m "not (parallel or xdist_incompatible) and c ${{ inputs.pytest_mark }}" --ignore=ndarrays 2>&1 | tee s1_outfile.out
       shell: ${{ inputs.shell_cmd }}
       working-directory: ./tests
       id: pytest_1
@@ -45,19 +45,19 @@ runs:
       id: pytest_2
     - name: Test multi-file C translations
       run: |
-         python -m pytest -rX ${FLAGS} -m "xdist_incompatible and not parallel and c ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s3_outfile.out
+         python -m pytest -rX ${FLAGS} -m "xdist_incompatible and not parallel and c ${{ inputs.pytest_mark }}" --ignore=ndarrays 2>&1 | tee s3_outfile.out
          pyccel-clean
       shell: ${{ inputs.shell_cmd }}
       working-directory: ./tests
       id: pytest_3
     - name: Test Fortran translations
-      run: python -m pytest -n auto -rX ${FLAGS} -m "not (parallel or xdist_incompatible) and not (c or python) ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s4_outfile.out
+      run: python -m pytest -n auto -rX ${FLAGS} -m "not (parallel or xdist_incompatible) and not (c or python) ${{ inputs.pytest_mark }}" --ignore=ndarrays 2>&1 | tee s4_outfile.out
       shell: ${{ inputs.shell_cmd }}
       working-directory: ./tests
       id: pytest_4
     - name: Test multi-file Fortran translations
       run: |
-        python -m pytest -rX ${FLAGS} -m "xdist_incompatible and not parallel and not (c or python) ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s5_outfile.out
+        python -m pytest -rX ${FLAGS} -m "xdist_incompatible and not parallel and not (c or python) ${{ inputs.pytest_mark }}" --ignore=ndarrays 2>&1 | tee s5_outfile.out
         pyccel-clean
       shell: ${{ inputs.shell_cmd }}
       working-directory: ./tests
diff --git a/tests/codegen/ccode/test_ccode_codegen.py b/tests/codegen/ccode/test_ccode_codegen.py
index b16e2a5474..bd31e56c4d 100644
--- a/tests/codegen/ccode/test_ccode_codegen.py
+++ b/tests/codegen/ccode/test_ccode_codegen.py
@@ -45,8 +45,8 @@ def test_codegen(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint(language='c')
+    codegen = Codegen(ast, name, 'c')
+    codegen.printer.doprint(codegen.ast)
 
     # Assert codegen success
     assert(not errors.has_errors())
diff --git a/tests/codegen/fcode/test_fcode_codegen.py b/tests/codegen/fcode/test_fcode_codegen.py
index 34593e4acf..e3f960698b 100644
--- a/tests/codegen/fcode/test_fcode_codegen.py
+++ b/tests/codegen/fcode/test_fcode_codegen.py
@@ -44,8 +44,8 @@ def test_codegen(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint()
+    codegen = Codegen(ast, name, 'fortran')
+    codegen.printer.doprint(codegen.ast)
 
     # Assert codegen success
     assert(not errors.has_errors())
diff --git a/tests/codegen/pycode/test_pycode_codegen.py b/tests/codegen/pycode/test_pycode_codegen.py
index 0219037700..33244e8437 100644
--- a/tests/codegen/pycode/test_pycode_codegen.py
+++ b/tests/codegen/pycode/test_pycode_codegen.py
@@ -30,8 +30,8 @@ def test_codegen(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint(language='python')
+    codegen = Codegen(ast, name, 'python')
+    codegen.printer.doprint(codegen.ast)
 
     # reset Errors singleton
     errors = Errors()
diff --git a/tests/epyccel/modules/arrays.py b/tests/epyccel/modules/arrays.py
index 13a192f388..2f866a1cb3 100644
--- a/tests/epyccel/modules/arrays.py
+++ b/tests/epyccel/modules/arrays.py
@@ -1581,6 +1581,29 @@ def array_2d_C_slice_stride_23(a : 'int[:,:]'):
     b = a[::d, ::c]
     return np.sum(b), b[0][0], b[-1][-1], len(b), len(b[0])
 
+#==============================================================================
+# Slice assignment
+#==============================================================================
+
+def copy_to_slice_issue_1218(n : int):
+    from numpy import zeros, array
+    x = 1
+    arr = zeros((2, n))
+    arr[0:x, 0:6:2] = array([2, 5, 6])
+    return arr
+
+def copy_to_slice_1(a : 'float[:]', b : 'float[:]'):
+    a[1:-1] = b
+
+def copy_to_slice_2(a : 'float[:,:]', b : 'float[:]'):
+    a[:, 1:-1] = b
+
+def copy_to_slice_3(a : 'float[:,:]', b : 'float[:]'):
+    a[:, 0] = b
+
+def copy_to_slice_4(a : 'float[:]', b : 'float[:]'):
+    a[::2] = b
+
 #==============================================================================
 # ARITHMETIC OPERATIONS
 #==============================================================================
@@ -1718,14 +1741,6 @@ def arr_arange_7(arr : 'int[:,:]'):
     for i in range(n):
         arr[i] = np.arange(i, i+m)
 
-def iterate_slice(i : int):
-    import numpy as np
-    a = np.arange(15)
-    res = 0
-    for ai in a[:i]:
-        res += ai
-    return res
-
 #==============================================================================
 # NUMPY SUM
 #==============================================================================
@@ -1753,3 +1768,333 @@ def multiple_np_linspace():
     y = np.linspace(0, 4, 128)
     z = np.linspace(0, 8, 128)
     return x[0] + y[1] + z[2] + linspace_index
+
+#==============================================================================
+# NUMPY ARRAY DATA TYPE CONVERSION
+#==============================================================================
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_bool(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='bool')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_int8(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='int8')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_int16(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='int16')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_int32(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='int32')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_int64(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='int64')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_float32(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='float32')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_float64(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='float64')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_cfloat(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='complex64')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_cdouble(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype='complex128')
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_pyint(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype=int)
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def dtype_convert_to_pyfloat(arr : 'T1'):
+    from numpy import shape, array
+    c = array(arr, dtype=float)
+    s = shape(c)
+    return len(s), c[0,0], c[0,1], c[1,0], c[1,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_bool(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='bool')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int8(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int8')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int16(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int16')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int32(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int32')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int64(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int64')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_float32(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='float32')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_float64(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='float64')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_cfloat(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='complex64')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_cdouble(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='complex128')
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_pyint(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype=int)
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_pyfloat(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype=float)
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_bool_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='bool', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int8_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int8', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int16_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int16', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int32_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int32', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_int64_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='int64', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_float32_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='float32', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_float64_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='float64', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='complex64', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype='complex128', order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_pyint_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype=int, order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+@template('T1', ['bool[:,:]', 'int[:,:]', 'int8[:,:]', 'int16[:,:]', 'int32[:,:]', 'int64[:,:]', 'float[:,:]', 'float32[:,:]', 'float64[:,:]', 'complex64[:,:]', 'complex128[:,:]'])
+def src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(arr1 : 'T1', arr2 : 'T1', arr3 : 'T1'):
+    from numpy import shape, array
+    a = array(arr1)
+    b = array(arr2)
+    c = array(arr3)
+    d = array([a, c, b], dtype=float, order="F")
+    s = shape(d)
+    return s[0], s[1], s[2], d[0,0,0], d[0,0,1], d[1,0,0], d[1,0,1], d[2,0,0], d[2,0,1]
+
+#==============================================================================
+# Iteration
+#==============================================================================
+
+def iterate_slice(i : int):
+    from numpy import arange
+    a = arange(15)
+    res = 0
+    for ai in a[:i]:
+        res += ai
+    return res
+
+@template('T', ['int[:]', 'int[:,:]', 'int[:,:,:]', 'int[:,:](order=F)', 'int[:,:,:](order=F)'])
+def unpack_array(arr : 'T'):
+    x, y, z = arr[:]
+    return x, y, z
+
+def unpack_array_of_known_size():
+    from numpy import array
+    arr = array([1,2,3], dtype='float64')
+    x, y, z = arr[:]
+    return x, y, z
+
+def unpack_array_2D_of_known_size():
+    from numpy import array
+    arr = array([[1,2,3], [4,5,6], [7,8,9]], dtype='float64')
+    x, y, z = arr[:]
+    return x.sum(), y.sum(), z.sum()
diff --git a/tests/epyccel/recognised_functions/test_numpy_funcs.py b/tests/epyccel/recognised_functions/test_numpy_funcs.py
index a32a7fc79d..bd83df74cd 100644
--- a/tests/epyccel/recognised_functions/test_numpy_funcs.py
+++ b/tests/epyccel/recognised_functions/test_numpy_funcs.py
@@ -281,6 +281,7 @@ def numpy_isinf_expr_test(x : 'float', y : 'float'):
     assert matching_types(obtained, expected_output)
 
 #------------------------------ isfinite function ----------------------------#
+@pytest.mark.xfail(os.environ.get('PYCCEL_DEFAULT_COMPILER', None) == 'intel', reason='Different inf representation.')
 def test_numpy_isfinite(language):
     def numpy_isfinite_test(x : 'float'):
         from numpy import isfinite
diff --git a/tests/epyccel/test_arrays.py b/tests/epyccel/test_arrays.py
index f279137ff0..809d266243 100644
--- a/tests/epyccel/test_arrays.py
+++ b/tests/epyccel/test_arrays.py
@@ -1,8 +1,8 @@
 # pylint: disable=missing-function-docstring, missing-module-docstring
 import pytest
 import numpy as np
-from numpy import iinfo
-from numpy.random import randint
+from numpy import iinfo, finfo
+from numpy.random import randint, uniform
 
 from pyccel.epyccel import epyccel
 from modules        import arrays
@@ -21,6 +21,7 @@ def check_array_equal(a, b):
     assert a.dtype is b.dtype
     assert a.flags.c_contiguous == b.flags.c_contiguous
     assert a.flags.f_contiguous == b.flags.f_contiguous
+
 #==============================================================================
 # TEST: VERIFY ARRAY'S DTYPE CORRESPONDENCE TO THE PASSED ELEMENTS
 #==============================================================================
@@ -99,6 +100,7 @@ def test_array_int32_1d_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_add_stride(language):
 
     f1 = arrays.array_int32_1d_scalar_add
@@ -113,6 +115,7 @@ def test_array_int32_1d_scalar_add_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_sub(language):
 
     f1 = arrays.array_int32_1d_scalar_sub
@@ -127,6 +130,7 @@ def test_array_int32_1d_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_sub_stride(language):
 
     f1 = arrays.array_int32_1d_scalar_sub
@@ -141,6 +145,7 @@ def test_array_int32_1d_scalar_sub_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_mul(language):
 
     f1 = arrays.array_int32_1d_scalar_mul
@@ -155,6 +160,7 @@ def test_array_int32_1d_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_mul_stride(language):
 
     f1 = arrays.array_int32_1d_scalar_mul
@@ -169,6 +175,7 @@ def test_array_int32_1d_scalar_mul_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_div(language):
 
     f1 = arrays.array_int32_1d_scalar_div
@@ -183,6 +190,7 @@ def test_array_int32_1d_scalar_div(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_idiv(language):
 
     f1 = arrays.array_int32_1d_scalar_idiv
@@ -197,6 +205,7 @@ def test_array_int32_1d_scalar_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_scalar_idiv_stride(language):
 
     f1 = arrays.array_int32_1d_scalar_idiv
@@ -211,6 +220,7 @@ def test_array_int32_1d_scalar_idiv_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_add(language):
 
     f1 = arrays.array_int32_1d_add
@@ -225,6 +235,7 @@ def test_array_int32_1d_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_sub(language):
 
     f1 = arrays.array_int32_1d_sub
@@ -239,6 +250,7 @@ def test_array_int32_1d_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_mul(language):
 
     f1 = arrays.array_int32_1d_mul
@@ -253,6 +265,7 @@ def test_array_int32_1d_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_idiv(language):
 
     f1 = arrays.array_int32_1d_idiv
@@ -267,6 +280,7 @@ def test_array_int32_1d_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_add_augassign(language):
 
     f1 = arrays.array_int32_1d_add_augassign
@@ -281,6 +295,7 @@ def test_array_int32_1d_add_augassign(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_1d_sub_augassign(language):
 
     f1 = arrays.array_int32_1d_sub_augassign
@@ -295,6 +310,7 @@ def test_array_int32_1d_sub_augassign(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_initialization_1(language):
 
     f1 = arrays.array_int_1d_initialization_1
@@ -302,6 +318,7 @@ def test_array_int_1d_initialization_1(language):
 
     assert f1() == f2()
 
+
 @pytest.mark.parametrize( 'language', (
         pytest.param("fortran", marks = pytest.mark.fortran),
         pytest.param("c", marks = [
@@ -318,6 +335,7 @@ def test_array_int_1d_initialization_2(language):
 
     assert f1() == f2()
 
+
 def test_array_int_1d_initialization_3(language):
 
     f1 = arrays.array_int_1d_initialization_3
@@ -343,6 +361,7 @@ def test_array_int32_2d_C_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_scalar_add_stride(language):
 
     f1 = arrays.array_int32_2d_C_scalar_add
@@ -357,6 +376,7 @@ def test_array_int32_2d_C_scalar_add_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_scalar_sub(language):
 
     f1 = arrays.array_int32_2d_C_scalar_sub
@@ -371,6 +391,7 @@ def test_array_int32_2d_C_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.xfail(reason="Ordering is unknown on non-contiguous array"),
@@ -395,6 +416,7 @@ def test_array_int32_2d_C_scalar_sub_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_scalar_mul(language):
 
     f1 = arrays.array_int32_2d_C_scalar_mul
@@ -409,6 +431,7 @@ def test_array_int32_2d_C_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_scalar_mul_stride(language):
 
     f1 = arrays.array_int32_2d_C_scalar_mul
@@ -423,6 +446,7 @@ def test_array_int32_2d_C_scalar_mul_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_scalar_idiv(language):
 
     f1 = arrays.array_int32_2d_C_scalar_idiv
@@ -437,6 +461,7 @@ def test_array_int32_2d_C_scalar_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.xfail(reason="Ordering is unknown on non-contiguous array"),
@@ -461,6 +486,7 @@ def test_array_int32_2d_C_scalar_idiv_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_add(language):
 
     f1 = arrays.array_int32_2d_C_add
@@ -475,6 +501,7 @@ def test_array_int32_2d_C_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_sub(language):
 
     f1 = arrays.array_int32_2d_C_sub
@@ -489,6 +516,7 @@ def test_array_int32_2d_C_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_mul(language):
 
     f1 = arrays.array_int32_2d_C_mul
@@ -503,6 +531,7 @@ def test_array_int32_2d_C_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_idiv(language):
 
     f1 = arrays.array_int32_2d_C_idiv
@@ -535,6 +564,7 @@ def test_array_int32_2d_F_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.xfail(reason="Ordering is unknown on non-contiguous array"),
@@ -559,6 +589,7 @@ def test_array_int32_2d_F_scalar_add_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_scalar_sub(language):
 
     f1 = arrays.array_int32_2d_F_scalar_sub
@@ -573,6 +604,7 @@ def test_array_int32_2d_F_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.xfail(reason="Ordering is unknown on non-contiguous array"),
@@ -597,6 +629,7 @@ def test_array_int32_2d_F_scalar_sub_stride(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_scalar_mul(language):
 
     f1 = arrays.array_int32_2d_F_scalar_mul
@@ -611,6 +644,7 @@ def test_array_int32_2d_F_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_scalar_idiv(language):
 
     f1 = arrays.array_int32_2d_F_scalar_idiv
@@ -625,6 +659,7 @@ def test_array_int32_2d_F_scalar_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_add(language):
 
     f1 = arrays.array_int32_2d_F_add
@@ -639,6 +674,7 @@ def test_array_int32_2d_F_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_sub(language):
 
     f1 = arrays.array_int32_2d_F_sub
@@ -653,6 +689,7 @@ def test_array_int32_2d_F_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_mul(language):
 
     f1 = arrays.array_int32_2d_F_mul
@@ -667,6 +704,7 @@ def test_array_int32_2d_F_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_idiv(language):
 
     f1 = arrays.array_int32_2d_F_idiv
@@ -700,6 +738,7 @@ def test_array_int_1d_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_scalar_sub(language):
 
     f1 = arrays.array_int_1d_scalar_sub
@@ -714,6 +753,7 @@ def test_array_int_1d_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_scalar_mul(language):
 
     f1 = arrays.array_int_1d_scalar_mul
@@ -728,6 +768,7 @@ def test_array_int_1d_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_scalar_idiv(language):
 
     f1 = arrays.array_int_1d_scalar_idiv
@@ -742,6 +783,7 @@ def test_array_int_1d_scalar_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_add(language):
 
     f1 = arrays.array_int_1d_add
@@ -756,6 +798,7 @@ def test_array_int_1d_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_sub(language):
 
     f1 = arrays.array_int_1d_sub
@@ -770,6 +813,7 @@ def test_array_int_1d_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_mul(language):
 
     f1 = arrays.array_int_1d_mul
@@ -784,6 +828,7 @@ def test_array_int_1d_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_1d_idiv(language):
 
     f1 = arrays.array_int_1d_idiv
@@ -816,6 +861,7 @@ def test_array_int_2d_C_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_scalar_sub(language):
 
     f1 = arrays.array_int_2d_C_scalar_sub
@@ -830,6 +876,7 @@ def test_array_int_2d_C_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_scalar_mul(language):
 
     f1 = arrays.array_int_2d_C_scalar_mul
@@ -844,6 +891,7 @@ def test_array_int_2d_C_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_scalar_idiv(language):
 
     f1 = arrays.array_int_2d_C_scalar_idiv
@@ -858,6 +906,7 @@ def test_array_int_2d_C_scalar_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_add(language):
 
     f1 = arrays.array_int_2d_C_add
@@ -872,6 +921,7 @@ def test_array_int_2d_C_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_sub(language):
 
     f1 = arrays.array_int_2d_C_sub
@@ -886,6 +936,7 @@ def test_array_int_2d_C_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_mul(language):
 
     f1 = arrays.array_int_2d_C_mul
@@ -900,6 +951,7 @@ def test_array_int_2d_C_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_idiv(language):
 
     f1 = arrays.array_int_2d_C_idiv
@@ -914,6 +966,7 @@ def test_array_int_2d_C_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_C_initialization(language):
 
     f1 = arrays.array_int_2d_C_initialization
@@ -945,6 +998,7 @@ def test_array_int_2d_F_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_scalar_sub(language):
 
     f1 = arrays.array_int_2d_F_scalar_sub
@@ -959,6 +1013,7 @@ def test_array_int_2d_F_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_scalar_mul(language):
 
     f1 = arrays.array_int_2d_F_scalar_mul
@@ -973,6 +1028,7 @@ def test_array_int_2d_F_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_scalar_idiv(language):
 
     f1 = arrays.array_int_2d_F_scalar_idiv
@@ -987,6 +1043,7 @@ def test_array_int_2d_F_scalar_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_add(language):
 
     f1 = arrays.array_int_2d_F_add
@@ -1001,6 +1058,7 @@ def test_array_int_2d_F_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_sub(language):
 
     f1 = arrays.array_int_2d_F_sub
@@ -1015,6 +1073,7 @@ def test_array_int_2d_F_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_mul(language):
 
     f1 = arrays.array_int_2d_F_mul
@@ -1029,6 +1088,7 @@ def test_array_int_2d_F_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_idiv(language):
 
     f1 = arrays.array_int_2d_F_idiv
@@ -1043,6 +1103,7 @@ def test_array_int_2d_F_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int_2d_F_initialization(language):
 
     f1 = arrays.array_int_2d_F_initialization
@@ -1074,6 +1135,7 @@ def test_array_float_1d_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_scalar_sub(language):
 
     f1 = arrays.array_float_1d_scalar_sub
@@ -1088,6 +1150,7 @@ def test_array_float_1d_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_scalar_mul(language):
 
     f1 = arrays.array_float_1d_scalar_mul
@@ -1102,6 +1165,7 @@ def test_array_float_1d_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_scalar_div(language):
 
     f1 = arrays.array_float_1d_scalar_div
@@ -1116,6 +1180,7 @@ def test_array_float_1d_scalar_div(language):
 
     assert np.allclose(x1, x2, rtol=RTOL, atol=ATOL)
 
+
 def test_array_float_1d_scalar_mod(language):
     f1 = arrays.array_float_1d_scalar_mod
     f2 = epyccel( f1 , language = language)
@@ -1129,6 +1194,7 @@ def test_array_float_1d_scalar_mod(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_scalar_idiv(language):
 
     f1 = arrays.array_float_1d_scalar_idiv
@@ -1143,6 +1209,7 @@ def test_array_float_1d_scalar_idiv(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_add(language):
 
     f1 = arrays.array_float_1d_add
@@ -1157,6 +1224,7 @@ def test_array_float_1d_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_sub(language):
 
     f1 = arrays.array_float_1d_sub
@@ -1171,6 +1239,7 @@ def test_array_float_1d_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_mul(language):
 
     f1 = arrays.array_float_1d_mul
@@ -1185,6 +1254,7 @@ def test_array_float_1d_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_div(language):
 
     f1 = arrays.array_float_1d_div
@@ -1199,6 +1269,7 @@ def test_array_float_1d_div(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_1d_mod(language):
 
     f1 = arrays.array_float_1d_mod
@@ -1213,6 +1284,7 @@ def test_array_float_1d_mod(language):
 
     assert np.array_equal( x1, x2)
 
+
 def test_array_float_1d_idiv(language):
 
     f1 = arrays.array_float_1d_idiv
@@ -1245,6 +1317,7 @@ def test_array_float_2d_C_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_scalar_sub(language):
 
     f1 = arrays.array_float_2d_C_scalar_sub
@@ -1259,6 +1332,7 @@ def test_array_float_2d_C_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_scalar_mul(language):
 
     f1 = arrays.array_float_2d_C_scalar_mul
@@ -1273,6 +1347,7 @@ def test_array_float_2d_C_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_scalar_div(language):
 
     f1 = arrays.array_float_2d_C_scalar_div
@@ -1287,6 +1362,7 @@ def test_array_float_2d_C_scalar_div(language):
 
     assert np.allclose(x1, x2, rtol=RTOL, atol=ATOL)
 
+
 def test_array_float_2d_C_scalar_mod(language):
 
     f1 = arrays.array_float_2d_C_scalar_mod
@@ -1301,6 +1377,7 @@ def test_array_float_2d_C_scalar_mod(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_add(language):
 
     f1 = arrays.array_float_2d_C_add
@@ -1315,6 +1392,7 @@ def test_array_float_2d_C_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_sub(language):
 
     f1 = arrays.array_float_2d_C_sub
@@ -1329,6 +1407,7 @@ def test_array_float_2d_C_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_mul(language):
 
     f1 = arrays.array_float_2d_C_mul
@@ -1343,6 +1422,7 @@ def test_array_float_2d_C_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_div(language):
 
     f1 = arrays.array_float_2d_C_div
@@ -1357,6 +1437,7 @@ def test_array_float_2d_C_div(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_mod(language):
 
     f1 = arrays.array_float_2d_C_mod
@@ -1371,6 +1452,7 @@ def test_array_float_2d_C_mod(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_array_initialization(language):
 
     f1 = arrays.array_float_2d_C_array_initialization
@@ -1384,6 +1466,7 @@ def test_array_float_2d_C_array_initialization(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_3d_C_array_initialization_1(language):
 
     f1 = arrays.array_float_3d_C_array_initialization_1
@@ -1401,6 +1484,7 @@ def test_array_float_3d_C_array_initialization_1(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_3d_C_array_initialization_2(language):
 
     f1 = arrays.array_float_3d_C_array_initialization_2
@@ -1414,6 +1498,7 @@ def test_array_float_3d_C_array_initialization_2(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_4d_C_array_initialization(language):
 
     f1 = arrays.array_float_4d_C_array_initialization
@@ -1430,6 +1515,7 @@ def test_array_float_4d_C_array_initialization(language):
     f2(x, y, x2)
 
     assert np.array_equal(x1, x2)
+
 #==============================================================================
 # TEST: 2D ARRAYS OF REAL WITH F ORDERING
 #==============================================================================
@@ -1448,6 +1534,7 @@ def test_array_float_2d_F_scalar_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_scalar_sub(language):
 
     f1 = arrays.array_float_2d_F_scalar_sub
@@ -1462,6 +1549,7 @@ def test_array_float_2d_F_scalar_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_scalar_mul(language):
 
     f1 = arrays.array_float_2d_F_scalar_mul
@@ -1476,6 +1564,7 @@ def test_array_float_2d_F_scalar_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_scalar_div(language):
 
     f1 = arrays.array_float_2d_F_scalar_div
@@ -1490,6 +1579,7 @@ def test_array_float_2d_F_scalar_div(language):
 
     assert np.allclose(x1, x2, rtol=RTOL, atol=ATOL)
 
+
 def test_array_float_2d_F_scalar_mod(language):
 
     f1 = arrays.array_float_2d_F_scalar_mod
@@ -1504,6 +1594,7 @@ def test_array_float_2d_F_scalar_mod(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_add(language):
 
     f1 = arrays.array_float_2d_F_add
@@ -1518,6 +1609,7 @@ def test_array_float_2d_F_add(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_sub(language):
 
     f1 = arrays.array_float_2d_F_sub
@@ -1532,6 +1624,7 @@ def test_array_float_2d_F_sub(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_mul(language):
 
     f1 = arrays.array_float_2d_F_mul
@@ -1546,6 +1639,7 @@ def test_array_float_2d_F_mul(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_div(language):
 
     f1 = arrays.array_float_2d_F_div
@@ -1560,6 +1654,7 @@ def test_array_float_2d_F_div(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_mod(language):
 
     f1 = arrays.array_float_2d_F_mod
@@ -1574,6 +1669,7 @@ def test_array_float_2d_F_mod(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_array_initialization(language):
 
     f1 = arrays.array_float_2d_F_array_initialization
@@ -1587,6 +1683,7 @@ def test_array_float_2d_F_array_initialization(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_3d_F_array_initialization_1(language):
 
     f1 = arrays.array_float_3d_F_array_initialization_1
@@ -1604,6 +1701,7 @@ def test_array_float_3d_F_array_initialization_1(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_3d_F_array_initialization_2(language):
 
     f1 = arrays.array_float_3d_F_array_initialization_2
@@ -1617,6 +1715,7 @@ def test_array_float_3d_F_array_initialization_2(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_4d_F_array_initialization(language):
 
     f1 = arrays.array_float_4d_F_array_initialization
@@ -1634,6 +1733,7 @@ def test_array_float_4d_F_array_initialization(language):
 
     assert np.array_equal(x1, x2)
 
+
 @pytest.mark.xfail(reason='Inhomogeneous arguments due to unknown shape')
 def test_array_float_4d_F_array_initialization_mixed_ordering(language):
 
@@ -1656,11 +1756,11 @@ def test_array_float_4d_F_array_initialization_mixed_ordering(language):
     f2(x, x2)
 
     assert np.array_equal(x1, x2)
+
 #==============================================================================
 # TEST: COMPLEX EXPRESSIONS IN 3D : TEST CONSTANT AND UNKNOWN SHAPES
 #==============================================================================
 
-
 def test_array_int32_1d_complex_3d_expr(language):
 
     f1 = arrays.array_int32_1d_complex_3d_expr
@@ -1675,6 +1775,7 @@ def test_array_int32_1d_complex_3d_expr(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_C_complex_3d_expr(language):
 
     f1 = arrays.array_int32_2d_C_complex_3d_expr
@@ -1689,6 +1790,7 @@ def test_array_int32_2d_C_complex_3d_expr(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_2d_F_complex_3d_expr(language):
 
     f1 = arrays.array_int32_2d_F_complex_3d_expr
@@ -1703,6 +1805,7 @@ def test_array_int32_2d_F_complex_3d_expr(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_int32_in_bool_out_1d_complex_3d_expr(language):
 
     f1 = arrays.array_int32_in_bool_out_1d_complex_3d_expr
@@ -1718,6 +1821,7 @@ def test_array_int32_in_bool_out_1d_complex_3d_expr(language):
 
     assert np.array_equal( r1, r2 )
 
+
 def test_array_int32_in_bool_out_2d_C_complex_3d_expr(language):
 
     f1 = arrays.array_int32_in_bool_out_2d_C_complex_3d_expr
@@ -1733,6 +1837,7 @@ def test_array_int32_in_bool_out_2d_C_complex_3d_expr(language):
 
     assert np.array_equal( r1, r2 )
 
+
 def test_array_int32_in_bool_out_2d_F_complex_3d_expr(language):
 
     f1 = arrays.array_int32_in_bool_out_2d_F_complex_3d_expr
@@ -1748,6 +1853,7 @@ def test_array_int32_in_bool_out_2d_F_complex_3d_expr(language):
 
     assert np.array_equal( r1, r2 )
 
+
 def test_array_float_1d_complex_3d_expr(language):
 
     f1 = arrays.array_float_1d_complex_3d_expr
@@ -1762,6 +1868,7 @@ def test_array_float_1d_complex_3d_expr(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_C_complex_3d_expr(language):
 
     f1 = arrays.array_float_2d_C_complex_3d_expr
@@ -1776,6 +1883,7 @@ def test_array_float_2d_C_complex_3d_expr(language):
 
     assert np.array_equal( x1, x2 )
 
+
 def test_array_float_2d_F_complex_3d_expr(language):
 
     f1 = arrays.array_float_2d_F_complex_3d_expr
@@ -1802,6 +1910,7 @@ def test_array_float_sum_stack_array(language):
     x2 = f2()
     assert np.equal( x1, x2 )
 
+
 def test_array_float_div_stack_array(language):
 
     f1 = arrays.array_float_1d_div_stack_array
@@ -1810,12 +1919,14 @@ def test_array_float_div_stack_array(language):
     x2 = f2()
     assert np.equal( x1, x2 )
 
+
 def test_multiple_stack_array_1(language):
 
     f1 = arrays.multiple_stack_array_1
     f2 = epyccel(f1, language = language)
     assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_multiple_stack_array_2(language):
 
     f1 = arrays.multiple_stack_array_2
@@ -1834,6 +1945,7 @@ def test_array_float_sum_2d_stack_array(language):
     x2 = f2()
     assert np.equal( x1, x2 )
 
+
 def test_array_float_div_2d_stack_array(language):
 
     f1 = arrays.array_float_2d_div_stack_array
@@ -1842,12 +1954,14 @@ def test_array_float_div_2d_stack_array(language):
     x2 = f2()
     assert np.equal( x1, x2 )
 
+
 def test_multiple_2d_stack_array_1(language):
 
     f1 = arrays.multiple_2d_stack_array_1
     f2 = epyccel(f1, language = language)
     assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_multiple_2d_stack_array_2(language):
 
     f1 = arrays.multiple_2d_stack_array_2
@@ -1876,6 +1990,7 @@ def test_array_float_1d_1d_prod(language):
     f2(x2, y2)
     assert np.array_equal(y1, y2)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="matmul not implemented in c"),
@@ -1898,6 +2013,7 @@ def test_array_float_2d_1d_matmul(language):
     f2(A2, x2, y2)
     assert np.array_equal(y1, y2)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="matmul not implemented in c"),
@@ -1918,6 +2034,7 @@ def test_array_float_2d_1d_matmul_creation(language):
     y2 = f2(A2, x2)
     assert np.isclose(y1, y2)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="matmul not implemented in c"),
@@ -1940,6 +2057,7 @@ def test_array_float_2d_1d_matmul_order_F_F(language):
     f2(A2, x2, y2)
     assert np.array_equal(y1, y2)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="matmul not implemented in c"),
@@ -1962,6 +2080,7 @@ def test_array_float_2d_2d_matmul(language):
     f2(A2, B2, C2)
     assert np.array_equal(C1, C2)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="matmul not implemented in c"),
@@ -1984,6 +2103,7 @@ def test_array_float_2d_2d_matmul_F_F_F_F(language):
     f2(A2, B2, C2)
     assert np.array_equal(C1, C2)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="matmul not implemented in c"),
@@ -2009,6 +2129,7 @@ def test_array_float_2d_2d_matmul_mixorder(language):
     f2(A2, B2, C2)
     assert np.array_equal(C1, C2)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="matmul not implemented in c"),
@@ -2031,6 +2152,7 @@ def test_array_float_2d_2d_matmul_operator(language):
     f2(A2, B2, C2)
     assert np.array_equal(C1, C2)
 
+
 def test_array_float_loopdiff(language):
     f1 = arrays.array_float_loopdiff
     f2 = epyccel( f1 , language = language)
@@ -2052,6 +2174,7 @@ def test_array_kwargs_full(language):
     f2 = epyccel( f1 , language = language)
     assert f1() == f2()
 
+
 def test_array_kwargs_ones(language):
     f1 = arrays.array_kwargs_ones
     f2 = epyccel( f1 , language = language)
@@ -2068,6 +2191,7 @@ def test_constant_negative_index(language):
     f2 = epyccel( f1 , language = language)
     assert f1(n) == f2(n)
 
+
 def test_almost_negative_index(language):
     from numpy.random import randint
     n = randint(2, 10)
@@ -2075,6 +2199,7 @@ def test_almost_negative_index(language):
     f2 = epyccel( f1 , language = language)
     assert f1(n) == f2(n)
 
+
 def test_var_negative_index(language):
     from numpy.random import randint
     n = randint(2, 10)
@@ -2083,6 +2208,7 @@ def test_var_negative_index(language):
     f2 = epyccel( f1 , language = language)
     assert f1(n,idx) == f2(n,idx)
 
+
 def test_expr_negative_index(language):
     from numpy.random import randint
     n = randint(2, 10)
@@ -2092,24 +2218,28 @@ def test_expr_negative_index(language):
     f2 = epyccel( f1 , language = language)
     assert f1(n,idx1,idx2) == f2(n,idx1,idx2)
 
+
 def test_multiple_negative_index(language):
     f1 = arrays.test_multiple_negative_index
     f2 = epyccel(f1, language = language)
 
     assert f1(-2, -1) == f2(-2, -1)
 
+
 def test_multiple_negative_index_2(language):
     f1 = arrays.test_multiple_negative_index_2
     f2 = epyccel(f1, language = language)
 
     assert f1(-4, -2) == f2(-4, -2)
 
+
 def test_multiple_negative_index_3(language):
     f1 = arrays.test_multiple_negative_index_3
     f2 = epyccel(f1, language = language)
 
     assert f1(-1, -1, -3) == f2(-1, -1, -3)
 
+
 def test_argument_negative_index_1(language):
     a = arrays.a_1d
 
@@ -2117,6 +2247,7 @@ def test_argument_negative_index_1(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_argument_negative_index_2(language):
     a = arrays.a_1d
 
@@ -2124,6 +2255,7 @@ def test_argument_negative_index_2(language):
     f2 = epyccel(f1, language = language)
     assert f1(a, a) == f2(a, a)
 
+
 def test_c_order_argument_negative_index(language):
     a = np.random.randint(20, size=(3,4))
 
@@ -2131,6 +2263,7 @@ def test_c_order_argument_negative_index(language):
     f2 = epyccel(f1, language = language)
     assert f1(a, a) == f2(a, a)
 
+
 def test_f_order_argument_negative_index(language):
     a = np.array(np.random.randint(20, size=(3,4)), order='F')
 
@@ -2155,6 +2288,7 @@ def test_array_random_size(language):
     s1, s2 = f2()
     assert s1 == s2
 
+
 def test_array_variable_size(language):
     f1 = arrays.array_variable_size
     f2 = epyccel( f1 , language = language)
@@ -2176,6 +2310,7 @@ def test_array_1d_slice_1(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_2(language):
     a = arrays.a_1d
 
@@ -2184,6 +2319,7 @@ def test_array_1d_slice_2(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_3(language):
     a = arrays.a_1d
 
@@ -2192,6 +2328,7 @@ def test_array_1d_slice_3(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_4(language):
     a = arrays.a_1d
 
@@ -2200,6 +2337,7 @@ def test_array_1d_slice_4(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_5(language):
     a = arrays.a_1d
 
@@ -2208,6 +2346,7 @@ def test_array_1d_slice_5(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_6(language):
     a = arrays.a_1d
 
@@ -2216,6 +2355,7 @@ def test_array_1d_slice_6(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_7(language):
     a = arrays.a_1d
 
@@ -2224,6 +2364,7 @@ def test_array_1d_slice_7(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_8(language):
     a = arrays.a_1d
 
@@ -2232,6 +2373,7 @@ def test_array_1d_slice_8(language):
 
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_9(language):
     a = arrays.a_1d
 
@@ -2240,6 +2382,7 @@ def test_array_1d_slice_9(language):
 
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2255,6 +2398,7 @@ def test_array_1d_slice_10(language):
 
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2270,6 +2414,7 @@ def test_array_1d_slice_11(language):
 
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2296,6 +2441,7 @@ def test_array_2d_F_slice_1(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_2(language):
     a = arrays.a_2d_f
 
@@ -2303,6 +2449,7 @@ def test_array_2d_F_slice_2(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_3(language):
     a = arrays.a_2d_f
 
@@ -2310,6 +2457,7 @@ def test_array_2d_F_slice_3(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_4(language):
     a = arrays.a_2d_f
 
@@ -2317,6 +2465,7 @@ def test_array_2d_F_slice_4(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_5(language):
     a = arrays.a_2d_f
 
@@ -2324,6 +2473,7 @@ def test_array_2d_F_slice_5(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_6(language):
     a = arrays.a_2d_f
 
@@ -2331,6 +2481,7 @@ def test_array_2d_F_slice_6(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_7(language):
     a = arrays.a_2d_f
 
@@ -2338,6 +2489,7 @@ def test_array_2d_F_slice_7(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_8(language):
     a = arrays.a_2d_f
 
@@ -2345,6 +2497,7 @@ def test_array_2d_F_slice_8(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_9(language):
     a = arrays.a_2d_f
 
@@ -2352,6 +2505,7 @@ def test_array_2d_F_slice_9(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_10(language):
     a = arrays.a_2d_f
 
@@ -2359,6 +2513,7 @@ def test_array_2d_F_slice_10(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_11(language):
     a = arrays.a_2d_f
 
@@ -2366,6 +2521,7 @@ def test_array_2d_F_slice_11(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_12(language):
     a = arrays.a_2d_f
 
@@ -2373,6 +2529,7 @@ def test_array_2d_F_slice_12(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_13(language):
     a = arrays.a_2d_f
 
@@ -2380,6 +2537,7 @@ def test_array_2d_F_slice_13(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_14(language):
     a = arrays.a_2d_f
 
@@ -2387,6 +2545,7 @@ def test_array_2d_F_slice_14(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_15(language):
     a = arrays.a_2d_f
 
@@ -2394,6 +2553,7 @@ def test_array_2d_F_slice_15(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_16(language):
     a = arrays.a_2d_f
 
@@ -2401,6 +2561,7 @@ def test_array_2d_F_slice_16(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_17(language):
     a = arrays.a_2d_f
 
@@ -2408,6 +2569,7 @@ def test_array_2d_F_slice_17(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_18(language):
     a = arrays.a_2d_f
 
@@ -2415,6 +2577,7 @@ def test_array_2d_F_slice_18(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_19(language):
     a = arrays.a_2d_f
 
@@ -2422,6 +2585,7 @@ def test_array_2d_F_slice_19(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_20(language):
     a = arrays.a_2d_f
 
@@ -2429,6 +2593,7 @@ def test_array_2d_F_slice_20(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2443,6 +2608,7 @@ def test_array_2d_F_slice_21(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2457,6 +2623,7 @@ def test_array_2d_F_slice_22(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2475,7 +2642,6 @@ def test_array_2d_F_slice_23(language):
 # TEST : 2d array slices order C
 #==============================================================================
 
-
 def test_array_2d_C_slice_1(language):
     a = arrays.a_2d_c
 
@@ -2483,6 +2649,7 @@ def test_array_2d_C_slice_1(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_2(language):
     a = arrays.a_2d_c
 
@@ -2490,6 +2657,7 @@ def test_array_2d_C_slice_2(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_3(language):
     a = arrays.a_2d_c
 
@@ -2497,6 +2665,7 @@ def test_array_2d_C_slice_3(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_4(language):
     a = arrays.a_2d_c
 
@@ -2504,6 +2673,7 @@ def test_array_2d_C_slice_4(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_5(language):
     a = arrays.a_2d_c
 
@@ -2511,6 +2681,7 @@ def test_array_2d_C_slice_5(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_6(language):
     a = arrays.a_2d_c
 
@@ -2518,6 +2689,7 @@ def test_array_2d_C_slice_6(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_7(language):
     a = arrays.a_2d_c
 
@@ -2525,6 +2697,7 @@ def test_array_2d_C_slice_7(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_8(language):
     a = arrays.a_2d_c
 
@@ -2532,6 +2705,7 @@ def test_array_2d_C_slice_8(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_9(language):
     a = arrays.a_2d_c
 
@@ -2539,6 +2713,7 @@ def test_array_2d_C_slice_9(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_10(language):
     a = arrays.a_2d_c
 
@@ -2546,6 +2721,7 @@ def test_array_2d_C_slice_10(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_11(language):
     a = arrays.a_2d_c
 
@@ -2553,6 +2729,7 @@ def test_array_2d_C_slice_11(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_12(language):
     a = arrays.a_2d_c
 
@@ -2560,6 +2737,7 @@ def test_array_2d_C_slice_12(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_13(language):
     a = arrays.a_2d_c
 
@@ -2567,6 +2745,7 @@ def test_array_2d_C_slice_13(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_14(language):
     a = arrays.a_2d_c
 
@@ -2574,6 +2753,7 @@ def test_array_2d_C_slice_14(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_15(language):
     a = arrays.a_2d_c
 
@@ -2581,6 +2761,7 @@ def test_array_2d_C_slice_15(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_16(language):
     a = arrays.a_2d_c
 
@@ -2588,6 +2769,7 @@ def test_array_2d_C_slice_16(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_17(language):
     a = arrays.a_2d_c
 
@@ -2595,6 +2777,7 @@ def test_array_2d_C_slice_17(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_18(language):
     a = arrays.a_2d_c
 
@@ -2602,6 +2785,7 @@ def test_array_2d_C_slice_18(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_19(language):
     a = arrays.a_2d_c
 
@@ -2609,6 +2793,7 @@ def test_array_2d_C_slice_19(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_20(language):
     a = arrays.a_2d_c
 
@@ -2616,6 +2801,7 @@ def test_array_2d_C_slice_20(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2630,6 +2816,7 @@ def test_array_2d_C_slice_21(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2644,6 +2831,7 @@ def test_array_2d_C_slice_22(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Array slicing does not work with negative variables in c. See #1311"),
@@ -2746,6 +2934,7 @@ def test_array_1d_slice_stride_8(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_stride_9(language):
     a = arrays.a_1d
 
@@ -2768,6 +2957,7 @@ def test_array_1d_slice_stride_10(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_stride_11(language):
     a = arrays.a_1d
 
@@ -2790,6 +2980,7 @@ def test_array_1d_slice_stride_12(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_stride_13(language):
     a = arrays.a_1d
 
@@ -2797,6 +2988,7 @@ def test_array_1d_slice_stride_13(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -2826,6 +3018,7 @@ def test_array_1d_slice_stride_15(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_stride_16(language):
     a = arrays.a_1d
 
@@ -2833,6 +3026,7 @@ def test_array_1d_slice_stride_16(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -2847,6 +3041,7 @@ def test_array_1d_slice_stride_17(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -2861,6 +3056,7 @@ def test_array_1d_slice_stride_18(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_stride_19(language):
     a = arrays.a_1d
 
@@ -2868,6 +3064,7 @@ def test_array_1d_slice_stride_19(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -2882,6 +3079,7 @@ def test_array_1d_slice_stride_20(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -2896,6 +3094,7 @@ def test_array_1d_slice_stride_21(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_stride_22(language):
     a = arrays.a_1d
 
@@ -2903,6 +3102,7 @@ def test_array_1d_slice_stride_22(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_1d_slice_stride_23(language):
     a = arrays.a_1d
 
@@ -2921,6 +3121,7 @@ def test_array_2d_F_slice_stride_1(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -2935,6 +3136,7 @@ def test_array_2d_F_slice_stride_2(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -2949,6 +3151,7 @@ def test_array_2d_F_slice_stride_3(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_stride_4(language):
     a = arrays.a_2d_f
 
@@ -2956,6 +3159,7 @@ def test_array_2d_F_slice_stride_4(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_stride_5(language):
     a = arrays.a_2d_f
 
@@ -2963,6 +3167,7 @@ def test_array_2d_F_slice_stride_5(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_stride_6(language):
     a = arrays.a_2d_f
 
@@ -2970,6 +3175,7 @@ def test_array_2d_F_slice_stride_6(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_stride_7(language):
     a = arrays.a_2d_f
 
@@ -2985,6 +3191,7 @@ def test_array_2d_F_slice_stride_8(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_F_slice_stride_9(language):
     a = arrays.a_2d_f
 
@@ -2992,6 +3199,7 @@ def test_array_2d_F_slice_stride_9(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3006,6 +3214,7 @@ def test_array_2d_F_slice_stride_10(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3020,6 +3229,7 @@ def test_array_2d_F_slice_stride_11(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3034,6 +3244,7 @@ def test_array_2d_F_slice_stride_12(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3048,6 +3259,7 @@ def test_array_2d_F_slice_stride_13(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3062,6 +3274,7 @@ def test_array_2d_F_slice_stride_14(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3076,6 +3289,7 @@ def test_array_2d_F_slice_stride_15(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3090,6 +3304,7 @@ def test_array_2d_F_slice_stride_16(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3104,6 +3319,7 @@ def test_array_2d_F_slice_stride_17(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3118,6 +3334,7 @@ def test_array_2d_F_slice_stride_18(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3132,6 +3349,7 @@ def test_array_2d_F_slice_stride_19(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3161,6 +3379,7 @@ def test_array_2d_F_slice_stride_21(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3175,6 +3394,7 @@ def test_array_2d_F_slice_stride_22(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3200,6 +3420,7 @@ def test_array_2d_C_slice_stride_1(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3214,6 +3435,7 @@ def test_array_2d_C_slice_stride_2(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3228,6 +3450,7 @@ def test_array_2d_C_slice_stride_3(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_stride_4(language):
     a = arrays.a_2d_c
 
@@ -3235,6 +3458,7 @@ def test_array_2d_C_slice_stride_4(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3249,6 +3473,7 @@ def test_array_2d_C_slice_stride_5(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 def test_array_2d_C_slice_stride_6(language):
     a = arrays.a_2d_c
 
@@ -3256,6 +3481,7 @@ def test_array_2d_C_slice_stride_6(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3278,6 +3504,7 @@ def test_array_2d_C_slice_stride_8(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3292,6 +3519,7 @@ def test_array_2d_C_slice_stride_9(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3306,6 +3534,7 @@ def test_array_2d_C_slice_stride_10(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3320,6 +3549,7 @@ def test_array_2d_C_slice_stride_11(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3334,6 +3564,7 @@ def test_array_2d_C_slice_stride_12(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3348,6 +3579,7 @@ def test_array_2d_C_slice_stride_13(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3362,6 +3594,7 @@ def test_array_2d_C_slice_stride_14(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3376,6 +3609,7 @@ def test_array_2d_C_slice_stride_15(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3390,6 +3624,7 @@ def test_array_2d_C_slice_stride_16(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3404,6 +3639,7 @@ def test_array_2d_C_slice_stride_17(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3418,6 +3654,7 @@ def test_array_2d_C_slice_stride_18(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3432,6 +3669,7 @@ def test_array_2d_C_slice_stride_19(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3446,6 +3684,7 @@ def test_array_2d_C_slice_stride_20(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3460,6 +3699,7 @@ def test_array_2d_C_slice_stride_21(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3474,6 +3714,7 @@ def test_array_2d_C_slice_stride_22(language):
     f2 = epyccel(f1, language = language)
     assert f1(a) == f2(a)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3489,39 +3730,105 @@ def test_array_2d_C_slice_stride_23(language):
     assert f1(a) == f2(a)
 
 #==============================================================================
-# TEST : arithmetic operations
+# TEST : Slice assignment
 #==============================================================================
+def test_copy_to_slice_issue_1218(language):
+    pyth_f = arrays.copy_to_slice_issue_1218
+    epyc_f = epyccel(pyth_f, language = language)
 
-def test_arrs_similar_shapes_0(language):
-    f1 = arrays.arrs_similar_shapes_0
-    f2 = epyccel(f1, language = language)
-    assert f1() == f2()
+    n = 10
+    pyth_arr = pyth_f(n)
+    epyc_arr = epyc_f(n)
+    check_array_equal(pyth_arr, epyc_arr)
 
-def test_arrs_similar_shapes_1(language):
-    f1 = arrays.arrs_similar_shapes_1
-    f2 = epyccel(f1, language = language)
-    assert f1() == f2()
 
-def test_arrs_different_shapes_0(language):
-    f1 = arrays.arrs_different_shapes_0
+def test_copy_to_slice_1(language):
+    pyth_f = arrays.copy_to_slice_1
+    epyc_f = epyccel(pyth_f, language = language)
+
+    pyth_a = np.arange(10, dtype=float)
+    epyc_a = pyth_a.copy()
+    b = np.arange(20, 28, dtype=float)
+    pyth_f(pyth_a, b)
+    epyc_f(epyc_a, b)
+    check_array_equal(pyth_a, epyc_a)
+
+
+def test_copy_to_slice_2(language):
+    pyth_f = arrays.copy_to_slice_2
+    epyc_f = epyccel(pyth_f, language = language)
+
+    pyth_a = np.arange(20, dtype=float).reshape(2, 10)
+    epyc_a = pyth_a.copy()
+    b = np.arange(20, 28, dtype=float)
+    pyth_f(pyth_a, b)
+    epyc_f(epyc_a, b)
+    check_array_equal(pyth_a, epyc_a)
+
+
+def test_copy_to_slice_3(language):
+    pyth_f = arrays.copy_to_slice_3
+    epyc_f = epyccel(pyth_f, language = language)
+
+    pyth_a = np.arange(20, dtype=float).reshape(4, 5)
+    epyc_a = pyth_a.copy()
+    b = np.arange(20, 24, dtype=float)
+    pyth_f(pyth_a, b)
+    epyc_f(epyc_a, b)
+    check_array_equal(pyth_a, epyc_a)
+
+
+def test_copy_to_slice_4(language):
+    pyth_f = arrays.copy_to_slice_4
+    epyc_f = epyccel(pyth_f, language = language)
+
+    pyth_a = np.arange(10, dtype=float)
+    epyc_a = pyth_a.copy()
+    b = np.arange(20, 25, dtype=float)
+    pyth_f(pyth_a, b)
+    epyc_f(epyc_a, b)
+    check_array_equal(pyth_a, epyc_a)
+
+#==============================================================================
+# TEST : arithmetic operations
+#==============================================================================
+
+def test_arrs_similar_shapes_0(language):
+    f1 = arrays.arrs_similar_shapes_0
+    f2 = epyccel(f1, language = language)
+    assert f1() == f2()
+
+
+def test_arrs_similar_shapes_1(language):
+    f1 = arrays.arrs_similar_shapes_1
+    f2 = epyccel(f1, language = language)
+    assert f1() == f2()
+
+
+def test_arrs_different_shapes_0(language):
+    f1 = arrays.arrs_different_shapes_0
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_arrs_uncertain_shape_1(language):
     f1 = arrays.arrs_uncertain_shape_1
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_arrs_2d_similar_shapes_0(language):
     f1 = arrays.arrs_2d_similar_shapes_0
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_arrs_2d_different_shapes_0(language):
     f1 = arrays.arrs_2d_different_shapes_0
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="Negative start of range does not work in c. See #1311"),
@@ -3534,21 +3841,25 @@ def test_arrs_1d_negative_index_1(language):
     f2 = epyccel(f1, language = language)
     assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_arrs_1d_negative_index_2(language):
     f1 = arrays.arrs_1d_negative_index_2
     f2 = epyccel(f1, language = language)
     assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_arrs_1d_int32_index(language):
     f1 = arrays.arrs_1d_int32_index
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_arrs_1d_int64_index(language):
     f1 = arrays.arrs_1d_int64_index
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_arr_tuple_slice_index(language):
     f1 = arrays.arr_tuple_slice_index
     f2 = epyccel(f1, language = language)
@@ -3558,6 +3869,7 @@ def test_arr_tuple_slice_index(language):
 
     check_array_equal(r_python, r_pyccel)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3570,11 +3882,13 @@ def test_arrs_1d_negative_index_negative_step(language):
     f2 = epyccel(f1, language = language)
     assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_arrs_1d_negative_step_positive_step(language):
     f1 = arrays.arrs_1d_negative_step_positive_step
     f2 = epyccel(f1, language = language)
     assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 @pytest.mark.parametrize( 'language', [
         pytest.param("c", marks = [
             pytest.mark.skip(reason="negative step does not work in c. See #1311"),
@@ -3596,11 +3910,13 @@ def test_numpy_arange_one_arg(language):
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_numpy_arange_two_arg(language):
     f1 = arrays.arr_arange_2
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_numpy_arange_full_arg(language):
     f1 = arrays.arr_arange_3
     f2 = epyccel(f1, language = language)
@@ -3611,11 +3927,13 @@ def test_numpy_arange_full_arg(language):
     assert (type(r_f1[1]) is type(r_f2[1]))
     np.testing.assert_allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_numpy_arange_with_dtype(language):
     f1 = arrays.arr_arange_4
     f2 = epyccel(f1, language = language)
     assert f1() == f2()
 
+
 def test_numpy_arange_negative_step(language):
     f1 = arrays.arr_arange_5
     f2 = epyccel(f1, language = language)
@@ -3626,6 +3944,7 @@ def test_numpy_arange_negative_step(language):
     assert (type(r_f1[1]) is type(r_f2[1]))
     np.testing.assert_allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_numpy_arange_negative_step_2(language):
     f1 = arrays.arr_arange_6
     f2 = epyccel(f1, language = language)
@@ -3636,6 +3955,7 @@ def test_numpy_arange_negative_step_2(language):
     assert (type(r_f1[1]) is type(r_f2[1]))
     np.testing.assert_allclose(f1(), f2(), rtol=RTOL, atol=ATOL)
 
+
 def test_numpy_arange_into_slice(language):
     f1 = arrays.arr_arange_7
     f2 = epyccel(f1, language = language)
@@ -3647,11 +3967,6 @@ def test_numpy_arange_into_slice(language):
     f2(x)
     np.testing.assert_allclose(x, x_expected, rtol=RTOL, atol=ATOL)
 
-def test_iterate_slice(language):
-    f1 = arrays.iterate_slice
-    f2 = epyccel(f1, language = language)
-    i = randint(2, 10)
-    assert f1(i) == f2(i)
 ##==============================================================================
 ## TEST NESTED ARRAYS INITIALIZATION WITH ORDER C
 ##==============================================================================
@@ -3674,6 +3989,7 @@ def test_array_float_nested_C_array_initialization(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_nested_C_array_initialization_2(language):
     f1 = arrays.array_float_nested_C_array_initialization_2
     f2 = epyccel(f1, language = language)
@@ -3691,6 +4007,7 @@ def test_array_float_nested_C_array_initialization_2(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_nested_C_array_initialization_3(language):
     f1 = arrays.array_float_nested_C_array_initialization_3
     f2 = epyccel(f1, language = language)
@@ -3717,6 +4034,7 @@ def test_arr_bool_sum(language):
     assert f1() == f2()
     assert isinstance(f1(), type(f2()))
 
+
 def test_tuple_sum(language):
     f1 = arrays.tuple_sum
     f2 = epyccel(f1, language = language)
@@ -3752,6 +4070,7 @@ def test_array_float_nested_F_array_initialization(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_nested_F_array_initialization_2(language):
     f1 = arrays.array_float_nested_F_array_initialization_2
     f2 = epyccel(f1, language = language)
@@ -3769,6 +4088,7 @@ def test_array_float_nested_F_array_initialization_2(language):
 
     assert np.array_equal(x1, x2)
 
+
 def test_array_float_nested_F_array_initialization_3(language):
     f1 = arrays.array_float_nested_F_array_initialization_3
     f2 = epyccel(f1, language = language)
@@ -3796,6 +4116,7 @@ def test_array_view_steps_C_1D_1(language):
     f2 = epyccel(f1, language = language)
     check_array_equal(f1(a), f2(a))
 
+
 def test_array_view_steps_C_1D_2(language):
     a = arrays.a_1d
 
@@ -3814,6 +4135,7 @@ def test_array_view_steps_C_2D_1(language):
     f2 = epyccel(f1, language = language)
     check_array_equal(f1(a), f2(a))
 
+
 def test_array_view_steps_C_2D_2(language):
     a = arrays.a_2d_c
 
@@ -3821,6 +4143,7 @@ def test_array_view_steps_C_2D_2(language):
     f2 = epyccel(f1, language = language)
     check_array_equal(f1(a), f2(a))
 
+
 def test_array_view_steps_C_2D_3(language):
     a = arrays.a_2d_c
 
@@ -3839,6 +4162,7 @@ def test_array_view_steps_F_1D_1(language):
     f2 = epyccel(f1, language = language)
     check_array_equal(f1(a), f2(a))
 
+
 def test_array_view_steps_F_1D_2(language):
     a = arrays.a_1d_f
 
@@ -3857,6 +4181,7 @@ def test_array_view_steps_F_2D_1(language):
     f2 = epyccel(f1, language = language)
     check_array_equal(f1(a), f2(a))
 
+
 def test_array_view_steps_F_2D_2(language):
     a = arrays.a_2d_f
 
@@ -3864,6 +4189,7 @@ def test_array_view_steps_F_2D_2(language):
     f2 = epyccel(f1, language = language)
     check_array_equal(f1(a), f2(a))
 
+
 def test_array_view_steps_F_2D_3(language):
     a = arrays.a_2d_f
 
@@ -3900,6 +4226,7 @@ def test_array_ndmin_1(language):
     check_array_equal(f1(d), f2(d))
     check_array_equal(f1(e), f2(e))
 
+
 @pytest.mark.parametrize( 'language', (
         pytest.param("fortran", marks = pytest.mark.fortran),
         pytest.param("c", marks = pytest.mark.c),
@@ -3925,6 +4252,7 @@ def test_array_ndmin_2(language):
     check_array_equal(f1(d), f2(d))
     check_array_equal(f1(e), f2(e))
 
+
 @pytest.mark.parametrize( 'language', (
         pytest.param("fortran", marks = pytest.mark.fortran),
         pytest.param("c", marks = pytest.mark.c),
@@ -3950,6 +4278,7 @@ def test_array_ndmin_4(language):
     check_array_equal(f1(d), f2(d))
     check_array_equal(f1(e), f2(e))
 
+
 @pytest.mark.parametrize( 'language', (
         pytest.param("fortran", marks = pytest.mark.fortran),
         pytest.param("c", marks = pytest.mark.c),
@@ -3976,10 +4305,2207 @@ def test_array_ndmin_2_order(language):
     check_array_equal(f1(e), f2(e))
 
 
-#def teardown_module():
-#    import os, glob
-#    dirname  = os.path.dirname( arrays.__file__ )
-#    pattern  = os.path.join( dirname, '__epyccel__*' )
-#    filelist = glob.glob( pattern )
-#    for f in filelist:
-#        os.remove( f )
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_dtype_conversion_to_bool_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_bool, language=language)
+
+    assert epyccel_func(bl) == arrays.dtype_convert_to_bool(bl)
+    assert epyccel_func(integer) == arrays.dtype_convert_to_bool(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_bool(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_bool(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_bool(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_bool(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_bool(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_bool(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_bool(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_bool(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_bool(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_dtype_conversion_to_int8_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8   = randint(low = iinfo('int8').min,   high = iinfo('int8').max, size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_int8, language=language)
+
+    assert epyccel_func(integer) == arrays.dtype_convert_to_int8(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_int8(integer8)
+    assert epyccel_func(bl) == arrays.dtype_convert_to_int8(bl)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_int8(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_int8(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_int8(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_int8(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_int8(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_int8(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_int8(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_int8(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_dtype_conversion_to_int16_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_int16, language=language)
+
+    assert epyccel_func(integer) == arrays.dtype_convert_to_int16(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_int16(integer8)
+    assert epyccel_func(bl) == arrays.dtype_convert_to_int16(bl)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_int16(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_int16(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_int16(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_int16(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_int16(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_int16(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_int16(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_int16(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_dtype_conversion_to_int32_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_int32, language=language)
+
+    assert epyccel_func(integer) == arrays.dtype_convert_to_int32(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_int32(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_int32(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_int32(integer32)
+    assert epyccel_func(bl) == arrays.dtype_convert_to_int32(bl)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_int32(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_int32(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_int32(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_int32(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_int32(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_int32(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_dtype_conversion_to_int64_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_int64, language=language)
+
+    assert epyccel_func(integer) == arrays.dtype_convert_to_int64(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_int64(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_int64(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_int64(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_int64(integer64)
+    assert epyccel_func(bl) == arrays.dtype_convert_to_int64(bl)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_int64(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_int64(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_int64(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_int64(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_int64(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_dtype_conversion_to_float32_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_float32, language=language)
+
+    assert epyccel_func(integer) == arrays.dtype_convert_to_float32(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_float32(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_float32(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_float32(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_float32(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_float32(fl)
+    assert epyccel_func(bl) == arrays.dtype_convert_to_float32(bl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_float32(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_float32(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_float32(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_float32(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_dtype_conversion_to_float64_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_float64, language=language)
+
+    assert epyccel_func(integer) == arrays.dtype_convert_to_float64(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_float64(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_float64(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_float64(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_float64(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_float64(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_float64(fl32)
+    assert epyccel_func(bl) == arrays.dtype_convert_to_float64(bl)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_float64(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_float64(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_float64(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_dtype_conversion_to_complex64_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_cfloat, language=language)
+
+    assert epyccel_func(bl) == arrays.dtype_convert_to_cfloat(bl)
+    assert epyccel_func(integer) == arrays.dtype_convert_to_cfloat(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_cfloat(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_cfloat(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_cfloat(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_cfloat(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_cfloat(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_cfloat(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_cfloat(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_cfloat(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_cfloat(cmplx128)
+
+
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_dtype_conversion_to_complex128_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_cdouble, language=language)
+
+    assert epyccel_func(bl) == arrays.dtype_convert_to_cdouble(bl)
+    assert epyccel_func(integer) == arrays.dtype_convert_to_cdouble(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_cdouble(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_cdouble(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_cdouble(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_cdouble(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_cdouble(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_cdouble(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_cdouble(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_cdouble(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_cdouble(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_dtype_conversion_to_pyint_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_pyint, language=language)
+
+    assert epyccel_func(bl) == arrays.dtype_convert_to_pyint(bl)
+    assert epyccel_func(integer) == arrays.dtype_convert_to_pyint(integer)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_pyint(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_pyint(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_pyint(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_pyint(integer64)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_pyint(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_pyint(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_pyint(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_pyint(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_pyint(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_dtype_conversion_to_pyfloat_from_other_types(language):
+    size = (2, 2)
+
+    bl = randint(0, 2, size = size, dtype= bool)
+
+    integer   = randint(low = iinfo('int').min,   high = iinfo('int').max, size = size, dtype=int)
+    integer8 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer16 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer32 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer64 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl32 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32 = np.float32(fl32)
+    fl64 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    cmplx128_from_float32 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx64 = np.complex64(cmplx128_from_float32)
+    cmplx128 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.dtype_convert_to_pyfloat, language=language)
+
+    assert epyccel_func(bl) == arrays.dtype_convert_to_pyfloat(bl)
+    assert epyccel_func(integer8) == arrays.dtype_convert_to_pyfloat(integer8)
+    assert epyccel_func(integer16) == arrays.dtype_convert_to_pyfloat(integer16)
+    assert epyccel_func(integer32) == arrays.dtype_convert_to_pyfloat(integer32)
+    assert epyccel_func(integer64) == arrays.dtype_convert_to_pyfloat(integer64)
+    assert epyccel_func(integer) == arrays.dtype_convert_to_pyfloat(integer)
+    assert epyccel_func(fl) == arrays.dtype_convert_to_pyfloat(fl)
+    assert epyccel_func(fl32) == arrays.dtype_convert_to_pyfloat(fl32)
+    assert epyccel_func(fl64) == arrays.dtype_convert_to_pyfloat(fl64)
+    assert epyccel_func(cmplx64) == arrays.dtype_convert_to_pyfloat(cmplx64)
+    assert epyccel_func(cmplx128) == arrays.dtype_convert_to_pyfloat(cmplx128)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_bool(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_bool, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int8(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int8, language=language)
+
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(integer_1, integer_2, integer_3)
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(b1, b2, b3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int16(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int16, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16(cmplx128_1, cmplx128_2, cmplx128_3)
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int32(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int32, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int64(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int64, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_float32(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_float32, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_float64(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_float64, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_cfloat(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_cfloat, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_cdouble(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_cdouble, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_pyint(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_pyint, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_pyfloat(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_bool_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_bool_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int8_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF, language=language)
+
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(b1, b2, b3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int8_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int16_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int16_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int32_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int32_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_int64_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_int64_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_float32_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float32_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_float64_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_float64_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_cfloat_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cfloat_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+            pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_cdouble_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_cdouble_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+def test_src_dest_array_diff_sizes_dtype_conversion_to_pyint_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyint_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+
+@pytest.mark.filterwarnings("ignore:Casting complex values to real discards the imaginary part")
+@pytest.mark.filterwarnings("ignore:overflow")
+@pytest.mark.filterwarnings("ignore:invalid value encountered in cast")
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.skip(reason=("Missing boolean cast in Fortran code, see #1785")),
+                      pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = pytest.mark.python)
+    )
+)
+def test_src_dest_array_diff_sizes_dtype_conversion_to_pyfloat_orderF(language):
+    size = (1,2)
+
+    integer_1 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_2 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+    integer_3 = randint(low = iinfo('int').min, high = iinfo('int').max , size = size, dtype=int)
+
+    integer8_1 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_2 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+    integer8_3 = randint(low = iinfo('int8').min, high = iinfo('int8').max , size = size, dtype=np.int8)
+
+    integer16_1 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_2 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+    integer16_3 = randint(low = iinfo('int16').min, high = iinfo('int16').max , size = size, dtype=np.int16)
+
+    integer32_1 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_2 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+    integer32_3 = randint(low = iinfo('int32').min, high = iinfo('int32').max , size = size, dtype=np.int32)
+
+    integer64_1 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_2 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+    integer64_3 = randint(low = iinfo('int64').min, high = iinfo('int64').max , size = size, dtype=np.int64)
+
+    fl_1 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_2 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+    fl_3 = uniform(finfo('float').min / 2, finfo('float').max / 2, size = size)
+
+    fl32_1 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_2 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_3 = uniform(finfo('float32').min / 2, finfo('float32').max / 2, size = size)
+    fl32_1 = np.float32(fl32_1)
+    fl32_2 = np.float32(fl32_2)
+    fl32_3 = np.float32(fl32_3)
+
+    fl64_1 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_2 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+    fl64_3 = uniform(finfo('float64').min / 2, finfo('float64').max / 2, size = size)
+
+    b1 = randint(0, 2, size = size, dtype= bool)
+    b2 = randint(0, 2, size = size, dtype= bool)
+    b3 = randint(0, 2, size = size, dtype= bool)
+
+    cmplx128_from_float32_1 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_2 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+    cmplx128_from_float32_3 = uniform(low= finfo('float32').min / 2, high= finfo('float32').max / 2, size = size) + uniform(low=finfo('float32').min / 2, high=finfo('float32').max / 2, size = size) * 1j
+
+    cmplx64_1 = np.complex64(cmplx128_from_float32_1)
+    cmplx128_1 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_2 = np.complex64(cmplx128_from_float32_2)
+    cmplx128_2 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    cmplx64_3 = np.complex64(cmplx128_from_float32_3)
+    cmplx128_3 = uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) + uniform(low=finfo('float64').min / 2, high=finfo('float64').max / 2, size = size) * 1j
+
+    epyccel_func = epyccel(arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF, language=language)
+
+    assert epyccel_func(b1, b2, b3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(b1, b2, b3)
+    assert epyccel_func(integer_1, integer_2, integer_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(integer_1, integer_2, integer_3)
+    assert epyccel_func(integer8_1, integer8_2, integer8_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(integer8_1, integer8_2, integer8_3)
+    assert epyccel_func(integer16_1, integer16_2, integer16_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(integer16_1, integer16_2, integer16_3)
+    assert epyccel_func(integer32_1, integer32_2, integer32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(integer32_1, integer32_2, integer32_3)
+    assert epyccel_func(integer64_1, integer64_2, integer64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(integer64_1, integer64_2, integer64_3)
+    assert epyccel_func(fl_1, fl_2, fl_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(fl_1, fl_2, fl_3)
+    assert epyccel_func(fl32_1, fl32_2, fl32_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(fl32_1, fl32_2, fl32_3)
+    assert epyccel_func(fl64_1, fl64_2, fl64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(fl64_1, fl64_2, fl64_3)
+    assert epyccel_func(cmplx64_1, cmplx64_2, cmplx64_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(cmplx64_1, cmplx64_2, cmplx64_3)
+    assert epyccel_func(cmplx128_1, cmplx128_2, cmplx128_3) == arrays.src_dest_diff_sizes_dtype_convert_to_pyfloat_orderF(cmplx128_1, cmplx128_2, cmplx128_3)
+
+##==============================================================================
+## TEST ITERATION
+##==============================================================================
+
+def test_iterate_slice(language):
+    f1 = arrays.iterate_slice
+    f2 = epyccel(f1, language = language)
+    i = randint(2, 10)
+    assert f1(i) == f2(i)
+
+@pytest.mark.parametrize( 'language', (
+        pytest.param("fortran", marks = [
+            pytest.mark.xfail(reason=("Cannot return a non-contiguous slice. See #1796")),
+                      pytest.mark.fortran]),
+        pytest.param("c", marks = pytest.mark.c),
+        pytest.param("python", marks = [
+            pytest.mark.xfail(reason=("Slicing code differs between types. Fixed by #1756")),
+            pytest.mark.python]),
+    )
+)
+def test_unpacking(language):
+    f1 = arrays.unpack_array
+    f2 = epyccel(f1, language = language)
+
+    arr = np.arange(3, dtype=int)
+    assert f1(arr) == f2(arr)
+
+    arr = np.arange(12, dtype=int).reshape((3,4))
+    x1, y1, z1 = f1(arr)
+    x2, y2, z2 = f2(arr)
+    check_array_equal(x1, x2)
+    check_array_equal(y1, y2)
+    check_array_equal(z1, z2)
+
+    arr = np.arange(24, dtype=int).reshape((3,4,2))
+    x1, y1, z1 = f1(arr)
+    x2, y2, z2 = f2(arr)
+    check_array_equal(x1, x2)
+    check_array_equal(y1, y2)
+    check_array_equal(z1, z2)
+
+    arr = np.arange(12, dtype=int).reshape((3,4), order='F')
+    x1, y1, z1 = f1(arr)
+    x2, y2, z2 = f2(arr)
+    check_array_equal(x1, x2)
+    check_array_equal(y1, y2)
+    check_array_equal(z1, z2)
+
+    arr = np.arange(24, dtype=int).reshape((3,4,2), order='F')
+    x1, y1, z1 = f1(arr)
+    x2, y2, z2 = f2(arr)
+    check_array_equal(x1, x2)
+    check_array_equal(y1, y2)
+    check_array_equal(z1, z2)
+
+def test_unpacking_of_known_size(language):
+    f1 = arrays.unpack_array_of_known_size
+    f2 = epyccel(f1, language = language)
+    assert f1() == f2()
+
+def test_unpacking_2D_of_known_size(language):
+    f1 = arrays.unpack_array_2D_of_known_size
+    f2 = epyccel(f1, language = language)
+    assert f1() == f2()
diff --git a/tests/epyccel/test_epyccel_generators.py b/tests/epyccel/test_epyccel_generators.py
index 12c999a575..f010db331d 100644
--- a/tests/epyccel/test_epyccel_generators.py
+++ b/tests/epyccel/test_epyccel_generators.py
@@ -109,7 +109,7 @@ def f(b : 'float[:]'):
 
     f_epyc = epyccel(f, language = language)
 
-    assert f(x) == f_epyc(x)
+    assert np.isclose(f(x), f_epyc(x), rtol=1e-14, atol=1e-14)
 
 @pytest.mark.parametrize( 'language', (
         pytest.param("fortran", marks = pytest.mark.fortran),
diff --git a/tests/epyccel/test_epyccel_return_arrays.py b/tests/epyccel/test_epyccel_return_arrays.py
index 229ccba4f9..9038002669 100644
--- a/tests/epyccel/test_epyccel_return_arrays.py
+++ b/tests/epyccel/test_epyccel_return_arrays.py
@@ -889,3 +889,19 @@ def copy_f_to_default(b : 'T'):
         assert pyth_out.dtype is pycc_out.dtype
         assert pyth_out.flags.c_contiguous == pycc_out.flags.c_contiguous
         assert pyth_out.flags.f_contiguous == pycc_out.flags.f_contiguous
+
+def test_annotated_return(language):
+    def annotated_return(b : 'float[:,:]', c : 'float[:,:]') -> 'float[:,:]':
+        return b + c
+
+    epyccel_func = epyccel(annotated_return, language=language)
+    fl_b = np.array(uniform(min_float / 2, max_float / 2, (3,4)))
+    fl_c = np.array(uniform(min_float / 2, max_float / 2, (3,4)))
+
+    pyth_out = annotated_return(fl_b, fl_c)
+    pycc_out = epyccel_func(fl_b, fl_c)
+
+    assert np.array_equal(pyth_out, pycc_out)
+    assert pyth_out.dtype is pycc_out.dtype
+    assert pyth_out.flags.c_contiguous == pycc_out.flags.c_contiguous
+    assert pyth_out.flags.f_contiguous == pycc_out.flags.f_contiguous
diff --git a/tests/errors/codegen/fortran/FORTRAN_ALLOCATABLE_IN_EXPRESSION.py b/tests/errors/codegen/fortran_blocking/FORTRAN_ALLOCATABLE_IN_EXPRESSION.py
similarity index 100%
rename from tests/errors/codegen/fortran/FORTRAN_ALLOCATABLE_IN_EXPRESSION.py
rename to tests/errors/codegen/fortran_blocking/FORTRAN_ALLOCATABLE_IN_EXPRESSION.py
diff --git a/tests/errors/codegen/fortran/randint.py b/tests/errors/codegen/fortran_blocking/randint.py
similarity index 100%
rename from tests/errors/codegen/fortran/randint.py
rename to tests/errors/codegen/fortran_blocking/randint.py
diff --git a/tests/errors/codegen/fortran_non_blocking/issue_1339.py b/tests/errors/codegen/fortran_non_blocking/issue_1339.py
new file mode 100644
index 0000000000..5d1d710cee
--- /dev/null
+++ b/tests/errors/codegen/fortran_non_blocking/issue_1339.py
@@ -0,0 +1,7 @@
+# pylint: disable=missing-function-docstring, missing-module-docstring
+from pyccel.decorators import types
+
+@types('int')
+@types('int[:]')
+def f(a):
+    return a+3
diff --git a/tests/errors/test_errors.py b/tests/errors/test_errors.py
index ca109ecdc3..ebcc3ada69 100644
--- a/tests/errors/test_errors.py
+++ b/tests/errors/test_errors.py
@@ -133,8 +133,8 @@ def test_semantic_non_blocking_developer_errors(f):
     error_mode.set_mode('user')
     assert(errors.has_errors())
 
-@pytest.mark.parametrize("f",get_files_from_folder("codegen/fortran"))
-def test_codegen_errors(f):
+@pytest.mark.parametrize("f",get_files_from_folder("codegen/fortran_blocking"))
+def test_codegen_blocking_errors(f):
     # reset Errors singleton
     errors = Errors()
     errors.reset()
@@ -148,12 +148,32 @@ def test_codegen_errors(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
+    codegen = Codegen(ast, name, 'fortran')
     with pytest.raises(PyccelCodegenError):
-        codegen.doprint()
+        codegen.printer.doprint(codegen.ast)
 
     assert(errors.has_errors())
 
+@pytest.mark.parametrize("f",get_files_from_folder("codegen/fortran_non_blocking"))
+def test_codegen_non_blocking_errors(f):
+    # reset Errors singleton
+    errors = Errors()
+    errors.reset()
+
+    pyccel = Parser(f)
+    ast = pyccel.parse()
+
+    settings = {}
+    ast = pyccel.annotate(**settings)
+
+    name = os.path.basename(f)
+    name = os.path.splitext(name)[0]
+
+    codegen = Codegen(ast, name, 'fortran')
+    codegen.printer.doprint(codegen.ast)
+
+    assert errors.has_errors()
+
 @pytest.mark.parametrize("f",get_files_from_folder("known_bugs"))
 def test_neat_errors_for_known_bugs(f):
     # reset Errors singleton
diff --git a/tests/ndarrays/test_ndarrays.c b/tests/ndarrays/test_ndarrays.c
index e308aced9c..c28c465b5e 100644
--- a/tests/ndarrays/test_ndarrays.c
+++ b/tests/ndarrays/test_ndarrays.c
@@ -1,7 +1,7 @@
-/* --------------------------------------------------------------------------------------- */
-/* This file is part of Pyccel which is released under MIT License. See the LICENSE file   */
-/* or go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. */
-/* --------------------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------------------- */
+/* This file is part of Pyccel which is released under MIT License. See the LICENSE file  */
+/* or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. */
+/* -------------------------------------------------------------------------------------- */
 
 #include "ndarrays.h"
 #include <unistd.h>
diff --git a/tests/pyccel/scripts/endif.py b/tests/pyccel/scripts/endif.py
new file mode 100644
index 0000000000..9a12b2ac58
--- /dev/null
+++ b/tests/pyccel/scripts/endif.py
@@ -0,0 +1,21 @@
+# pylint: disable=missing-function-docstring, missing-module-docstring
+
+def matmul(a: 'float[:,:](order=C)',
+           b: 'float[:,:](order=F)',
+           c: 'float[:,:](order=C)'):
+
+    m, p = a.shape
+    q, n = b.shape
+    r, s = c.shape
+
+    if p != q or m != r or n != s:
+        return -1
+
+    for i in range(m):
+        for j in range(n):
+            c[i, j] = 0.0
+            for k in range(p):
+                c[i, j] += a[i, k] * b[k, j]
+
+    return 0
+
diff --git a/tests/pyccel/scripts/runtest_badly_named_module.py b/tests/pyccel/scripts/runtest_badly_named_module.py
new file mode 100644
index 0000000000..ae2efb5e39
--- /dev/null
+++ b/tests/pyccel/scripts/runtest_badly_named_module.py
@@ -0,0 +1,10 @@
+# pylint: disable=missing-function-docstring, missing-module-docstring
+import numpy as np
+from endif import matmul
+
+if __name__ == '__main__':
+    a = np.ones((3,4))
+    b = np.ones((4,3), order='F')
+    c = np.empty((3,3))
+    matmul(a, b, c)
+    print(c)
diff --git a/tests/pyccel/test_pyccel.py b/tests/pyccel/test_pyccel.py
index 4422ec7c88..25822eb368 100644
--- a/tests/pyccel/test_pyccel.py
+++ b/tests/pyccel/test_pyccel.py
@@ -1192,3 +1192,15 @@ def test_time_execution_flag():
     assert 'Total' in result_lines[-2]
     for l in result_lines[1:-1]:
         assert ' : ' in l
+
+#------------------------------------------------------------------------------
+def test_module_name_containing_conflict(language):
+    base_dir = os.path.dirname(os.path.realpath(__file__))
+    path_dir = os.path.join(base_dir, "scripts")
+    compile_pyccel(path_dir, get_abs_path("scripts/endif.py"), options = f"--language={language}")
+
+    test_file = get_abs_path("scripts/runtest_badly_named_module.py")
+    out1 = get_python_output(test_file)
+    out2 = get_python_output(test_file)
+
+    assert out1 == out2
diff --git a/tests/symbolic/mappings.py b/tests/symbolic/mappings.py
new file mode 100644
index 0000000000..51b545335d
--- /dev/null
+++ b/tests/symbolic/mappings.py
@@ -0,0 +1,31 @@
+""" A file containing 2D analytical mappings to test Pyccel lambdify function.
+"""
+
+class PolarMapping:
+    """
+    Represents a Polar 2D Mapping object (Annulus).
+    """
+    expressions = {'x': 'c1 + (rmin*(1-x1)+rmax*x1)*cos(x2)',
+                    'y': 'c2 + (rmin*(1-x1)+rmax*x1)*sin(x2)'}
+    constants = {'rmin': 0.0, 'rmax': 1.0, 'c1' : 0.0, 'c2' : 0.0}
+
+#==============================================================================
+class TargetMapping:
+    """
+    Represents a Target 2D Mapping object.
+    """
+    expressions = {'x': 'c1 + (1-k)*x1*cos(x2) - D*x1**2',
+                    'y': 'c2 + (1+k)*x1*sin(x2)'}
+    constants = {'c1': 0.0, 'c2': 0.0, 'k' : 0.5, 'D' : '1.0'}
+
+#==============================================================================
+class CzarnyMapping:
+    """
+    Represents a Czarny 2D Mapping object.
+    """
+    expressions = {'x': '(1 - sqrt( 1 + eps*(eps + 2*x1*cos(x2)) )) / eps',
+                    'y': 'c2 + (b / sqrt(1-eps**2/4) * x1 * sin(x2)) /'
+                        '(2 - sqrt( 1 + eps*(eps + 2*x1*cos(x2)) ))'}
+    constants = {'eps' : 0.1, 'c2' : 0.0, 'b' : 1.0}
+
+
diff --git a/tests/symbolic/scripts/lambdas.py b/tests/symbolic/scripts/lambdas.py
deleted file mode 100644
index 828674e593..0000000000
--- a/tests/symbolic/scripts/lambdas.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# pylint: disable=missing-function-docstring, missing-module-docstring
-# coding: utf-8
-
-f1 = lambda x: x**2 + 1
-f2 = lambda x,y: x**2 + f1(y)*f1(x)
-g1 = lambda x: f1(x)**2 + 1
-
-# lambda expressions can be printed
-
-#$ header m1(double)
-m1 = lambdify(g1)
-print(f1)
-print(f2)
-print(g1)
diff --git a/tests/symbolic/scripts/neural_net.py b/tests/symbolic/scripts/neural_net.py
deleted file mode 100644
index 2d491fad8f..0000000000
--- a/tests/symbolic/scripts/neural_net.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# pylint: disable=missing-function-docstring, missing-module-docstring
-#$ header function f(double[:],double[:,:,:],int)
-@sympy
-def g(v,w,i):
-    from sympy import Lambda, Function ,symbols ,IndexedBase,Idx ,Max, Sum
-    x = Function('x')
-    i, n, j, dim, k =symbols('i, n, j, dim, k')
-    v=IndexedBase('v')
-    w=IndexedBase('w')
-    net = Lambda((i, n, dim, k), Max(0.0, Sum(x(k)*w[n, k, i], (k, 0, dim-1))))
-    dim = [10**4]*10
-    index =[symbols('i%s'%m) for m in range(len(dim)+1)]
-    y = [0]*len(dim)
-    new = v[index[0]]
-    for n in range(len(dim)):
-        y[n] = net(index[n+1], n, dim[n], index[n])
-        y[n] = y[n].subs(x(index[n]), new)
-        new = y[n]
-    return y[-1]
-
-f=lambdify(g)
-
diff --git a/tests/symbolic/test_symbolic.py b/tests/symbolic/test_symbolic.py
index aecdcfb0ae..a5d5da9199 100644
--- a/tests/symbolic/test_symbolic.py
+++ b/tests/symbolic/test_symbolic.py
@@ -4,18 +4,27 @@
 import os
 import pytest
 
+import numpy as np
+import sympy as sp
+
+import mappings
+
+from pyccel import lambdify as pyc_lambdify
 from pyccel.parser.parser   import Parser
 from pyccel.codegen.codegen import Codegen
 from pyccel.errors.errors   import Errors
 
+RTOL = 1e-13
+ATOL = 1e-14
+
 base_dir = os.path.dirname(os.path.realpath(__file__))
 path_dir = os.path.join(base_dir, 'scripts')
 
 files = sorted(os.listdir(path_dir))
-files = [f for f in files if (f.endswith(".py"))]
+files = [f for f in files if f.endswith(".py")]
 
 @pytest.mark.parametrize( "f", files )
-@pytest.mark.xfail(reason="Broken symbolic function support, see issue #330")
+@pytest.mark.skip(reason="Broken symbolic function support, see issue #330")
 def test_symbolic(f):
 
     pyccel = Parser(f)
@@ -27,13 +36,71 @@ def test_symbolic(f):
     name = os.path.basename(f)
     name = os.path.splitext(name)[0]
 
-    codegen = Codegen(ast, name)
-    codegen.doprint()
+    codegen = Codegen(ast, name, 'fortran')
+    codegen.printer.doprint(codegen.ast)
 
     # reset Errors singleton
     errors = Errors()
     errors.reset()
 
+def test_lambdify(language):
+    r1 = np.linspace(0.0, 1.0, 100)
+    p1 = np.linspace(0.0, 2*np.pi, 100)
+    r,p = np.meshgrid(r1, p1)
+    x,y = sp.symbols('x1,x2')
+    for m in (mappings.PolarMapping, mappings.TargetMapping, mappings.CzarnyMapping):
+        expr_x = sp.sympify(m.expressions['x']).subs(m.constants)
+        expr_y = sp.sympify(m.expressions['y']).subs(m.constants)
+        sp_x = sp.lambdify([x, y], expr_x)
+        sp_y = sp.lambdify([x, y], expr_y)
+        pyc_x = pyc_lambdify(expr_x, {x : 'float[:,:]', y : 'float[:,:]'}, result_type = 'float[:,:]',
+                    language = language)
+        pyc_y = pyc_lambdify(expr_y, {x : 'float[:,:]', y : 'float[:,:]'}, result_type = 'float[:,:]',
+                    language = language)
+
+        assert np.allclose(sp_x(r, p), pyc_x(r, p), rtol=RTOL, atol=ATOL)
+        assert np.allclose(sp_y(r, p), pyc_y(r, p), rtol=RTOL, atol=ATOL)
+
+        pyc_x = pyc_lambdify(expr_x, {x : 'T', y : 'T'}, templates = {'T': ['float[:]', 'float[:,:]']},
+                    language = language)
+        pyc_y = pyc_lambdify(expr_y, {x : 'T', y : 'T'}, templates = {'T': ['float[:]', 'float[:,:]']},
+                    language = language)
+
+        assert np.allclose(sp_x(r, p), pyc_x(r, p), rtol=RTOL, atol=ATOL)
+        assert np.allclose(sp_y(r, p), pyc_y(r, p), rtol=RTOL, atol=ATOL)
+
+        assert np.allclose(sp_x(r[0,:], p[0,:]), pyc_x(r[0,:], p[0,:]), rtol=RTOL, atol=ATOL)
+        assert np.allclose(sp_y(r[0,:], p[0,:]), pyc_y(r[0,:], p[0,:]), rtol=RTOL, atol=ATOL)
+
+def test_lambdify_out_arg(language):
+    r1 = np.linspace(0.0, 1.0, 100)
+    p1 = np.linspace(0.0, 2*np.pi, 100)
+    r,p = np.meshgrid(r1, p1)
+    x,y = sp.symbols('x1,x2')
+    for m in (mappings.PolarMapping, mappings.TargetMapping, mappings.CzarnyMapping):
+        expr_x = sp.sympify(m.expressions['x']).subs(m.constants)
+        expr_y = sp.sympify(m.expressions['y']).subs(m.constants)
+        sp_x = sp.lambdify([x, y], expr_x)
+        sp_y = sp.lambdify([x, y], expr_y)
+        pyc_x = pyc_lambdify(expr_x, {x : 'float[:,:]', y : 'float[:,:]'}, result_type = 'float[:,:]',
+                    use_out = True, language = language)
+        pyc_y = pyc_lambdify(expr_y, {x : 'float[:,:]', y : 'float[:,:]'}, result_type = 'float[:,:]',
+                    use_out = True, language = language)
+
+        print(pyc_x.__doc__)
+
+        sp_out_x = np.empty_like(r)
+        sp_out_y = np.empty_like(r)
+        pyc_out_x = np.empty_like(r)
+        pyc_out_y = np.empty_like(r)
+        sp_out_x = sp_x(r, p)
+        sp_out_y = sp_y(r, p)
+        pyc_x(r, p, pyc_out_x)
+        pyc_y(r, p, out = pyc_out_y)
+
+        assert np.allclose(sp_out_x, pyc_out_x, rtol=RTOL, atol=ATOL)
+        assert np.allclose(sp_out_y, pyc_out_y, rtol=RTOL, atol=ATOL)
+
 ######################
 if __name__ == '__main__':
     print('*********************************')
@@ -43,6 +110,6 @@ def test_symbolic(f):
     print('*********************************')
 
     for f in files:
-        print('> testing {0}'.format(str(f)))
+        print(f'> testing {f}')
         test_symbolic(f)
         print('\n')
diff --git a/tests/warnings/test_warnings.py b/tests/warnings/test_warnings.py
index 354f259fa3..dbeb84264b 100644
--- a/tests/warnings/test_warnings.py
+++ b/tests/warnings/test_warnings.py
@@ -69,8 +69,8 @@ def test_semantic_warnings(f):
 #    name = os.path.basename(f)
 #    name = os.path.splitext(name)[0]
 #
-#    codegen = Codegen(ast, name)
-#    code = codegen.doprint()
+#    codegen = Codegen(ast, name, 'fortran')
+#    code = codegen.printer.doprint(codegen.ast)
 #
 #    assert(errors.has_warnings())
 #    assert(not errors.has_errors())