Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #983 | Add Round function and implement the conversion to C, Fortran, and Python #996

Open
wants to merge 39 commits into
base: devel
Choose a base branch
from

Conversation

nandiniraja348
Copy link

I have added the Round Python function.

Added tests.

pyccel/ast/builtins.py Outdated Show resolved Hide resolved
@EmilyBourne EmilyBourne changed the title Issue #983 | Add Round function and implement the conversion to C and Fortran Issue #983 | Add Round function and implement the conversion to C, Fortran, and Python Oct 19, 2021
@EmilyBourne
Copy link
Member

Hi, how are you doing? Are you still working on this PR? Do you need a hand? I just wanted to remind you to keep your branch up to date with the master branch. There have been a few aesthetic changes recently (mainly PR #1012) which should be merged sooner rather than later to avoid accumulating conflicts

@EmilyBourne
Copy link
Member

round in python has a very strange way of handling values that are equally close to 2 integers (see here):

For the built-in types supporting round(), values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2). Any integer value is valid for ndigits (positive, zero, or negative). The return value is an integer if ndigits is omitted or None. Otherwise, the return value has the same type as number.

This needs to be handled, maybe we need to implement our own round function in pyc_math for c and fortran

@EmilyBourne EmilyBourne linked an issue May 30, 2022 that may be closed by this pull request
pyccel/ast/builtins.py Show resolved Hide resolved
@EmilyBourne EmilyBourne added Ready_for_review Received at least one approval. Requires review from senior developer and removed needs_initial_review labels Jul 16, 2022
@aihya
Copy link
Member

aihya commented Jul 19, 2022

An error is raised when I compile the following code for Fortran:

if __name__ == "__main__":
    print(round(42, ndigits=5))

The error:

ERROR at shared library generation stage
Traceback (most recent call last):
  File "/home/glitch/Documents/nandiniraja348/nandiniraja348_env/bin/pyccel", line 33, in <module>
    sys.exit(load_entry_point('pyccel', 'console_scripts', 'pyccel')())
  File "/home/glitch/Documents/nandiniraja348/pyccel/commands/console.py", line 241, in pyccel
    execute_pyccel(filename,
  File "/home/glitch/Documents/nandiniraja348/pyccel/codegen/pipeline.py", line 382, in execute_pyccel
    generated_program_filepath = src_compiler.compile_program(compile_obj=prog_obj,
  File "/home/glitch/Documents/nandiniraja348/pyccel/codegen/compiling/compilers.py", line 345, in compile_program
    self.run_command(cmd, verbose)
  File "/home/glitch/Documents/nandiniraja348/pyccel/codegen/compiling/compilers.py", line 429, in run_command
    raise RuntimeError(err_msg)
RuntimeError: Failed to build module
/home/glitch/Documents/nandiniraja348/__pyccel__/prog_test_round.f90:9:36:

    9 |   write(*, '(F0.12)', advance="yes") pyc_bankers_round(42_i64, 5_i64)
      |                                    1
Error: There is no specific function for the generic ‘pyc_bankers_round’ at (1)

@yguclu
Copy link
Member

yguclu commented Jul 19, 2022

@aihya Good catch! This is because the two functions implemented in Fortran require the first argument to be a float (single or double precision), while here you are passing an integer.

@nandiniraja348 Unit tests should be added to cover the case of integer input.

cc: @EmilyBourne

@aihya
Copy link
Member

aihya commented Jul 20, 2022

Following code is compiled for C

if __name__ == "__main__":
    print(round(42, ndigits=4.2))

Output:

$> pyccel test_round.py --language c
/home/glitch/Documents/nandiniraja348/pyccel/codegen/compiling/compilers.py:431: UserWarning: /home/glitch/Documents/nandiniraja348/__pyccel__/prog_test_round.c: In function ‘main’:
/home/glitch/Documents/nandiniraja348/__pyccel__/prog_test_round.c:7:15: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘double’ [-Wformat=]
    7 |     printf("%ld\n", lrint(42 * pow(10.0, 4.2)) / pow(10.0, 4.2));
      |             ~~^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |               |                                |
      |               long int                         double
      |             %f

  warnings.warn(UserWarning(err))

$> ./test_round
140733447113224

Incorrect rounded value when passing non-integer to ndigits:

if __name__ == "__main__":
    print(round(4.2, ndigits=4.2))

Output: 4.200030659267

@EmilyBourne
Copy link
Member

@aihya
Pyccel doesn't translate code which doesn't run in python. Your example:

if __name__ == "__main__":
    print(round(4.2, ndigits=4.2))

gives:

TypeError                                 Traceback (most recent call last)
<ipython-input-1-dd8329dcb3e7> in <module>
----> 1 print(round(4.2, ndigits=4.2))

TypeError: 'float' object cannot be interpreted as an integer

@EmilyBourne
Copy link
Member

The last failing test is due to an integer not being stored accurately in a floating point. I'm not sure how to fix this without using python's integer round method (operating on strings). Does anyone have any ideas?

@EmilyBourne EmilyBourne removed the Ready_for_review Received at least one approval. Requires review from senior developer label Aug 3, 2022
@yguclu yguclu assigned bauom and jalalium and unassigned bauom Mar 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add round function to pyccel
6 participants