diff --git a/_posts/2021-02-01-Fortran-Newsletter-February-2021.md b/_posts/2021-02-01-Fortran-Newsletter-February-2021.md new file mode 100644 index 000000000..f251b47a8 --- /dev/null +++ b/_posts/2021-02-01-Fortran-Newsletter-February-2021.md @@ -0,0 +1,202 @@ +--- +layout: post +title: "Fortran newsletter: February 2021" +category: newsletter +author: Sebastian Ehlert, Milan Curcic, Laurence Kedward, Jérémie Vandenplas, Alexis Perry-Holby +--- + +Welcome to the February 2021 edition of the monthly Fortran newsletter. +The newsletter comes out at the beginning of every month and details +Fortran news from the previous month. + + + +## fortran-lang.org + +This month we've had a few updates to the website: + +* [#190](https://github.com/fortran-lang/fortran-lang.org/pull/190): + Add links to fpm contributing guidelines + +Ongoing work: + +* [#191](https://github.com/fortran-lang/fortran-lang.org/pull/191) (WIP): + Fix author/maintainer output in fpm registry +* [#187](https://github.com/fortran-lang/fortran-lang.org/pull/187) (WIP): + Correct compiler page and tutorial regarding Intel oneAPI and PGI to NVIDIA +* [#174](https://github.com/fortran-lang/fortran-lang.org/issues/174) (WIP): + We are searching for a representative Fortran code snippet for the website and are looking forward to suggestions. + +[Let us know](https://github.com/fortran-lang/fortran-lang.org/issues) if you have any suggestions for the website and its content. +We welcome any new contributors to the website and the tutorials page in particular - see the [contributor guide](https://github.com/fortran-lang/fortran-lang.org/blob/master/CONTRIBUTING.md) for how to get started. + +## Fortran Standard Library + +Here's what's new in `stdlib`: + +* [#303](https://github.com/fortran-lang/stdlib/pull/303), + [#301](https://github.com/fortran-lang/stdlib/pull/301), + [#294](https://github.com/fortran-lang/stdlib/pull/294): + Fixes and improvements for the manual Makefile build +* [#293](https://github.com/fortran-lang/stdlib/pull/293): + Write a more verbose introduction to building stdlib +* [#291](https://github.com/fortran-lang/stdlib/pull/291): + Export package files (CMake and pkg-config) +* [#290](https://github.com/fortran-lang/stdlib/pull/290): + Rename CMake project from stdlib to fortran\_stdlib +* [#288](https://github.com/fortran-lang/stdlib/pull/288): + Follow GNU install conventions +* [#284](https://github.com/fortran-lang/stdlib/pull/284): + Required changes to be able to use `stdlib` as a subproject in CMake +* [CMake example](https://github.com/fortran-lang/stdlib-cmake-example): + Integration of the Fortran standard library in CMake projects + +Work in progress: + +* [#304](https://github.com/fortran-lang/stdlib/pull/304) (WIP): + Add supported compilers MinGW 8, 9, 10 +* [#269](https://github.com/fortran-lang/stdlib/pull/269) (WIP): + Implementation of a module for handling lists of strings +* [#271](https://github.com/fortran-lang/stdlib/pull/271) (WIP), + [#272](https://github.com/fortran-lang/stdlib/pull/272) (WIP), + [#273](https://github.com/fortran-lang/stdlib/pull/273) (WIP), + [#276](https://github.com/fortran-lang/stdlib/pull/276) (WIP), + [#278](https://github.com/fortran-lang/stdlib/pull/278) (WIP): + Implementation of the `stdlib_stats_distribution` modules. + It provides probability distribution and statistical functions. +* [#189](https://github.com/fortran-lang/stdlib/pull/189) (WIP): + Initial implementation of sparse matrices. + +Don't hesitate to test and review these pull requests! + +Otherwise, ongoing discussions continue about usability of `stdlib` +([#7](https://github.com/fortran-lang/stdlib/issues/7), +[#215](https://github.com/fortran-lang/stdlib/issues/215), +[#279](https://github.com/fortran-lang/stdlib/issues/279), +[#280](https://github.com/fortran-lang/stdlib/issues/280), +[#285](https://github.com/fortran-lang/stdlib/issues/285)), +and new implementations for `stdlib` +([#135](https://github.com/fortran-lang/stdlib/issues/135), +[#212](https://github.com/fortran-lang/stdlib/issues/212), +[#234](https://github.com/fortran-lang/stdlib/issues/234), +[#241](https://github.com/fortran-lang/stdlib/issues/241), +[#258](https://github.com/fortran-lang/stdlib/issues/258), +[#259](https://github.com/fortran-lang/stdlib/issues/259), +[#262](https://github.com/fortran-lang/stdlib/issues/262), +[#268](https://github.com/fortran-lang/stdlib/issues/268), +[#277](https://github.com/fortran-lang/stdlib/issues/277)). + + +The candidate for file system operations to be included in stdlib is being developed by +[@MarDiehl](https://github.com/MarDiehl) and [@arjenmarkus](https://github.com/arjenmarkus) +in [this repository](https://github.com/MarDiehl/stdlib_os). +Please try it out and let us know how it works, if there are any issues, or if the API can be improved. + +## Fortran Package Manager + +Here's what's new in `fpm`: + +* [#342](https://github.com/fortran-lang/fpm/pull/342): + Fix broken link in contributing guidelines +* [#337](https://github.com/fortran-lang/fpm/pull/337): + Allow hyphens in fpm project names in "fpm new" +* [#335](https://github.com/fortran-lang/fpm/pull/335): + Fix: performance regression +* [#334](https://github.com/fortran-lang/fpm/pull/334): + Remove a name clash in the fpm testsuite + +Work in progress: + +* [First beta release](https://github.com/fortran-lang/fpm/milestone/1) (WIP): + First feature-complete release of the Fortran implementation. +* [#230](https://github.com/fortran-lang/fpm/pull/230), + [#261](https://github.com/fortran-lang/fpm/pull/261) (WIP): + Specification of the fpm CLI. +* [#316](https://github.com/fortran-lang/fpm/pull/316) (WIP): + Update subcommand "new" to reflect the addition of support for examples +* [#345](https://github.com/fortran-lang/fpm/pull/345) (WIP): + Update: fpm\_backend with dynamic openmp scheduling + +`fpm` is still in early development and we need as much help as we can get. +Here's how you can help today: + +* Use it and let us know what you think! Read the [fpm packaging guide](https://github.com/fortran-lang/fpm/blob/master/PACKAGING.md) to learn how to build your package with fpm, and the [manifest reference](https://github.com/fortran-lang/fpm/blob/master/manifest-reference.md) to learn what are all the things that you can specify in the fpm.toml file. +* Browse existing *fpm* packages on the [fortran-lang website](https://fortran-lang.org/packages/fpm) +* Browse the [open issues](https://github.com/fortran-lang/fpm/issues) and see if you can help implement any fixes or features. +* Adapt your Fortran package for fpm and submit it to the [Registry](https://github.com/fortran-lang/fpm-registry). +* Improve the documentation. + +The short-term goal of fpm is to make development and installation of Fortran packages with dependencies easier. +Its long term goal is to build a rich and decentralized ecosystem of Fortran packages and create a healthy +environment in which new open source Fortran projects are created and published with ease. + +## Compilers + +### Classic Flang + +There are a number of pull requests out for evaluation. + +A total of 12 pull requests were merged in January. + +* [PR#932 Do not assume unempty derived types](https://github.com/flang-compiler/flang/pull/932) +* [PR#957 Support Prefetch Directive](https://github.com/flang-compiler/flang/pull/957) +* [PR#947 Fix gcc-10 compilaton issues](https://github.com/flang-compiler/flang/pull/947) +* [PR#948 Expand CI to run with GCC-9/10 and LLVM-9/10/11](https://github.com/flang-compiler/flang/pull/948) +* [PR#949 USE rename should check if renamed sptr is available in the scope](https://github.com/flang-compiler/flang/pull/949) +* [PR#971 Remove dwarfdump_prolog.f90 test since it is dependent on codegen](https://github.com/flang-compiler/flang/pull/971) +* [PR#940 Flang should generate debug location for limited instructions in prolog](https://github.com/flang-compiler/flang/pull/940) +* [PR#977 Update apt data before installing sphinx](https://github.com/flang-compiler/flang/pull/977) +* [PR#751 Fix for len intrinsic returning int*8 in some cases](https://github.com/flang-compiler/flang/pull/751) +* [PR#956 Minor FileCheck pattern fixes](https://github.com/flang-compiler/flang/pull/956) +* [PR#978 Fix the readme to point to the correct flang-dev list](https://github.com/flang-compiler/flang/pull/978) +* [PR#979 Rename direct header to avoid windows conflict](https://github.com/flang-compiler/flang/pull/979) + + +### LLVM Flang + +Recent development updates: + +* OpenMP semantic checks: private, firstprivate, lastprivate, Workshare Construct, `DO` loop restrictions +* Detect call to abstract interface +* OpenMP - add task_reduction clause, make reduction clause part of OmpClause +* New Driver - adding support for various options, testing improvements, standard macro pre-definitions, fixed-form detection, CMake improvements +* OpenACC - semantic checks to enforce declare directive restrictions +* Internal subprogram improvements +* OpenMP/OpenACC - Extend CheckNoBranching to handle branching provided by LabelEnforce +* Disallow `INTENT` attribute on procedure dummy arguments +* Module file improvements and bug fixes +* Add tests for procedure arguments with implicit interfaces + +Call notes will be sent to the _flang-dev_ email list and also recorded [here](https://docs.google.com/document/d/10T-S2J3GrahpG4Ooif93NSTz2zBW0MQc_RlwHi0-afY). + + +## Events + +* We had our 8th Fortran Monthly call on January 19. +You can watch the recording below: + + + +* This year fortran-lang will be applying as a mentor organisation for [Google Summer of Code](https://summerofcode.withgoogle.com/). +We have started working on the application and the project ideas; you can join the ongoing discussion [here](https://fortran-lang.discourse.group/t/google-summer-of-code-2021/658). +If you'd like to help us flesh out the ideas, or have a project idea of your own, please join our upcoming video calls on February 9 and 16 (call info will be posted in the Discourse thread), or write directly in the Discourse thread. +If you're a student, or know students who are [eligible to participate](https://developers.google.com/open-source/gsoc/faq#what_are_the_eligibility_requirements_for_participation), and you'd like to help build the Fortran ecosystem please reach out and let us know. + +As usual, subscribe to the [mailing list](https://groups.io/g/fortran-lang) and/or +join the [Discourse](https://fortran-lang.discourse.group) to stay tuned with the future meetings. + +## Contributors + +We thank everybody who contributed to fortran-lang in the past month by +commenting in any of these repositories: + +* [fortran-lang/stdlib](https://github.com/fortran-lang/stdlib) +* [fortran-lang/stdlib-cmake-example](https://github.com/fortran-lang/stdlib-cmake-example) +* [fortran-lang/fpm](https://github.com/fortran-lang/fpm) +* [fortran-lang/fpm-registry](https://github.com/fortran-lang/fpm-registry) +* [fortran-lang/setup-fpm](https://github.com/fortran-lang/setup-fpm) +* [fortran-lang/fortran-lang.org](https://github.com/fortran-lang/fortran-lang.org) +* [fortran-lang/benchmarks](https://github.com/fortran-lang/benchmarks) +* [j3-fortran/fortran\_proposals](https://github.com/j3-fortran/fortran_proposals) + +
diff --git a/community/github_stats_data/data-fortran-lang-fortran-lang.org.json b/community/github_stats_data/data-fortran-lang-fortran-lang.org.json index da916e593..9805af27e 100644 --- a/community/github_stats_data/data-fortran-lang-fortran-lang.org.json +++ b/community/github_stats_data/data-fortran-lang-fortran-lang.org.json @@ -1,6 +1,62 @@ { "name": "fortran-lang/fortran-lang.org", "issues": [ + { + "number": 193, + "user": "awvwgk", + "date": "2021-01-30 13:58:26+00:00", + "title": "Monthly newsletter for February 2021", + "text": "I put together a draft for the February monthly newsletter and populated it from the repository activities.\n\n collect PRs from stdlib\n collect PRs from fpm, setup-fpm and fpm-registry\n collect PRs from fortran-lang.org\n add link to Fortran monthly call recording\n update contributor data (@LKedward)\n add updates on classic flang\n add updates on LLVM flang\n add updates on LFortran (@certik)\n\nPlease review and edit if needed. As usual, please add your name to the authors list if you add, edit, or review content.", + "comments": [ + { + "user": "LKedward", + "date": "2021-01-30 14:40:39+00:00", + "text": "Thanks for starting! I'll update contributor data tomorrow." + }, + { + "user": "milancurcic", + "date": "2021-01-30 16:38:50+00:00", + "text": "Thanks for starting it. Do you think we should mention GSoC to try gather early interest from prospective students? Something like:\n\nThis year fortran-lang will be applying as an Org for Google Summer of Code. We started working on the application and the project ideas. If you'd like to help us flesh them out, please join our video call on (Milan TODO). If you're a student and you'd like to help build the Fortran ecosystem, or have a project idea you'd like to work on, please reach out and let us know (how exactly? Milan TODO).\n\nI think this would go in the Events section." + }, + { + "user": "milancurcic", + "date": "2021-01-30 16:45:41+00:00", + "text": "Regarding news from Classic Flang and LLVM Flang: @AlexisPerry, would you like to provide updates from both Flang projects for the monthly newsletter? We distribute these on the mailing list (131 subscribers), Discourse, and Twitter (604 followers). Flang updates in the newsletter may bring new users, and who knows, maybe even new contributors.\nHere's a sample newsletter from last month and what Flang updates look like: https://fortran-lang.org/newsletter/2021/01/01/Fortran-Newsletter-January-2021/#compilers\nPreviously @gklimowicz has been helping with these, but he stepped back and mentioned your name. It would be very helpful if you agreed to do it! :)" + } + ] + }, + { + "number": 192, + "user": "awvwgk", + "date": "2021-01-03 09:21:26+00:00", + "title": "Sort fpm registry alphabetically", + "text": "The fpm registry at packages/fpm is currently sorted chronologically in the order of addition to the registry, a more useful sorting would be alphabetically.\nIt appears that Liquid is not able to sort a hash map alphabetically (!) by itself, therefore implementing this in Liquid will be ugly.", + "comments": [ + { + "user": "LKedward", + "date": "2021-01-03 11:29:29+00:00", + "text": "Perhaps the best option is to structure the index differently, as an array instead of a hash map" + }, + { + "user": "awvwgk", + "date": "2021-01-03 12:23:25+00:00", + "text": "A hash map is the right representation for the registry, I see no need to adapt it due to the shortcomings of a templating language. An easy fix from the fpm-registry side would be sorting the index before committing it, alternatively we have to search for a gem that can add the feature we need for the webpage here." + }, + { + "user": "LKedward", + "date": "2021-01-04 10:52:45+00:00", + "text": "True, though the index is only a serialisation, converting to an array serialisation does not preclude implementation as a hash map. I'd rather not complicate the build with additional Ruby code so sorting the index would be preferred. It's unfortunate to rely on the ordering of the data for rendering the site but your proposed solution is perhaps the simplest." + } + ] + }, + { + "number": 191, + "user": "awvwgk", + "date": "2021-01-03 09:15:26+00:00", + "title": "Fix author/maintainer output in fpm registry", + "text": "Joins arrays of author/maintainer names with \" and \".\nAlso, simplifies fetching of registry in workflow file.", + "comments": [] + }, { "number": 190, "user": "awvwgk", @@ -30,6 +86,21 @@ "user": "LKedward", "date": "2020-12-30 10:31:41+00:00", "text": "Thanks for starting @jvdp1 and thanks for populating the fpm section @awvwgk - it was a busy month for fpm!\nLeft a few minor suggestions but everything else looks good. I'll update the contributor data tomorrow." + }, + { + "user": "milancurcic", + "date": "2021-01-04 16:36:04+00:00", + "text": "Thank you, @gklimowicz!\n@certik are there any updates for LFortran or is this good to go?" + }, + { + "user": "certik", + "date": "2021-01-04 17:30:49+00:00", + "text": "There are updates, but I don't have time to write them down, so this is good to go." + }, + { + "user": "milancurcic", + "date": "2021-01-04 18:25:45+00:00", + "text": "Okay, sounds good, we can defer LFortran news to the next newsletter. I'll merge now. Thank you all!" } ] }, diff --git a/community/github_stats_data/data-fortran-lang-fpm.json b/community/github_stats_data/data-fortran-lang-fpm.json index 562e86d86..0ed03b113 100644 --- a/community/github_stats_data/data-fortran-lang-fpm.json +++ b/community/github_stats_data/data-fortran-lang-fpm.json @@ -1,6 +1,293 @@ { "name": "fortran-lang/fpm", "issues": [ + { + "number": 345, + "user": "LKedward", + "date": "2021-01-29 12:43:12+00:00", + "title": "Update: fpm_backend with dynamic openmp scheduling", + "text": "I noticed the parallel compilation time for my stdlib-fpm package was quite poor (on 4 threads) and realised the default static scheduling of threads was causing poor utilisation since compilation times can vary significantly between individual targets. (This is less of a problem for higher core counts)\nThis PR makes dynamic scheduling explicit when using OpenMP for parallel compilation which gives much better utilisation (2x improvement for stdlib-fpm) and avoids implementation-dependent choice of scheduling. We have no pressing need for static scheduling and the overhead for dynamic scheduling appears to be small compared to the time for compilation.", + "comments": [] + }, + { + "number": 344, + "user": "milancurcic", + "date": "2021-01-27 20:50:53+00:00", + "title": "Using fpm to upgrade fpm itself", + "text": "Say I have fpm-0.1.3 and want to upgrade to current master or some future tag like v0.1.4. After the step 2 of #253 is implemented (so that the fpm.toml is in root dir), I think this should be possible by going through the following steps:\n\nfpm new a dummy project.\nAdd fpm as a dependency to the manifest and specify the v0.1.4 tag.\nRun fpm install. This will build the fpm library and binary as a dependency and put it to ~/.local/bin.\n\nThis will be somewhat awkward and not easy to do. Having the fpm upgrade command do this for you would be useful and nice UX I think.\nWhat do you think?", + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-28 08:05:22+00:00", + "text": "This workflow can't work, executables are currently only installed from the root project but not from the dependencies and I don't think it is a good idea to change this behaviour.\nMaybe a more pip like syntax could be desirable here\nfpm install https://github.com/fortran-lang/fpm\n\nThis would clone into a temporary directory, build the project and install into ~/.local/bin." + }, + { + "user": "milancurcic", + "date": "2021-01-28 14:49:18+00:00", + "text": "Yes, I didn't suggest that workflow as a solution, but used it as an example of what the user would have to do if it had worked as I thought.\nfpm install https://github.com/fortran-lang/fpm\n\nseems nice to me, though not as easy as fpm upgrade. What do you think about this command being an alias for what you suggested?" + }, + { + "user": "awvwgk", + "date": "2021-01-28 14:54:29+00:00", + "text": "fpm upgrade would require a local registry of fpm installed packages to check for all packages that should be updated." + }, + { + "user": "milancurcic", + "date": "2021-01-28 15:02:07+00:00", + "text": "Why? What fpm installed packages depend on an fpm binary?" + }, + { + "user": "awvwgk", + "date": "2021-01-28 15:04:45+00:00", + "text": "Ah, now I understand, we are talking about a self-upgrade command here. I thought we are talking about a general upgrade strategy and fpm was used as example." + }, + { + "user": "awvwgk", + "date": "2021-01-28 16:26:43+00:00", + "text": "Just as a note, self-upgrading programs are usually not well-received in most packaging ecosystems (except maybe in their own one). The user experience of updating fpm would preferably boil down to pacman -Syu fpm, brew upgrade fpm or mamba update fpm. I'm not sure if fpm has to roll its own self-updating strategy at all." + }, + { + "user": "epagone", + "date": "2021-01-28 16:35:56+00:00", + "text": "I also add that I think the misunderstanding above suggests one more potential problem: IIRC fpm update updates the dependencies of the project, whereas the proposed fpm upgrade would be an upgrade of fpm itself. This is somehow inconsistent and can confuse the user." + }, + { + "user": "milancurcic", + "date": "2021-01-28 16:46:39+00:00", + "text": "self-upgrading programs are usually not well-received in most packaging ecosystems (except maybe in their own one)\n\nThis is no surprise for obvious reasons. I would too recommend that people don't write self-upgrading fpm packages, but to use fpm to do that for them. :)\n\nThe user experience of updating fpm would preferably boil down to pacman -Syu fpm, brew upgrade fpm or mamba update fpm.\n\nIn theory, I think you're right, but in practice it doesn't work. There are so many system-specific package managers that there would be a lot of work for the fpm developers to keep shipping updates on all of them. System-specific managers also have an end-of-life for updates.\nI don't think this is a priority now, but wanted to get a pulse from people. It could also be a plugin (#211) or 3rd party tool, so people like me who want to use it, can." + }, + { + "user": "brocolis", + "date": "2021-01-28 19:14:22+00:00", + "text": "On Windows there's a problem when trying to upgrade a program that is currently running (already in use Error). On Linux, it should work.\nTentative implementation\nhttps://gist.github.com/brocolis/e2fc06743652f939d95d351b16721f5c" + } + ] + }, + { + "number": 343, + "user": "awvwgk", + "date": "2021-01-23 18:18:13+00:00", + "title": "Fortran fpm help_test invokes fpm", + "text": "The help_test currently invokes fpm, this usually triggers a complete rebuild of both debug and release version unconditionally.\n\n \n \n fpm/fpm/test/help_test/help_test.f90\n \n \n Lines 21 to 46\n in\n c485357\n \n \n \n \n\n \n \n ! debug version \n \n\n \n \n 'fpm run -- --version ',& ! verify fpm version being used \n \n\n \n \n 'fpm run -- --help > fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help new >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help update >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- build --help >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help run >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help test >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help runner >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help install >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help list >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- help help >> fpm_scratch_help.txt',& \n \n\n \n \n 'fpm run -- --version >> fpm_scratch_help.txt',& \n \n\n \n \n ! release version \n \n\n \n \n 'fpm run --release -- --version ',& ! verify fpm version being used \n \n\n \n \n 'fpm run --release -- --help > fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help new >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help update >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- build --help >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help run >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help test >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help runner >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help install >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help list >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- help help >> fpm_scratch_help3.txt',& \n \n\n \n \n 'fpm run --release -- --version >> fpm_scratch_help3.txt',& \n \n \n \n\n\nIt might also invoke another version of fpm or completely fail if no fpm is in the PATH.", + "comments": [ + { + "user": "urbanjost", + "date": "2021-01-24 03:06:58+00:00", + "text": "A lot has changed since it was written, including where a \"run\" only did a build test if the binary was missing, but it was my understandng that each test was run in an environment that was created on demand and included the fpm command. It is running the help on the latest version built by the fpm command. I have not looked recently at a build log but the last time I looked it displayed the expected version number and did not show a build of fpm itself in the log file. So it has been testing the latest version successfully in the manner expected. Need a better definition of exactly how the test environment is deployed that the tests run in, but what you describe sounds basically what would be desired if the test environment is set up the way I thought; so need some more details, as I believe those conditions are not supposed to occur for the test environment." + }, + { + "user": "awvwgk", + "date": "2021-01-24 07:30:31+00:00", + "text": "You can see a new build starting in the testing environment at https://github.com/fortran-lang/fpm/runs/1754249868?check_suite_focus=true#step:12:2331 in the test step.\nAlso a common case I encountered this was when testing a bootstrapped build with\nfpm run -- test" + }, + { + "user": "urbanjost", + "date": "2021-01-24 15:15:42+00:00", + "text": "It builds the latest version if required and runs the new copy to verify it gets the expected results. It is slower than expected but is doing the intended test. I believe there is an item open to add more actual fpm tests; but testing the actual executable in the CLI and help tests was intentional. I might have misunderstood the exact nature of the test environment? Is it overwriting something? I thought the test environment was created on the fly specifically to do testing like this. What exactly is damaged?" + }, + { + "user": "LKedward", + "date": "2021-01-24 18:16:43+00:00", + "text": "The rebuild appears to be because the test invokes both the debug and --release configurations. In the CI, the --release version is not built prior to running the tests and hence it is built during execution of help_test.\nI would say that the desired behaviour for tests is to test the current build configuration only. i.e. fpm test tests the debug configuration and fpm test --release only tests the --release configuration. The reason for this is that Haskell fpm allows other configurations as specified by --flag and in fact this is what is used in the CI.\nThe --release version is not directly built at all by the CI since the release version used for binaries is specified explicitly with --flag in order to get static executables:\n\n \n \n fpm/.github/workflows/CI.yml\n \n \n Line 36\n in\n c485357\n \n \n \n \n\n \n \n RELEASE_FLAGS: --flag --static --flag -g --flag -fbacktrace --flag -O3 \n \n \n \n\n\nHence this test is not actually running at all for the binary release version specified in our CI.\nThis problem is related to #328 in terms of a test needing information about its context. A possible solution suggested by Brad is to provide environment variables for the build output directory, however this does rely on some specification of the output file structure which has thus far been avoided.\nIt is worth noting also that cli_test solves a similar problem by providing an alternate entry point within the test executable instead of invoking the main fpm executable.." + }, + { + "user": "urbanjost", + "date": "2021-01-24 20:10:47+00:00", + "text": "I made the cli_test version before discussions about just what the test environment was. During development of the help_test I made inquiries about whether fpm could be called and at the time that apparently was considered OK. I was under the impression the test environment was a virtual platform created on demand for the tests and had the f-fpm command in it's path.\nSo exactly what is the test platform? Unit tests etc. are satisfactory for testing procedures and objects (I have used such tests before they had a name) but at some point if you are building an application you want to test the application, both test and production versions; especially since I do not even have several of the environments available that the tests run on. So what is the best way to call the latest version of the program fpm from a test? Even if not done for fpm itself an environment variable giving a path to a built version would seem reasonable. I\nPS:\nI am particularly surprised the test environment even has h-fpm in it; I have been using f-fpm for months on different platforms just bootstrapping it on machines with just gfortran and git." + }, + { + "user": "LKedward", + "date": "2021-01-25 09:57:13+00:00", + "text": "Yes you're right @urbanjost, we do need a way of testing the application end-to-end in addition to unit tests. As you're aware we have previously found bugs with the CLI this way. The issue for discussion is what is the best way to call the executable from a test. For the reasons I mentioned I don't think calling fpm run from within the test is the best option. (The problem isn't with the test environment.)\nSince we don't have support for the required path environment variables currently (needs discussion/specification), do you think you would be able to test the same functionality by invoking the test executable like the cli_test?" + }, + { + "user": "everythingfunctional", + "date": "2021-01-25 16:32:19+00:00", + "text": "I think that fpm needs a facility for integration/end-2-end testing.\n\nTests are specified for a given executable.\nTests are run in an isolated directory\nIt must be possible to specify\na. the runner (i.e. equivalent to fpm run --runner)\nb. command line arguments (i.e. equivalent to fpm run --args)\nc. Any inputs which should be copied into the isolated directory\nd. A way (optionally) of checking the \"screen\" outputs\ne. A way (optionally) of checking output files\n\nGiven that we would like to at least encourage these test be portable (i.e. work for any environment that fpm supports), d and e imply some sort of fpm specific scripting language. Or maybe fpm could carry around a Bash implementation to run these scripts?\nWhat do you guys think?" + }, + { + "user": "awvwgk", + "date": "2021-01-25 16:41:50+00:00", + "text": "That would be a great addition, with 1, 2, 3a-c the important functionality. 3d and 3e could possibly be implemented outside of fpm by a package used as dev-dependency or by a combination of --runner and --args for a test. A related issue on this is #179." + } + ] + }, + { + "number": 342, + "user": "awvwgk", + "date": "2021-01-23 14:28:43+00:00", + "title": "Fix broken link in contributing guidelines", + "text": "Closes #340", + "comments": [ + { + "user": "LKedward", + "date": "2021-01-23 15:04:39+00:00", + "text": "CI passes after rerunning so not sure if there's some non-determinism (?) in the tests. Think it was the 'help_test' that failed. (This test is actually a little problematic since it invokes fpm run to run Fortran fpm, but this doesn't test the release flags properly.)" + }, + { + "user": "awvwgk", + "date": "2021-01-23 18:28:41+00:00", + "text": "Think it was the 'help_test' that failed. (This test is actually a little problematic since it invokes fpm run to run Fortran fpm, but this doesn't test the release flags properly.)\n\nI opened #343 to discuss this." + }, + { + "user": "awvwgk", + "date": "2021-01-30 13:07:02+00:00", + "text": "Since this is a simple change, I'll go ahead and merge." + } + ] + }, + { + "number": 341, + "user": "MarkWieczorek", + "date": "2021-01-21 15:25:51+00:00", + "title": "build script=\"make all\" no longer works", + "text": "About a year ago, I was able to compile of complex project of mine using a pre-existing Makefile. After finding out about the environment variables $BUILD_DIR and $FC, this was pretty easy, I only needed to specify the following:\n[library]\nbuild-script = \"make all F95=$FC LIBPATH=$BUILD_DIR MODPATH=$BUILD_DIR\"\n\nHowever, I just updated to the latest alpha version (0.1.3), and this does't seem to work anymore: the makefile is not being executed and instead fpm is trying to compile the file in the src directory.\nIs there a way to specify using a prexisting makefile, or a way pass optional variables to the Makefile?", + "comments": [ + { + "user": "milancurcic", + "date": "2021-01-21 15:41:30+00:00", + "text": "Are you using the Haskell (fpm-haskell-0.1.3*) or Fortran (fpm-0.1.3*) client? This is not yet implemented in the latter." + }, + { + "user": "ivan-pi", + "date": "2021-01-21 15:42:07+00:00", + "text": "Hello @MarkWieczorek,\nnote the build-script was an \"experimental\" feature available in the bootstrap fpm (the Haskell version). In the meantime a Fortran version of fpm has been built. You can check the manifest reference to see what is available.\nExecutables for the Haskell version can be found in the assets section of the latest release.\nA specification for the build-script feature is currently under discussion in #249." + }, + { + "user": "MarkWieczorek", + "date": "2021-01-21 15:50:33+00:00", + "text": "I'm using the Fortran client. Should the Haskell version be the default? or is the plan to make the Fortran version the default?\nSo, I am guessing the answer is: Check back later\nThat's fine with me. However, I just want to emphasize that if you want old, or complicated projects to work with fpm, eventually, you will need to pass environment variables to the makefile!" + }, + { + "user": "ivan-pi", + "date": "2021-01-21 15:53:14+00:00", + "text": "The Fortran version is (and will remain) the default. The build script is just one of the features which hasn't been implemented yet in the Fortran version." + }, + { + "user": "LKedward", + "date": "2021-01-22 10:01:23+00:00", + "text": "Thanks for the feedback @MarkWieczorek. Support for a custom build script is one of two (big) priority items remaining in our milestone . I'll close this issue as a duplicate of #219." + } + ] + }, + { + "number": 340, + "user": "ivan-pi", + "date": "2021-01-21 10:22:01+00:00", + "title": "Link in contributing guide is broken", + "text": "You can learn how from this great tutorial.\n\nThe link at the end of the contributing is broken. The correct address is:\nhttps://app.egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github", + "comments": [] + }, + { + "number": 337, + "user": "milancurcic", + "date": "2021-01-12 22:20:53+00:00", + "title": "Allow hyphens in fpm project names in \"fpm new\"", + "text": "fpm new currently requires a package name to be a valid Fortran name.\n$ fpm new test-new\nthe new directory basename must be an allowed \n Fortran name. It must be composed of 1 to 63 ASCII \n characters and start with a letter and be composed \n entirely of alphanumeric characters [a-zA-Z0-9] \n and underscores. \nSTOP 4\n\nTo have a hyphen in a package name is rather common though. For example, we have stdlib-cmake-example, there's toml-f and others, and I enjoy using hyphens as well.\nThis PR removes the restriction to use hyphens in new fpm package names in fpm new. The function that I used to do that (to_fortran_name()) can be easily expanded to other special characters if a need arises.\nIf you try this PR, you should get:\n$ ./fpm new test-new\n + mkdir -p test-new\n + cd test-new\n + mkdir -p test-new/src\n + mkdir -p test-new/test\n + mkdir -p test-new/app\n + git init test-new\nInitialized empty Git repository in /your/path/to/fpm/build/gfortran_debug/app/test-new/.git/\n\n$ cd test-new\n$ head fpm.toml \nname = \"test-new\"\nversion = \"0.1.0\"\nlicense = \"license\"\nauthor = \"Jane Doe\"\nmaintainer = \"jane.doe@example.com\"\ncopyright = \"2021 Jane Doe\"\n\n\n[library]\nsource-dir=\"src\"\n\n$ cat src/test-new.f90 \nmodule test_new\n implicit none\n private\n\n public :: say_hello\ncontains\n subroutine say_hello\n print *, \"Hello, test-new!\"\n end subroutine say_hello\nend module test_new\n\nI also updated the error message that you get if you pass some other special character:\n$ ./fpm new test^new\n the fpm project name must be made of up to 63 ASCII letters, \n numbers, underscores, or hyphens, and start with a letter. \nSTOP 4\n\nWe can discuss at a later time if there are some other special characters that we'd want to allow.", + "comments": [ + { + "user": "urbanjost", + "date": "2021-01-13 01:32:29+00:00", + "text": "Forcing the directory, package, and module name to be the same and to be an allowable Fortran module name was a deliberate decision. Obviously, the module name must conform to these rules, and it was considered that the simplest solution was to enforce them all being consistent. This disallows such options as the package and directory name being UTF-8 and so on so it is defnitely restrictive. I do not know if the discussions are still available, but now that there is auto-discovery it is far less of an issue. The question I have is should there be an option to name the package and the module independently instead of making a special case where dashes are replaced with underscores? If we are going to relax the restriction I think it would be better to leave the default behavior as-is and allow for an optional parameter to name the directory and project. I do not know if UTF-8 or other characters are allowed or easily supported in all the places the name might appear, but I believe toml-f supports UTF-8. So if we allowed any arbitrary name would it cause issues with git, github, gitlab, the fpm repository and/or toml files ?" + }, + { + "user": "awvwgk", + "date": "2021-01-13 08:16:47+00:00", + "text": "I agree that we might have to enforce some restrictions on the project name (e.g. I would consider newlines always invalid), but requiring it to be a valid Fortran identifier seems harsh. Allowing more freedom in fpm-new is very welcome from my side (in fact all my fpm packages but one are using hyphens in the project name).\nI like the idea to just underscorify everything we can't use in Fortran, in case we encounter problems with the names of the targets, archive, directories a similar approach could be used as well. The limitations of the programming language shouldn't be imposed on the user in my opinion.\nAlso, cargo allows a --name option in the new subcommand to specify the project name independently from the project directory. For our case this doesn't solve the issue with the name of the module but I would consider this a placeholder anyway, so chances are good that it will be renamed." + }, + { + "user": "LKedward", + "date": "2021-01-13 08:53:37+00:00", + "text": "Thanks @milancurcic, I too use hyphens commonly in package names and welcome this change. The proposed solution of replacing with underscores where needed seems reasonable.\nWith that said, I think the relevant discussion that drives the current behaviour is #153 (Prevent Name Collisions Between Packages) where it was agreed that all module names should be prefixed by the package name. This check is not yet implemented in fpm; when implemented, there will be a small burden on users to ensure modules are correctly prefixed by the fortranised package name. Alternatively, the module namespace prefix could be specified in the manifest separately." + }, + { + "user": "arjenmarkus", + "date": "2021-01-13 09:03:03+00:00", + "text": "As an aside: we should be thinking about the support for UTF-8. That is a\nrather tricky topic, as it may well depend on what the compilers allow\n(think of file names).\n\nNote: My remark is not to complicate matters for fpm, just to remind us of\nthe topic in general.\n\nOp wo 13 jan. 2021 om 09:53 schreef Laurence Kedward <\nnotifications@github.com>:\n\u2026\n Thanks @milancurcic , I too use hyphens\n commonly in package names and welcome this change. The proposed solution of\n replacing with underscores where needed seems reasonable.\n\n With that said, I think the relevant discussion that drives the current\n behaviour is #153 <#153>\n (Prevent Name Collisions Between Packages) where it was agreed that all\n module names should be prefixed by the package name. This check is not yet\n implemented in *fpm*; when implemented, there will be a small burden on\n users to ensure modules are correctly prefixed by the fortranised package\n name. Alternatively, the module namespace prefix could be specified in the\n manifest separately.\n\n \u2014\n You are receiving this because you are subscribed to this thread.\n Reply to this email directly, view it on GitHub\n <#337 (comment)>, or\n unsubscribe\n \n ." + }, + { + "user": "awvwgk", + "date": "2021-01-13 09:05:29+00:00", + "text": "For UTF-8 support I will link to the upstream issue at TOML-Fortran (toml-f/toml-f#3) as this will become relevant." + }, + { + "user": "milancurcic", + "date": "2021-01-13 17:17:46+00:00", + "text": "With this PR, I didn't mean to ignore #153, which I still think is important. But I forgot about it in the moment.\nWhen fpm checks that all module names do begin with the project name, the change in this PR will require an extra clause explaining the restriction to the user. For example:\n\nFpm requires that the names of all modules in your package begin with the package name. If your package name contains hyphens (-), the module names should have underscores (_) in place of hyphens.\n\nor similar. So there is a bit of burden that is being put on the user with this. On the other side, with this PR fpm new already generates correct module names with underscores instead of hyphens. Further, when the #153 check is implemented, fpm will be able to tell the user exactly how to prefix the module names. For example, if package name is \"my-fortran-lib\", fpm can report something like:\n All module names in this package must begin with \"my_fortran_lib\"." + }, + { + "user": "urbanjost", + "date": "2021-01-14 01:11:15+00:00", + "text": "Even now nothing obvious breaks if the directory is renamed, as I have done myself several times so I would prefer a second parameter for naming the directory to a non-default value, but at least for now this is satisfactory for the specific case of a dash.\nI can picture where the user might want the entire directory name to be a UTF8 string which could produce a project name of something like \"___\" so in the long term I think this will need revisited, but during the original discussion I think the conclusion was something along the lines \"of a consistent name is simplest and most intuitive, let us go with the restriction and revisit if if there are complaints\", which, lo and behold is the case so lets go with this as it covers the most common case and appears to be commonly desired. If there are requests for other changes I think the additional option would be cleaner, but this has been the only request so far.\nI believe it is telling that other package managers appear to address this with an additional option, but apparently in the reverse order of precedence I would suggest (the name always names the directory and an alternate project name is allowed for). After trying it that might be better, as it allows for things like fpm . --backfill. So in the future if the name on \"new\" allows for any name, but if it is required you supply a \"Fortran-acceptable\" name as well as the primary project name if the directory name is not one I would go with that.\nfpm new ANY_DIRECTORY_NAME --name PACKAGE_NAME\nappears to be how cargo handles this. I am wondering if anyone using cargo could see if PACKAGE_NAME is required with unusual directory names or if there are any other restrictions. The documentation I read does not mention it, but I wonder what would something like \"cargo --new ___\" or \"cargo --new @\" do. And right now, what about \"fpm new ./---\" ? Obviously unlikely a Linux user in particular would use that particular name, but non-ASCII characters could produce something as bad." + }, + { + "user": "milancurcic", + "date": "2021-01-14 15:39:56+00:00", + "text": "I think there would be value in a CLI parameter to specify a directory name different from the project name. I have projects like this. For example, the repo and directory are called \"datetime-fortran\" and \"functional-fortran\" (to help them stand out on GitHub), but the fpm project names (and modules) are called \"datetime\" and \"functional\" because \"fortran\" is redundant in the context of fpm.\n\nI can picture where the user might want the entire directory name to be a UTF8 string which could produce a project name of something like \"___\" so in the long term I think this will need revisited\n\nNo, currently only hyphen is converted to an underscore. I don't think this should expand to all special ASCII characters and definitely not all Unicode. If the restriction is lifted, it should be on a character by character basis and motivated by user requests.\n\nAnd right now, what about \"fpm new ./---\" ?\n\nThis will error out because you need to start it with a letter. fpm new a--- should work with this PR but I didn't test it. I doubt this will be a common use of fpm new.\nThank you all for the feedback, I will go ahead and merge." + } + ] + }, + { + "number": 336, + "user": "AndreMikulec", + "date": "2021-01-06 00:49:06+00:00", + "title": "Building R CRAN packages with Fortran code using \"fpm\" is not possible, but should be!", + "text": "All,\nFirst,\nThank you for the wonderful work on the \"fpm\".\nSecond,\nIn the manual \"Writing R Extensions\"\nIn the section \"1.2.3 Using F9x code\"\nhttps://cran.r-project.org/doc/manuals/r-release/R-exts.html\nreads\nModern versions of Fortran support modules, \nwhereby compiling one source file creates a module file which is then included in others. \n(Module files typically have a .mod extension: they do \ndepend on the compiler used and so should never be included in a package.) \nThis creates a dependence which make will not know about \nand often causes installation with a parallel make to fail\n\nBut the page https://github.com/Fortran-lang/fpm/blob/master/PACKAGING.md\nreads in the section \"Single-module library\"\nfpm first ran gFortran to emit the binary object (math_constants.o) \nand module (math_constants.mod) files. \n. . .\nUniquely and exactly map a source file (.f90) to its object (.o) and module (.mod) files.\n\nIn conclusion,\nMay one consider creating the modules with the .f90 extension (instead of the .mod extension),\nso in the future, one can use \"fpm\" in the processes of building\nR CRAN package that contains Fortran source code.\nFortran is found in many places in the 20,000 R CRAN packages.\nThis could be a great area of expansion for the \"fpm\".\nIf \"fpm\" can get compatible as a helper method to build R CRAN packages that contain Fortran code,\nthen this situation may be a big boost to \"fpm\" (and Fortran).\nHere are the Fortran files found in R CRAN packages.\n.f -> 4,192 hits\nhttps://github.com/search?q=org%3Acran+extension%3Af\n.f90 -> 881 hits\nhttps://github.com/search?q=org%3Acran+extension%3Af90\n.f95 -> 156 hits\nhttps://github.com/search?q=org%3Acran+extension%3Af95\nAndre Mikulec\nAndre_Mikulec@Hotmail.com", + "comments": [ + { + "user": "certik", + "date": "2021-01-06 01:53:05+00:00", + "text": "Hi @AndreMikulec, we definitely want fpm to work with the R ecosystem. Can you expand on your proposal? I don't understand how it would help to rename .mod to .f90, or why that is a good idea.\nIn general, our approach is to first figure out a good workflow that makes sense for Fortran, and then work with other communities such as Spack, Conda, R, etc., how to make it work." + }, + { + "user": "LKedward", + "date": "2021-01-06 12:07:16+00:00", + "text": "Hi @AndreMikulec, thanks for opening this issue.\nRegarding Fortran modules, fpm automatically works out the inter-module dependencies and builds objects in the correct order and in parallel where possible, so there is no need to worry about the .mod files.\nI am not familiar with R CRAN packages and how they are built, however I see no fundamental reason why fpm can't already be used to build the Fortran dependencies. It looks like the CRAN packages are in a compatible folder structure for fpm.\nAfter a brief look it looks like CRAN packages cannot have multiple Fortran modules in different files since, as you mention, module dependencies are not accounted for currently; using fpm would solve this issue." + }, + { + "user": "AndreMikulec", + "date": "2021-01-10 04:10:25+00:00", + "text": "First\n\".mod\" is not-a-file-extension, of a file, that contains Fortran code.\nFile extensions\nhttp://fortranwiki.org/fortran/show/File+extensions\nThe \".mod\" file extension is a \"compiler specific thing\". So, this not a \"Fortran Package Manager? So, is this a \"Compiler-Specific-Fortran Package Manager\"?\nA quick discussion is here:\nA primary problem for distributing a compiled library for a specific platform\nis that module files are compiler-specific.\n\nhttp://fortranwiki.org/fortran/show/Library+distribution\nSecond\nIn R, to create a \"dll\" that is loadable into R, one does the following:\nR CMD SHLIB [options] files | linker options\nTherefore, one does, the following to create a .dll on windows (or to create an equivalent shared object on Linux, Mac, or Solaris).\nR CMD SHLIB *.f90 \n(The command to create (and install) an R CRAN package that contains compiled Fortran is R CMD INSTALL (and this is just a thick wrapper (and more) over 'R CMD SHLIB . . .'.\nIn the Fortran packaging system (if, it is, to be able to work with R Fortran compiling):\n\"R\" would replace \"gfortran\". \"CMD SHLIB options\" would be, of course, options. \"link options\" would be options, of course, sent to the linker. The rest is controlled by either variables that were set when R was compiled or variables set in the environment where \"R CMD SHLIB . . .\" is ran.\nSummary\nWhat I am, essentially saying, is that the packaging system should more \"flexible\" than what is there now." + }, + { + "user": "awvwgk", + "date": "2021-01-10 09:10:13+00:00", + "text": "@AndreMikulec Thank you for your input on this.\nFrom my experience of interfacing Fortran projects with C and Python, the process of creating an extension for another language is quite orthogonal to reusing Fortran packages/modules in Fortran projects. Currently fpm focus primarily on the latter, but we want to make fpm more flexible to allow interfacing with other languages as well.\nIf I read the R CRAN documentation on extensions correctly a Fortran extension module must be bound either via iso_c_binding as C external to R or as non-module procedure using a Fortran 77 style implicit interface. This is quite similar to the approach used to bind to Python. In any case this requires to export a shared object, but in general no special attention beside include paths or link line arguments. Building shared objects is something fpm currently can't do, but should be able to do at some point.\nFrom the R CRAN documentation I get the impression that extensions all builds around the autoconf intrastructure and rely pretty heavily on automake and m4 features, but correct me if I'm wrong. Comparing this again to Python which relies heavily on setuptools to build extensions, I found that building Python extensions without setuptools becomes much easier.\nIn summary, we first have to give fpm some basic intercompatibility functionality and than build on-top of this more elaborated language specific extensions." + }, + { + "user": "AndreMikulec", + "date": "2021-01-12 13:51:41+00:00", + "text": "R CMD SHLIB does not provide any infrastructure to interface Fortran to another language. Interfacing to another language is not the objective. Interfacing to another language (if the R package author wishes to do so), would be a function of the chosen compiler (of which can actually be many different compilers and OS platforms) and/or handwritten code (or code generated from an external helper tool) by the author.\nThe \"autoconf intrastructure\" does not matter. The point is that, the situation would be useful to be able to replace out \"gfortran\" or \"ifort\" or \"whatever\", using \"R CMD SHLIB\", and replace out \".mod\" files with just \".f90\" files.\nThe replacement of gfortran\" or \"ifort\" or \"whatever\", using \"R CMD SHLIB\" should not be (obviously) too hard.\nHowever, leaving \"fpm\" hardcoded to use only \".mod\" files (to store Fortran module code) would eliminate the ability of a user of \"fpm\" to use R as an \"alternate\"(specific) compiler." + }, + { + "user": "awvwgk", + "date": "2021-01-12 14:44:18+00:00", + "text": "I think we are talking about different things here. There might be a confusion between shared modules and Fortran module files here. The creation of the shared module, which can be eventually loaded into R, does not depend on the Fortran module files.\nCreating a shared module is independent of the actual compilation of the Fortran source code to object files. Replacing the compiler with R CMD SHLIB would not yield the expected result in the context of fpm.\nThe important step for creation of the shared module from the already available object file following the naming convention required by R from the fpm side." + } + ] + }, + { + "number": 335, + "user": "LKedward", + "date": "2021-01-03 14:49:43+00:00", + "title": "Fix: performance regression from #303", + "text": "33ad2ce (#303) introduced a severe performance regression when checking for empty source files during the source parsing phase. This is particularly noticeable on Windows.\nThis PR adds a string_len_trim routine to check for empty source files instead of inefficiently using string_cat.\nI see 5-10x improvement in the time to construct the model from this PR for a project with ~80 source files.", + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-06 17:59:13+00:00", + "text": "I'm going ahead and merge this PR." + } + ] + }, + { + "number": 334, + "user": "awvwgk", + "date": "2021-01-03 13:33:23+00:00", + "title": "Remove a name clash in the fpm testsuite", + "text": "local variable uses same name as used module (testsuite)\n\nSee: https://groups.google.com/g/comp.lang.fortran/c/FdOcg3dGuK4", + "comments": [] + }, { "number": 331, "user": "urbanjost", @@ -328,6 +615,11 @@ "user": "certik", "date": "2020-12-24 12:36:34+00:00", "text": "Just like Sebastian, I felt it should not create examples by default.\n\nUrbanjost explained above why it's a good idea to include them by default.\n\nI think it's for a wider discussion what the default behavior should be.\n\nContrary to what was said, I use new very frequently, just like git init. I use it for all kinds of quick projects to test things out. So the default behavior matters a lot I think.\n\u2026\nOn Sun, Dec 20, 2020, at 5:29 PM, Milan Curcic wrote:\n\n\n I think example/ and a program source file in it should be created by\n default, as originally implemented in this PR, and for the same reason\n that @urbanjost explained above.\n\n Let's get more eyes on this. @certik \n @everythingfunctional \n @LKedward what do you think is a saner\n default?\n\n Otherwise I think this PR is good to go.\n\n \u2014\n You are receiving this because you were mentioned.\n Reply to this email directly, view it on GitHub\n <#316 (comment)>,\n or unsubscribe\n ." + }, + { + "user": "awvwgk", + "date": "2021-01-30 13:06:17+00:00", + "text": "@urbanjost could you bring this branch up-to-date with the default branch again. I'll try to have a look over the changes hopefully next week(end)." } ] }, @@ -424,6 +716,16 @@ "user": "certik", "date": "2020-12-17 18:28:52+00:00", "text": "Yes, I asked @everythingfunctional to open an issue for this, as he mentioned this at our last Fortran call.\nIt's a broader issue of: do we want to use fpm as a vehicle to extend Fortran, or to provide default pre-processing (for all compilers, for example using fypp), etc.\nAnd for now I recommend to stick to standard Fortran. We can still deliver most of our goals with that.\nIn general, I would like to see Fortran being used without pre-processing.\nIf it turns out there is no other way, we can (in the future) make fpm do all kinds of default pre-processing." + }, + { + "user": "interkosmos", + "date": "2021-01-26 20:05:17+00:00", + "text": "C preprocessor macros are probably the most common, and they are supported (at least) by GNU Fortran, IFORT, and LLVM. The only problem is that the different implementations do not predefine the same macros. It should therefore be the task if fpm to set common macros (e.g., operating system identifier) if preprocessing/conditional compilation is selected." + }, + { + "user": "arjenmarkus", + "date": "2021-01-27 07:48:38+00:00", + "text": "Another problem is that the C preprocessor does not conform to Fortran\nsyntax. That limits the kinds of macros that you can reasonably apply. But\nan #if ... #endif construction is probably safe.\n\nOp di 26 jan. 2021 om 21:05 schreef Philipp :\n\u2026\n C preprocessor macros are\n probably the most common, and they are supported (at least) by GNU Fortran,\n IFORT, and LLVM. The only problem is that the different implementations do\n not predefine the same macros. It should therefore be the task if *fpm*\n to set common macros (e.g., operating system identifier) if\n preprocessing/conditional compilation is selected.\n\n \u2014\n You are receiving this because you are subscribed to this thread.\n Reply to this email directly, view it on GitHub\n <#308 (comment)>,\n or unsubscribe\n \n ." } ] }, @@ -1591,6 +1893,41 @@ "user": "awvwgk", "date": "2020-11-25 19:57:29+00:00", "text": "Sounds like a good idea, having to maintain redundant information in different places is really error prone. For meson and CMake I use configure_file to insert build system meta data as parameter into Fortran source code. I very much in favour of having a configure_file or similar option for fpm as well." + }, + { + "user": "ivan-pi", + "date": "2021-01-22 16:13:41+00:00", + "text": "@awvwgk is a configure_file in your case a Fortran include file? Nevermind, I see configure_file is essentially a preprocessor mechanism.\nWould there be any advantages to doing this with a (read-only) namelist or maybe having a public fpm_tools module which contains some functions and subroutines to recover such meta-data from some cached build/toml files?" + }, + { + "user": "awvwgk", + "date": "2021-01-22 16:18:58+00:00", + "text": "Preferably we keep in line with existing configure_file implementations as present in CMake and meson instead of making up our own: https://mesonbuild.com/Configuration.html. In a multi-build system approach one might want to use the same template for fpm, CMake and meson and get the same result independent of the build system used." + }, + { + "user": "ivan-pi", + "date": "2021-01-22 16:55:58+00:00", + "text": "Can you point me to a Fortran example of yours in a public repository? I still have trouble grasping if the concept relies upon use of the cpp/fpp preprocessor or are the input files preprocessed independently by CMake/meson.\nIs the following a valid setup example?\nI have a template file called projconfig.fi.in, containing\ncharacter(*), parameter :: version = \"@FPM_VERSION_STR@\"\ninteger, parameter :: version_major = @FPM_VERSION_MAJOR@\ninteger, parameter :: version_minor = @FPM_VERSION_MINOR@\ninteger, parameter :: version_bugfix = @FPM_VERSION_BUGFIX@\n\nIn the manifest file of the project, we then specify this as a target for configuration, with the actual preprocessing/replacement done by an extension to fpm or a special command. The template substitution rules would follow the same definitions as CMake and Meson.\nFinally in the main module of my project, I can include the configured template file as:\nmodule myproject\n\n include \"projconfig.fi\"\n\nend module" + }, + { + "user": "awvwgk", + "date": "2021-01-22 17:04:56+00:00", + "text": "For an example see:\nhttps://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.name.in\nhttps://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.f90#L43\nI made a small implementation here when working on the fpm-dist command\nhttps://github.com/fortran-lang/fpm/blob/e2a837b/fpm/src/fpm/dist/meson.f90#L433-L473" + }, + { + "user": "ivan-pi", + "date": "2021-01-22 17:18:37+00:00", + "text": "For an example see:\nhttps://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.name.in\nhttps://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.f90#L43\n\nInteresting, if stdlib-os currently relies upon this configuration mechanism, and we want fpm to rely upon on stdlib-os in the future to get the operating system ID, does this mean that to bootstrap fpm using the Haskell version, it is necessary to use the current build-script feature (using CMake) or extend the Haskell version to support OS identification and configure file template substitution? This reminds me of the movie Inception..." + }, + { + "user": "awvwgk", + "date": "2021-01-22 17:24:02+00:00", + "text": "You can just cut the loop short and drop Haskell fpm from it, with support for configure_file in Fortran fpm we are already fine to dependent on stdlib_os once it is ported to fpm. No need to make life more complicated than necessary, just look for changeable parts were changes are simple to make." + }, + { + "user": "urbanjost", + "date": "2021-01-24 04:02:05+00:00", + "text": "As a simpler scheme that leverages some of the existing fpm components and required user knowledge, and does not require a preprocessor I would propose something like this:\no fpm parses the fpm.toml file (which it already does) and obtains the version number and other metadata such as the project name and author. It then gets the compiler name from the command line, and the current time, and possibly the compiler options and the OS type.\no the build commands could add a -D $OS_TYPE and -D $COMPILER option or equivalent to the compiles, which I think all major compilers support for use with cpp/fpp or their equivalent.\no using the metatadata it writes and compiles a module called fpm_metadata that creates a type of METADATA.\nThis could be ignored by the fpm user, but if desired they could include \"use fpm_metadata, only : metadata\" in their program and then get to at least a standard set of keywords by using such things as:\nwrite(*,*)'VERSION',metadata%version\nwrite(*,*)'COMPILE_TIME',metadata%compile_time\nand so on. As more functions become available (via stdlib, preferably) such things as the equivalent of the output of a uname(1) command could also become default behavior.\nThis would require no preprocessing of the user code, supply a standard set of variables that could be used by all packages,\nand allow for standard names to be used in preprocessing and leverage the existing TOML configuration file and syntax. Since the existing code already parses the TOML file and it already contains some of the most common metadata such as the version number this would fit into the existing fpm quite naturally, I believe.\nThe drawback to the user would be that no such module would exist outside of fpm. So adding -DFPM to the build lines would allow for #ifdef FPM to be used as a preprocessor directive, and leaving the built code in build/ for the user to grab or use as a template for a build outside of fpm(1) would be desirable." } ] }, @@ -1713,7 +2050,53 @@ "date": "2020-11-22 09:01:00+00:00", "title": "build-script location", "text": "Currently the build-script can specified in the [library] table with:\nlibrary.build-script = \"build.mk\"\nFor an executable only project, a library table would still be required to select a build script, even if no library sources are actually available.\nAdding the build-script to the [build] table feels more intuitive. Either as build-script or to reduce redundancy, just script:\nbuild.build-script = \"build.mk\"\nbuild.script = \"build.mk\"\nThis might be a breaking change for some projects using this fpm feature.", - "comments": [] + "comments": [ + { + "user": "ivan-pi", + "date": "2021-01-20 20:27:10+00:00", + "text": "In Cargo, the default behavior is to check for a file named build.rs in the root of the package. A custom build script can be specified as:\n[package]\n# ...\nbuild = \"custom_build_name.rs\"\n\nTo disable automatic build script detection the setting is simply build = false. The possibility to use other build systems is then delegated to custom user packages which are called from build.rs.\nThe suggestion from @certik in #94 was to allow any kind of build script, be it a binary executable, shell script, Makefile, or other build system. Since fpm is only allowed to interact with the build script through environment variables and the output of the build script to standard output prepended with fpm:. This seemed like a reasonable idea. Upon further thought, I am worried this might become an obstacle for cross-compatibility between different operating systems. In this case fpm will need to report to the user to install CMake, Meson, Make, bash, etc. or whatever build system necessary.\nIn any case, do we also want to support such automatic build script detection?\nRelated to the immediate issue above, I agree that the [library] section does not feel right in case of executable-only projects. The build.script seems more fitting, also considering the fact the link keyword is in the same table." + }, + { + "user": "awvwgk", + "date": "2021-01-20 21:51:10+00:00", + "text": "I always wondered why Makefiles take such a special role in fpm, while CMake and meson are standardized enough to give a somewhat predictable behaviour for third-party tools, a Makefile can hide all kind of surprises and caveats inside (I never get tired of a random Makefile suddenly starting to write stuff in my home directory).\nInteracting with other build files will always be difficult for fpm, have a look at fortran-lang/fortran-lang.org#157 for an incomplete list. Preferably we can convince projects to switch to fpm, but most likely we will end up with projects supporting fpm and their original build system. My projects currently all support meson, but many have additional fpm support or CMake support, depending on the communities they find use in.\n\nIn any case, do we also want to support such automatic build script detection?\n\nPlease don't, those features should be opt-in only, I don't want fpm to start auto-detecting my meson build files and force me to disable another of the automatic detection features in my projects." + }, + { + "user": "ivan-pi", + "date": "2021-01-20 22:56:30+00:00", + "text": "I certainly agree we don't want fpm interacting with other build systems aimed to be use independently from fpm.\nMy proposition/question was only related to the way Cargo automatically looks for a build.rs file. Under this model behavior, and the suggestion from @certik, fpm could look for build.sh, build.mk, build.cmake, etc.\nBut given that Fortran is not a monolithic/centralized language like Rust, and that there is a large variety of different build systems in everday use, it makes more sense to require package developers to specify a build script explicitly and save us the trouble from having to disable it manually.\n(I admit to having a soft spot for auto-detecting a build.f90 program; the idea of writing a Fortran executable to specify a foreign language package build sounds both crazy and very fascinating at the same time.)" + }, + { + "user": "awvwgk", + "date": "2021-01-20 23:17:07+00:00", + "text": "Okay, let's try to make the manifest syntax a bit more concrete.\nI would propose we could have external build scripts (as array of strings), they are invoked by fpm and we just hope they play nicely together with fpm, but guarantee for nothing:\nbuild.script = [\"make\", \"-f\", \"build.mk\"] # or just [\"build.mk\"], make extension is detected\nbuild.script = [\"sh\", \"build.sh\"] # or just [\"build.sh\"], shell extension is detected\nbuild.script = [\"python\", \"build.py\"] # or just [\"build.py\"], Python extension is detected\nbuild.script = [\"ruby\", \"build.rb\"] # or just [\"build.rb\"], Ruby extension is detected\nbuild.script = [\"cmake\"] # we might detect that it is CMake and run multiple steps for this script\nAnd actual build scripts like proposed in #94 (provided as string), we will allow any format supported by fpm (f90, f, F90, F and c) as well as scripts (we can detect extensions as well and try to call the script with the correct program):\nbuild.script = \"build.f90\" # compile and run Fortran executable\nbuild.script = \"build.c\" # compile and run C executable\nbuild.script = \"build.sh\" # run shell script\nbuild.script = \"build.py\" # run Python script\nbuild.script = \"build.rb\" # run Ruby script\nThe script is expected to produce fpm: instructions which fpm parses and uses to build the project.\nThis might require a new table of build-dependencies at some point, which are usable in the build script." + }, + { + "user": "ivan-pi", + "date": "2021-01-21 00:36:41+00:00", + "text": "This might require a new table of build-dependencies at some point, which are usable in the build script.\n\nThis only seems to make sense for build scripts which are C or Fortran executables, allowing fpm to resolve (and reuse) their dependencies. Am I right? (I see many signs fpm will ultimately evolve also into a C package manager. )\nIs there any intrinsic benefit to supporting build scripts in dynamic languages directly (apart from user convenience)? This could be done after all in a Fortran main program:\n! build.f90\nwrite(*,*) \"fpm:rerun-if-changed=build.py\"\ncall execute_command_line(\"python build.py\")\nend" + }, + { + "user": "LKedward", + "date": "2021-01-22 11:01:04+00:00", + "text": "I wonder whether we should perhaps separate discussion of build scripts into those with one-way and two-way communication with fpm. The former, implemented experimentally in Haskell version, receive inputs via environment variables and are expected to place libraries in the correct location. The latter have reverse-communication with fpm via stdout (#94) for more advanced behaviour.\nMy intention for #219 was only to initially implement one-way build scripts to support cases such as #341. In terms of specification I think that we should avoid hard-coding the detection of specific file-extensions or build systems and simply have an array of strings to be invoked at the command line by fpm (I like your proposed syntax for this above @awvwgk).\nWhile I like the idea of build.f90 etc., I'm hesitant to prioritise build scripts with reverse communication at such an early stage in fpm development. IMHO I think we should encourage package maintainers to adopt the native fpm package structure and work with them to improve fpm accordingly." + }, + { + "user": "ivan-pi", + "date": "2021-01-22 15:56:03+00:00", + "text": "That is a good way to look at it. I imagine in a one way setup, the script invoked would be responsible to place all the necessary executable files, module files, and binaries into a specified folder.\nWould it then be up to the package developer to hard code any flags required for linkage straight into the manifest of the package?" + }, + { + "user": "ivan-pi", + "date": "2021-01-22 16:04:03+00:00", + "text": "In terms of specification I think that we should avoid hard-coding the detection of specific file-extensions or build systems and simply have an array of strings to be invoked at the command line by fpm (I like your proposed syntax for this above @awvwgk).\n\nWould this also work in the eventual case of a Fortran main program? For example:\nbuild.script = ['$FPM_FC', 'build.f90', '-o', 'build', '&&', './build']\n\nI can imagine this would become unwieldy, if my build program requires some other fpm-sourced modules.\nBut I agree to prioritise the first case (no reverse communication), as it would already enable a lot more complex projects." + }, + { + "user": "awvwgk", + "date": "2021-01-22 16:13:36+00:00", + "text": "Would this also work in the eventual case of a Fortran main program? For example:\nbuild.script = ['$FPM_FC', 'build.f90', '-o', 'build', '&&', './build']\n\n\nThis should not be allowed, because we will guard the command execution against variable expansion and command chaining at some point, see #166.\nI took some inspiration from docker where entry points and commands are defined differently by syntax, of course we can separate the one and two way communication more easily by allowing separate entries which are mutually exclusive. The advantage of only allowing a string for a two way build script instead of a full command line is that we move the complexity from the package manifest (configuration file) to the build script (full programming language)." + } + ] }, { "number": 248, @@ -2765,7 +3148,28 @@ "date": "2020-10-28 11:09:25+00:00", "title": "Support custom build script", "text": "Match behaviour of bootstrap version", - "comments": [] + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-19 22:03:21+00:00", + "text": "I would prefer to restructure the build-script logic in the package manifest first, see #249, before implementing the logic in Fortran fpm." + }, + { + "user": "ivan-pi", + "date": "2021-01-20 15:35:13+00:00", + "text": "I could not find any previous discussion pertaining to the bootstrap fpm design of the build-script logic. It seems to be something that @everythingfunctional built in initially to get the project off the ground?\nEdit: I found a former discussion in this issue: #118\nDo any of the libraries used to bootstrap fpm actually require a custom build script? If not, I don't see any reasons why not to restructure the build script logic in the manifest. Since fpm is still in an alpha stage, I don't think this will cause many problems for users." + }, + { + "user": "everythingfunctional", + "date": "2021-01-20 18:02:59+00:00", + "text": "I did indeed come up with the initial design primarily on my own. I was trying be compatible with what I believed to be common best practice in Makefiles, but we did discuss some changes that probably ought to be made. Primarily I think we concluded that all \"inputs\" to the build scripts should be through environment variables prefixed with FPM_, and any information the script would like to report back to fpm would be via stdout on lines prefixed with fpm:. This is similar to Cargo's design, and I agree it seems to be working out pretty well for them.\nI'm open to suggestions on how such scripts should be specified and executed in fpm.toml. Mine was just a first draft." + }, + { + "user": "ivan-pi", + "date": "2021-01-20 21:14:07+00:00", + "text": "Thanks @everythingfunctional for the explanation. I suggest we shift to #249 to figure out a specification." + } + ] }, { "number": 218, @@ -4676,6 +5080,16 @@ "user": "certik", "date": "2020-09-10 18:41:25+00:00", "text": "Awesome, thank you @interkosmos !" + }, + { + "user": "ivan-pi", + "date": "2021-01-19 19:20:25+00:00", + "text": "@interkosmos Do you have a public repository available?" + }, + { + "user": "interkosmos", + "date": "2021-01-19 21:22:21+00:00", + "text": "@ivan-pi: Not yet, although, I did not work on the interface library in the last weeks.\nCurrent status:\n-------------------------------------------------------------------------------\nLanguage files blank comment code\n-------------------------------------------------------------------------------\nFortran 90 26 149 129 1045\n-------------------------------------------------------------------------------\nSUM: 26 149 129 1045\n-------------------------------------------------------------------------------\n\nI try to publish an alpha release in the next time." } ] }, @@ -4919,6 +5333,36 @@ "user": "awvwgk", "date": "2020-09-07 18:00:02+00:00", "text": "True, it usually feels like a compiler command when using it, but there is a lot automation for us hidden in the compiler.\nI thought of it more like a dependency since it is handled in conda like one (see https://conda-forge.org/docs/maintainer/knowledge_base.html#openmp). Also meson is handling it usually as a dependency rather than a compiler command (see https://mesonbuild.com/Dependencies.html#openmp).\nHaving a dependency model that allows propagating linker and compiler flags would be well suited for OpenMP as well in fpm. OpenMP would be useful as simple prototype if dependencies require to export link or compile flags to a dependent project. Projects using OpenMP must propagate at least the linker flag, possibly also the library with the OpenMP implementation to dependent projects to allow correct linking." + }, + { + "user": "LKedward", + "date": "2021-01-04 11:35:10+00:00", + "text": "It would be good to get this implemented so that we can self-bootstrap Fortran fpm with parallel builds enabled.\nI am however still opposed to the treatment of OpenMP as a dependency in the manifest syntax; OpenMP isn't just an additional library for linking, it changes the way the compiler behaves in processing sources and in generating code. Similarly the invocation flag and link libraries are different for each compiler. Hence why I think an entry like openmp=true in the existing [build] table is more appropriate (#112). What do other people think?\n\nHaving a dependency model that allows propagating linker and compiler flags would be well suited for OpenMP as well in fpm.\n\nAgreed, but I see no reason to conflate the manifest syntax for OpenMP with that of package dependencies." + }, + { + "user": "awvwgk", + "date": "2021-01-04 11:45:03+00:00", + "text": "I think we should get #112 working first, this would allow us to define flags on a per package basis (optimization) and global flags that propagate in the dependency tree (fast-math). Based on this we can easily implement OpenMP as either a build.openmp entry or a dependency." + }, + { + "user": "awvwgk", + "date": "2021-01-04 12:10:25+00:00", + "text": "I am however still opposed to the treatment of OpenMP as a dependency in the manifest syntax; OpenMP isn't just an additional library for linking, it changes the way the compiler behaves in processing sources and in generating code. Similarly the invocation flag and link libraries are different for each compiler.\n\nKeep in mind that OpenMP is versioned as well, how do we deal with the fact that a program requires OpenMP version 4.5 or newer if the compiler used only provides OpenMP 3.x?\nAnother important thing is linking against the OpenMP runtime, if you use LLVM and GCC toolchains on your system you can link GCC applications with the LLVMs OpenMP runtime library and vice versa, depending on the features used. Same holds true for Intel OpenMP which can safely be linked into GCC compiled application instead of the GCC OpenMP runtime library.\nCreating an OpenMP dependency, which exports compiler flags to the dependent projects would allow to safely support various OpenMP implementation including versioning and also gives you the freedom to overwrite the OpenMP dependency by creating a mock fpm-package to export your special OpenMP setup." + }, + { + "user": "LKedward", + "date": "2021-01-04 12:56:57+00:00", + "text": "Can these cases not also be specified in the [build] table, e.g.:\n[build]\nopenmp = true\nopenmp-version = \"^4.5\"\nopenmp-library = \"iomp5\"\nWe will already need logic for correctly exporting compiler options to dependents, why not use the same model for OpenMP?\nPerhaps I am misunderstanding you; is your intention that there is no special code for handling OpenMP and that the OpenMP dependency is processed internally in exactly the same way as any other dependency?" + }, + { + "user": "awvwgk", + "date": "2021-01-04 13:35:57+00:00", + "text": "I would prefer to extend the current dependency model to support OpenMP on equal footing with normal fpm dependencies. With a solution for #112 we should be able to create an fpm package that will enable OpenMP support in its dependents.\nSupporting OpenMP with this approach wouldn't require any special entries in build and allows to test if this is a suitable model for OpenMP before implementing a special shortcut with build.openmp in the package manifest. I'm not opposed to create a build.openmp entry, but I wouldn't make it the first step for supporting OpenMP." + }, + { + "user": "LKedward", + "date": "2021-01-04 14:14:03+00:00", + "text": "... we should be able to create an fpm package that will enable OpenMP support in its dependents.\n\nAh I see, I understand what you mean now. Thanks for explaining (and for your patience ;)). This is an elegant approach.\nSo a hypothetical default OpenMP package manifest might look something like this then:\nname=\"OpenMP\"\n\n[build]\ncompile-args.gfortran= [\"-fopenmp\"] # append\ncompile-args.ifort= [\"-qopenmp\"]\n# etc...\nor, to introduce a possible general syntax, perhaps:\nname=\"OpenMP\"\n\n[build]\n[[compiler-arg]]\ngfortran= [\"-fopenmp\"]\nifort= [\"-qopenmp\"]\n# ...\nexport = \"link\" # export arg to linker command only\n# export = \"dependents\" # export arg up to dependent packages only\n# export = \"all\" # export arg to entire project" } ] }, @@ -6857,6 +7301,11 @@ "user": "ivan-pi", "date": "2020-11-27 11:19:02+00:00", "text": "To aid the discussion I have tried to summarize some of the available optimization flags. Note that the specific optimizations will slightly differ between compilers. As a single example, to optimize for executable size, gfortran has the flag -Os, however the Intel documentation recommends using -O1.\n(perhaps this table can also be moved to a Wiki)\n\n\n\nFlag\ngfortran\nifort\nnagfor\nflang\nCray\nIBM\n\n\n\n\n-O\nequal to -O1\n/\nequal to -O2\nequal to -O2\n\nequal to -O2\n\n\n-O0\nno optimization (default)\nno optimization\nno optimization\ndisable optimization\ndisable optimization\ndisable optimization\n\n\n-O1\noptimize\noptimize for size\nminimal quick optimisation\nbetween -O0 and -O2\nconservative optimization\nno effect, reserved for future use\n\n\n-O2\noptimize even more\nmaximize speed (default)\nnormal optimisation (default)\nmoderate optimization\ndefault optimization\noptimize for performance\n\n\n-O3\noptimize yet more\nsimilar to -O2 with additional floating point optimizations\nfurther optimisation\nfull optimization\naggresive optimisation\nadditional optimization (similar to gfortran -Ofast)\n\n\n-O4\n/\n/\nmaximal optimisation\nreserved for future use\n/\naggresive optimization\n\n\n-O5\n/\n/\n/\n/\n/\nequal to -O4 with additional interprocedure analysis\n\n\n-Ofast\nsimilar to -O3 with unsafe math\n/\n/\nsimilar to -O3 with further math optimizations\n/\n/\n\n\n-fast\n/\nmaximize speed across entire program\n/\n/\n/\n/\n\n\n-Os\noptimize for size\n/\n/\nlike -O2 but reduces code size\n/\n/\n\n\n-Oz\n/\n/\n/\nlike -Os, but reduces code size further\n/\n/\n\n\n-Og\nturns on optimizations which do not interfere with debugging\n/\n/\n/\n/\n/\n\n\n\nSince we are limited by the available compilers for CI, I would suggest to only handle the -O0, -O1, -O2, and -O3 flags for now, which are common for most Fortran compilers." + }, + { + "user": "awvwgk", + "date": "2021-01-04 15:12:57+00:00", + "text": "With #322 the package scope of the source files is now available in the fpm model, extending each package object in the fpm model by its compilation profile would allow to implement customized arguments on per package basis.\nThe main issue to solve is the presentation of the build arguments in the package manifest.\nI would suggest to use a table of tables either in build or in the top-level:\n[build.profile.*] # with * = debug, release, ...\nThe command line argument could be --profile to access the compilation profile.\nWe should abstract as many options as possible in specific entries in a profile (optimization, fast-math, ...), but we won't get around implementing compiler vendor specific arguments. Again I would suggest to represent them with a table of tables:\n[build.profile.*] # with * = debug, release, ...\n[build.profile.*.compile-args] # link-args, global-args ?\ngnu = [\"...\", \"...\"]\nintel = [\"...\", \"...\"] # Intel with GCC like CLI on Unix\nintel-cl = [\"...\", \"...\"] # Intel with MSVS like CLI on Windows\nflang = [\"...\", \"...\"]\n# or inverted?\n[build.profile.*.gnu]\ncompile-args = [\"...\", \"...\"]\nlink-args = [\"...\", \"...\"]\nglobal-args = [\"...\", \"...\"]\nThe allowed IDs should preferably match existing IDs used in CMake or meson. Internally, all abstracted options could be implemented using the same representation as the compile-args table.\nWe will require three kinds of arguments, compile arguments for the current project (e.g. -O3), link arguments for the current project (e.g. -flto) and all dependent projects and global compile arguments for all dependent projects (e.g. -fopenmp, -fast-math). We can than fine-tune the exact scopes of the arguments at a later stage.\nImplementing the three different kind of arguments allows us to prototype profiles for the different compilers without having to modify fpm. Options and profiles we choose to stabilize in fpm can get specific entries in the profile or build tables later." } ] }, @@ -7113,6 +7562,16 @@ "user": "lauvergn", "date": "2020-07-07 18:08:02+00:00", "text": "Yes, it's a little more complicated, but it makes life so much easier for the end user. That is the whole point of fpm. :)\n\nYes, that will great !!\nalias gardhor" + }, + { + "user": "ivan-pi", + "date": "2021-01-19 19:24:36+00:00", + "text": "Is this issue still relevant?\nI recall @LKedward mentioning somewhere that my fortran_lsp repo could be built fpm, meaning that this has been resolved." + }, + { + "user": "LKedward", + "date": "2021-01-22 09:27:46+00:00", + "text": "Hi @ivan-pi, yes I believe this issue is now solved." } ] }, diff --git a/community/github_stats_data/data-fortran-lang-stdlib.json b/community/github_stats_data/data-fortran-lang-stdlib.json index 2e91a9d25..107ad62bc 100644 --- a/community/github_stats_data/data-fortran-lang-stdlib.json +++ b/community/github_stats_data/data-fortran-lang-stdlib.json @@ -1,6 +1,517 @@ { "name": "fortran-lang/stdlib", "issues": [ + { + "number": 308, + "user": "awvwgk", + "date": "2021-01-26 17:02:51+00:00", + "title": "Subprocesses and Multiprocessing", + "text": "Motivation\nSpawning or forking synchronous and asynchronous processes in an Fortran application is currently not easily doable in a cross-platform way. This is usually required for job servers which cannot access a functionality from a dynamically loaded library but have to access this functionality by other means, e.g. invoking a program with some input (standard input, files or arguments) and processing its output (standard output or files). Redesigning the functionality to allow dynamically loading symbols is not always possible or desirable.\nA current alternative is the execute_command_line which allows to create a new shell or CMD instance, which in turn can invoke commands. Together with OpenMP, MPI or coarrays this can be done even asynchronous but is tedious and somewhat errorprone. Using a shell or CMD instance has some security and speed implications as well.\nPossible API\n\nprocedural API similar to POSIX API (basically thin iso_c_binding wrapper)\nobject oriented API similar to Python's subprocess module\n\nAvailable Implementations\nFeel free to add entries to this list.\nFor POSIX API:\n\nM_process\nfortran-unix\nfortyxima\n\nFor Windows API?", + "comments": [ + { + "user": "ivan-pi", + "date": "2021-01-26 18:27:15+00:00", + "text": "I few months ago I was trying to replicate the process API from Rust. Ultimately, I got stuck exactly on this issue and tried to solicit some help/ideas at Fortran Discourse: https://fortran-lang.discourse.group/t/ideas-for-command-module/439/4\nA number of Fortran Posix API's are linked here: #22 (comment) It's a shame the Fortran community didn't unite earlier, and instead allowed compiler vendors to role out several incompatible Posix interfaces.\nEdit: the C runtime library for Microsoft Windows has the _spawn, _wspawn Functions which seem to fit the purpose." + } + ] + }, + { + "number": 307, + "user": "ivan-pi", + "date": "2021-01-21 00:03:41+00:00", + "title": "Modify goal and workflow of stdlib", + "text": "Currently the front page of stdlib states:\n\nstdlib is both a specification and a reference implementation. [...] if the Committee wants to standardize some feature already available in stdlib, it would base it on stdlib's implementation.\n\nAs I understand things, the Fortran committee has little to do with the actual implementation. Instead this is primarily a job of the compiler vendors (of course they are able to influence the standardization process to some degree). On the other hand the committee has everything to do with the specification which defines the interface and the behavior.\nSince the introduction of submodules, the interface part, and the implementation (behavior) can be decoupled from each other. For the language users who are willing to use a compatible C/C++ compiler (meaning the majority of currently available compilers) this provides an opportunity to speed development efforts by interfacing with external libraries such as the C++ standard library, Boost, libm, and other respected sources, in order to converge to a specification faster.\nThe current work flow document asks contributors to present a draft Fortran implementation in stage 3. I am wondering if we could agree to a modified work flow that would allow contributors to still propose an experimental Fortran API, but draft the implementation in C or C++ potentially with external dependencies? A reasonable requirement for the routine to move out of experimental would still be a Fortran implementation, as an assurance that Fortran can \"stand on it's own\".\nI realize this approach has many downsides, e. g. having to maintain a mixed Fortran/C/C++ repository, introduce a bunch of preprocessor commands and optional flags, increase the potential for memory leaks and C related bugs, and finally introduced unwanted dependencies to the project.", + "comments": [ + { + "user": "milancurcic", + "date": "2021-01-21 01:10:26+00:00", + "text": "I think that if we can agree (on a case by case basis) that the pros of a C or C++ implementation outweigh the cons (which you listed), that's fine with me. Fortran compilers usually come with companion C and C++ compilers, so it wouldn't impact compiling from source for developers, and it wouldn't impact users who download the binary files.\nBut I don't see why this needs the workflow to be modified. Does the workflow doc say that the implementation must be in Fortran? The specification would describe the Fortran API, which you'd need to have regardless of the implementation language under the hood." + }, + { + "user": "ivan-pi", + "date": "2021-01-21 08:57:26+00:00", + "text": "But I don't see why this needs the workflow to be modified. Does the workflow doc say that the implementation must be in Fortran?\n\nOn more careful reading it actually doesn't. It only says \"a reference implementation\" should be provided.\nThe primary advantage I see is that the C code might be already available. As an example to develop and test an efficient Fortran sorting function from scratch would likely take someone several man-hours/days. If we could agree to Fortranic interface and just use the C qsort function for our implementation we could have a fast and verified sorting routine sooner. qsort is in fact already allowed as a non-standard extension in some compilers, however the interface is bothersome.\n(The article Engineering a Sort Function by Bentley & McIlroy from Bell laboratories explains the trickery that actually goes into a performant sort function.)" + } + ] + }, + { + "number": 306, + "user": "jvdp1", + "date": "2021-01-19 20:51:47+00:00", + "title": "stdlib_logger: structure of the different log messages?", + "text": "With the PR #261, a hierarchy of levels for the different types of log messages was added in stdlib_logger led by @wclodius2 . Currently the user can only choose a level from which all messages with a level higher than the chosen level can be written. See these specs for more details on the different levels.\nDuring the review of the #261, @ivan-pi proposed another possibility that would consider the different levels as switches.\nUsig a binary representation of integers, levels would look like:\nnone_level = 0\ntext_error_level = shiftl(1,0) \nio_error_level = shiftl(1,1) ! or the error levels can have the same switch\nerror_level = shiftl(1,2)\nwarning_level = shiftl(1,3)\ninformation_level = shiftl(1,4)\ndebug_level = shiftl(1,5)\nall_level = text_error_level + io_error_level + error_level + warning_level + &\n information_level + debug_level\nThis representation would allow the user to turn on selectively only certains combinations of log messages needed to be written to the output.\nI often use stdlib_logger and I am happy with the current behaviour. However, I can see the advantages of such an approach.\nWhat do you think?", + "comments": [ + { + "user": "wclodius2", + "date": "2021-01-20 03:18:50+00:00", + "text": "I am also happy with the current behavior. I worry that allowing arbitrary combinations of levels would be hard to reason about, and hard to test (With six levels I believe there are 64 different combinations)." + } + ] + }, + { + "number": 305, + "user": "LucaArgentiUCF", + "date": "2021-01-19 20:22:41+00:00", + "title": "Special Functions", + "text": "There is a standard for the class of numerical functions that are needed in scientific computation. Traditionally, that was for a long time the \"blue book\" *Handbook of Mathematical Functions\", by Abramowitz and Stegun. However, the American National Institute of Standard and Technology (NIST) has sing long ago taken the burden on its shoulder. After countless years of work and revision, the new\nDigital Library of Mathematical Functions (DLMF) \nhas been published.\nThe DLMF is a the perfect starting point to broaden the standard library. All formulas are tested, some are implemented, and all rigorously referenced and documented. So there is no better blueprint.\nAnywhere would be good to start, but I suggest\n\nconfluent hypergeometric functions\nlegendre and related functions\northogonal polynomials\nCoulomb functions\nspherical-group coefficients (3j, 6j, 9j)", + "comments": [ + { + "user": "Jim-215-Fisher", + "date": "2021-01-19 20:44:24+00:00", + "text": "I like the idea. The special functions are needed in almost all areas. Currently, there are only gamma, log_gamma and bessel functions as standard intrinsic, we need more functions like beta, incomplete gamma, incomplete beta functions etc." + }, + { + "user": "arjenmarkus", + "date": "2021-01-20 08:55:37+00:00", + "text": "Definitely. There are quite a number of libraries out there that claim to\ncalculate these functions. But a good reference is necessary to ensure the\nquality. In addition to the NIST library, I have a digital copy of the book\n\"The Mathematical Function Computation Handbook\" by Nelson Beebe, He pays a\nlot of attention to the accuracy and to the corner cases. It could serve as\na second opinion :).\n\nOp di 19 jan. 2021 om 21:44 schreef Jing :\n\u2026\n I like the idea. The special functions are needed in almost all areas.\n Currently, there are only gamma, log_gamma and bessel functions as standard\n intrinsic, we need more functions like beta, incomplete gamma, incomplete\n beta functions etc.\n\n \u2014\n You are receiving this because you are subscribed to this thread.\n Reply to this email directly, view it on GitHub\n <#305 (comment)>,\n or unsubscribe\n \n ." + }, + { + "user": "ivan-pi", + "date": "2021-01-20 11:09:18+00:00", + "text": "Hello @LucaArgentiUCF ,\nI think this issue might be a duplicate of #179 and #102. The former thread contains a link to a proposal with a specification for a special functions module. (The proposal to include such functions directly in the Fortran language standard was ultimately scrapped or rejected.)\nIf we could agree on an interface, that would be a good first step. We could also \"borrow\" the interfaces from the major vendor libraries:\n\nIMSL\u00ae Fortran Math Special Functions Library\nNAG FL Interface S (Specfun) Approximations of Special Functions (this appears to be an interface to the specfun package)\n\nI had a go at implementing the inverse error function last year using some preprocessing magic: #179 (comment)\nI also started an implementation for a (non-special) cube root function: #214. Initially I thought it would be an easy one, but it turns out catching all the corner cases and guaranteeing full precision over the entire range of floating point variable range, while maintaining good performance is quite tricky. You definitely need a very good understanding of the mathematics, hardware, and numerical analysis if you want to produce high quality implementations.\nUltimately, I halted work on the erfinv function, because I lacked the knowledge (and time) to implement the tests recommed in post #179 (comment) to tabulate the units in last place (ULP). I would appreciate any help to push the erfinv further." + }, + { + "user": "arjenmarkus", + "date": "2021-01-20 11:51:00+00:00", + "text": "The SLATEC library on the Netlib site seems to offer quite a few routines\nfor special functions as well.\n\nThings I am wondering about:\n\n - Should we formulate accuracy requirements, beyond the obvious\n (reasonable range, reasonable number of decimals, ...)?\n - All these venerable codes use some means to determine machine\n parameters - Fortran now offers standard functions. Replace the old probing\n code by modern Fortran means?\n - Would there be a license problem if we adopt and adapt these codes?\n\nMostly thinking out loud :).\n\nOp wo 20 jan. 2021 om 12:09 schreef Ivan Pribec :\n\u2026\n Hello @LucaArgentiUCF ,\n\n I think this issue might be a duplicate of #179\n <#179> and #102\n <#102>. The former thread\n contains a link to a proposal with a specification for a special functions\n module. (The proposal to include such functions directly in the Fortran\n language standard was ultimately scrapped or rejected.)\n\n If we could agree on an interface, that would be a good first step. We\n could also borrow the interfaces from the major vendor libraries:\n\n - IMSL\u00ae Fortran Math Special Functions Library\n \n - NAG FL Interface S (Specfun) Approximations of Special Functions\n \n (this appears to be an interface to the specfun\n package)\n\n I had a go at implementing the inverse error function last year using some\n preprocessing magic: #179 (comment)\n <#179 (comment)>\n\n I also started an implementation for a (non-special) cube root function:\n #214 <#214>. Initially I\n thought it would be an easy one, but it turns out catching all the corner\n cases and guaranteeing full precision over the entire range of floating\n point variable range, while maintaining good performance can be very\n tricky. You definitely need a very good understand of both the mathematics,\n hardware, and numerical analysis if you want to produce high quality\n implementations.\n\n \u2014\n You are receiving this because you commented.\n Reply to this email directly, view it on GitHub\n <#305 (comment)>,\n or unsubscribe\n \n ." + }, + { + "user": "LucaArgentiUCF", + "date": "2021-01-20 13:38:09+00:00", + "text": "I agree the issue overlaps with 179. However, I think that the Digital Library of Mathematical Functions (DLMF) is as authoritative and standard a reference as one can ever possibly get. My suggestion, therefore, would be to shape the special function libraries in terms of one module per DLMF chapter, and figure out which already existing libraries provide the functionalities.\nRegarding TOMS, I do not quite get the statement that I have read in some threads that \"it is not usable\". Unless this sentiment meant to imply poor quality of the library (?), the copyright restrictions to CALGO are not particularly severe: for software past 2013, the rights are with the authors, so one can just ask them (I guess they would be happy to give the rights to use to a standard library they can boast about). For software prior to that date there is only the non-commercial-use clause. Maybe someone see that as a no-go. However, fortran users are for the most part from academia and research centers, so the library modules could include such a disclaimer. Or, if one has just one or two functions from TOMS in a module, one could try to convince ACM to issue a special perpetual no-cost license for those functions in the library. It may be seen by them as a way to promote CALGO, provided that their contribution is advertised in the description of the library.\nCheers,\nLuca" + }, + { + "user": "ivan-pi", + "date": "2021-01-20 14:23:23+00:00", + "text": "For software prior to that date there is only the non-commercial-use clause. Maybe someone see that as a no-go. However, fortran users are for the most part from academia and research centers, so the library modules could include such a disclaimer.\n\nI don't think this is fully the case. There are numerous engineering companies in the aeronautical, petrochemical, and other industries (optics, physics, astronomy, finance, defense, environment...) which are using Fortran. (I remember at a few Fortran monthly calls we had an employee from Boeing join in.) The projects listed on the fortran-lang page: https://fortran-lang.org/packages/scientific are likely only the tip of the Fortran iceberg.\nThe presence of the vendor libraries make me think there must be clients willing to pay for them. Personally, I work at the Technical University of Munich which is a high-ranking public research university, yet we don't have direct access to these libraries. (Access to the NAG library is available indirectly through the SuperMUC cluster funded by the Bavarian Academy of Sciences and Humanities. This resource is shared among many European universities, but even internally we need to submit a formal request to gain access.)\nI have seen in multiple places of the Julia libraries they rolled their own versions of mathematical algorithms to avoid the ACM license. I lack experience with software licenses and their application in practice to judge whether this was really necessary or not." + }, + { + "user": "arjenmarkus", + "date": "2021-01-20 14:29:36+00:00", + "text": "The Netlib site is a trifle vague, On their FAQ page:\n\n\n* 2.3) Are there restrictions on the use of software retrieved from Netlib?\n* Most netlib software packages have no restrictions on their use but we\nrecommend you check with the authors to be sure. Checking with the authors\nis a nice courtesy anyway since many authors like to know how their codes\nare being used.\n\n\nSo, unless code is associated with a TOMS algorithm, it is likely to come\nwith a very permissive license.\n\nOp wo 20 jan. 2021 om 15:23 schreef Ivan Pribec :\n\u2026\n For software prior to that date there is *only* the non-commercial-use\n clause. Maybe someone see that as a no-go. However, fortran users are for\n the most part from academia and research centers, so the library modules\n could include such a disclaimer.\n\n I don't think this is fully the case. There are numerous engineering\n companies in the aeronautical, petrochemical, and other industries (optics,\n physics, astronomy, finance, defense, environment...) which are using\n Fortran. (I remember at a few Fortran monthly calls we had an employee from\n Boeing join in.) The projects listed on the fortran-lang page:\n https://fortran-lang.org/packages/scientific are likely only the tip of\n the Fortran iceberg.\n\n The presence of the vendor libraries make me think there must be clients\n willing to pay for them. Personally, I work at the Technical University of\n Munich which is a high-ranking public research university, yet we don't\n have direct access to these libraries. (Access to the NAG library is\n available indirectly through the SuperMUC cluster funded by the Bavarian\n Academy of Sciences and Humanities. This resource is shared among many\n European universities, but even internally we need to submit a formal\n request to gain access.)\n\n I have seen in multiple places of the Julia libraries they rolled their\n own versions of mathematical algorithms to avoid the ACM license. I lack\n experience with software licenses and their application in practice to\n judge whether this was really necessary or not.\n\n \u2014\n You are receiving this because you commented.\n Reply to this email directly, view it on GitHub\n <#305 (comment)>,\n or unsubscribe\n \n ." + }, + { + "user": "ivan-pi", + "date": "2021-01-20 14:32:02+00:00", + "text": "All these venerable codes use some means to determine machine parameters - Fortran now offers standard functions. Replace the old probing code by modern Fortran means?\n\n\nI have seen this done in a few places previously. One example is here:\nhttps://github.com/certik/fortran-utils/blob/master/src/legacy/amos/d1mach.f90\nI can't remember which code it was, but I think I have seen the D1MACH function replaced by a static array somewhere.\nConcerning SLATEC, I believe it is in the public domain. @jacobwilliams has refactored several components from SLATEC." + }, + { + "user": "ivan-pi", + "date": "2021-01-20 16:11:21+00:00", + "text": "Matching the special functions introduced in C++17 is another reasonable goal:\nhttps://en.cppreference.com/w/cpp/numeric/special_functions" + } + ] + }, + { + "number": 304, + "user": "brocolis", + "date": "2021-01-19 15:11:39+00:00", + "title": "Add supported compilers MinGW 8, 9, 10", + "text": "Add supported compilers MinGW 8, 9, 10 (x86_64 and i686) on Windows 10.", + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-20 18:15:37+00:00", + "text": "@brocolis Did you install the GCC versions from http://winlibs.com/? We might be able to download the corresponding GCC versions from https://github.com/brechtsanders/winlibs_mingw/releases/ and actually test them in the CI to keep supporting a wide range of compilers on Windows as well." + }, + { + "user": "brocolis", + "date": "2021-01-21 10:51:48+00:00", + "text": "@awvwgk I did download and build MinGW/GFortran from sources. I used the scripts written by https://github.com/StephanTLavavej/mingw-distro/ with minor modifications." + }, + { + "user": "awvwgk", + "date": "2021-01-21 10:56:46+00:00", + "text": "Thanks for the clarification. Using this approach would be taxing on the CI runners, if you find a good way to (semi-)automatically install different GCC versions on Windows, let me know, I would be interested to extend the stdlib CI testing for those at some point." + }, + { + "user": "brocolis", + "date": "2021-01-22 13:34:45+00:00", + "text": "Hello. I'm not familiar with CI setup. Anyway, I'll upload the binaries/build scripts to the internet in the next few days." + }, + { + "user": "brocolis", + "date": "2021-01-26 11:33:38+00:00", + "text": "Hello. I'm not familiar with CI setup. Anyway, I'll upload the binaries/build scripts to the internet in the next few days.\n\nOK, mingw/gfortran-8.4.0, 9.3.0 and 10.2.0 for Windows (i686, x64) are now available at https://fortran.rocks/all.html" + } + ] + }, + { + "number": 303, + "user": "jvdp1", + "date": "2021-01-18 22:21:56+00:00", + "title": "Fix missing dependencies in Makefile", + "text": "Fixes #302", + "comments": [ + { + "user": "milancurcic", + "date": "2021-01-18 23:28:54+00:00", + "text": "\ud83d\udc4d \ud83d\ude4f" + } + ] + }, + { + "number": 302, + "user": "milancurcic", + "date": "2021-01-18 21:51:55+00:00", + "title": "CI fails in manual Makefile build", + "text": "Manual Makefile build fails following the merge of #301: https://github.com/fortran-lang/stdlib/runs/1724103766?check_suite_focus=true. I re-ran the jobs to make sure it's reproducible. It is. #301 build was fine at the PR stage. But I think it's incompatible with the parallel Makefile build introduced in #294.", + "comments": [ + { + "user": "jvdp1", + "date": "2021-01-18 22:16:11+00:00", + "text": "Dependencies for some submodules seem to be missing. I'll have a look." + } + ] + }, + { + "number": 301, + "user": "jvdp1", + "date": "2021-01-17 16:20:49+00:00", + "title": "Fix some issues with Makefiles mentioned in #294", + "text": "Fixing the following issues related to Makefiles mentioned in #294:\n\nGenerated .f90 files by fypp can now be cleaned with the clean rule\nDependency added for common.fypp", + "comments": [ + { + "user": "milancurcic", + "date": "2021-01-18 21:10:40+00:00", + "text": "Thanks @jvdp1, I will merge." + } + ] + }, + { + "number": 300, + "user": "awvwgk", + "date": "2021-01-16 12:57:24+00:00", + "title": "Fix compilation error for NAG", + "text": "NAG detects a duplicated name for error_handler which is defined as module procedure as well as the name of the interface of said procedure:\nError: src/stdlib_bitsets.f90, line 2131: ERROR_HANDLER previously declared as a generic procedure name\n detected at ERROR_HANDLER@(\n\nSee #108 for discussion on NAG.", + "comments": [ + { + "user": "jvdp1", + "date": "2021-01-17 16:28:54+00:00", + "text": "Thanks @awvwgk for this workaround. However, it a bug in the compiler, I am not sure if it is wise to introduce this workaround." + }, + { + "user": "awvwgk", + "date": "2021-01-17 16:34:17+00:00", + "text": "I'm not sure if this is actually a compiler error, since it flags a name clash between an overloaded interface and a procedure name. Somebody with more detailed knowledge of the standard could probably help out here." + }, + { + "user": "jvdp1", + "date": "2021-01-17 17:08:12+00:00", + "text": "I'm not sure if this is actually a compiler error, since it flags a name clash between an overloaded interface and a procedure name. Somebody with more detailed knowledge of the standard could probably help out here.\n\nI am not sure neither. I will just flag a few people: @certik @sblionel @milancurcic @everythingfunctional : any ideas/comments?" + }, + { + "user": "sblionel", + "date": "2021-01-17 18:24:29+00:00", + "text": "Could I see a small but complete example that shows the problem? I tried to figure it out from the Files Changed but am worried I might be missing something.\n15.4.3.4.1p3 says \"A generic name may be the same as any one of the procedure names in the generic interface, or the same as any accessible generic name.\" I haven't thought about this related to submodules." + }, + { + "user": "awvwgk", + "date": "2021-01-17 18:41:23+00:00", + "text": "A minimal example reproducing the issue would be\nmodule stdlib_bitsets\n implicit none\n private\n\n public :: error_handler\n\n interface error_handler\n module subroutine error_handler( message, error, status, &\n module, procedure )\n character(*), intent(in) :: message\n integer, intent(in) :: error\n integer, intent(out), optional :: status\n character(*), intent(in), optional :: module\n character(*), intent(in), optional :: procedure\n end subroutine error_handler\n end interface error_handler\n\ncontains\n\n module subroutine error_handler( message, error, status, module, procedure )\n character(*), intent(in) :: message\n integer, intent(in) :: error\n integer, intent(out), optional :: status\n character(*), intent(in), optional :: module\n character(*), intent(in), optional :: procedure\n ! \n end subroutine error_handler\n\nend module stdlib_bitsets\nRunning nagfor -c yields:\nNAG Fortran Compiler Release 7.0(Yurakucho) Build 7038\nError: example.f90, line 20: ERROR_HANDLER previously declared as a generic procedure name\n detected at ERROR_HANDLER@(\n[NAG Fortran Compiler pass 1 error termination, 1 error]\n\nUsing the module procedure and the same generic interface name as the procedure name works, so this might be submodule related.\nmodule stdlib_bitsets\n implicit none\n private\n\n public :: error_handler\n\n interface error_handler\n module procedure :: error_handler\n end interface error_handler\n\ncontains\n\n subroutine error_handler( message, error, status, module, procedure )\n character(*), intent(in) :: message\n integer, intent(in) :: error\n integer, intent(out), optional :: status\n character(*), intent(in), optional :: module\n character(*), intent(in), optional :: procedure\n ! \n end subroutine error_handler\n\nend module stdlib_bitsets" + }, + { + "user": "sblionel", + "date": "2021-01-17 19:03:52+00:00", + "text": "Thanks. I don't see a problem with this code. ifort doesn't complain, but I can confirm a recent NAG does. I'll ask Malcolm about it." + }, + { + "user": "sblionel", + "date": "2021-01-18 00:36:47+00:00", + "text": "Malcolm says, \"Thanks for your bug report. I concur that this is a bug. It should be fixed in build 7041.\"" + }, + { + "user": "awvwgk", + "date": "2021-01-18 09:17:23+00:00", + "text": "I will close this PR since the issue is now fixed upstream. Thanks everybody." + }, + { + "user": "jvdp1", + "date": "2021-01-18 09:18:58+00:00", + "text": "Malcolm says, \"Thanks for your bug report. I concur that this is a bug. It should be fixed in build 7041.\"\n\nThank you for this quick answer. Nice that it will be fixed." + } + ] + }, + { + "number": 299, + "user": "awvwgk", + "date": "2021-01-16 11:52:15+00:00", + "title": "Build fails with Intel Fortran 18", + "text": "I just rolled back my Intel version to check which Intel compilers are supported with stdlib. Testing the range from Intel 16 to Intel 20, I found Intel 18 and older will currently fail to compile stdlib.\nTested on OpenSUSE with\n\nCMake 3.19.2\nninja 1.10.2\nfypp 3.0.0 (Python 3.9.1)\nifort versions failing\n\n18.0.2.20180210\n17.0.7.20180403\n17.0.5.20170817\n16.0.3.20160415\n16.0.0.20150815\n\n\n\nConfiguration test results look similar to latest Intel oneAPI compilers:\n-- Performing Test f18errorstop - Failed\n-- Performing Test f03rank - Success\n-- Performing Test f03real128 - Success\n\nThe build for Intel 18 also generates the warning\nifort: command line warning #10159: invalid argument for option '-stand'\n\nAll builds fail for stdlib_quadrature_simps with\n[79/171] Building Fortran object src/CMakeFil...tran_stdlib.dir/stdlib_quadrature_simps.f90.o\nFAILED: src/CMakeFiles/fortran_stdlib.dir/stdlib_quadrature_simps.f90.o src/mod_files/stdlib_quadrature@stdlib_quadrature_simps.smod \n/software/intel/parallel_studio_xe_2018/compilers_and_libraries_2018.2.199/linux/bin/intel64/ifort -Isrc -Isrc/mod_files -module src/mod_files/ -warn declarations,general,usage,interfaces,unused -standard-semantics -stand f18 -c src/CMakeFiles/fortran_stdlib.dir/stdlib_quadrature_simps.f90-pp.f90 -o src/CMakeFiles/fortran_stdlib.dir/stdlib_quadrature_simps.f90.o\nifort: command line warning #10159: invalid argument for option '-stand'\nsrc/stdlib_quadrature_simps.f90(50): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), dx) + simps(y(4:6), dx)\n------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(54): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:3), dx) + simps38(y(3:6), dx)\n-------------------------------^\nsrc/stdlib_quadrature_simps.f90(70): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), dx) + simps(y(4:n), dx)\n---------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(74): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:n-3), dx) + simps38(y(n-3:n), dx)\n-----------------------------------^\nsrc/stdlib_quadrature_simps.f90(113): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), dx) + simps(y(4:6), dx)\n------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(117): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:3), dx) + simps38(y(3:6), dx)\n-------------------------------^\nsrc/stdlib_quadrature_simps.f90(133): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), dx) + simps(y(4:n), dx)\n---------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(137): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:n-3), dx) + simps38(y(n-3:n), dx)\n-----------------------------------^\nsrc/stdlib_quadrature_simps.f90(176): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), dx) + simps(y(4:6), dx)\n------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(180): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:3), dx) + simps38(y(3:6), dx)\n-------------------------------^\nsrc/stdlib_quadrature_simps.f90(196): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), dx) + simps(y(4:n), dx)\n---------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(200): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:n-3), dx) + simps38(y(n-3:n), dx)\n-----------------------------------^\nsrc/stdlib_quadrature_simps.f90(260): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n))\n-------------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(264): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n))\n-----------------------------------^\nsrc/stdlib_quadrature_simps.f90(271): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = 0.5_sp * ( simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n)) &\n----------------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(272): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n + simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n)) )\n----------------------^\nsrc/stdlib_quadrature_simps.f90(323): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n))\n-------------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(327): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n))\n-----------------------------------^\nsrc/stdlib_quadrature_simps.f90(334): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = 0.5_dp * ( simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n)) &\n----------------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(335): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n + simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n)) )\n----------------------^\nsrc/stdlib_quadrature_simps.f90(386): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n))\n-------------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(390): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n))\n-----------------------------------^\nsrc/stdlib_quadrature_simps.f90(397): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n integral = 0.5_qp * ( simps38(y(1:4), x(1:4)) + simps(y(4:n), x(4:n)) &\n----------------------------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(398): error #6284: There is no matching specific function for this generic function reference. [SIMPS]\n + simps(y(1:n-3), x(1:n-3)) + simps38(y(n-3:n), x(n-3:n)) )\n----------------------^\nsrc/stdlib_quadrature_simps.f90(445): error #6284: There is no matching specific function for this generic function reference. [SIMPS_WEIGHTS]\n w(4:n) = w(4:n) + simps_weights(x(4:n)) ! position 4 needs both rules\n------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(450): error #6284: There is no matching specific function for this generic function reference. [SIMPS_WEIGHTS]\n w(1:n-3) = simps_weights(x(1:n-3))\n-----------------------------------^\nsrc/stdlib_quadrature_simps.f90(461): error #6284: There is no matching specific function for this generic function reference. [SIMPS_WEIGHTS]\n w(4:n) = w(4:n) + simps_weights(x(4:n))\n----------------------------------^\nsrc/stdlib_quadrature_simps.f90(463): error #6284: There is no matching specific function for this generic function reference. [SIMPS_WEIGHTS]\n w(1:n-3) = w(1:n-3) + simps_weights(x(1:n-3))\n--------------------------------------^\nsrc/stdlib_quadrature_simps.f90(513): error #6284: There is no matching specific function for this generic function reference. [SIMPS_WEIGHTS]\n w(4:n) = w(4:n) + simps_weights(x(4:n)) ! position 4 needs both rules\n------------------------------------------^\nsrc/stdlib_quadrature_simps.f90(518): error #6284: There is no matching specific function for this generic function reference. [SIMPS_WEIGHTS]\n w(1:n-3) = simps_weights(x(1:n-3))\n-----------------------------------^\nsrc/CMakeFiles/fortran_stdlib.dir/stdlib_quadrature_simps.f90-pp.f90(751): catastrophic error: Too many errors, exiting\ncompilation aborted for src/CMakeFiles/fortran_stdlib.dir/stdlib_quadrature_simps.f90-pp.f90 (code 1)", + "comments": [] + }, + { + "number": 298, + "user": "awvwgk", + "date": "2021-01-16 10:48:03+00:00", + "title": "Intel Fortran and -standard-semantics", + "text": "Compiling stdlib with Intel Fortran compilers sets the -standard-semantics flag. Unfortunately, this requires all Fortran projects in the dependency tree compiled by Intel Fortran to inherit this compilation flag since it changes the name mangling of the symbols. Setting the -standard-semantic flag by add_compile_options in the CMake build files makes it difficult to overwrite by dependent projects.\nIs there a reason why stdlib requires -standard-semantics? Would it be possible to make this optional for projects that want to use the stdlib project but don't want to use -standard-semantics flag?", + "comments": [ + { + "user": "Romendakil", + "date": "2021-01-16 11:03:38+00:00", + "text": "This is for backward compatibility with Ifort 17 (and earlier). Ifort 18 and newer doesn\u2019t need this any more. It is mainly for the automatic allocation I believe." + }, + { + "user": "awvwgk", + "date": "2021-01-16 11:16:04+00:00", + "text": "In this case -assume realloc_lhs would be a more suitable option for Intel 17 and earlier without changing the name mangling for dependent project.\nAlso, I tested compiling stdlib with a range of Intel versions and found it can only be compiled with Intel 19 or newer right now (notes to open an issue on this as well see #299) ." + }, + { + "user": "jvdp1", + "date": "2021-01-18 22:39:46+00:00", + "text": "I don't remember the reason. Was it @MarDiehl who introduced this option?\nHere is a possible solution. Following this post, adding the option \"-assume nostd_mod_proc_name\" could solve the issue.\nHowever, since it doesn't seem possible to compile stdlib with Intel ifort 18 and lower, is this option still a problem? On the other hand, it could be removed if not appropriate anymore for the newest versions of ifort." + }, + { + "user": "awvwgk", + "date": "2021-01-18 23:05:29+00:00", + "text": "blame says it was introduced in #205 with 39bb56c." + }, + { + "user": "MarDiehl", + "date": "2021-01-21 14:13:19+00:00", + "text": "The general idea was to check for standard conformance. I was not aware of the fact that this also implies a different scheme for name mangling. The name -assume nostd_mod_proc_name indicates that Intel thinks that this mangling scheme is standard conforming. I would assume that this is related to interoperability with C." + } + ] + }, + { + "number": 297, + "user": "awvwgk", + "date": "2021-01-15 19:36:25+00:00", + "title": "Ubuntu runners are failing", + "text": "The CI on the Ubuntu runner is currently hitting a certificate verification failure In the GFortran install step:\nErr:21 https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04 Release\n Certificate verification failed: The certificate is NOT trusted. The received OCSP status response is invalid. Could not handshake: Error in the certificate verification. [IP: 195.135.221.134 443]\n...\nE: The repository 'https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04 Release' no longer has a Release file.\n\nNeeds investigation (might get fixed on the image).", + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-15 19:41:02+00:00", + "text": "Restarting the job fixed the issue" + } + ] + }, + { + "number": 296, + "user": "brocolis", + "date": "2021-01-10 04:14:47+00:00", + "title": "test_loadtxt_qp error with gfortran-7.4.0 (32-bit) on Windows", + "text": "I got an error testing test_loadtxt_qp.f90 with gfortran-7.4.0 (32-bit) on Windows.\nHere are the debugging sessions.\nGDB-8.2\n\nGDB-9.1", + "comments": [ + { + "user": "LKedward", + "date": "2021-01-10 11:17:23+00:00", + "text": "Hi @brocolis, I believe this test is not supported on Windows (due to quad precision) and is hence ignored when running the tests with cmake ctest.\nIf you're running these tests with the fpm package that I recommended to you then unfortunately there is no way to ignore these tests on Windows (except for deleting them)." + }, + { + "user": "brocolis", + "date": "2021-01-10 19:53:53+00:00", + "text": "Hi @LKedward. After a few more testing I found that stdlib passes all tests when compiled by gfortran-9.3.0 (32 bit) or gfortran-8.4.0 (64 bit) or gfortran-10.2.0 (64 bit). When stdlib is compiled by gfortran-7.4.0 (32 bit), I have to remove tests tests\\io\\test_loadtxt_qp.f90, tests\\io\\test_savetxt_qp.f90 and tests\\stats\\test_var.f90 from the Makefile, then stdlib passes the test command.\n\n\n\nCompiler\nPlatform\nBuild\nTest\n\n\n\n\ngfortran 7.4.0\nmingw 32-bit\n\u2705\n\u274c\n\n\ngfortran 8.4.0\nmingw 64-bit\n\u2705\n\u2705\n\n\ngfortran 9.3.0\nmingw 32-bit\n\u2705\n\u2705\n\n\ngfortran 10.2.0\nmingw 64-bit\n\u2705\n\u2705\n\n\n\nBuild command\nmake -f Makefile.manual FYPPFLAGS=-DMAXRANK=4\nTest command\nmake -f Makefile.manual FYPPFLAGS=-DMAXRANK=4 test" + }, + { + "user": "LKedward", + "date": "2021-01-11 08:42:44+00:00", + "text": "Thanks for the comprehensive testing @brocolis, that's helpful in pinpointing this as a compiler bug.\nI was testing with gfortran 8.1.0 on mingw 64-bit where the same tests build but fail to run.\nSo stdlib requires at least gfortran >= 8.4.0 on mingw-w64.\n(See also: #58 and #61 where this bug is first mentioned.)\nThe quad precision tests should probably be enabled in the MSYS workflows which use gfortran 10.2.0" + }, + { + "user": "jvdp1", + "date": "2021-01-11 08:47:44+00:00", + "text": "There are several with GFortran 7 and stdlib (even on Linux). See e.g., #171.\nIt should be probably mentioned in #293." + }, + { + "user": "awvwgk", + "date": "2021-01-11 09:39:19+00:00", + "text": "Maybe it is worth updating to GCC 7.5, the previous minor version of GCC 7 are known to be buggy but most of those issues have been resolved in GCC 7.5." + }, + { + "user": "LKedward", + "date": "2021-01-11 10:01:46+00:00", + "text": "Maybe it is worth updating to GCC 7.5,\n\nSee my previous comment; this issue also affects gcc 8.1.0 on mingw-64bit which is what runs in the 'plain' Windows CI. The affected tests are currently not run in the Windows CI. These test can however be enabled in the recent MSYS2-based workflows which run 10.2.0." + }, + { + "user": "awvwgk", + "date": "2021-01-11 10:11:12+00:00", + "text": "The latest version of the GCC 8 series is 8.4, which works nicely. We are using 8.1 because it is the latest version uploaded on chocolatey and preinstalled on the Windows image. choco is apparently not the best way to get MinGW installations given the incomplete version history, so we shouldn't rely on them for our CI." + }, + { + "user": "brocolis", + "date": "2021-01-13 23:08:56+00:00", + "text": "OK, a few more tests: gfortran-7.5.0 (32 bit) and gfortran-7.5.0 (64 bit) don't work either. The error message is \"At line 60 of file test_var.f90\". gfortran-8.4.0 (32 bit) and gfortran-11-20210110 (experimental) (64 bit) work.\n\n\n\nCompiler\nPlatform\nBuild\nTest\n\n\n\n\ngfortran 7.5.0\nmingw 32-bit\n\u2705\n\u274c\n\n\ngfortran 7.5.0\nmingw 64-bit\n\u2705\n\u274c\n\n\ngfortran 8.4.0\nmingw 32-bit\n\u2705\n\u2705\n\n\ngfortran-11-20210110 (experimental)\nmingw 64-bit\n\u2705\n\u2705\n\n\n\nYes I agree I should focus efforts on the currently maintained compilers." + }, + { + "user": "awvwgk", + "date": "2021-01-14 07:43:27+00:00", + "text": "Thanks for testing this, it's a valuable insight. Too bad it's a GCC 7 issue you are only hitting on Windows. It also looks like GCC 7 is dropped from the supported releases at https://gcc.gnu.org/, so we probably can't expect to get fixed in future releases." + }, + { + "user": "brocolis", + "date": "2021-01-15 08:55:25+00:00", + "text": "Hello. Yes, it's a bit strange that stdlib works with gfortran-7 on Linux, but not on Windows; It may be something with my setup, but I can't say for sure without knowing the root cause. I'll now close this issue.\nThank you." + }, + { + "user": "brocolis", + "date": "2021-01-30 21:55:37+00:00", + "text": "Hi. I discovered a version of gfortran on my machine, that was installed by GNU Octave-4.4.1. I report that stdlib also doesn't work with gfortran-7.2.0 (x64) on Windows." + } + ] + }, + { + "number": 295, + "user": "awvwgk", + "date": "2021-01-08 21:19:20+00:00", + "title": "Manual makefile issues", + "text": "Finally arrived at testing the manual Makefile of stdlib and found a few issues I want to raise.\nFirst, the Makefile does not run in parallel due to missing dependencies between certain object files. Apparently the parallel build with the manual Makefile is not tested in the CI, therefore this issue has not popped up so far. Adding the missing dependencies does resolve the parallel build issue (see #294).\nSecond, the clean rule does not allow to remove all the build artifacts from the source tree, the fypp preprocessed files are not captured by the remove command in the clean rule. This means I have to manually remove the fypp preprocessed files in case I want to change the maximum array rank for the build, which is annoying. Related to this, the SRC variable interlaces build artifacts (fypp preprocessed files) and actual source files.\nFinally, I found the explicit rules regarding the preprocessing confusing, the set is generated implicitly by the %.f90: %.fypp rule already and the given list seems to be incomplete as well (there are other subtle issues to this rule, which makes it dangerous without a scope). Interestingly their is no dependency from the common.fypp to any fypp preprocessed file which includes the file, which means there is no rebuild triggered for changes in the global fypp header.\nIn summary, the manual Makefile is currently pretty fragile at the moment and due to the fixed compiler name in also very limited in scope.", + "comments": [ + { + "user": "jvdp1", + "date": "2021-01-18 22:25:28+00:00", + "text": "Fixed with #294 (first point) and #301 (second and third points).\nThank you @awvwgk for opening these issues.\nI'll close this issue." + } + ] + }, + { + "number": 294, + "user": "awvwgk", + "date": "2021-01-08 19:05:41+00:00", + "title": "Fix dependencies in manual Makefile", + "text": "This PR fixes the manual Makefile by including the correct dependencies. The manual Makefile build could fail in full parallel builds due to missing dependencies.\nTo test this use a slow computer and let make create as many build jobs as allowed by the dependency network with:\nmake -f Makefile.manual FYPPFLAGS=-DMAXRANK=4 -j\nThis error might be hard to catch in a sequential CI build due to the correct ordering of the source files in SRC variable.", + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-08 19:14:11+00:00", + "text": "Still fails occasionally for stdlib_quadrature_trapzd.o even if the dependency on stdlib_quadrature.o is explicitly specified in the Makefile. Typos in make are just annoying." + } + ] + }, + { + "number": 293, + "user": "awvwgk", + "date": "2021-01-07 22:13:56+00:00", + "title": "Write a more verbose introduction to building stdlib", + "text": "explicitly spell out the requirements on compilers, build system and preprocessor\nadd a short paragraph on how to install the build dependencies using pip or conda\nexplain the CMake build step by step\nlist all important CMake configuration options in the README\nadd the CMake install command to the build instructions\nmove the paragraph about the max array rank into the build instructions", + "comments": [ + { + "user": "milancurcic", + "date": "2021-01-14 15:57:54+00:00", + "text": "With no further suggestions, I'll go ahead and merge." + } + ] + }, + { + "number": 292, + "user": "awvwgk", + "date": "2021-01-07 19:33:23+00:00", + "title": "Is stdlib versioned?", + "text": "While writing package files for stdlib (see #291) I encountered a quite simple issue what puzzled me: What is the version number of stdlib?\nIt turns out that some package files simply don't work if there is no version number specified, i.e. pkg-config will not use any pc-file without a Version entry. Not specifying any version is therefore not possible if I want to use stdlib in a non-CMake project. I could just define a dummy version number for my purpose, but this calls for trouble.\nMaybe this issue has been discussed already somewhere, but I didn't found any hint on this here.", + "comments": [ + { + "user": "milancurcic", + "date": "2021-01-08 01:16:30+00:00", + "text": "Currently, no. It should be. You can think of stdlib being in perpetual 0.1.0, but that version number is not specified anywhere.\nThere have been discussions scattered across this repo, monthly call, and Discourse:\n\n#216\nJuly 2020 discussion on stdlib structure\nStabilization of Rust language and stdlib features\n\nTL'DR:\n\nWe started with the idea of having 2 separate namespaces/APIs, experimental and stable. Everything goes into experimental (equivalent to 0.x.x), and when parts of stdlib make it into the Standard, they become \"stable\" (equivalent to 1.x.x). Separate namespaces/APIs means that experimental functions are in separate modules from stable ones. So there could be a stdlib_experimental_io module, and a stdlib_stable_io module. Functions can exist only in one or the other. But of course, this wasn't too meaningful because we don't have anything stable. So every module has the word \"experimental\" in it.\nThis structure was challenged by @wclodius2 in #216. I mostly agreed and we discussed it on a call and had a follow-up discussion on Discourse.\nWe tentatively agreed to unify \"experimental\" and (future) \"stable\" into the same namespace, and start semantic versioning. We didn't start it in practice.\nWe also agreed to keep track of what's experimental or stable on a per procedure basis, by noting in the source code docstrings and spec docs, similar to Rust.\n\nSo, let's start versioning and making releases, like we do for fpm." + }, + { + "user": "awvwgk", + "date": "2021-01-08 18:27:40+00:00", + "text": "Thanks for the comprehensive summary. Really looking forward to see the first release of stdlib." + }, + { + "user": "awvwgk", + "date": "2021-01-19 08:31:17+00:00", + "text": "With #291 merged there is now a dummy version in place." + }, + { + "user": "jvdp1", + "date": "2021-01-19 20:26:32+00:00", + "text": "So, let's start versioning and making releases, like we do for fpm.\n\nI agree with that. A couple of questions:\n\nShould we start with, let say, the version 0.1.0?\nWould all procedures still remain in the \"experimental\" namespace? Or should some produres be associated with the new version?" + }, + { + "user": "awvwgk", + "date": "2021-01-20 07:16:02+00:00", + "text": "Version 0.1.0 is a reasonable choice." + }, + { + "user": "ivan-pi", + "date": "2021-01-20 16:35:18+00:00", + "text": "* Would all procedures still remain in the \"experimental\" namespace? Or should some produres be associated with the new version?\n\n\nAccording to the workflow established in #94:\n\nIn order to move from experimental to release, the specification document must be approved by the wide community and the standards committee (informally). If that happens, it has now been blessed for broad use and we can move the code into the main section of stdlib, and the particular specification document becomes part of the Fortran Standard Library.\n\nPersonally, I would preserve everything in experimental for now.\n@certik also suggested to introduce release notes, for example: https://github.com/sympy/sympy/wiki/Writing-Release-Notes" + } + ] + }, + { + "number": 291, + "user": "awvwgk", + "date": "2021-01-07 09:48:29+00:00", + "title": "Export package files", + "text": "Part 3/3 for #287, status: required.\nChanges:\n\nset project version (just 0 as dummy) and project description in CMake (required to generate a valid pc-file)\nexport CMake package fortran_lang-config.cmake for CMake projects\nexport pkg-config file fortran_lang.pc for non-CMake projects\n\nImportant: This PR defines a version number for stdlib. This should be considered carefully (see #292).", + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-07 19:11:29+00:00", + "text": "Tested this by integrating a local installation of stdlib with make via pc-file and with meson via CMake package." + }, + { + "user": "jvdp1", + "date": "2021-01-18 17:26:49+00:00", + "text": "@milancurcic approved thi PR. I 'll merge it." + } + ] + }, + { + "number": 290, + "user": "awvwgk", + "date": "2021-01-06 23:08:31+00:00", + "title": "Rename CMake project from stdlib to fortran_stdlib", + "text": "Part 2/3 for #287, status: optional. If you do not like this approach we can do #287 without it.\nChanges:\n\nrename CMake project from stdlib to fortran_stdlib\nreuse the PROJECT_NAME CMake variable instead of using fortran_stdlib directly\n\nReasoning:\n\nexported CMake targets usually match the project name (fortran_stdlib seems less likely to clash with something compared to stdlib)\nallows to easily use PROJECT_NAME to write reusable/transferable CMake code for different projects (interesting for fpm generated CMake files as well)\nPROJECT_NAME is accessible in configure_file and can be used to create more general template files", + "comments": [] + }, + { + "number": 289, + "user": "awvwgk", + "date": "2021-01-06 22:32:40+00:00", + "title": "API docs workflow", + "text": "Just a question out of curiosity is there a particular reason to perform the build of the API documentation on the OSX runner?\nThe OSX runner happens to be the most expensive runner available on GH actions and the workflow doesn't seem to need any OSX specific features to run FORD on the source of stdlib.", + "comments": [ + { + "user": "jvdp1", + "date": "2021-01-06 22:36:27+00:00", + "text": "Good question. @zbeekman wrote the API docs workflow. Indeed, a Linux OS should be fine, as I often run FORD on my machine." + }, + { + "user": "zbeekman", + "date": "2021-01-07 16:01:22+00:00", + "text": "There was an issue when using the Linux images due to using some of the python markdown extensions. It may now be resolved, we can look into it at some point." + } + ] + }, + { + "number": 288, + "user": "awvwgk", + "date": "2021-01-06 22:29:35+00:00", + "title": "Follow GNU install conventions", + "text": "Part 1/3 for #287, status: optional. If you do not like this approach we can do #287 without it.\nChanges:\n\nremove hard coded subpaths for installation with CMake\nallow customization of install locations by GNUInstallDirs module\nenable project installation on CI testing (CMake targets are only generated on install)\n\nReasoning:\n\nallows customization of the include directory if it shouldn't go into the top-level include directory\nmakes the life of packagers easier, because we don't have to patch the CMakeLists.txt, but can use command line arguments instead to apply our directory naming conventions", + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-11 16:25:54+00:00", + "text": "Since this is a simple change I will go ahead and merge this PR with two approvals." + } + ] + }, + { + "number": 287, + "user": "awvwgk", + "date": "2021-01-05 19:00:30+00:00", + "title": "Using stdlib in meson", + "text": "Using stdlib is currently only possible with CMake by inclusion as subproject or by systemwide installation (either /usr or /usr/local prefix). The first approach excludes certain CMake setups and other build systems like meson, while the latter is not acceptable in case several compilers are used for development.\nAn usual approach to install packages in a local prefix is exporting CMake package files or pkg-config files, the latter makes the project discoverable by most non-CMake build systems.\nAre there plans in the short-term to allow exporting of package files to make stdlib accessible for other projects?", + "comments": [ + { + "user": "milancurcic", + "date": "2021-01-06 19:51:26+00:00", + "text": "I don't know of any plans for this. I'm not too familiar with pkg-config files so I don't use them regularly. It would be helpful for people who use them to post here and express that this is a desired feature. But even if it's useful for only you, I'd say just go ahead because something like this increases ease of use without adding complexity for the end-user." + }, + { + "user": "ivan-pi", + "date": "2021-01-06 23:00:10+00:00", + "text": "I used pkg-config recently to link with the Intel MKL libraries and found it easy enough to use. Essentially, using pkg-config requires writing a small file with some meta-data about the project, the required link flags and include folders of the library.\nOne downside in case of Fortran is that the link flags might be compiler specific (in C this is less of a problem as icc borrows the gcc front-end). Intel MKL offers a \"link line advisor\" tool which helps generate the right flags that can be pasted into a pkg-config file (ideally you only do this once upon installation). The GNU Scientific library (and also it's Fortran wrapper FSGL) offer pkg-config files, meaning some potential users will be familiar with this already." + } + ] + }, { "number": 286, "user": "Jim-215-Fisher", @@ -29,7 +540,33 @@ "date": "2020-12-29 09:35:40+00:00", "title": "Fix subproject build", "text": "Required changes to use stdlib as subproject in CMake.", - "comments": [] + "comments": [ + { + "user": "awvwgk", + "date": "2021-01-02 12:22:51+00:00", + "text": "I created a repo to ease the review process of this PR: https://github.com/awvwgk/stdlib-cmake-example\nYou can check the subprojects/CMakeLists.txt and switch between my fork and this repo to investigate the difference for CMake integration." + }, + { + "user": "milancurcic", + "date": "2021-01-05 17:17:56+00:00", + "text": "I'm a true CMake n00b so I can't comment on the code. It seems good to me.\nBut I played with the stdlib-cmake-example and it works like a charm. Actually, CMake fetching stdlib and using it as a dependency felt like magic because I never did anything like that with CMake. So I think this will significantly lower the bar for using stdlib for some users.\nI'm still a bit confused what this PR addresses exactly. If I'm not mistaken, the stdlib-cmake-example works as is with the current master. I think that is using the fetch method. Does this PR then allow using stdlib with the other method described in the stdlib-cmake-example README? Likely just me not understanding the CMake lingo.\nAnyhow, whichever it is, I trust that this is good to go." + }, + { + "user": "awvwgk", + "date": "2021-01-05 17:30:54+00:00", + "text": "I'm still a bit confused what this PR addresses exactly. If I'm not mistaken, the stdlib-cmake-example works as is with the current master. I think that is using the fetch method. Does this PR then allow using stdlib with the other method described in the stdlib-cmake-example README? Likely just me not understanding the CMake lingo.\n\n@milancurcic It does not, I currently let it fetch from my fork instead of the fortran-lang/stdlib repo (see https://github.com/awvwgk/stdlib-cmake-example/blob/623da353140578646daf125f6b6dd46981d9947a/subprojects/CMakeLists.txt#L11-L21). I force-pushed the repo a few times, the initial example fetching from fortran-lang/stdlib is still in the actions log at https://github.com/awvwgk/stdlib-cmake-example/runs/1636468980?check_suite_focus=true and has actually failed (see #285).\nThe repo README still explains it with the fortran-lang/stdlib repo, which will start to work once this PR is merged. Also, I will than match the implementation with the docs again \ud83d\ude09." + }, + { + "user": "milancurcic", + "date": "2021-01-05 17:34:00+00:00", + "text": "@awvwgk Perfect, that's clear now. :)" + }, + { + "user": "awvwgk", + "date": "2021-01-05 17:35:16+00:00", + "text": "I'll go ahead and merge this PR, we can still revert or patch it later." + } + ] }, { "number": 283, @@ -270,6 +807,151 @@ "user": "hsnyder", "date": "2020-12-23 19:03:15+00:00", "text": "@jvdp1 I think that since the use case for gaussian quadrature is a bit different (usually you're integrating a function rather than discrete samples), it makes more sense to return the points and weights instead.\n@certik sounds good, I like your tabulated implementation from hfsolver. I propose to use that as the basis for an implementation, and fall back on another implementation in the n > 64 case. From what various people have posted in this thread and in #112, it seems like there are several options. Is there a favourite among them? Quadpack perhaps?" + }, + { + "user": "hsnyder", + "date": "2021-01-02 03:10:28+00:00", + "text": "I've started working on an implementation... Should we provide separate implementations for getting the points and weights in real32, or support double precision only and let the user convert if they care? If we do want to offer real32 versions, is it important that the whole implementation be real32, or can the computation be done in 64 and then down-converted?\nI'd be surprised if there's a lot of use of 32 bit platforms anymore, but figured I'd ask." + }, + { + "user": "arjenmarkus", + "date": "2021-01-04 12:59:31+00:00", + "text": "Wrt 32 bits platforms: probably not that much indeed, but that is a different matter than 32 bits versus 64 bits reals ;).\nFor the sort of problems I work on professionally, 32 bits (or, I prefer to talk of single precision, the two are not entirely equivalent), offer in general quite enough precision. Single-precision means 5 or 6 decimals. If you consider such quantities as the water depth (to borrow from my field), that would typically mean better than 1 mm precision (assuming water depths up to 1 km). That is far more precise than any measurements in that field. Using single-precision means a more economic use of memory and disk space. That is certainly not to say that double-precision does not enter my field of expertise - I merely mean that both types of real precision are still useful.\nThat said, I would say that for the purposes of this part of the standard library it suffices to have double-precision points and weights and have a convenient interface to convert to single-precision." + }, + { + "user": "hsnyder", + "date": "2021-01-04 18:02:01+00:00", + "text": "Hi @arjenmarkus\nGood points - it was lazy of me to conflate 32 bit reals with 32 bit platforms. As per your suggestion, I'll provide interfaces for both kinds of reals, but the back-end computation of the nodes and weights will be done in 64 bit." + }, + { + "user": "milancurcic", + "date": "2021-01-06 19:59:32+00:00", + "text": "Should we provide separate implementations for getting the points and weights in real32, or support double precision only and let the user convert if they care? If we do want to offer real32 versions, is it important that the whole implementation be real32, or can the computation be done in 64 and then down-converted?\n\n@hsnyder Sorry for the late chime in on this.\nIf feasible, ideal would be to have 32, 64, and 128-bit real specific procedures. i.e. if the implementation is the same for all three but only the interface changes, I think we should provide them.\nBut if the implementation is different for each, then I suggest pick one that's most useful for you (e.g. real64). If there are users who also want real32, they will chime in or contribute code.\nI recommend against providing a real32 interface that is real64 under the hood, for two reasons:\n\nUsers would think they're using a real32 procedure, but they wouldn't be getting the benefit of real32 because it's real64 under the hood. IMO this interface would be misleading.\nUsers can convert to real32 themselves if they really need that.\n\nI also tend to use real32 for the same reason as @arjenmarkus.\nWhat do you think?" + }, + { + "user": "ivan-pi", + "date": "2021-01-07 13:22:47+00:00", + "text": "I agree with the previous comments that single precision reals are still sufficient for many engineering applications.\nI agree with @milancurcic only partially concerning the misleading interface. For Gaussian quadrature typically the user will only calculate the weights once at the beginning of the program, this calculation will normally be only a minor fraction of the total calculation cost.\nRecently, Larry Young, a retired chemical engineer with interest in numerics, camshaft design, and also Fortran, wrote a very comprehensive monograph about collocation methods and Gaussian quadrature. A PDF version can be found at: https://www.tildentechnologies.com/Numerics/\nHe provides a through analysis of the accuracy and algorithmic efficiency of various methods for computing Gaussian quadrature weights. Quoting from section 2.4.8 on page 94:\n\nGauss or Lobatto points and weights with n= 100 can be calculated in only 25 or 60 \u03bcsec with recurrent and composite calculations, respectively, while a million points and weights can be calculated in less than 0.3 sec.\nWith nAsmpof 40 the switch from recurrent to composite method causes a factor of 3 to 4 increase in computation time, but the overall time is so small it hardly seems relevant, so the small improvement in accuracy seems justified.\n\n(I believe this paragraph applies to double precision calculations on a Intel Core i7-7600u, 2.8 GHz)\nThe conditioning of the calculations is such that you are typically able to obtain at least 14 decimals (out of a range of 16 decimals for 64-bit reals). Assuming the conditioning issues remain similar for single precision reals, it would mean you only get 5-6 decimals for a range of 7. Especially, when using single precision Gaussian quadrature coefficients I think it would be crucial to have all the digits correct. This only seems possible if you compute them in higher precision, initialize them as known constants, or load them from a file. Given that most processors with supporting Fortran compilers provide double precision reals, I don't think this would really be a problem.\nHaving written this, I support your option # 2, users should convert to a single precision real themselves." + }, + { + "user": "arjenmarkus", + "date": "2021-01-07 14:05:15+00:00", + "text": "Option 2 has the benefit that people will be aware of the difference in\nprecision. Yes ,that is worthwhile.\n\nOp do 7 jan. 2021 om 14:23 schreef Ivan Pribec :\n\u2026\n I agree with the previous comments that single precision reals are still\n sufficient for many engineering applications.\n\n I agree with @milancurcic only partially\n concerning the misleading interface. For Gaussian quadrature typically the\n user will only calculate the weights once at the beginning of the program,\n this calculation will normally be only a minor fraction of the total\n calculation cost.\n\n Recently, Larry Young, a retired chemical engineer with interest in\n numerics, camshaft design, and also Fortran, wrote a very comprehensive\n monograph about collocation methods and Gaussian quadrature. A PDF version\n can be found at: https://www.tildentechnologies.com/Numerics/\n\n He provides a through analysis of the accuracy and algorithmic efficiency\n of various methods for computing Gaussian quadrature weights. Quoting from\n section 2.4.8 on page 94:\n\n Gauss or Lobatto points and weights with n= 100 can be calculated in only\n 25 or 60 \u03bcsec with recurrent and composite calculations, respectively,\n while a million points and weights can be calculated in less than 0.3 sec.\n\n With nAsmpof 40 the switch from recurrent to composite method causes a\n factor of 3 to 4 increase in computation time, but *the overall time is\n so small* it hardly seems relevant, so the small improvement in accuracy\n seems justified.\n\n (I believe this paragraph applies to double precision calculations on a\n Intel Core i7-7600u, 2.8 GHz)\n\n The conditioning of the calculations is such that you are typically able\n to obtain at least 14 decimals (out of a range of 16 decimals for\n 64-reals). Assuming the conditioning issues remain similar for single\n precision reals, it would mean you only get 5-6 decimals for a range of 7.\n Especially, when using single precision Gaussian quadrature coefficients I\n think it would be crucial to have all the digits correct. This only seems\n possible if you compute them in higher precision, initialize them as known\n constants, or load them from a file. Given that most processors with\n supporting Fortran compilers provide double precision reals, I don't think\n this would really be a problem.\n\n Having written this, I support your option # 2, users should convert to a\n single precision real themselves.\n\n \u2014\n You are receiving this because you were mentioned.\n Reply to this email directly, view it on GitHub\n <#277 (comment)>,\n or unsubscribe\n \n ." + }, + { + "user": "hsnyder", + "date": "2021-01-08 15:28:14+00:00", + "text": "Good points all around. I'm in agreement that we should provide a 64 bit version only, for all the reasons already discussed. I have a bit of work done on the implementation already, but looking at the workflow document it looks like I'm supposed to post the spec first? I'll write that as soon as I have a chance, and will post it for discussion.\nI'll also look at the monograph linked by ivan-pi, sounds interesting.\nDo we use a typical fork and PR workflow? Should I fork the stdlib, put my implementation in my copy, and then open a PR?" + }, + { + "user": "milancurcic", + "date": "2021-01-08 15:36:07+00:00", + "text": "@hsnyder Great, thank you!\nWe don't need the full and final spec before opening the PR. What's important to discuss before the PR is the API of the function, i.e. procedure name, dummy arguments, their types, etc. We can develop the spec doc during the PR. There should be a complete spec done before the PR is merged. In summary:\n\nDiscuss API in this thread and get consensus;\nOpen a PR with implementation and spec draft.\n\n\nDo we use a typical fork and PR workflow? Should I fork the stdlib, put my implementation in my copy, and then open a PR?\n\n\ud83d\udc4d" + }, + { + "user": "hsnyder", + "date": "2021-01-10 22:30:47+00:00", + "text": "Understood. Here are the subroutine signatures I propse:\n subroutine gausslegendre(x,w,interval)\n real(real64), intent(out) :: x(:), w(:)\n real(real64), optional, intent(in) :: interval(2) ! This defaults to [-1.0_real64, 1.0_real64]\n end subroutine\n\n subroutine gausslobatto(x,w,interval)\n real(real64), intent(out) :: x(:), w(:)\n real(real64), optional, intent(in) :: interval(2) ! This defaults to [-1.0_real64, 1.0_real64]\n end subroutine\n\nx and w are the points and weights respectively. The size of the arrays passed is used to determine the number of points to be calculated (which is obvious, I suppose). The optional arguments a and b, if provided, will scale the points and weights for the interval [a,b] (the default would be [-1,1] ).\nI'm not particularly married to the actual names, though these seem clear to me without being excessively verbose.\nEDIT: updated function signatures in accordance with the below comments from @gareth-d-ga and @milancurcic" + }, + { + "user": "gareth-d-ga", + "date": "2021-01-11 07:59:56+00:00", + "text": "You might consider making the domain of integration (interval(2)) an optional argument to gausslegendre_xw and gauslobatto_xw, with a default value of [-1.0_real64, 1.0_real64]. Then there is no need for shift_xw.\nsubroutine gausslegendre_xw(x, w, interval)\n real(real64), intent(out) :: x(:), w(:)\n real(real64), optional, intent(in) :: interval(2) ! This defaults to [-1.0_real64, 1.0_real64]\nend subroutine\n\nsubroutine gausslobatto_xw(x, w, interval)\n real(real64), intent(out) :: x(:), w(:)\n real(real64), optional, intent(in) :: interval(2) ! This defaults to [-1.0_real64, 1.0_real64]\nend subroutine" + }, + { + "user": "hsnyder", + "date": "2021-01-11 15:48:38+00:00", + "text": "Excellent idea, I updated the proposed API in accordance with your suggestion." + }, + { + "user": "milancurcic", + "date": "2021-01-11 17:21:19+00:00", + "text": "In the naive interpretation of the name gausslegendre_xw, the _xw part suggests to me that this returns x and w (correct), but also that this serves to differentiate it from gausslegendre_somethingelse.\nIn other words, is there anything else that these quadratures could do or return? If not, then the _xw part is redundant. Can we do:\nsubroutine gausslegendre(x, w, interval)\n ...\nsubroutine gausslobatto(x, w, interval)\n ...\n\n?" + }, + { + "user": "hsnyder", + "date": "2021-01-11 17:25:05+00:00", + "text": "Another good point, I've updated the proposed API" + }, + { + "user": "hsnyder", + "date": "2021-01-11 18:12:43+00:00", + "text": "Actually, @milancurcic, I'm having second thoughts about that... \"gausslegendre\" suggests the function has something to do with gauss-legendre quadrature, but \"gausslegendre_xw\" more clearly signifies that the function returns the points and weights. If it's too terse we could change the suffix to \"_ptswts\", but I prefer \"_xw\" personally.\nNot that big a deal either way, but curious for your reaction." + }, + { + "user": "milancurcic", + "date": "2021-01-11 18:39:42+00:00", + "text": "You're right that \"gausslegendre_xw\" is more specific. But the arguments already document this.\nIs there anything else that \"gausslegendre\" could be confused with? In other words, a user coming to the library and wanting the Gauss-Legendre quadrature--would they wonder what \"gausslegendre\" does assuming that they see the subroutine signature?\nIf some appendage is required, _xw is my favorite.\n@arjenmarkus @jvdp1 @ivan-pi what do you think about the naming?\nFor reference, here's a short list of names elsewhere:\n\nJulia:\n\ngausslegendre in FastGaussQuadrature.jl\nlegendre in GaussQuadrature.jl\n\n\nPython:\n\nleggauss in numpy.polynomial.legendre\n\n\nC:\n\ngsl_integration_gl* in GNU Scientific Library" + }, + { + "user": "jvdp1", + "date": "2021-01-11 19:40:55+00:00", + "text": "I am not a typical user of such procedures.\nHowever, regarding the name, if gausslegendre cannot be confused with another procedure having a different objective, then I think that _xw is redundant because x and w are already in the API as arguments.\nTo add to @milancurcic 's list:\n\n\nR: gaussLegendre\n\n\nNumpy: leggauss\n\n\nSee also name examples of such F90 procedures here" + }, + { + "user": "arjenmarkus", + "date": "2021-01-12 07:21:17+00:00", + "text": "I can imagine that another procedure in this context might be the direct\napplication of the quadrature method to a given function. That would likely\nbe called \"integrate_gausslegendre\" or something along those lines, though.\nAlso the name of the encompassing module could serve as an indicator. I\nmust admit that I did not immediately associate the \"_xw\" with the\nx-coordinates and weights ;).\nThat said, I lean towards \"gausslegendre\" without the suffix (but\ndefinitely both names, not one of the abbreviations or omissions that are\nused in the Julia, Python or C examples).\n\nOp ma 11 jan. 2021 om 20:41 schreef Jeremie Vandenplas <\nnotifications@github.com>:\n\u2026\n I am not a typical user of such procedures.\n However, regarding the name, if gausslegendre cannot be confused with\n another procedure having a different objective, then I think that _xw is\n redundant because x and w are already in the API as arguments.\n\n To add to @milancurcic 's list:\n\n -\n\n R: gaussLegendre\n \n -\n\n Numpy: leggauss\n \n\n See also name examples of such F90 procedures here\n \n\n \u2014\n You are receiving this because you were mentioned.\n Reply to this email directly, view it on GitHub\n <#277 (comment)>,\n or unsubscribe\n \n ." + }, + { + "user": "hsnyder", + "date": "2021-01-17 19:26:39+00:00", + "text": "So I was working on the implementation for this and realized that under the hood there's an implementation of calulating the legendre polynomials and their derivatives. So I thought, why not expose it? The most natural function name for computing the legendre polynomial is, in my opinion, simply legendre. The derivative could be dlegendre.\nAnyways, I propose adding these functions as well. Proposed API:\nelemental real function legendre (N, x)\n integer :: N ! which legendre polynomial?\n real :: x ! the point to evaluate at\nend function\n\nelemental real function dlegendre (N, x)\n integer :: N ! which legendre polynomial?\n real :: x ! the point to evaluate at\nend function\n\nWe could make these generic and supply implementations for real32 and real64 - really no reason not to in this case.\n\nA seperate concern: I was thinking about the method name gausslobatto and to be honest it is ambiguous. For example, gauss-chebyshev-lobatto quadrature also exists. The correct term is gauss-legendre-lobatto quadrature. So I propose amending the names suggested above to gauss_legendre and gauss_legendre_lobatto. Is that okay?\nLastly, regarding @arjenmarkus's thought about offering integrate_gauss_legendre, I'm open to offering the implementation but I'll need someone else to propose the API - I'm still pretty new to fortran and don't understand much about passing procedures as function arguments." + }, + { + "user": "ivan-pi", + "date": "2021-01-18 01:36:11+00:00", + "text": "Anyways, I propose adding these functions as well. Proposed API:\nreal function legendre (N, x)\n integer :: N ! which legendre polynomial?\n real :: x ! the point to evaluate at\nend function\n\nreal function dlegendre (N, x)\n integer :: N ! which legendre polynomial?\n real :: x ! the point to evaluate at\nend function\n\nWe could make these generic and supply implementations for real32 and real64 - really no reason not to in this case. We can't make these functions elemental, but we could supply versions for scalar x and for arrays of any valid rank.\n\nI believe this is something we want and has been mentioned previously in issue #179. See page 15 of this former WG5 proposal: https://wg5-fortran.org/N1651-N1700/N1688.pdf\nI can't see any reason why this could not be an elemental function. If the arguments are scalars, then as long as you put the elemental attribute in front, it should just work. (The use of an elemental procedure does not fit well with the way the polynomials are actually calculated, using the recurrence relations.) I guess the actual challenge is writing a bullet-proof implementation which works accurately for any N or x." + }, + { + "user": "hsnyder", + "date": "2021-01-18 02:27:43+00:00", + "text": "I had thought that only single-argument functions could be elemental but you're right of course, we can make them elemental. I have an implementation that is iterative rather than recursive. I believe it will work. I've edited my above post to reflect the use of elemental.\nShould these polynomial functions be in stdlib_quadrature, or in another module? stdlib_math or stdlib_functions maybe?" + }, + { + "user": "bcornille", + "date": "2021-01-18 02:58:50+00:00", + "text": "A common pattern for evaluating Legendre polynomials is to request the result of all polynomials up to a certain order. For this case it would be beneficial to have an interface like\nsubroutine legendre(N, x, p)\n integer :: N ! highest legendre polynomial degree\n real :: x ! the point to evaluate\n real :: p(0:N)\nend subroutine\n\nThe downside of this interface is of course it is not a function and it cannot be marked elemental. It could be made into a GENERIC interface for single and multi-point evaluation as well as array or scalar output. I have implemented some classes for Gauss-Legendre and Labatto-Legendre cardinal function evaluation that use this type of interface. They also store the reference interval nodes and weights, which could be useful for reuse in quadrature over many segments. An interface for requesting nodes and weights for arbitrary intervals is provided. Implementing gaussian quadrature as a class may not be right for stdlib, but it would allow efficient re-use of a single quadrature scheme over many intervals." + }, + { + "user": "bcornille", + "date": "2021-01-18 03:27:26+00:00", + "text": "I think it's true that you can't mix subroutines and functions. The generic would have to be something like\ninterface legendre\n module subroutine legendre_scalar(N, x, p)\n integer :: N\n real :: x\n real :: p\n end subroutine\n module subroutine legendre_array(N, x, p)\n integer :: N\n real :: x\n real :: p(0:N)\n end subroutine\nend interface\n\nI know this would not be compatible with your currently proposed API. Two more overloads for x(:) input could also be added. The upside here is flexibility, but the downside is of course the scalar cases have a poorer API than the functions." + }, + { + "user": "hsnyder", + "date": "2021-01-18 03:33:02+00:00", + "text": "I think it's true that you can't mix subroutines and functions.\n\nSorry, I deleted the post that @bcornille was responding to here, because I realized it was based on a misread of his first post.\nHmmm, I do prefer the function interface for the scalar/elemental case... What about including the function versions I proposed above, and, seperately:\nsubroutine legendre_upto (N, x, p)\n integer :: N ! highest legendre polynomial degree\n real :: x ! the point to evaluate\n real :: p(0:N)\nend subroutine\n\nWe can change the suffix to something else (upto isn't the best), but my point is what about using a different procedure name to offer that interface as well?" + }, + { + "user": "bcornille", + "date": "2021-01-18 03:43:04+00:00", + "text": "@hsnyder That seems like a perfectly reasonable solution as well. I'm new to this forum so I would open up the discussion and utility of this additional function to others.\nI do think there may be some value in the use of a class for the Gaussian quadrature scheme since the calculation of nodes and weights of a certain order could be expensive if redone for many intervals. The implementation of Gauss-Legendre and Labatto-Legendre cardinal functions I mentioned can be founde here. There is some additional setup done, but something similar could be done where the quadrature scheme is setup with a call to a type-bound procedure and then provide additional type-bound procedures to get the nodes, weights, or pass a function and an interval to do the integration. This may be much more OO-style than desired for stdlib." + }, + { + "user": "hsnyder", + "date": "2021-01-18 14:47:02+00:00", + "text": "I would strongly prefer a simple subroutine call that just gives me the nodes and weights. I agree that an object would be useful for some applications but I think we should provide the simpler interface and let the user build scaffolding around it if it's of use to them, rather than force them to deal with a more complex API when they just want the nodes and weights once.\nBut yes, let's see what the rest of the community thinks." + }, + { + "user": "jvdp1", + "date": "2021-01-18 16:39:51+00:00", + "text": "I would strongly prefer a simple subroutine call that just gives me the nodes and weights. I agree that an object would be useful for some applications but I think we should provide the simpler interface and let the user build scaffolding around it if it's of use to them, rather than force them to deal with a more complex API when they just want the nodes and weights once.\n\nIn the past, the preference has been for simple procedures, over OOP. If OOP is desired by the community, it can be always built on top of the simpler procedures." + }, + { + "user": "ivan-pi", + "date": "2021-01-18 16:45:57+00:00", + "text": "There have been multiple similar discussions in other issues. Ultimately, the choice between a procedural or OO interface will be a user preference and so we could provide both. In some applications, there is good potential for code reuse meaning once the procedural interface for gausslegendre is available, we can build a derived type with members x and w and various methods (integration, interval selection, etc). (Of course you could also do it the other way round, the procedural interface uses the derived type internally.)\nPersonally, my interest in Gaussian quadrature is related to solving one-dimensional PDE's with the method of weighted residuals. A fully fledged package for this purpose (like the one in preparation by Tilden Technologies (TT) would cover all of the following functionalities (imaged borrowed from the TT website):\n\nOn the other hand looking at the Scipy library, currently it only provides routines for Gaussian quadrature (fixed_quad), nodes and weights of such quadratures (roots_legendre) and evaluation of orthogonal polynomials (eval_legendre and legendre, where the latter returns a np.poly1d object containing which contains the coefficients of the polynomial in monomial form).\nA search on GitHub for eval_legendre returns around 6000 code hits, the majority of which appear to be simply copies of the original scipy repository. In between you can find actual usage cases in electrostatic solvers, quantum mechanics, et cetera. If we could count the number of times they are used from Boost, Julia, R, MATLAB, and C, and all of the historical Fortran codes, I am sure we can conclude that evaluation and quadrature are used frequently enough to deserve inclusion in stdlib. On the other hand the full orthogonal polynomial tool set would probably be better pursued as a fpm project first (less need for review, more flexibility to experiment with API, etc.)." + }, + { + "user": "hsnyder", + "date": "2021-01-18 16:58:59+00:00", + "text": "My use case is also weighted residual techniques and I'd love to see more functionality in the stdlib cater to that sort of thing. However, I'm also mindful of scope creep.. I really just want to get the quadrature functions in ASAP, and since I'm internally computing the legendre polys, I figured why not expose an API for that too. We can revisit other functionality related to PDE solvers in future proposals. @ivan-pi I'd be happy to work on the extended functionality with you in the future if you want." + }, + { + "user": "ivan-pi", + "date": "2021-01-18 17:11:43+00:00", + "text": "I agree we should not pursue any advanced targets at the moment. I am looking forward to reviewing your pull request \ud83d\udc4d.\nHopefully, the procedural interfaces will open a door to other polynomials and quadratures and get more people involved." } ] }, @@ -382,6 +1064,21 @@ "user": "Jim-215-Fisher", "date": "2020-12-20 19:04:46+00:00", "text": "Thank you @Jim-215-Fisher for this PR. Is it ready for review?\n\nYes. I think it is ready." + }, + { + "user": "Jim-215-Fisher", + "date": "2021-01-08 18:10:33+00:00", + "text": "I agreed completely. Actually I prepared a module as a container to include all the probability modules and export the public access procedures. I thought it might be reduntant to have a separate PR.\n\nPersonally, I am OK with including this pending a few comments.\nI inspected the original xorshift256 code in C and this seems to be a faithful reproduction. Testing with TestU01 could give us more assurance. But I think this is best done in a separate repository.\nI appreciate you following our suggestion of splitting the distributions module for ease of the review process. However, on inspection of the remaining modules I think we should change it in the next pull request.\nThe way I see it, there should be a top module stdlib_stats_distributions which exports all the public routines for uniform, normal, and other distributions and also the random_seed routine needed for the PRNG generator used internally. The implementations of the random-number generator used internally, and the actual distributions functions can then go in sub-modules." + }, + { + "user": "jvdp1", + "date": "2021-01-18 17:30:06+00:00", + "text": "Thank you @Jim-215-Fisher for this PR. I have no additional comments for now.\n@ivan-pi @milancurcic any other comments? If not, I suggest that we mege this PR as is. So we can move to the next one associated to this PR. Are you ok with that?" + }, + { + "user": "ivan-pi", + "date": "2021-01-18 18:07:23+00:00", + "text": "I agree. +1 to merge and move to the next pull request." } ] }, @@ -430,6 +1127,31 @@ "user": "arjenmarkus", "date": "2020-12-22 07:53:45+00:00", "text": "Yes, my remark also reflects my personal grievances against those smart\naleck spelling checkings.\n\nOp ma 21 dec. 2020 om 17:25 schreef Milan Curcic :\n\u2026\n Just one remark: \"initialise\" is quite acceptable according to a\n dictionary I checked (even though it is UK spelling).\n\n It is, it's why I scolded the ReviewDog. :) I think we can just ignore it.\n\n \u2014\n You are receiving this because you authored the thread.\n Reply to this email directly, view it on GitHub\n <#269 (comment)>,\n or unsubscribe\n \n ." + }, + { + "user": "arjenmarkus", + "date": "2021-01-04 15:21:59+00:00", + "text": "Thanks for the comments - I will give a more detailed reply later.\n\nOp zo 3 jan. 2021 om 17:58 schreef Sebastian Ehlert <\nnotifications@github.com>:\n\u2026\n ***@***.**** commented on this pull request.\n\n I looked over the API documentations and left a few comments on the API\n design. Mainly the special positions list_head and list_end are\n inconsistent in my opinion.\n ------------------------------\n\n In doc/specs/stdlib_stringlist.md\n <#269 (comment)>:\n\n > +call list%insert( list_head, \"The first string\" )\n\n +call list%insert( 20, \"The last string\" )\n\n +\n\n +write(*,*) 'The last: ', list%get(list_end)\n\n +write(*,*) 'Beyond that: ', list%get(30)\n\n +```\n\n +The special position `list_head` represents the position *before* the first element. Likewise,\n\n +the special position `list_end` represents the position of the *last* element. You can\n\n +use these positions to insert a string before the first string that is already in the\n\n +list or to insert after the last string that has been inserted.\n\n +\n\n +If you specify a position beyond the last, the `list%get()` method simply returns an empty\n\n +string.\n\n +\n\n +You can also specify *negative* positions, but they are interpreted as going back from the\n\n +last inserted string. If you need the last but one string, you can do so innthis way:\n\n\n \u2b07\ufe0f Suggested change\n\n -last inserted string. If you need the last but one string, you can do so innthis way:\n\n +last inserted string. If you need the last but one string, you can do so in this way:\n\n\n ------------------------------\n\n In doc/specs/stdlib_stringlist.md\n <#269 (comment)>:\n\n > +The special position `list_head` represents the position *before* the first element. Likewise,\n\n +the special position `list_end` represents the position of the *last* element. You can\n\n\n This feels inconsistent to me. list_head represents an element outside of\n the list, while list_end represents an element in the list. I would\n prefer either having both special indices refer to elements inside or\n outside the list, but not mixed.\n ------------------------------\n\n In doc/specs/stdlib_stringlist.md\n <#269 (comment)>:\n\n > +write(*,*) 'The last: ', list%get(list_end)\n\n +write(*,*) 'Beyond that: ', list%get(30)\n\n +```\n\n +The special position `list_head` represents the position *before* the first element. Likewise,\n\n +the special position `list_end` represents the position of the *last* element. You can\n\n +use these positions to insert a string before the first string that is already in the\n\n +list or to insert after the last string that has been inserted.\n\n +\n\n +If you specify a position beyond the last, the `list%get()` method simply returns an empty\n\n +string.\n\n +\n\n +You can also specify *negative* positions, but they are interpreted as going back from the\n\n +last inserted string. If you need the last but one string, you can do so innthis way:\n\n +\n\n +```fortran\n\n +write(*,*) 'The last but onw: ', list%get(list_end-1)\n\n\n \u2b07\ufe0f Suggested change\n\n -write(*,*) 'The last but onw: ', list%get(list_end-1)\n\n +write(*,*) 'The last but one: ', list%get(list_end-1)\n\n\n ------------------------------\n\n In doc/specs/stdlib_stringlist.md\n <#269 (comment)>:\n\n > +\n\n +#### Class\n\n +\n\n +Function\n\n +\n\n +#### Arguments\n\n +\n\n +`list`: the stringlist variable to retrieve a string from\n\n +\n\n +`string`: the string to be found in the list\n\n +\n\n +`back` (optional): logical argument indicating the first occurrence should be returned (`false`) or the last (`true`)\n\n +\n\n +#### Result value\n\n +\n\n +The result is either the index of the string in the list or -1 if the string was not found\n\n\n Why is -1 chosen here? The intrinsics index/scan/verify return 0 on\n \u201cfailure\u201d rather than -1.\n ------------------------------\n\n In doc/specs/stdlib_stringlist.md\n <#269 (comment)>:\n\n > +\n\n +#### Class\n\n +\n\n +Function\n\n +\n\n +#### Arguments\n\n +\n\n +`list`: the stringlist variable to retrieve a string from\n\n +\n\n +`substring`: the substring in question\n\n +\n\n +`back` (optional): logical argument indicating the first occurrence should be returned (`false`) or the last (`true`)\n\n +\n\n +#### Result value\n\n +\n\n +The result is either the index of the string in the list or -1 if the string was not found\n\n\n Same question on the return code as with index.\n ------------------------------\n\n In doc/specs/stdlib_stringlist.md\n <#269 (comment)>:\n\n > +\n\n +Experimental\n\n +\n\n +#### Description\n\n +\n\n +Concatenate a list with a string, a list of strings or a plain array\n\n +\n\n +#### Syntax\n\n +\n\n +`concatenatedlist = list // string`\n\n +\n\n +`concatenatedlist = string // list`\n\n +\n\n +#### Class\n\n +\n\n +Assignment\n\n\n \u2b07\ufe0f Suggested change\n\n -Assignment\n\n +Operator\n\n\n \u2014\n You are receiving this because you authored the thread.\n Reply to this email directly, view it on GitHub\n <#269 (review)>,\n or unsubscribe\n \n ." + }, + { + "user": "arjenmarkus", + "date": "2021-01-06 08:13:33+00:00", + "text": "I have been thinking about the use of integers to indicate the head and the end of the list. Clearly this is a bad design choice, as there is no way to make it unambiguous. My current idea is to use instead a special derived type, something along the lines:\ntype list_special_index_type\n logical :: head = .true.\n integer :: offset = 0\nend type\nwith appropriate operations + and - for defining an offset. Then there can be no confusion about the meaning.\n(Of course, a bit more work, but that is limited :))." + }, + { + "user": "epagone", + "date": "2021-01-06 10:35:01+00:00", + "text": "I have been thinking about the use of integers to indicate the head and the end of the list. Clearly this is a bad design choice, as there is no way to make it unambiguous. My current idea is to use instead a special derived type, something along the lines:\ntype list_special_index_type\n logical :: head = .true.\n integer :: offset = 0\nend type\nwith appropriate operations + and - for defining an offset. Then there can be no confusion about the meaning.\n(Of course, a bit more work, but that is limited :)).\n\nI really like this solution: it seems to address at once most of the shortcomings that I have identified. I had a very limited amount of time to play with it but the current implementation seems to work already very well.\nThe aspects that I did not like much.\n\nAs already commented in the related issue, I believe that the sorting method should not be part of this PR but it should be included in the stdlib sorting module and stdlib_stringlist should depend on it.\nI would prefer to encapsulate into the derived type the control variables (e.g. list_head, list_end in the current implementation, head and offset in the future one) to not \"pollute\" the user namespace. It is a bit more verbose but I think it's a better choice.\nI do not understand fully the need to hard code the initial_size = 20 parameter to a somewhat arbitrary value that also \"pollutes\" the user namespace (see previous point).\nI personally believe that the only way to let the user add an element to an already \"initialised\" list should be with the append method. Any other attempt to add new elements \"out of bounds\" should return an error. Quite strict, I know, but I think it's safer.\n\nThanks @arjenmarkus for doing this!" + }, + { + "user": "ivan-pi", + "date": "2021-01-10 17:29:27+00:00", + "text": "@arjenmarkus I suspect you initiated this project in an old branch. The stdlib_ascii module is the old version you already modified (and is now in the master branch). The solution would be to rebase against the master branch." + }, + { + "user": "arjenmarkus", + "date": "2021-01-11 10:59:53+00:00", + "text": "Is it? I recently did a rebase. Okay, I will have to check.\n\nOp zo 10 jan. 2021 om 18:29 schreef Ivan Pribec :\n\u2026\n @arjenmarkus I suspect you initiated\n this project in an old branch. The stdlib_ascii module is the old version\n you already modified (and is now in the master branch). The solution would\n be to rebase against the master branch.\n\n \u2014\n You are receiving this because you were mentioned.\n Reply to this email directly, view it on GitHub\n <#269 (comment)>,\n or unsubscribe\n \n ." } ] }, @@ -529,6 +1251,41 @@ "user": "jvdp1", "date": "2020-12-31 15:49:45+00:00", "text": "Thank you @arjenmarkus for the implementation. I will try to have a look at it next week.\n\nConcerning the sorting routines, should not these be a more generic part of stdlib and then applied to this case as only one of the possible applications? What do you think @jvdp1 @certik @milancurcic?\n\n@epagone I think that sorting algoritghms are definetely in the scope of stdlib, and are needed at several places (e.g., for sparse matrices, computation of median,...). Therefore sorting procedures should have their own module. See some discussions around sorting algorithms and implementations in #98." + }, + { + "user": "ivan-pi", + "date": "2021-01-08 16:38:06+00:00", + "text": "Thanks @arjenmarkus! I hope I'll be able to test it a little bit at some point.\nConcerning the sorting routines, should not these be a more generic part of stdlib and then applied to this case as only one of the possible applications? What do you think @jvdp1 @certik @milancurcic?\n\nAs @jvdp1 has mentioned already, I think we all agree sorting routines are in the scope of stdlib. But I also think we should not shy away from providing specific sort methods which are private to the module in development (in this case list of strings). This could be either due to using a specialized algorithm more suitable than a generic one, or simply as a temporary building block." + }, + { + "user": "epagone", + "date": "2021-01-08 16:57:15+00:00", + "text": "As @jvdp1 has mentioned already, I think we all agree sorting routines are in the scope of stdlib. But I also think we should not shy away from providing specific sort methods which are private to the module in development (in this case list of strings). This could be either due to using a specialized algorithm more suitable than a generic one, or simply as a temporary building block.\n\n@ivan-pi I understand and agree with the rationale and the general principle. However, is this the case? I am far from an expert of sorting algorithms, but to my eyes the one in the relevant PR does not seem to be tailored to list of strings (except for the data type)." + }, + { + "user": "ivan-pi", + "date": "2021-01-08 19:36:56+00:00", + "text": "I am not an expert for sorting algorithms either. I've tried to compile a list of available routines in #98. I've had a look at the implementation from @arjen. If we were to generalize the sorting routine and move it out of the string list module, we would need to:\n\nAgree to introduce string_type as the suggested OO string type (similar to varying_string or the many string types defined by others; see #69)\nProvide a generic argsort routine which takes an array of type(string_type) and returns the indices that would sort an array." + }, + { + "user": "epagone", + "date": "2021-01-08 19:45:52+00:00", + "text": "I am not an expert for sorting algorithms either. I've tried to compile a list of available routines in #98. I've had a look at the implementation from @arjen. If we were to generalize the sorting routine and move it out of the string list module, we would need to:\n1. Agree to introduce `string_type` as the suggested OO string type (similar to `varying_string` or the many string types defined by others; see #69)\n\n\nI see this as an advantage to keep the ball rolling also on the front of stdlib string types. We can always roll back at a later time if, for some reason, this implementation is unsuitable: we are still in \"experimental mode\".\n\n2. Provide a generic `argsort` routine which takes an array of `type(string_type)` and returns the indices that would sort an array.\n\n\nI don't know if this would be a lot of work but to me it does not seem super-complicated." + }, + { + "user": "arjenmarkus", + "date": "2021-01-25 19:59:26+00:00", + "text": "I am making progress with the implementation of a better way to specify the indices and en passant with the various versions to be supported. This made me think of some design questions for which I would like some advice:\n\nI want to avoid error conditions, so whatever index you give, beyond the end OR beyond the beginning it always succeeds (modulo memory issues). An alternative is to set an error flag when especially negative indices are passed in.\nHandling negative indices (to the \"left\" of the head of the list) requires a choice: I first thought of handling that as an implicit shift to the right of all other entries, so that the most negative index becomes 1. and all the other entries simply shift. But that does not feel good. An alternative could be to simply extend the list to the left, so that\ncall list%insert( 1, \"A\")\ncall list%insert( -10, 'B' )\nwrite(*,*) list%get(-10)\nproduces \"B\".\nInserting a string at position n will shift all strings with index >n to the right. But if we implement negative indices like above, it might make sense to have an operation to shift them to the left as well.\n\nOf course, negative indices may be not so useful in the first place and I should not put too much effort in that feature. If so, the alternative of flagging an error is probably best.\nWhat do you think?" + }, + { + "user": "certik", + "date": "2021-01-25 22:21:23+00:00", + "text": "This is the behavior on Python:\n>>> a = [1, 2, 3]\n>>> a[2]\n3\n>>> a[0]\n1\n>>> a[-1]\n3\n>>> a.insert(-10, 4)\n>>> a\n[4, 1, 2, 3]\n\nIt looks like it prepends it at the beginning? Notice that a negative index wraparounds from the right when you do a[-1]." + }, + { + "user": "arjenmarkus", + "date": "2021-01-27 15:22:32+00:00", + "text": "Hm, negative indices start at the end and when you get outside the list the\nitem is either inserted at the start (negative indices) or at the end.\n\nWell, that is an acceptable model, as well, I suppose :). Perhaps even more\nthan trying to accommodate for inserting in arbitrary places. I can\ncertainly do that.\n\nOp ma 25 jan. 2021 om 23:21 schreef Ond\u0159ej \u010cert\u00edk >> a = [1, 2, 3]\n >>> a[2]\n 3\n >>> a[0]\n 1\n >>> a[-1]\n 3\n >>> a.insert(-10, 4)\n >>> a\n [4, 1, 2, 3]\n\n It looks like it prepends it at the beginning?\n\n \u2014\n You are receiving this because you were mentioned.\n Reply to this email directly, view it on GitHub\n <#268 (comment)>,\n or unsubscribe\n \n ." } ] }, @@ -900,6 +1657,11 @@ "user": "urbanjost", "date": "2020-12-11 22:52:42+00:00", "text": "Thanks, but I can't at this time. I made a small fpm package with a seed anyone pursuing this is welcome to use with no restrictions.\nIt is the subdirectory in miscellaneous under the directory M_input. It contains\nan input(3f) function as close to the description as I could manage with the time I have available.\ngit clone https://github.com/urbanjost/miscellaneous\ncd miscellaneous/M_input\nfpm run \nIf you use \"fpm run --compiler NAME\" you will find it is never as simple as it seems if you enter ctrl-D at the prompt for a number or enter a huge integer string like\n11111111111111111111111111111111111111111111111111111111111111111111111\n\nyou will find ifort, nvfortran, and gfortran all handle it differently. It should handle Inf and NaN more robustly, but I have seen other parts of stdlib that should be able to handle that so I did not duplicate it here. It would be useful if a version of stdlib was available as a simple fpm(1) package.\nHope it is helpful, but I have to opt out on this one. Having had a routine like this for a long time I find I use it mostly in a quick prototype; but I use the getline(3f) routine that it uses a lot, actually." + }, + { + "user": "urbanjost", + "date": "2021-01-10 21:16:38+00:00", + "text": "Deleting the example github repository, so thought I would put a copy of the alpha version here for anyone interested in the future.\nmodule M_input\nuse,intrinsic :: iso_fortran_env, only : stdin=>input_unit, stderr=>error_unit\nimplicit none\nprivate\npublic :: getline\npublic :: input\ninteger,parameter,private :: dp=kind(0.0d0)\ninterface input\n module procedure rd_character\n module procedure rd_integer\n module procedure rd_real\n module procedure rd_dp\nend interface input\ncontains\n!>NAME\n!> getline(3f) - [M_input] read line from specified LUN into allocatable string\n!> up to line length limit\n!> (LICENSE:PD)\n!>\n!>SYNTAX\n!> function getline(line,lun) result(ier)\n!>\n!> character(len=:),allocatable,intent(out) :: line\n!> integer,intent(in),optional :: lun\n!> integer,intent(out) :: ier\n!>\n!>DESCRIPTION\n!> Read a line of any length up to programming environment maximum\n!> line length. Requires Fortran 2003+.\n!>\n!> It is primarily expected to be used when reading input which will\n!> then be parsed.\n!>\n!> The input file must have a PAD attribute of YES for the function\n!> to work properly, which is typically true.\n!>\n!> The simple use of a loop that repeatedly re-allocates a character\n!> variable in addition to reading the input file one buffer at a\n!> time could (depending on the programming environment used) be\n!> inefficient, as it could reallocate and allocate memory used for\n!> the output string with each buffer read.\n!>\n!>OPTIONS\n!> LINE line read. Trailing spaces are significant.\n!> LUN optional LUN (Fortran logical I/O unit) number. Defaults\n!> to stdin.\n!>RETURNS\n!> IER zero unless an error occurred. If not zero, LINE returns the\n!> I/O error message.\n!>\n!>EXAMPLE\n!> Sample program:\n!>\n!> program demo_getline\n!> use,intrinsic :: iso_fortran_env, only : stdin=>input_unit\n!> use M_input, only : getline\n!> implicit none\n!> character(len=:),allocatable :: line\n!> open(unit=stdin,pad='yes')\n!> INFINITE: do while (getline(line)==0)\n!> write(*,'(a)')'['//line//']'\n!> enddo INFINITE\n!> if(is_iostat_end(ier))stop 'end of file'\n!> write(*,'(*(g0))')'ended on ',trim(line)\n!> end program demo_getline\n!>\n!>LICENSE\n!> MIT License\n\nfunction getline(line,lun) result(ier)\nimplicit none\n\n!>> getline(3f): read line from LUN into allocatable string up to length limit\n\ncharacter(len=:),allocatable,intent(out) :: line\ninteger,intent(in),optional :: lun\ninteger :: ier\ncharacter(len=256) :: message\n\ninteger,parameter :: buflen=1024\ncharacter(len=:),allocatable :: line_local\ncharacter(len=buflen) :: buffer\ninteger :: isize\ninteger :: lun_local\n\n line_local=''\n ier=0\n if(present(lun))then\n lun_local=lun\n else\n lun_local=stdin\n endif\n open(lun_local,pad='yes')\n\n INFINITE: do\n ! read characters from line and append to result\n message=''\n read(lun_local,iostat=ier,fmt='(a)',advance='no',size=isize,&\n & iomsg=message) buffer\n ! read next buffer (might use stream I/O for files\n\n ! other than stdin so system line limit is not limiting\n if(isize.gt.0)line_local=line_local//buffer(:isize)\n ! append what was read to result\n if(is_iostat_eor(ier))then\n !if hit EOR reading is complete unless backslash ends the line\n ier=0\n ! hitting end of record is not an error for this routine\n exit INFINITE\n ! end of reading line\n elseif(ier.ne.0)then\n ! end of file or error\n line=trim(message)\n exit INFINITE\n endif\n enddo INFINITE\n line=line_local\nend function getline\n\n!>NAME\n!>input(3f) - [M_input] ask for string from standard input with\n!> user-definable prompt\n!>(LICENSE:PD)\n!>\n!> function input(prompt,default) result(strout)\n!>\n!> character(len=*),intent(in) :: prompt\n!>\n!> Any one of\n\n!> character(len=*),intent(in),optional :: default\n!> integer,intent(in),optional :: default\n!> real,intent(in),optional :: default\n!> integer,parameter :: dp=kind(0.0d0)\n!> real(kind==dp),intent(in),optional :: default\n!>\n!> character(len=:),allocatable,intent(out) :: strout\n!>\n!>DESCRIPTION\n!> Ask for string or value from standard input with user-definable prompt\n!>\n!> Do not use the function in an I/O statement as not all versions of\n!> Fortran support this form of recursion. Numeric values may be input\n!> in standard INTEGER, REAL, and DOUBLEPRECISION formats.\n!>\n!>OPTIONS\n!> prompt Prompt string; displayed on same line as input is read from\n!> default default answer on carriage-return. The type of the default\n!> determines the type of the output.\n!>RETURNS\n!> strout returned string or value. If an end-of-file or system error\n!> is encountered the null character is returned when returning\n!> a string, or a \"Nan\" numeric value for REAL values or\n!> HUGE(0) for an INTEGER.\n!>EXAMPLE\n!> Sample program:\n!>\n!> program demo_input\n!> use M_input, only : input\n!> character(len=:),allocatable :: mystring\n!> integer,parameter,private :: dp=kind(0.0d0)\n!> real(kind=dp) :: d\n!> real :: r\n!> integer :: i\n!>\n!> INFINITE: do\n!> mystring=input('Enter string or \"STOP\":',default='Today')\n!> if(mystring.eq.'STOP')stop\n!> i=input('Enter integer:',default=huge(0))\n!> r=input('Enter real:',default=huge(0.0))\n!> d=input('Enter double:',default=huge(0.0d0))\n!>\n!> write(*,'(*(g0))')'I=',i,' R=',r,' D=',d,' MYSTRING=',mystring\n!> enddo INFINITE\n!>\n!> end program demo_input\n!>\n!>LICENSE\n!> MIT License\n\nfunction rd_character(prompt,default,iostat) result(strout)\nimplicit none\n\n!>> rd_character(3fp): ask for string with user-definable prompt\n\ncharacter(len=*),intent(in) :: prompt\ncharacter(len=*),intent(in),optional :: default\ninteger,optional,intent(out) :: iostat\ncharacter(len=:),allocatable :: strout\n\ninteger :: len_prompt\ninteger :: iostat_local\n!>*!integer :: idum\n\n len_prompt=len(prompt)\n iostat_local=0\n\n if(len_prompt.gt.0)then\n write(*,'(a)',advance='no')prompt\n else\n write(*,'(\"Enter value>\")',advance='no')prompt\n endif\n iostat_local=getline(strout,stdin)\n if(iostat_local.ne.0)then\n !*!attempt to work-around nvfortran and gfortran bug|unexpected feature\n !*! once a ctrl-D |EOF is encountered gfortran|nvfortran do not allow subsequent reads\n !*!if(is_iostat_end(iostat_local))rewind(stdin,iostat=idum)\n !*!if(is_iostat_end(iostat_local))open(stdin,pad='yes')\n if(is_iostat_end(iostat_local))backspace stdin\n strout=char(0)\n elseif(present(default).and.strout.eq.'')then\n strout=default\n endif\n if(present(iostat))iostat=iostat_local\nend function rd_character\n\nfunction nan()\ncharacter(len=3),save :: nanstring='NaN'\nreal(kind=dp) :: nan\n read(nanstring,*)nan\nend function nan\n\nfunction rd_dp(prompt,default,iostat) result(dvalue)\nimplicit none\n\n!>> rd_dp(3fp): ask for DOUBLE number with user-definable prompt\n\nreal(kind=dp) :: dvalue\ncharacter(len=*),intent(in) :: prompt\nreal(kind=dp),intent(in) :: default\ninteger,intent(out),optional :: iostat\n\ncharacter(len=:),allocatable :: strout\ncharacter(len=256) :: message\ninteger :: iostat_local\n\n iostat_local=0\n strout=rd_character(prompt,iostat=iostat_local)\n if(iostat_local.ne.0)then\n write(*,'(*(g0))')'*input* failed to read from stdin:',strout\n dvalue=nan()\n elseif(strout.eq.'')then\n dvalue=default\n else\n read(strout,*,iostat=iostat_local,iomsg=message)dvalue\n if(iostat_local.ne.0)then\n write(stderr,'(*(g0))') &\n & '*input* input ['//strout//'] failed as a number:', &\n & trim(message)\n dvalue=nan()\n endif\n endif\n if(present(iostat))iostat=iostat_local\nend function rd_dp\n\nfunction rd_real(prompt,default,iostat) result(rvalue)\nimplicit none\n!>> rd_real(3fp): ask for REAL number input with user-definable prompt\nreal :: rvalue\nreal(kind=dp) :: dvalue\ncharacter(len=*),intent(in) :: prompt\nreal,intent(in) :: default\ninteger,intent(out),optional :: iostat\n !*! what about Nan, Inf, -Inf? Likely place for compiler bugs\n dvalue=rd_dp(prompt,dble(default),iostat)\n if(dvalue.ne.dvalue)then\n write(stderr,'(*(g0))') &\n & '*input* value [',dvalue,'] is indefinite'\n rvalue=huge(0.0)\n else\n rvalue=real(dvalue)\n endif\nend function rd_real\n\nfunction rd_integer(prompt,default,iostat) result(ivalue)\nimplicit none\n!>> rd_integer(3fp): ask for INTEGER number with user-definable prompt\ninteger :: ivalue\nreal(kind=dp) :: dvalue\ncharacter(len=*),intent(in) :: prompt\ninteger,intent(in) :: default\ninteger,intent(out),optional :: iostat\n dvalue=rd_dp(prompt,dble(default),iostat)\n !*! what about Nan, Inf, -Inf?\n if(dvalue.ne.dvalue)then\n write(stderr,'(*(g0))') &\n & '*input* value [',dvalue,'] is indefinite'\n ivalue=huge(0)\n elseif(dvalue.gt.huge(0))then\n write(stderr,'(*(g0))') &\n & '*input* value [',dvalue,'] greater than ', huge(0)\n ivalue=huge(0)\n elseif(dvalue.lt.1-huge(0))then\n write(stderr,'(*(g0))') &\n & '*input* value [',dvalue,'] less than ', 1-huge(0)\n ivalue=1-huge(0)\n else\n ivalue=nint(dvalue)\n endif\nend function rd_integer\n\nend module M_input" } ] }, @@ -2128,6 +2890,21 @@ "user": "David-Duffy", "date": "2020-12-22 23:53:03+00:00", "text": "\"a generalized version\" - yes, I had been looking at their C++ code, but dreading how how long it would take to fully test a Fortran port. One reason Boost etc are using time-tested algorithms rather than bleeding edge," + }, + { + "user": "rryley", + "date": "2021-01-15 13:42:56+00:00", + "text": "The R documents provide a listing of the available probability distributions. Considering another, independent request for better interop with R, it might save some effort to follow the R conventions as much as possible.\nHere is the list: https://cran.r-project.org/doc/manuals/r-release/R-intro.html#Probability-distributions\nIs there another discussion on what should be in the statistical methods portion of the Fortran Standard Library? The GNU Scientific Library stats section is limited. I also think the R stats package provides a good model of what should be included, but that might be too ambitious. If you have R installed, open up the REPL and type:\nlibrary(help=\"stats\") for a list of what is available." + }, + { + "user": "jvdp1", + "date": "2021-01-15 13:50:23+00:00", + "text": "Is there another discussion on what should be in the statistical methods portion of the Fortran Standard Library?\n\n@rryley Different PRs were already submitted regarding probability distributions (#271, #272, #273, #26, #278, #286, ...). It seems some of them cover the R probability distributions." + }, + { + "user": "peteroupc", + "date": "2021-01-22 03:35:11+00:00", + "text": "I want to draw attention in this issue thread to algorithms for geometric and binomial variates published from 2013 through 2015, by Bringmann and colleagues as well as Farach-Colton/Tsai, which were designed especially for small p parameters (geometric) or large numbers of trials (binomial).\nSee my notes on samplers for both distributions.\nREFERENCES:\n\nBinomial: K. Bringmann, F. Kuhn, et al., \u201cInternal DLA: Efficient Simulation of a Physical Growth Model.\u201d In: Proc. 41st International Colloquium on Automata, Languages, and Programming (ICALP'14), 2014.\nBinomial: Farach-Colton, M. and Tsai, M.T., 2015. Exact sublinear binomial sampling. Algorithmica 73(4), pp. 637-651.\nGeometric: Bringmann, K., and Friedrich, T., 2013, July. Exact and efficient generation of geometric random variates and random graphs, in International Colloquium on Automata, Languages, and Programming (pp. 267-278)." } ] }, @@ -2413,6 +3190,21 @@ "user": "certik", "date": "2020-09-16 14:35:16+00:00", "text": "I see. I feel this must go into the API that is above the low level API.\nI see his architecture all over many of the other issues in stdlib. In this case, the API layers as I can see them could be (from lowest to highest):\n\n\nlowest level: the goal is to output the correct ANSI string without having to deal with ansi sequences directly, but there should be no over head and it should be as simple as possible. The two proposed solutions would both work:\n\nprint *, fg_red, bg_green, bold, 'Hello!', reset\nprint *, color('Hello!', fg=fg_red, bg=bg_green, style=style_bold) (notice the fg_red is not a string \"red\" to avoid string parsing / comparison, and just efficiently output the ANSI sequence)\n\n\n\nhigher level: a function color that can work in many ways, output both ANSI or HTML output and allows to turn off colors\n\n\nhigh level: some intermediate representation (XML) that can be parsed into, and then manipulated to any output (HTML, ANSI, latex, ...)" + }, + { + "user": "brocolis", + "date": "2021-01-29 18:06:01+00:00", + "text": "It would be nice to have some sort of pre-alpha version of this module in stdlib. I'd certainly use it.\nI believe many programmers don't use colors, because colors are not cheap. He has to find a third party library, figure how to install and use. This process is not always easy.\nWriting use stdlib_color and instantly get beautiful output on any platform is a good idea, imho." + }, + { + "user": "urbanjost", + "date": "2021-01-30 02:02:34+00:00", + "text": "I was hoping a few people would try it via fpm or even GPF and bounce around some ideas and firm it up before trying to go straight to stdlib. It is very easy to access it from fpm. That has not been happening so perhaps a more direct approach would be better. There are a number of stdlib projects (sort, split, LAPACK interface, ...) that I think are occupying a lot of resources and I did not want things to get even more fragmented and I was hoping some other things that would make this better (some system routines like ISATTY, Regular Expressions, ...) would emerge quickly that would make this simpler. Would you find one interface style preferable? Would other options like cursor positioning (\"curses\" type functions) be something you want too or should we just look at color? To use ANSI in-line color it is really useful to be able to use the ANSI query strings to detect color support, etc. and that is hard to do without a C interface to raw mode and so far stdlib has been avoiding such things, which is another limiting feature. Maybe just keeping it simple and doing basic text attributes really is the starting point and all that can come later. I have some old (really old) basic color conversion routines that might be useful for allowing HLS color models as a supplement for RGB values (I find HLS much more intuitive myself)." + }, + { + "user": "brocolis", + "date": "2021-01-30 21:02:44+00:00", + "text": "Hi @urbanjost . I think you are right. I've tried M_escape with fpm and it works beautifuly on Windows. Yes, I use only basic color formatting (don't need cursor positioning).\nIt seems that the only open question is the redirection issue pointed out above." } ] }, @@ -4049,6 +4841,36 @@ "user": "awvwgk", "date": "2020-12-29 15:20:36+00:00", "text": "I just tried to use stdlib as subproject in CMake and it is in fact currently impossible. I collected a patch for this in #284." + }, + { + "user": "awvwgk", + "date": "2021-01-05 17:45:42+00:00", + "text": "I created a template project using stdlib in CMake at https://github.com/awvwgk/stdlib-cmake-example, if there is interest I can transfer it to the @fortran-lang organization." + }, + { + "user": "milancurcic", + "date": "2021-01-05 17:58:21+00:00", + "text": "\ud83d\udc4d for fortran-lang/stdlib-cmake-example." + }, + { + "user": "awvwgk", + "date": "2021-01-05 18:08:45+00:00", + "text": "Looks like I cannot transfer the repo because I'm missing permissions in fortran-lang." + }, + { + "user": "milancurcic", + "date": "2021-01-05 18:11:48+00:00", + "text": "Okay, that will be easy to fix, but let's wait to hear from @certik @jvdp1 @ivan-pi @everythingfunctional and any others." + }, + { + "user": "jvdp1", + "date": "2021-01-05 18:27:41+00:00", + "text": "Thank you @awvwgk fr this proposition.\nI think it is a good idea to move this in fortran-lang. When fpm will be ready to use stdlib, it will give a complete view on how to integrate easily stdlib with different tools. Some comments in the README of stdlib should be then probably added to point the users to this example." + }, + { + "user": "milancurcic", + "date": "2021-01-12 17:16:16+00:00", + "text": "With no objections, stdlib-cmake-example has moved to fortran-lang/stdlib-cmake-example.\nThanks to @awvwgk for making it." } ] }, @@ -9120,6 +9942,11 @@ "user": "scivision", "date": "2020-01-27 19:40:54+00:00", "text": "NAG could require CMake 3.16.3 like:\nif(CMAKE_Fortran_COMPILER_ID STREQUAL NAG)\n cmake_policy(VERSION 3.16.3)\nendif()\nwhile allowing other compilers to use older CMake" + }, + { + "user": "awvwgk", + "date": "2021-01-16 12:50:16+00:00", + "text": "I can report a successful build with NAG 7.0 and CMake 3.16 after a minimal patch\ndiff --git a/src/stdlib_bitsets.fypp b/src/stdlib_bitsets.fypp\nindex ad52517..f1f204d 100644\n--- a/src/stdlib_bitsets.fypp\n+++ b/src/stdlib_bitsets.fypp\n@@ -2006,7 +2006,7 @@ module stdlib_bitsets\n \n end interface operator(<=)\n \n- interface error_handler\n+ interface\n module subroutine error_handler( message, error, status, &\n module, procedure )\n character(*), intent(in) :: message\n@@ -2015,7 +2015,7 @@ module stdlib_bitsets\n character(*), intent(in), optional :: module\n character(*), intent(in), optional :: procedure\n end subroutine error_handler\n- end interface error_handler\n+ end interface\n \n contains\n \nUnfortunately the tests still fail\nThe following tests FAILED:\n\t 13 - stdlib_logger (Child aborted)\n\t 15 - corr (Child aborted)\n\t 16 - cov (Child aborted)\n\t 17 - mean (Child aborted)\n\t 18 - moment (Child aborted)\n\t 19 - rawmoment (Child aborted)\n\t 20 - var (Child aborted)\n\t 21 - varn (Child aborted)\n\nTest log: LastTest.log.gz" } ] }, @@ -9588,6 +10415,11 @@ "user": "jacobwilliams", "date": "2020-01-13 04:06:28+00:00", "text": "Here are some of mine:\n\nhttps://github.com/jacobwilliams/fortran-search-and-sort\nhttps://github.com/jacobwilliams/stringsort (see also here about natural sorting of strings)." + }, + { + "user": "ivan-pi", + "date": "2021-01-08 19:19:30+00:00", + "text": "A few more:\nSorting routines in various libraries\n\nACM\n\nAlgorithm 402 (version linked here is part of CLAWPACK)\n\n\nHSL\n\nKB07\n\n\nIBM Engineering and Scientific Subroutine Library (ESSL)\n\nISORT, SSORT, and DSORT\nISORTX, SSORTX, and DSORTX\nISORTS, SSORTS, and DSORTS\n\n\nIMSL\n\nSORT_REAL\nSVRGN\nSVRGP\nSVIGN\nSVIGP\nSVRBN\nSVRBP\nSVIBN\nSVIBP\n\n\nLAPACK\n\nslasrt\ndlasrt\n\n\nNAG\n\nSearching and sorting\n\n\nNumerical Recipes\nORDERPACK\nSLATEC (search for the routines ipsort, isort, spsort, ssort, dpsort, dsort, and hpsort)\n\nVarious user routines\n\nSorting in Fortran by Michael Rutter\nsorting programs in Fortran by Jean-Pierre Moreau\nSorting by John Mahaffy\nFORTRAN Bubble Sort Speghetti Code by Thomas W Bennet\nMULTI-THREADED SORT by Bal Software\nquicksort by Tim Hoar\nlcpsort - Module for sorting and merging ASCII text strings by N. Shamsundar, University of Houston (a C version by the same author is provided here)\nqsort_inline by Joseph M. Krahn at FortranWiki\nCoding Fortran: a sorting module by Michael Wirth\nParsing and Sorting with Fortran by Mike Rourke\nquicksort by @t-nissie and a modified version by @1AdAstra1\nSelection sort by C.-K. Shene\nLexicalSort by unknown author from comp.lang.fortran newsgroup\nAncora sul sort di \u2018Compilati vs. Interpretati\u2019 \u2013 2; blog post comparing various Fortran sort implementations (in Italian!)\nM_sort by @urbanjost\nsimple_fortran_argsort by @Astrokiwi\nBubble Sort (WikiBooks)\nGnome sort (Rosetta Code)\nInsertion sort (Rosetta Code)\n\nInternet forums and discussion boards\n\nordering function in Fortran (comp.lang.fortran)\nReverse quick sort in Fortran (StackExchange)\nSorting an array from lowest to greatest FORTRAN (StackExchange)\nFortran Bubble Sort Algorithm (StackExchange)\nOpen-source version of Intel Fortran sort routines (StackExchange) provided by Rafik Zurob\n\nInterfaces to C qsort\n\nOracle\nIntel Fortran\n\nPublished works\n\nBooks\n\nAlgorithms and Data Structures in F and Fortran by Robin Vowels (see chapter 1)\nIntroduction to Programming with Fortran by Ian Chivers and Jane Sleightholme (see pp. 703-732)\nFortran 90 & 95 Array and Pointer Techniques (eBook) by Loren P. Meissner (see chapters 2 and 3)\n\n\nArticles\n\nTransferable FORTRAN Subroutine for Rapid Extended Sorting\nTechnical Note: Efficient sorting routines in FORTRAN 77" } ] }, @@ -10062,6 +10894,41 @@ "user": "ivan-pi", "date": "2020-04-15 18:51:16+00:00", "text": "The NLopt library contains several constrained and unconstrained nonlinear optimization routines and comes with a Fortran interface (geared toward the old F77 style of Fortran). Ironically, many of the routines are translations of old Fortran ones to C using f2c. I find the NLopt API very intuitive and simple to use. I made a pull request with a modern Fortran interface for NLopt a while ago. Maybe it could serve as a template for the stdlib one." + }, + { + "user": "epagone", + "date": "2021-01-06 11:52:27+00:00", + "text": "Would root bracketing routines be in scope for this issue? I believe so but I am struggling to find any prior art in this area. I remember some in the Numerical Recipes (that have a well-known troublesome licence) and szero/dzero of MATH77 (that have some partial bracketing embedded to expand the initial search range).\nAre you aware of any high-quality bracketing routines available in the wild?" + }, + { + "user": "arjenmarkus", + "date": "2021-01-06 13:41:48+00:00", + "text": "Usually such algorithms and high-quality implementations can be found on\nnetlib - https://www.netlib.org/.\n\nOp wo 6 jan. 2021 om 12:52 schreef Emanuele Pagone ,\n or unsubscribe\n \n ." + }, + { + "user": "epagone", + "date": "2021-01-06 18:09:50+00:00", + "text": "Usually such algorithms and high-quality implementations can be found on netlib - https://www.netlib.org/. Op wo 6 jan. 2021 om 12:52 schreef Emanuele Pagone , or unsubscribe https://github.com/notifications/unsubscribe-auth/AAN6YR4HH6RVHPQYQYQS3B3SYRFIZANCNFSM4KC5DBQQ .\n\nI am well aware of netlib but maybe I do not know the right keywords and I couldn't find much. I will check what other languages offer." + }, + { + "user": "epagone", + "date": "2021-01-06 19:53:57+00:00", + "text": "After searching a bit about bracketing routines in other languages, I have found only one solution and another partial one.\n\nIMO Boost has the best \"packaged\" solution (untested) with the routine Bracket and Solve Root:\n\n\nbracket_and_solve_root is a convenience function that calls TOMS 748 algorithm internally to find the root of f(x). It is generally much easier to use this function rather than TOMS 748 algorithm, since it does the hard work of bracketing the root for you. It's bracketing routines are quite robust and will usually be more foolproof than home-grown routines, unless the function can be analysed to yield tight brackets.\n\nTOMS 748 is an improved Brent's method with some additional constraints (see the Notes here).\n\nJulia's find_zeros (again, untested) claims to automatically find multiple roots in a specified interval, but I couldn't find anything regarding expanding an interval to try bracket a root.\n\nTo my surprise, I could not easily find anything relevant in python." + }, + { + "user": "ivan-pi", + "date": "2021-01-06 23:54:38+00:00", + "text": "I would definitely say bracketing is part of this issue. From the looks of it, the Julia find_zeros will attempt to find multiple roots on a defined interval, by dividing that interval into sub-intervals and checking for a difference in sign. It doesn't attempt to automatically expand the interval in search of a sign difference.\nI guess the reason you cannot find much prior art is that writing at least a simple bracket search is not that hard. For a fixed interval you divide it into smaller pieces. For an open interval you expand (e.g. by multiply the interval with a constant factor). In applications where I required a root-finder my problems typically had some \"intrinsic\" brackets (e.g. related to known solution limits), or I had a good initial guess (e.g. from a previous time step), meaning I could safely use an iterative method without bracketing.\nI think the way Boost does it is most flexible, either you can call the root-finding routine directly (on your interval of choice directly), or you allow the root-finder to expand/shrink the bracket as necessary. I would be in favor of having this. I would point out however, the Boost functions is limited to monotonic functions. Such bracketing routines will also fail at double roots (e.g. like in case of the function x^2). Unfortunately, no design will be completely foolproof.\nI also found the NAG library has a solution: NAG FL Interface - C05 (Roots)\nThe IMSL Fortran library on the other hand only provides one bracketed root-finding method (Brent's) and one iterative one (M\u00fcller's method): IMSL - Chapter 7: Nonlinear equations" + }, + { + "user": "arjenmarkus", + "date": "2021-01-07 07:29:33+00:00", + "text": "Wrt Netlib: I searched for \"Newton\" and came across quite a few references.\nI also have a number of the minimisation routines developed by Mike Powell.\nProbably of less relevance for the standard library is a collection of\narticles on probabilistic optimisation algorithms (I have implemented them\nin Tcl, my other favourite language, based on these articles). I can also\ndig up some other stuff concerning root finding and the like. Mind you: it\nis one thing to have an algorithm, it is quite another to ensure that they\nalways provide an answer (or detect that things are going wrong).\n\nIt might also be a good idea to consider \"automatic differentiation\" as the\nbasis for algorithms that require (first-order) derivatives, like\nNewton-Raphson.\n\nOp do 7 jan. 2021 om 00:54 schreef Ivan Pribec :\n\u2026\n I would definitely say bracketing is part of this issue. From the looks of\n it, the Julia find_zeros will attempt to find multiple roots on a\n *defined* interval, by dividing that interval into sub-intervals and\n checking for a difference in sign. It doesn't attempt to automatically\n expand the interval in search of a sign difference.\n\n I guess the reason you cannot find much prior art is that writing at least\n a simple bracket search is not that hard. For a fixed interval you divide\n it into smaller pieces. For an open interval you expand (e.g. by multiply\n the interval with a constant factor). In applications where I required a\n root-finder my problems typically had some \"intrinsic\" brackets (e.g.\n related to known solution limits), or I had a good initial guess (e.g. from\n a previous time step), meaning I could safely use an iterative method\n without bracketing.\n\n I think the way Boost does it is most flexible, either you can call the\n root-finding routine directly (on your interval of choice directly), or you\n allow the root-finder to expand/shrink the bracket as necessary. I would be\n in favor of having this. I would point out however, the Boost functions is\n limited to monotonic functions. Such bracketing routines will also fail at\n double roots (e.g. like in case of the function x^2). Unfortunately, no\n design will be completely foolproof.\n\n I also found the NAG library has a solution: NAG FL Interface - C05\n (Roots)\n \n\n The IMSL Fortran library on the other hand only provides one bracketed\n root-finding method (Brent's) and one iterative one (M\u00fcller's method): IMSL\n - Chapter 7: Nonlinear equations\n \n\n \u2014\n You are receiving this because you commented.\n Reply to this email directly, view it on GitHub\n <#87 (comment)>,\n or unsubscribe\n \n ." + }, + { + "user": "epagone", + "date": "2021-01-07 11:22:38+00:00", + "text": "I guess the reason you cannot find much prior art is that writing at least a simple bracket search is not that hard. For a fixed interval you divide it into smaller pieces. For an open interval you expand (e.g. by multiply the interval with a constant factor).\n\nTrue, but if you want to do a proper job (that is efficient and takes into account subtle numerical problems), it's not that trivial. Have a look at the algorithm of MATH77(that only looks outside of an interval to bracket a root):\n\nWhen F1$\\times \\text{F2} > 0$ at the initial point, iterates are generated\naccording to the formula $x = x_{\\min } + (x_{\\min } - x_{\\max }) \\times\n\\rho$, where the subscript ``min\" is associated with the $(x, f)$ pair\nthat has the smallest value for $|f|$, and $\\rho $ is 8 if $r = f_{\\min\n}:/:(f_{\\max } - f_{\\min }) \\geq 8$, else $\\rho = \\max (\\kappa /4, r)$,\nwhere $\\kappa $ is a count of the number of iterations that have been\ntaken without finding $f$'s with opposite signs. If X1 and X2 have the\nsame value initially (and F1 and F2 equal F(X1)), then the next $x$ is a\ndistance $0.008 + |x_{\\min }|/4$ from $x_{\\min }$ taken toward~0. (If\nX1 = X2 = 0, the next $x$ is $-$.008.)\n\nIt is a bit like coding on your own the scalar root finding method: it's not that hard, but to do it properly it's much harder.\n\nIn applications where I required a root-finder my problems typically had some \"intrinsic\" brackets (e.g. related to known solution limits), or I had a good initial guess (e.g. from a previous time step), meaning I could safely use an iterative method without bracketing.\n\nMe too...in some cases, but not all.\n\nI think the way Boost does it is most flexible, either you can call the root-finding routine directly (on your interval of choice directly), or you allow the root-finder to expand/shrink the bracket as necessary. I would be in favor of having this. I would point out however, the Boost functions is limited to monotonic functions. Such bracketing routines will also fail at double roots (e.g. like in case of the function x^2). Unfortunately, no design will be completely foolproof.\n\nAgreed\n\nI also found the NAG library has a solution: NAG FL Interface - C05 (Roots)\nThe IMSL Fortran library on the other hand only provides one bracketed root-finding method (Brent's) and one iterative one (M\u00fcller's method): IMSL - Chapter 7: Nonlinear equations\n\nNice, thanks." } ] }, diff --git a/community/github_stats_data/data-j3-fortran-fortran_proposals.json b/community/github_stats_data/data-j3-fortran-fortran_proposals.json index 702817928..6f20d22ef 100644 --- a/community/github_stats_data/data-j3-fortran-fortran_proposals.json +++ b/community/github_stats_data/data-j3-fortran-fortran_proposals.json @@ -1,6 +1,181 @@ { "name": "j3-fortran/fortran_proposals", "issues": [ + { + "number": 194, + "user": "certik", + "date": "2021-01-19 19:23:09+00:00", + "title": "Develop criteria for inclusion of special functions", + "text": "Currently Fortran implements special functions in an inconsistent way.\nAs an example, sin, cos, exp are supported for all complex arguments. But the error function is only available for real arguments (complex implementation provided as a library). The Bessel functions are only defined for integer orders (I had to implement my own for half integer orders).\nWe should develop criteria by which to decide what special functions belong into standard Fortran, and which don't.\nThere are several ways to go about it. The three main approaches that come to my mind are listed below, there are probably others (please propose them below).\nOption 1\n\nFortran should have no special functions, but rather those should be delegated to libraries such as stdlib.\n\nAs a consequence, the Bessel functions already in Fortran should be deprecated.\nOption 2\n\nWe decide on classes of special functions to include, and we should include all (complex) variants and all parameters.\n\nAs a consequence, we should add the remaining Bessel functions, and erf for complex arguments.\nOption 3\n\nWe decide on subset of a class of special functions, based for example on what is provided by libm (part of GNU libc).\n\nThat seems to be the current approach.", + "comments": [ + { + "user": "klausler", + "date": "2021-01-19 19:37:12+00:00", + "text": "Option 4\nFortran should support correctly-rounded implementations of the special functions in table 9.1 of IEEE 754-2008, as amended or extended in later revisions. Other special functions not already in the language should be included only when strong guarantees about rounding can be supported." + }, + { + "user": "certik", + "date": "2021-01-19 19:38:14+00:00", + "text": "Here are two more ideas:\nOption 5\n\nImplement all special functions that people ask for in stdlib first. This will provide a solid (trusted) reference implementation that is being used by (hopefully) a lot of people. Then the most frequented special functions could be considered for inclusion into Fortran itself. Or perhaps left in stdlib if stdlib becomes popular.\n\nOption 6\n\nAs fpm becomes more popular, ensure good implementations of special functions are available as libraries, implemented correctly and easy to use as dependencies as fpm packages. Later on, we can consider adding them to stdlib or the Fortran standard itself.\n\n\nThe advantages of Option 5 and 6 are that they are low friction, but they provide high value: as an example, I had to implement my own implementation of Bessel functions because the (Fortran) implementation in SciPy was providing incorrect values in some cases." + } + ] + }, + { + "number": 193, + "user": "difference-scheme", + "date": "2021-01-17 18:09:28+00:00", + "title": "Allow the default constructors of derived-types to initialize private fields", + "text": "One of the most annoying restrictions in the language is that Fortran's default constructors for derived types do not always allow one to initialize the private fields of these types. That is, if one has a derived type like the following,\ntype :: AClass\n private\n class(BClass), allocatable :: b\ncontains\n procedure :: some_method_of_aclass_that_uses_b\nend type AClass\n\n\nas it happens extremely frequently in object-oriented programming, then the language will typically forbid passing some instance of BClass to the default constructor that generates objects of type AClass, e.g. the following, perfectly reasonable code, would not be allowed\nsubroutine some_other_procedure(b)\n class(BClass), intent(in) :: b\n \n ! local declaration of an object of AClass\n class(AClass), allocatable :: a\n\n ! initialization using default constructor of AClass\n a = AClass(b)\nend subroutine some_other_procedure\n\n\nif some_other_procedure is not a part of the module in which AClass is declared. One has to either\n\nremove the private access specifier from the AClass derived type, in order to be able to use the default constructor, which is unacceptable in object-oriented programming, since the latter relies critically on implementation hiding, or\nwrite a user-defined constructor (despite the obvious triviality of the above example), with all the hoop-jumping and verbosity that this involves in Fortran, like overloading the name of the derived type, etc.\nput all these declarations into the same module, which is rarely possible in practice.\n\nThe net result presently is that the object-oriented programmer has to write user-defined constructors for all but the very simplest of his classes (namely those that contain no fields at all)!\nAllowing the initialization of private components by Fortran's default constructors, even if these are called from external scoping units, would go a long way in removing some of the drudgery that the language presently imposes on object-oriented programmers.", + "comments": [ + { + "user": "FortranFan", + "date": "2021-01-19 03:26:42+00:00", + "text": "You will know Fortran is not, and likely never will be, a fully class-based, object-oriented language the way are some other programming languages e.g., Java. Limitations with adopting OO approaches in Fortran are going to remain because of how the language evolves with ISO IEC standards process, committee consensus where language bloat and resource constraints all around, particularly with compiler implementations, are a matter of major concern.\nUnder the circumstances, some verbosity with custom initialization procedures is what programmers have to author in order to workaround such aspects. What really are the issues - beyond verbosity - with this such workarounds is the question. You may find the point - oh, it's way too verbose even for trivial situations - to be insufficient to convince a committee." + }, + { + "user": "difference-scheme", + "date": "2021-01-21 20:52:47+00:00", + "text": "To answer the question \"what really are the issues - beyond verbosity - with such workarounds\":\nThe language is inconsistent.\nIt provides a single feature (the derived type) to support both the notions of \"structures\", and \"classes\" (as they are called in other languages) in a unified manner. Hence, the programmer can rightly expect that the language's main facility to construct such derived types (the default constructor) will work equally well for both these application cases, i.e. structures and classes.\nWell, it doesn't.\nIt works for structures, but not (in general) for classes (where implementation hiding is of paramount importance). I consider this a design flaw in the language, a \"wart\" as such things have been called in the past. It makes the language inconsistent, and hence nonintuitive to use, especially for newbies.\nGood, consistent design would provide a single default means to construct instances of both cases, consistent with the language's aim of offering only a single feature to support both structures and classes. It is ok if the language wishes to offer more functionality (like, e.g., user-defined constructors) than the bare minimum required by consistency, but the bare minimum (the default constructor) must work!\nSo, my proposal is essentially one of \"wart removal\", as it has been done repeatedly in the past." + }, + { + "user": "klausler", + "date": "2021-01-21 21:00:11+00:00", + "text": "What specific change are you proposing -- simply ignoring accessibility of components in a structure constructor?" + }, + { + "user": "everythingfunctional", + "date": "2021-01-21 21:13:12+00:00", + "text": "@difference-scheme , I understand that most of the time one wants a public constructor whose arguments are simply the components of my type, but if we make that public by default then I don't see how I can prevent users of some module from using and relying on it in cases where I don't want that to be the case." + }, + { + "user": "difference-scheme", + "date": "2021-01-21 21:26:49+00:00", + "text": "@klausler My aim so far was simply to point out the problem, not necessarily to show a specific way to overcome it.\nI could imagine, that simply ignoring the accessibility of components in a structure constructor might lead to a lot of trouble. This needs to be thought through by someone with much more insight into how Fortran handles access attributes than myself." + }, + { + "user": "difference-scheme", + "date": "2021-01-21 21:55:42+00:00", + "text": "@everythingfunctional I am not sure I understood your concern.\nWhat does \"that\" refer to in your sentence \"but if we make that public\"? The constructor/underlying derived type itself?\nThe problem I pointed out is one related to access attributes of derived type components, not of derived types themselves!" + }, + { + "user": "everythingfunctional", + "date": "2021-01-21 22:04:42+00:00", + "text": "In Fortran, the derived type name and its default constructor have the same name. However, the default constructor is not made public along with the type if any of its components (without default initializers) are private. If you're suggesting that the default constructor should be made public even if its components are private, that can cause an issue, because I no longer have a way of making the default constructor private if the type is public. There are times where that is exactly what I want to do. I want to have complete control over how users of my type are allowed to construct instances of it, so that I can prevent them from being able to construct an object with inconsistent internal state." + }, + { + "user": "FortranFan", + "date": "2021-01-21 22:25:56+00:00", + "text": "@difference-scheme wrote Jan 21, 2021 3:51 PM EST:\n\n.. It works for structures, but not (in general) for classes ..\n\nPer the Fortran standard, there is no such distinction. Fortran language has intrinsic types and derived types.\nThe issue here is with PRIVATE components for a derived type: programmers have 2 options:\n\nWhen applicable, employ default initialization of derived type components e.g.,\n\ntype :: BClass\n integer :: n = 0\nend type\n\nWhen default initialization is inapplicable such as with components of allocatable attribute, one may employ a generic interface with the same name as the derived type e.g.,\n\ninterface BClass\n module procedure Construct_BClass1\n module procedure Construct_BClass2\n ..\nend interface\nSo then the matter becomes some programmer finding it too \"verbose\" and/or added work having to code one or more such functions (Construct_BClass1, etc.).\nMy point is if the verbosity and/or the tedium on the designer of the derived type (BClass) to do the above is the issue, this will not make priority.\nHence my question above as to what really are the issues - beyond verbosity - with the facilities in the current language." + }, + { + "user": "difference-scheme", + "date": "2021-01-21 23:35:02+00:00", + "text": "@everythingfunctional \"However, the default constructor is not made public along with the type if any of its components (without default initializers) are private.\"\nCould you point me to the Section number in the document of the Fortran 2018 standard where this is stated/discussed? Thanks." + }, + { + "user": "everythingfunctional", + "date": "2021-01-21 23:44:36+00:00", + "text": "Sure. In Section 7.5.10 Construction of derived-type values, there are two constraints when taken together imply the way I phrased it.\nC799 (R756) A component-spec shall be provided for a nonallocatable component unless it has default initialization\nC7102 (R756) The type name and all components of the type for which a component-spec appears shall be accessible in the scoping unit containing the structure constructor." + }, + { + "user": "FortranFan", + "date": "2021-01-22 00:15:12+00:00", + "text": "@everythingfunctional wrote Jan 21, 2021 6:44 PM EST:\n\n.. Section 7.5.10 Construction of derived-type values, there are two constraints when taken together imply the way I phrased it. ..\n\n@everythingfunctional ,\nPlease note the standard isn't prohibitive the way your statement would come across since a reader might overlook the parenthesis. This is given what those constraints do not cover when it comes to PRIVATE derived type components with ALLOCATABLE attribute in addition to those with default initialization.\nmodule m\n type :: t\n private\n integer, public :: n = 0\n real :: x = 99.0\n character(len=:), allocatable :: s\n end type\ncontains\n subroutine print_t( a )\n type(t) , intent(in) :: a\n print *, \"a%n: \", a%n\n print *, \"a%x: \", a%x\n print *, \"Is a%s allocated? \", allocated(a%s)\n end subroutine \nend module\n use m\n type(t) :: foo\n foo = t( n=42 )\n call print_t( foo )\nend \nFrom what I can deduce, this example conforms and a couple of processors agree.\n\nC:\\Temp>ifort /standard-semantics /warn:all /stand:f18 c.f90\nIntel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000\nCopyright (C) 1985-2020 Intel Corporation. All rights reserved.\nMicrosoft (R) Incremental Linker Version 14.26.28806.0\nCopyright (C) Microsoft Corporation. All rights reserved.\n-out:c.exe\n-subsystem:console\nc.obj\nC:\\Temp>c.exe\na%n: 42\na%x: 99.00000\nIs a%s allocated? F\nC:\\Temp>gfortran -Wall -std=f2018 c.f90 -o gcc-c.exe\nC:\\Temp>gcc-c.exe\na%n: 42\na%x: 99.0000000\nIs a%s allocated? F\nC:\\Temp>" + }, + { + "user": "FortranFan", + "date": "2021-01-22 00:23:29+00:00", + "text": "As I commented upthread, an author of a derived type can implement one or more functions to add to the generic interface in a manner that does satisfy the rules toward generic resolution in the standard. The consumer can then \"construct\" using the default structure constructor or the one added to the interface depending on the situation. See below.\nmodule m\n type :: t\n private\n integer, public :: n = 0\n real :: x = 99.0\n character(len=:), allocatable :: s\n end type\n interface t\n module procedure construct_t_1\n end interface \ncontains\n subroutine print_t( a )\n type(t) , intent(in) :: a\n print *, \"a%n: \", a%n\n print *, \"a%x: \", a%x\n print *, \"Is a%s allocated? \", allocated(a%s)\n if ( allocated(a%s) ) then\n print *, \"a%s: \", a%s\n end if \n end subroutine\n function construct_t_1( s ) result(new_t)\n ! Argument list\n character(len=*), intent(in) :: s\n ! Function result\n type(t) :: new_t\n new_t%s = s\n end function \nend module\n use m\n type(t) :: foo\n type(t) :: bar\n foo = t( n=42 )\n call print_t( foo )\n bar = t( s=\"Hello\" )\n call print_t( bar )\nend \n\nC:\\Temp>ifort /standard-semantics /warn:all /stand:f18 c.f90\nIntel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000\nCopyright (C) 1985-2020 Intel Corporation. All rights reserved.\nMicrosoft (R) Incremental Linker Version 14.26.28806.0\nCopyright (C) Microsoft Corporation. All rights reserved.\n-out:c.exe\n-subsystem:console\nc.obj\nC:\\Temp>c.exe\na%n: 42\na%x: 99.00000\nIs a%s allocated? F\na%n: 0\na%x: 99.00000\nIs a%s allocated? T\na%s: Hello\nC:\\Temp>gfortran -Wall -std=f2018 c.f90 -o gcc-c.exe\nC:\\Temp>gcc-c.exe\na%n: 42\na%x: 99.0000000\nIs a%s allocated? F\na%n: 0\na%x: 99.0000000\nIs a%s allocated? T\na%s: Hello\nC:\\Temp>" + }, + { + "user": "FortranFan", + "date": "2021-01-22 00:28:54+00:00", + "text": "As worded, the original post and the subsequent comments by OP come across as the case where an author (or author(s)) is unwilling to do the bit of extra work to extend the generic interface as I show in my previous comment. The hesitation can be due to added verbosity, programmer time, or laxity, or whatever.\nGiven where things are with Fortran though with all the resource constraints, especially with committee time, this will then be a rather low priority. Hence my suggestion to provide more of a justification with more detailed examples." + }, + { + "user": "everythingfunctional", + "date": "2021-01-22 01:20:09+00:00", + "text": "@FortranFan , your example does not have any private components without default initializers, hence it does not contradict my statement or the constraints in the standard." + }, + { + "user": "everythingfunctional", + "date": "2021-01-22 01:21:45+00:00", + "text": "@FortranFan , oh, I see. You just meant if someone skipped my parenthetical. Yes, my statement is not quite correct without that parenthetical." + }, + { + "user": "difference-scheme", + "date": "2021-01-22 19:05:09+00:00", + "text": "@everythingfunctional\n\nHowever, the default constructor is not made public along with the type if any of its components (without default initializers) are private.\n\n\nSure. In Section 7.5.10 Construction of derived-type values, there are two constraints when taken together imply the way I phrased it.\nC799 (R756) A component-spec shall be provided for a nonallocatable component unless it has default initialization\nC7102 (R756) The type name and all components of the type for which a component-spec appears shall be accessible in the scoping unit containing the structure constructor.\n\nJust to wrap this up.\nYour first statement, that I quoted above, is wrong. In particular, it does not follow in any way from the two constraints of the Fortran standard cited in your second statement.\nThere is an implicit assumption in your whole argument/concern, namely that the access specifiers of derived type components (appearing in a component-spec) affect in some way the accessibility of the type itself, and accordingly its structure constructor. This is wrong.\nDerived types as a whole have their own access specifiers, that are independent of the access specifiers of their components. The standard is very clear about this. Section \"7.5.2.2. Accessibility\" states (I'm quoting from the draft for ballot of the 2018 standard, so the numbering might not be the final one):\n\"The accessibility of a type name is determined as specified in 8.5.2. [i.e. by its own access specifier].The accessibility of a type name does not affect, and is not affected by, the accessibility of its components and type-bound procedures.\"\nThe comment in brackets in the above quote is mine. So, in summary, Section 7.5.2.2. of the standard invalidates your entire concern." + }, + { + "user": "difference-scheme", + "date": "2021-01-22 20:42:08+00:00", + "text": "@klausler After some thought, and after I had a look into the standard, here is the specific change that I propose. The aforementioned constraint C7102:\n\nC7102 (R756) The type name and all components of the type for which a component-spec appears shall be accessible in the scoping unit containing the structure constructor.\n\nshould be relaxed/changed to:\n\"The type name shall be accessible in the scoping unit calling the structure constructor.\"\nThis essentially follows your suggestion of ignoring the accessibilty of components during the initialization process.\nI have come to the conclusion that it doesn't make any sense to honour the privacy/accessibility of something that doesn't exist (in memory, because it hasn't been initialized) yet. Notice, that I have also changed the word \"containing\" (which I find ambiguous) into \"calling\" (but this is a minor thing).\nI believe this change should be backwards compatible, as it simply relaxes a former, more stringent, constraint.\nI'd be grateful for any feedback that you might have. Kudos for your original suggestion!" + }, + { + "user": "klausler", + "date": "2021-01-22 20:50:08+00:00", + "text": "I don't think this is a good idea. If a component is private, the designer of the derived type has chosen to hide that part of the implementation from the interface." + }, + { + "user": "difference-scheme", + "date": "2021-01-22 21:03:17+00:00", + "text": "@klausler Yes, but private or not, he (the designer) still needs to initialize that component.\nThe change would simply bring the default structure constructor on an equal footing with a user-defined constructor. The latter is allowed to effect such initialization, then why should we deny the same right to the structure constructor? It is as much associated to the derived type as a user-defined constructor is!" + }, + { + "user": "klausler", + "date": "2021-01-22 21:13:11+00:00", + "text": "The interface to a user-defined constructor (a generic interface with the same name as the derived type) is under control of the designer of the type, who can hide or expose aspects of the implementation as they see fit. Allowing private components to appear in a structure constructor would expose parts of the implementation that the type's designer has chosen to hide.\nWhen components are inaccessible, the implementation is free to remove them, change their types, rename them, and extend them without worrying about needing clients to make concomitant changes, so long as the published interface remains unchanged. Ignoring accessibility restrictions for structure constructors would wreck that guarantee." + }, + { + "user": "difference-scheme", + "date": "2021-01-22 21:33:55+00:00", + "text": "@klausler I see your point. Thanks for the feedback." + }, + { + "user": "difference-scheme", + "date": "2021-01-23 00:40:38+00:00", + "text": "From @klausler's last comment, I have to conclude that (due to the very way the language is designed) it is impossible to avoid the aforementioned asymmetry between default/structure constructors and user-defined constructors, without breaking the principle of information hiding in some form. I will therefore close this issue." + }, + { + "user": "FortranFan", + "date": "2021-01-23 01:51:47+00:00", + "text": "@difference-scheme wrote Jan. 22, 2021 7:40 PM EST:\n\n.. aforementioned asymmetry between default/structure constructors and user-defined constructors..\n\nThis point is wrong, there is no such asymmetry." + } + ] + }, + { + "number": 192, + "user": "urbanjost", + "date": "2021-01-09 04:35:01+00:00", + "title": "Allowing an INTEGER array as a LUN on WRITE() statements", + "text": "I have seen code many times with conditional execution of WRITE statements and loops repeatedly executing a WRITE statement using multiple LUNs to provide logging, verbose modes, and debug modes. Aside from the possibility of side-effects\nfrom functions called on the WRITE statements (which current methods have an issue with as well) I was wondering what thoughts there might be on allowing the LUN to be an INTEGER array, including of zero length (in which case I would prefer it be a no-op for efficiency). To illustrate the concept\nI put together a little sample program.\nprogram testit\n! Possible use cases, hopefully intuitively obvious would be such as :\nuse,intrinsic :: iso_fortran_env, only : stdin=>input_unit, stdout=>output_unit, stderr=>error_unit\nlogical :: verbose_on=.true.\ninteger,allocatable :: luns(:)\ninteger :: log\n ! assuming verbose_on and luns() are set in a module or global area and there are many WRITE\n ! statements thoughout the program\n if(verbose_on)then\n luns=[stdout]\n else\n luns=[integer ::]\n endif\n write(luns,*)'verbose or debug message (one of many throughout the program)'\n\n ! when you want to duplicate output in multiple files\n open(newunit=log,file='record.log')\n luns=[log,stdout]\n write(luns,*)'message'\n\nend program testit", + "comments": [ + { + "user": "urbanjost", + "date": "2021-01-10 02:38:26+00:00", + "text": "As a working example of the basic concept, here is procedure called WRT() that simulates a basic list-directed write statement\nthat can take up to ten intrinsic scalar variables and an array as a LUN for anyone interested in experimenting with the concept.\nmodule M_wrt\nuse, intrinsic :: iso_fortran_env, only : stderr=>error_unit\nprivate\npublic :: wrt\ncontains\nfunction str(g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, nospace)\nimplicit none\nclass(*),intent(in),optional :: g0, g1, g2, g3, g4, g5, g6, g7, g8, g9\nlogical,intent(in),optional :: nospace\ncharacter(len=:), allocatable :: str\ncharacter(len=4096) :: line\ninteger :: istart, increment\n if(present(nospace))then\n increment=merge(1,2,nospace)\n else\n increment=2\n endif\n istart=1\n line=''\n if(present(g0))call print_g(g0)\n if(present(g1))call print_g(g1)\n if(present(g2))call print_g(g2)\n if(present(g3))call print_g(g3)\n if(present(g4))call print_g(g4)\n if(present(g5))call print_g(g5)\n if(present(g6))call print_g(g6)\n if(present(g7))call print_g(g7)\n if(present(g8))call print_g(g8)\n if(present(g9))call print_g(g9)\n str=trim(line)\ncontains\nsubroutine print_g(g)\nuse,intrinsic :: iso_fortran_env, only : int8, int16, int32, int64, real32, real64, real128\nclass(*),intent(in) :: g\n select type(g)\n type is (integer(kind=int8)); write(line(istart:),'(i0)') g\n type is (integer(kind=int16)); write(line(istart:),'(i0)') g\n type is (integer(kind=int32)); write(line(istart:),'(i0)') g\n type is (integer(kind=int64)); write(line(istart:),'(i0)') g\n type is (real(kind=real32)); write(line(istart:),'(1pg0)') g\n type is (real(kind=real64)); write(line(istart:),'(1pg0)') g\n type is (real(kind=real128)); write(line(istart:),'(1pg0)') g !*! NOTE: nvfortran does not support this type\n type is (logical); write(line(istart:),'(l1)') g\n type is (character(len=*)); write(line(istart:),'(a)') trim(g)\n type is (complex); write(line(istart:),'(\"(\",1pg0,\",\",1pg0,\")\")') g\n end select\n istart=len_trim(line)+increment\nend subroutine print_g\nend function str\nsubroutine wrt(luns,g0, g1, g2, g3, g4, g5, g6, g7, g8, g9,iostat)\nimplicit none\ninteger,intent(in) :: luns(:)\nclass(*),intent(in),optional :: g0, g1, g2, g3, g4, g5, g6, g7, g8, g9\ninteger,intent(out),optional :: iostat\ninteger :: i\ncharacter(len=256) :: msg\n do i=1,size(luns)\n write(luns(i),'(a)',iostat=iostat,iomsg=msg)str(g0,g1,g2,g3,g4,g5,g6,g7,g8,g9)\n if(iostat.ne.0)then\n write(stderr,'(*(g0))')'*write*:',trim(msg)\n endif\n enddo\nend subroutine wrt\nend module M_wrt\nA simple use of the WRT() procedure demonstrates it can take arbitrary scalars and write to no files\nor multiple files depending on the size and contents of the LUN array.\nprogram demo_wrt\nuse, intrinsic :: iso_fortran_env, only : stdin=>input_unit, stdout=>output_unit, stderr=>error_unit\nuse M_wrt, only: wrt\nimplicit none\ninteger,allocatable :: luns(:)\ninteger :: iostat=0\n luns=[integer ::] ! a null list allows for turning off verbose or debug mode output \n call wrt(luns,'NULL LIST:',huge(0),'PI=',asin(1.0d0)*2.0d0,iostat=iostat)\n write(*,*)'IOSTAT=',iostat\n luns=[stderr,stdout] ! multiple files can be used to create a log file\n call wrt(luns,'TWO FILES:',huge(0),'PI=',asin(1.0d0)*2.0d0,iostat=iostat)\n write(*,*)'IOSTAT=',iostat\n ! unlike direct use of WRITE a function can be used as a list of LUNS if it returns an INTEGER array.\nend program demo_wrt\nThe wrt() procedure should be able to take up to any nine intrinsic scalars of the types listed:\ngfortran demo.f90;./a.out\n IOSTAT= 0\nTWO FILES: 2147483647 PI= 3.1415926535897931\nTWO FILES: 2147483647 PI= 3.1415926535897931\n IOSTAT= 0\n[urbanjs@localhost ~]$ ifort demo.f90;./a.out\n IOSTAT= 0\nTWO FILES: 2147483647 PI= 3.141592653589793\nTWO FILES: 2147483647 PI= 3.141592653589793\n IOSTAT= 0\nNote the default is to place a space between output values. This can be suppressed using \"nospace=.true\"." + }, + { + "user": "FortranFan", + "date": "2021-01-10 17:03:10+00:00", + "text": "Should the Fortran committee decide to pursue this - note it'll likely require a lot of effort and convincing and influencing - it will be a long wait (years) before an implementation starts to support the facility.\nIn the meantime, practitioners who are interested in this can consider a workaround with IMPURE ELEMENTAL and try to work within the stipulations of this option:\nmodule m\ncontains\n impure elemental subroutine write_dat( lun, dat )\n integer, intent(in) :: lun\n class(*), intent(in) :: dat\n select type ( dat )\n type is ( integer )\n write( lun, advance=\"no\", fmt=\"(*(g0,1x))\" ) dat\n type is ( character(len=*) )\n write( lun, advance=\"no\", fmt=\"(*(g0,1x))\" ) trim(dat)\n end select\n end subroutine\nend module\n use, intrinsic :: iso_fortran_env, only : stdout => output_unit\n use m, only : write_dat\n integer :: luns(2)\n open( newunit=luns(1), file=\"foo.dat\" )\n luns(2) = stdout\n call write_dat( luns, \"Hello World!\" )\n call write_dat( luns, \"The answer is\" )\n call write_dat( luns, 42 )\nend\n\nC:\\Temp>gfortran -Wall -std=f2018 io.f90 -o io.exe\nC:\\Temp>io.exe\nHello World! The answer is 42\nC:\\Temp>type foo.dat\nHello World! The answer is 42\nC:\\Temp>" + }, + { + "user": "urbanjost", + "date": "2021-01-10 18:15:15+00:00", + "text": "It had not occurred to me that calling an elemental function with a zero-sized array conditionally executed the function, but it makes sense on reflection. Worked fine when I added calls with the EMPTY array.\nmodule m \ncontains \n impure elemental subroutine write_dat( lun, dat ) \n integer, intent(in) :: lun \n class(*), intent(in) :: dat \n select type ( dat ) \n type is ( integer ) \n write( lun, advance=\"no\", fmt=\"(*(g0,1x))\" ) dat \n type is ( character(len=*) ) \n write( lun, advance=\"no\", fmt=\"(*(g0,1x))\" ) trim(dat) \n end select \n end subroutine \nend module \n use, intrinsic :: iso_fortran_env, only : stdout => output_unit \n use m, only : write_dat \n integer :: luns(2) \n integer :: empty(0) \n open( newunit=luns(1), file=\"foo.dat\" ) \n luns(2) = stdout \n call write_dat( luns, \"Hello World!\" ) \n call write_dat( luns, \"The answer is\" ) \n call write_dat( luns, 42 ) \n call write_dat( luns, NEW_LINE('A') ) \n \n call write_dat( empty, \"AGAIN:Hello World!\" ) \n call write_dat( empty, \"The answer is\" ) \n call write_dat( empty, 42 ) \n call write_dat( luns, NEW_LINE('A') ) \nend" + } + ] + }, + { + "number": 191, + "user": "Beliavsky", + "date": "2021-01-03 20:11:45+00:00", + "title": "Add format string corresponding to list-directed I/O", + "text": "I suggest that format string \"(LD)\" be added that corresponds to list-directed READ and WRITE in READ and WRITE statements. Having such a format would allow read (unit,fmt) and write (unit,fmt) to handle both formatted and list-directed output, removing the need for if blocks such as\nif (format_present) then\n write (unit,fmt) a,b\nelse \n write (unit,*) a,b\nend if\n\nThe idea was proposed and discussed here, where Ron Shephard explains how it would simplify reading data. The \"(LD)\" syntax was suggested by Bill Long.", + "comments": [] + }, { "number": 190, "user": "FortranFan", @@ -1302,6 +1477,41 @@ "user": "wclodius2", "date": "2020-07-12 20:19:04+00:00", "text": "Like I said I have no strong feelings about no intent. The users can do a lot of things in almost any programming language that I would consider foolish. With no intent the user could also write the code in such a way that when he provides no argument so the default is used, the routine behaves like an INTENT(IN) and behaves like INTENT(INOUT) otherwise.. Whatever we decide we should discuss the implications for no intent, either requiring that an argument with the DEFAULT may not have the INTENT(INOUT) or INTENT(OUT) (implicitly allowing no intent), or require that arguments with the DEFAULT attribute must have one of the attributes INTENT(IN) or VALUE (implicitly disallowing no intent).\n\u2026\n On Jul 12, 2020, at 2:07 PM, Jeremie Vandenplas ***@***.***> wrote:\n\n\n Unfortunately no intent is not equivalent to intent(inout), though I wouldn\u2019t object strongly if the revised proposal dropped allowing default assignment for no intent. INTENT(INOUT) means that the input value is always intended to be used and an output value is always expected. No INTENT could behave as an INTENT(IN), INTENT(OUT), or INTENT(INOUT), and its behavior could depend dynamically on the other arguments.\n\n Thank you for the precisions. Therefore, because \"no intent\" could behabe as an intent(out), wouldn't it make sense to not allowing default assignment for \"no intent\"? Otherwise, users could just drop \"intent(out)\" and add a default value for an argument actually behaving as intent(out)\n\n \u2014\n You are receiving this because you were mentioned.\n Reply to this email directly, view it on GitHub <#175 (comment)>, or unsubscribe ." + }, + { + "user": "certik", + "date": "2021-01-20 19:25:40+00:00", + "text": "I don't like specifying the default value in the argument list as in real function quadratic(x, a, b, c=0). I am ok with using default (and not mix this with optional).\nOne objection from the committee I believe is that the syntax integer, intent(in), default :: c = 0 implies the save attribute. So perhaps this syntax should be used instead: integer, intent(in), default(0) :: c." + }, + { + "user": "milancurcic", + "date": "2021-01-20 19:33:36+00:00", + "text": "One objection from the committee I believe is that the syntax integer, intent(in), default :: c = 0 implies the save attribute.\n\nI don't understand this objection because dummy arguments can't have a save attribute.\nI am also okay with not mixing default and optional. I slightly prefer the default :: c = 0 syntax, but default(0) :: c is fine too." + }, + { + "user": "klausler", + "date": "2021-01-20 19:40:17+00:00", + "text": "You need to decide whether the default value of a dummy argument (or just that fact that it has one) is meant to be a characteristic of the procedure or not. This matters in the implementation, because it determines whether an implementation has the freedom to implement the default value in the caller (as in C++) or in the called subprogram, or whether the language is forcing one or the other.\nWhy this matters: if the default value of a dummy argument is an expression involving other dummy arguments, host-associated variables, module or COMMON objects, &c., implementing the evaluation of the default value in the caller can be difficult or impossible. But if default values are expressions to be evaluated if need be in the called subprogram, then the value need not be part of the characteristics or interface, and the implementation of the calling side is no different from an OPTIONAL argument; and one could argue that an explicit interface need not distinguish between OPTIONAL and having a default value for purposes of procedure pointer assignment and other interface compatibility checking." + }, + { + "user": "certik", + "date": "2021-01-20 19:46:44+00:00", + "text": "Peter, when I discussed that at the last meeting (after the plenary), I think our idea was to implement the default value in the caller, which enables the compiler to compile the subroutine ahead of time without any if statements, and call it exactly the same way no matter if the user provides the default argument or not.\nYou have a good point about what if the default value is an expression involving other dummy arguments that it might be impossible. I don't know yet if it is impossible, and so a prior compiler implementation would be in order here. At least in gfortran it seems any of these expressions (such as a length of an array) is part of the function signature, so this would be also." + }, + { + "user": "klausler", + "date": "2021-01-20 19:57:03+00:00", + "text": "Peter, when I discussed that at the last meeting (after the plenary), I think our idea was to implement the default value in the caller, which enables the compiler to compile the subroutine ahead of time without any if statements, and call it exactly the same way no matter if the user provides the default argument or not.\nYou have a good point about what if the default value is an expression involving other dummy arguments that it might be impossible. I don't know yet if it is impossible, and so a prior compiler implementation would be in order here. At least in gfortran it seems any of these expressions (such as a length of an array) is part of the function signature, so this would be also.\n\nsubroutine host(defaultY)\n real, intent(in) :: defaultY\n call solver(f)\n contains\n real function f(x, y)\n real, intent(in) :: x, y\n default(defaultY) :: y\n ...\n end function\nend subroutine\n\nSeems like a compelling use case to me, but the default has to be implemented in the called subprogram to make it work. So there's reasons why defaults should be implemented in callees, and the only argument for implementing them in callers (it might save a predictable branch) is weak and also has other obvious solutions." + }, + { + "user": "certik", + "date": "2021-01-20 21:28:43+00:00", + "text": "I see. The nested subroutine f has access to the variables in the parent scope, such as defaultY, so this would work if the default is not part of the signature, using the current mechanism for nested subroutines. But if it is part of the signature of f, then one needs access to defaultY inside the function solver, which currently is not possible. Good point, thank you @klausler." + }, + { + "user": "klausler", + "date": "2021-01-21 19:19:33+00:00", + "text": "I see. The nested subroutine f has access to the variables in the parent scope, such as defaultY, so this would work if the default is not part of the signature, using the current mechanism for nested subroutines. But if it is part of the signature of f, then one needs access to defaultY inside the function solver, which currently is not possible. Good point, thank you @klausler.\n\nHere's an idea: extend the VALUE attribute to accept an expression, and allow it to be applied to an OPTIONAL dummy argument as its default value. (You could also accept VALUE with an expression to specify a per-invocation initializer for a local variable, too, I suppose.)" } ] }, @@ -1815,7 +2025,13 @@ "date": "2020-02-28 02:15:29+00:00", "title": "Namelist delimiter proposal update", "text": "This patch contains two main modifications to the namelist delimiter\nproposal:\n\n\nThe introduction has been modified for clarity and to include the\nproposed change, rather than simply a discussion of the problem.\n\n\nThe introduction and proposal sections have been modified to clarify\nthat list-directed output would be unaffected by the change.", - "comments": [] + "comments": [ + { + "user": "marshallward", + "date": "2021-01-02 13:25:24+00:00", + "text": "I am not sure how to submit this, and other feedback suggests that I am the only person on the planet who is concerned about this, so I am going to close this." + } + ] }, { "number": 158, @@ -5919,6 +6135,16 @@ "user": "FortranFan", "date": "2020-03-06 23:21:25+00:00", "text": "To those interested in this issue, here's a comment to take note at comp.lang.fortran thread where \"Lynn McGuire\" posted:\n\nThe number one dysfunctional item in Fortran is variable typing and\ndeclaration. At the 1977 specs, much less the 1990 specs, all Fortran\nvariables should be explicitly declared and typed. The implicit rule is\nok for small programs. Not at all for anything more than say, a\nthousand lines of code." + }, + { + "user": "elecprog", + "date": "2021-01-12 19:23:48+00:00", + "text": "I've been thinking a bit more on this issue lately, especially having used Fortran some more (after seemingly having partially opened Pandora's box with this thread).\nFirst four assumptions I'm making (which to my knowledge are true, but please correct me if I'm wrong):\n\nWe really want to get rid of implicit by default, but implicit semantics themselves don't have to go (in the short term at least).\nHaving code not compile\u2014but not break\u2014is a lesser evil than implicit by default, if that code can automatically be fixed.\nIf implicit none changes the semantics of the code, this always results in the code failing to compile.\nProgram units are easily detected.\n\nIf these assumptions are true, getting rid of implicit typing as a default is actually pretty straightforward:\nMake implicit none the default in the next standard and include a tool that detects the outer most program units, sees if there is any implicit statement and if not adds\nIMPLICIT INTEGER (I-N), REAL (A-H, O-Z)\nOptionally this tool could even verify if this change is needed, but it doesn't have to.\nAdditionally we could deprecate the implicit statement all together and leave it up to vendors if they support old code or not." + }, + { + "user": "certik", + "date": "2021-01-12 20:33:31+00:00", + "text": "Thanks @elecprog for writing down the assumptions that you used. Under your assumptions I think your proposal could work.\nThe issue that we have is that we can't get a community agreement on the assumptions. I have seen opposition to the assumption 2., and consequently also 1. I personally agree with 2. (i.e., implicit by default being more evil), but some others disagreed (older code not compiling being more evil: Fortran historically tries very hard to compile older code, so I understand this position)." } ] }, @@ -8646,6 +8872,16 @@ "user": "rouson", "date": "2020-02-27 04:22:18+00:00", "text": "I haven't read this entire thread, but I like the original idea and have been thinking for some time about repurposing the AdHoc repository to automate and democratize the generation of a standards-conformance table. Because AdHoc stores compiler bug reproducers, its build scripts are designed to continue building the remainder of the repository after a compile-time error occurs. This makes it feasible to generate a standards-conformance table based on a test suite that includes code with features not supported by the involved compilers. The build scripts could automatically generated table in GitHub Markdown structured something like the following:\n\n\n\n\nCompiler A\nCompiler B\n\n\n\n\nFeature A\nYes\nNo\n\n\nFeature B\nPartial\nYes\n\n\n\nEach entry would correspond to a unique subdirectory. Contributors would submit pull requests with tests that enable the build/test scripts to set the value of each entry according to the following rules:\n\n\"No\" for an empty subdirectory or one in which all tests fail,\n\"Yes\" if all tests in the subdirectory pass, or\n\"Partial\" otherwise.\n\nFor example, the following directory tree would yield the above table if the tests foo.f90, bar.f90, and foobartoo.f90 pass but foobar.f90 fails:\n$ tree tests\ntests/\n\u251c\u2500\u2500 compiler-a\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 feature-a\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 foo.f90\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 feature-b\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 bar.f90\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 foobar.f90\n\u2514\u2500\u2500 compiler-b\n \u251c\u2500\u2500 feature-a\n \u2514\u2500\u2500 feature-b\n \u2514\u2500\u2500 foobartoo.f90\n\nFor free compilers, the tests could be run at no cost using GitHub continuous integration features. For non-free compilers, another mechanism for running the tests might be required. The degree of comprehensiveness of the test suite would be determined by the community." + }, + { + "user": "FortranFan", + "date": "2021-01-08 16:07:19+00:00", + "text": "A case for consider in a test suite for the Fortran standard, this one with finalization.\n! Unit Test #: Test-1.F2018-7.5.6\n! Author : FortranFan\n! Reference : https://j3-fortran.org/doc/year/18/18-007r1.pdf\n!\n! Description:\n! Section 7.5.6.3 When finalization occurs in above pdf\n! c.f. page 80 paragraph starting line 17:\n! When finalization occurs\n!\n\nmodule m\n type :: t\n character(len=12) :: name = \"default\"\n contains\n final :: final_t\n end type\n interface t\n module procedure construct_t\n end interface\ncontains\n function construct_t( name ) result(r)\n character(len=*), intent(in), optional :: name\n type(t) :: r\n if ( present(name) ) r%name = name\n end function\n subroutine final_t( this )\n type(t), intent(inout) :: this\n print *, \"final_t: this%name = \", this%name\n return\n end subroutine\n subroutine sub1()\n type(t), allocatable :: foo\n foo = t( name=\"constructor\" )\n foo%name = \"foo\"\n end subroutine\n subroutine sub2()\n type(t), allocatable :: foo\n allocate( foo )\n foo = t( name=\"constructor\" )\n foo%name = \"foo\"\n end subroutine\nend module\n blk1: block\n use m, only : sub1\n print *, \"Block 1: Two lines from final_t are expected\"\n call sub1()\n end block blk1\n print *\n blk2: block\n use m, only : sub2\n print *, \"Block 2: Three lines from final_t are expected\"\n call sub2()\n end block blk2\nend\nConsider the program output using gcc version 10.0.1 (experimental)):\n\nC:\\temp>gfortran -Wall -std=f2018 p.f90 -o p.exe\nC:\\temp>p.exe\nBlock 1: Two lines from final_t are expected\nfinal_t: this%name = foo\nBlock 2: Three lines from final_t are expected\nfinal_t: this%name = foo\n\nWhereas the output I expect per the Fortran standard is this:\n\nBlock 1: Two lines from final_t are expected\nfinal_t: this%name = constructor\nfinal_t: this%name = foo\nBlock 2: Three lines from final_t are expected\nfinal_t: this%name = default\nfinal_t: this%name = constructor\nfinal_t: this%name = foo" + }, + { + "user": "FortranFan", + "date": "2021-01-09 00:42:37+00:00", + "text": "Here's a variant of the previous case, this one involves the expr on the right-hand side to include a component of the variable on the LHS:\n! Unit Test #: Test-2.F2018-7.5.6\n! Author : FortranFan\n! Reference : https://j3-fortran.org/doc/year/18/18-007r1.pdf\n!\n! Description:\n! Section 7.5.6.3 When finalization occurs in above pdf\n! c.f. page 80 paragraph starting line 17:\n! When finalization occurs\n!\n\nmodule m\n type :: t\n character(len=12) :: name = \"default\"\n contains\n private\n procedure, pass(lhs) :: add_t\n procedure, pass(this) :: clone_t\n generic, public :: operator(+) => add_t\n generic, public :: clone => clone_t\n final :: final_t\n end type\n interface t\n module procedure construct_t\n end interface\ncontains\n function construct_t( name ) result(r)\n character(len=*), intent(in), optional :: name\n type(t) :: r\n if ( present(name) ) r%name = name\n end function\n subroutine final_t( this )\n type(t), intent(inout) :: this\n print *, \"final_t: this%name = \", this%name\n return\n end subroutine\n function add_t( lhs, rhs ) result(r)\n class(t), intent(in) :: lhs\n type(t), intent(in) :: rhs\n type(t) :: r\n r%name = trim(lhs%name) // \"+\" // trim(rhs%name)\n end function\n function clone_t( this ) result(r)\n class(t), intent(in) :: this\n type(t) :: r\n r%name = trim(this%name) // \"*\"\n end function\n subroutine sub()\n type(t), allocatable :: foo\n foo = t( name=\"constructor\" )\n print *, \"1\"\n foo%name = \"foo\"\n foo = foo%clone()\n print *, \"2\"\n foo = foo + foo\n print *, \"3\"\n end subroutine\nend module\n use m, only : sub\n call sub()\nend\ngfortran program output is\n\n1\n2\n3\nfinal_t: this%name = foo*+foo*\n\nThe expected program output is\n\nfinal_t: this%name = constructor\n1\nfinal_t: this%name = foo\nfinal_t: this%name = foo*\n2\nfinal_t: this%name = foo*\nfinal_t: this%name = foo*+foo*\n3\nfinal_t: this%name = foo*+foo*" } ] }, @@ -10212,6 +10448,11 @@ "user": "vansnyder", "date": "2020-05-09 20:10:13+00:00", "text": "Array-like syntax would be the most natural, but obviously conflicts with, er, array syntax.\n\nTom:\nI proposed array/function syntax for structure components, getters, and setters at the X3J3 meeting in Albuquerque in 1986, when % was still controversial. John Reid, Rex Paige, and Brian Smith understood it. Others said \"Fortran programmers want to see what their program is doing.\" Of course, you DO NOT want to see HOW your program is doing things. Parnas had explained that 16 years earlier.\nThere is no syntax conflict. Processors can already work out the difference between function and array references. Setters would not be a new problem. Indeed, an assignment to an array element is an invocation of a setter that the processor knows how to write and inline." + }, + { + "user": "ivan-pi", + "date": "2021-01-18 01:15:58+00:00", + "text": "If the protected attribute is allowed for members of derived types as already under discussion in #16 and #156, the \"getter\" problem would be solved for many usage cases.\nI can still imagine instances where I would like to have something closer to the idea of Pythons @property decorator. An example of what I have in mind is something along the lines of\n\ntype :: matrix\n real, allocatable :: A(:,:)\n integer, property :: rows = size(matrix%A,1) ! a read-only property\n integer, property :: cols = size(matrix%A,2) ! a read-only property\ncontains\n procedure :: get_nrows ! I would like to avoid having to write this function\nend type\n\ntype(matrix) :: mat \n\nmat%A = reshape([1,2,3,4],[2,2])\n\nprint *, A%rows, A%cols ! prints: 2 2\n\nI am guessing this would conflict with the way some intrinsic functions work. The gfortran documentation says that size() will only return a meaningful result for an allocated array. On the other hand ifort appears to return 0 as the size of unallocated objects. In any case the idea is that the actual call to size() would be made when the member A%rows is referenced somewhere. It would probably make sense to limit the allowable property functions to pure intrinsic functions." } ] }, @@ -10889,6 +11130,16 @@ "user": "septcolor", "date": "2020-07-27 03:22:01+00:00", "text": "@wclodius2 Thanks very much for clarification! I will read the original and revised drafts (and this thread) more carefully..." + }, + { + "user": "jvdp1", + "date": "2021-01-20 19:19:52+00:00", + "text": "Just to remember that a revised version of the proposal is in the MR: #175 . It doesn't appear clearly in this thread..." + }, + { + "user": "vansnyder", + "date": "2021-01-21 02:09:49+00:00", + "text": "During the development of Fortran 90, back when it was still called Fortran 8x, there was a proposal for an AUTOMATIC attribute. When RECURSIVE was added, the argument was that every variable that isn't SAVE is automatic. The standard's definition of \"automatic variable\" was needlessly narrowed to one that used a variable to specify a bound or length parameter. I no longer have records from that time; I sent them to the Computer History Museum. Loren Meissner is the curator for them.\nHad the AUTOMATIC attribute been retained, an obvious definition of AUTOMATIC with initialization would have meant automatic initialization, not SAVE. Specifying the AUTOMATIC attribute without initialization would simply confirm what we already say now. Explicitly specifying AUTOMATIC and SAVE for a particular variable should be prohibited. Explicitly specified AUTOMATIC would override default SAVE. AUTOMATIC would naturally be prohibited for storage-associated variables.\nOnce AUTOMATIC is defined that way, all that is necessary to provide default values for absent optional arguments is to define an absent OPTIONAL argument that has initialization to be a local automatic variable.\nThe PRESENT intrinsic should still be available to inquire whether there was an associated actual argument. Even if there's a value for a local variable acting in lieu of the absent dummy argument, it's still useful to know whether the actual argument was present." } ] },