Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# AGENTS.md
AI Agent Operating Rules for This Repository

This file defines **hard constraints** and **preferred behaviors** for AI coding
agents (e.g., Claude, Codex) working in this repository. These rules exist to protect
numerical correctness, performance, and long-term maintainability of a
a dynamic equation parser Fortran library codebase.

Agents MUST follow all rules below unless explicitly instructed otherwise by a
human maintainer.

---

## 1. Project Purpose

This project implements and infix tokenizer, infix to postfix conversion utilities, and postfix calculator
that works with scalars and higher rank arrays in Fortran for dynamic equation parsing and evaluation in Fortran.

Primary goals:
- Users should be able to provide valid infix equations as strings and evaluate them reliably without error
- Numerical correctness
- High performance on CPUs

Changes must NOT degrade:
- Correctness

---

## 2. Fortran Standards & Toolchain

### Language Standard
- Target: **Fortran 2008**
- Code must remain compatible with:
- gfortran ≥ 11
- ifx
- nvfortran
- amdflang

### Prohibited Language Features
Do NOT introduce:
- Coarrays
- Fortran 2018+ features
- Compiler-specific extensions
- Automatic polymorphism in performance-critical paths

### Formatting & Conventions
- Free-form source
- `implicit none` required in all program units
- Explicit `intent(in|out|inout)` on all dummy arguments
- Lowercase keywords preferred
- Line length ≤ 100 characters

---

## 3. Numerical & Algorithmic Constraints

### Hard Rules
- Do NOT change the mathematical formulation without approval
- Do NOT change discretization order
- Do NOT change basis, quadrature, or nodal ordering
- Do NOT reorder floating-point reductions
- Do NOT alter time integration schemes

### Floating-Point Behavior
- Bitwise reproducibility may be required
- Preserve operation ordering in loops
- Avoid algebraic “simplifications” unless mathematically justified

### Array Semantics
- Do NOT replace explicit loops with array syntax unless equivalence is proven
- Avoid implicit temporaries

---

## 4. Performance Rules (Critical)

This is an HPC codebase. Performance regressions are unacceptable.

### Memory
- Avoid temporary allocations in hot paths
- No automatic arrays in tight loops
- No hidden allocations via array slicing

### Loops
- Preserve loop ordering for cache locality
- Do NOT replace DO loops with WHERE / FORALL
- Vectorization-friendly structure must be preserved

### Abstraction
- Do NOT introduce runtime polymorphism in kernels
- Avoid excessive modularization inside hot loops

---

## 5. Code Organization & APIs

### File & Module Structure
- Do NOT rename modules
- Do NOT move files between directories
- Do NOT change public interfaces without approval
- Preserve module dependency order

### Public APIs
- Public procedures are considered **stable**
- Backward compatibility is required unless stated otherwise

---

## 6. Testing & Validation

### Required
- All existing regression tests must pass
- Do NOT modify reference output files
- Numerical differences must be justified

### New Code
- New features require:
- A test case
- Clear validation criteria

---

## 7. Documentation & Comments

### Preserve Scientific Meaning
- Do NOT remove comments describing:
- Equations
- Algorithms
- Numerical assumptions

### New Routines
Must include:
- Mathematical description
- Variable meaning and units
- Expected input ranges

---

## 8. Prohibited Actions (Explicit)

Agents MUST NOT:
- Rewrite code in another language
- Convert procedural code to OO Fortran
- Replace MPI with coarrays
- Introduce external dependencies
- “Modernize” syntax without benefit
- Delete legacy code without explanation

---

## 10. Preferred Agent Behavior

Agents SHOULD:
- Ask before changing algorithms
- Explain numerical and performance implications
- Provide minimal diffs
- Reference existing patterns in the codebase
- Flag any uncertainty explicitly

Agents SHOULD NOT:
- Make large refactors unless requested
- Assume intent beyond the explicit request

---

## 11. When in Doubt

If a change could affect:
- Numerical accuracy
- Stability
- Performance
- Parallel behavior

STOP and ask for clarification.

---
## 12. Local Dev Commands (Required)

Agents MUST use the commands below for formatting and tests.
If these commands fail due to missing Docker, agents should not invent alternatives.

### Lint / Format (Fortran)
Run fprettify on the repository:

```bash
./scripts/lint.sh
```
To apply formatting changes:
```
./scripts/format.sh
```

### Unit/Regression tests

```
./scripts/test.sh
```
---

End of AGENTS.md

16 changes: 14 additions & 2 deletions src/FEQParse.f90
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,12 @@ subroutine ConvertToPostFix(parser)

tok = operator_stack%TopToken()

! Pop operators with higher priority, or equal priority for left-associative ops
! (all operators except '^' are left-associative)
do while(trim(tok%tokenString) /= '(' .and. &
parser%Priority(tok) > &
parser%Priority(parser%inFix%tokens(i)) .and. &
(parser%Priority(tok) > parser%Priority(parser%inFix%tokens(i)) .or. &
(parser%Priority(tok) == parser%Priority(parser%inFix%tokens(i)) .and. &
trim(parser%inFix%tokens(i)%tokenString) /= '^')) .and. &
.not. operator_stack%IsEmpty())

call parser%postFix%push(tok)
Expand Down Expand Up @@ -411,6 +414,15 @@ subroutine ConvertToPostFix(parser)
! Pop the opening parenthesis
call operator_stack%pop(tok)

! If there is a function token at the top of the operator stack, pop it to output
if(.not. operator_stack%IsEmpty()) then
tok = operator_stack%TopToken()
if(tok%tokenType == Function_Token) then
call parser%postFix%push(tok)
call operator_stack%pop(tok)
endif
endif

endif

enddo
Expand Down
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ add_fortran_tests (
"print_tokens.f90"
"custom_r1fp32.f90"
"custom_r1fp64.f90"
"parsing_simple_r1fp32.f90"
"parsing_difficult_r1fp64.f90"
"parsing_vanderpol_sfp64.f90")


78 changes: 78 additions & 0 deletions test/parsing_simple_r1fp32.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// !
!
! Maintainers : support@fluidnumerics.com
! Official Repository : https://github.com/FluidNumerics/feq-parse/
!
! Copyright © 2024 Fluid Numerics LLC
!
! Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
!
! 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
!
! 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
! the documentation and/or other materials provided with the distribution.
!
! 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from
! this software without specific prior written permission.
!
! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
! HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
! LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
!
! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// !

program test

implicit none
integer :: exit_code

exit_code = parsing_simple_r1fp32()
stop exit_code

contains

integer function parsing_simple_r1fp32() result(r)
use FEQParse
use iso_fortran_env
implicit none
integer,parameter :: N = 10
type(EquationParser) :: f
character(LEN=1),dimension(1) :: independentVars
character(LEN=2048) :: eqChar
real(real32) :: x(1:N,1)
real(real32) :: feval(1:N)
real(real32) :: fexact(1:N)
integer :: i

! Specify the independent variables
independentVars = (/'x'/)

! Specify an equation string that we want to evaluate
eqChar = 'f = x-sqrt(x) + 100'

! Create the EquationParser object
f = EquationParser(eqChar,independentVars)

x = 0.0_real32
do i = 1,N
x(i,1) = (2.0_real32)/real(N,real32)*real(i-1,real32)
fexact(i) = x(i,1)-sqrt(x(i,1))+100.0
enddo

! Evaluate the equation
feval = f%evaluate(x)
if(maxval(abs(feval-fexact)) <= epsilon(1.0_real32)) then
r = 0
else
do i = 1,N
print*,x(i,1),feval(i),fexact(i),abs(feval(i)-fexact(i))
enddo
r = 1
endif

endfunction parsing_simple_r1fp32

endprogram test
Loading