Skip to content

How to control the precision of dependency libraries in top-level projects? #950

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

Closed
zoziha opened this issue Jun 25, 2023 · 8 comments
Closed
Labels
enhancement New feature or request

Comments

@zoziha
Copy link
Contributor

zoziha commented Jun 25, 2023

Description

Fortran's default floating point precision is single precision, and the most used data type in scientific computing is floating point.

There are quite a few libraries (e.g. slsqp) that provide macro-based precision options, which seems very useful when developers don't want to write multiple precision versions of routines and polymorphic interfaces.

Is it possible to have macro definitions for dependency libraries in top-level projects, e.g.:

[features]
slsqp = ['REAL32']
minpack = ['REAL32']
M_stopwatch = ['_WIN32']

This also has a positive effect on the fpm library ecology.

Possible Solution

Style 1:

[dependencies]
slsqp.git = 'https://github.com/jacobwilliams/slsqp'
slsqp.tag = '1.4.1'
slsqp.features = ['REAL32']

Style 2:

[dependencies]
slsqp = { git = 'https://github.com/jacobwilliams/slsqp', tag = '1.4.1', features = ['REAL32'] }

Style 3:

[features]
slsqp = ['REAL32']

[dependencies]
slsqp.git = 'https://github.com/jacobwilliams/slsqp'
slsqp.tag = '1.4.1'

Additional Information

@zoziha zoziha added the enhancement New feature or request label Jun 25, 2023
@perazz
Copy link
Member

perazz commented Jun 25, 2023

@zoziha, do you think the current preprocessor macro feature is insufficient?

I think that the current feature is project-based, while you’re asking for the ability to specify macros on a per-dependency basis.

I think that if we do that, the two could clash. For example, if sqslp has real64 defined in the package manifest, what happens if we also define real32 when we require it as a dependency?

@zoziha
Copy link
Contributor Author

zoziha commented Jun 25, 2023

@zoziha, do you think the current preprocessor macro feature is insufficient?

Currently preprocess.cpp can't do that and impose the macro definition of the top-level project to the dependency library. For example, I added an example and running it I get:

> cd . \example_packages\preprocess_cpp_deps2
> cat . \fpm.toml
name = "preprocess_cpp_deps"

[dependencies]
utils = { path = "crate/utils" }

[preprocess]
[preprocess.cpp]
macros = ["REAL64"]

> fpm run
main.f90 failed.
[ 50%] Compiling...
app\main.f90:12:21.

   12 | call say_hello(x)
      | 1
Error: Type mismatch in argument 'x' at (1); passed REAL(8) to REAL(4)
<ERROR> Compilation failed for object " app_main.f90.o "
<ERROR> stopping due to failed compilation
STOP 1

I think that if we do that, the two could clash. For example, if sqslp has real64 defined in the package manifest, what happens if we also define real32 when we require it as a dependency?

For libraries like slsqp, it is better not to predefine REAL64, if you do, there will indeed be possible conflicts. (Maybe it should be overwritten, or have the compiler report an error.)

I understand REAL64 to be more of a fpm package feature, which is optional and definable, not necessarily required.
If I were a fpm package developer, I would write code like the following:

#ifdef REAL64
    use, intrinsic :: iso_fortran_env, only: rk => real64
#else
    use, intrinsic :: iso_fortran_env, only: rk => real32
#endif

But I won't define REAL64 or REAL32 macros in fpm.toml, I want to leave this option to the user.

I think that the current feature is project-based, while you’re asking for the ability to specify macros on a per-dependency basis.

@perazz Thanks for your reply.
Yes, I think preprocess.cpp does not meet this requirement and both cargo and meson support this feature or option functionality. This issue is an fpm feature request.

@ivan-pi
Copy link
Member

ivan-pi commented Jul 4, 2023

This issues comes back to one I opened previously: #122

@perazz
Copy link
Member

perazz commented Jul 4, 2023

Yep. using macros is not perfect, but one can have

[dependencies]
slsqp = { git = 'https://github.com/jacobwilliams/slsqp', tag = '1.4.1', preprocess.cpp.macros = ['REAL32'] }
quadpack = { git = 'https://github.com/jacobwilliams/quadpack', preprocess.cpp.macros = ['REAL128'] }

@ivan-pi
Copy link
Member

ivan-pi commented Jul 4, 2023

I don't see how to do chaining, say if quadpack had it's own dependency which requires setting a macro. There could be conflicts with package A requiring B+real32 and package C requiring B+real64.

@perazz
Copy link
Member

perazz commented Jul 4, 2023

There is no way to control the conflicts of course, because macros are just simple labels.
However, if quadpack had it's own dependency that requires a macro, quadpack's fpm.toml could specify

[dependencies]
quadpack_dep = { git='blablah', preprocess.cpp.macros = ["QUADPACK_DEP_MACRO"]}

@ivan-pi
Copy link
Member

ivan-pi commented Jul 4, 2023

Perhaps we could just ship a precision module with fpm, that defined three constants fpm_lp, fpm_wp, fpm_hp. Then everyone in the fpm ecosystem could all just depend on fpm:

[dependencies]
fpm = { git = 'https://github.com/fortran-lang/fpm' }
module mymod
use fpm_kinds, only: wp => fpm_wp

In addition we could implement special preprocessing of the fpm_kinds module and have a fpm flag --prec-model=4/8/16 (standard gfortran choice), --prec-model=1/2/3 (NAG flags), --prec-model="float/double/long double"(C-compatible). These could also be named presets, according to conventions different programmers follow. NAG Fortran has somewhat related flags such as -kind=sequential (the default), -kind=byte or -kind=unique to select representation methods. Users of the NAG library are provided a nag_wp kind for normal work purposes.

@perazz
Copy link
Member

perazz commented Jul 10, 2023

Closed by #952.

@perazz perazz closed this as completed Jul 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants