Skip to content

Add the missing built-in constant-expression functions (popcount, rotl, rotr, mod, exp, log, pow, ceiling, floor) #390

Description

@TheGupta2012

Limitation

Table 2 — Built-in mathematical functions
lists the functions every OpenQASM 3 implementation must provide in constant expressions:

arccos, arcsin, arctan, ceiling, cos, exp, floor, log, mod, popcount,
pow, rotl, rotr, sin, sqrt, tan.

pyqasm's FUNCTION_MAP provides only abs, real, imag, sqrt, sin, cos, tan,
arccos, arcsin, arctan. Nine of the spec's functions are missing:
ceiling, floor, exp, log, mod, popcount, pow, rotl, rotr.

Example QASM failure

Every one of these is a valid constant expression per the spec:

import pyqasm

for decl in [
    "const uint c = popcount(37);",
    'const bit[8] c = rotl("00101010", 3);',
    'const bit[8] c = rotr("00101010", 3);',
    "const int c = mod(7, 2);",
    "const float[64] c = exp(1.0);",
    "const float[64] c = log(2.0);",
    "const int c = ceiling(1.2);",
    "const int c = floor(1.8);",
]:
    m = pyqasm.loads("OPENQASM 3.0;\n" + decl)
    m.validate()
ValidationError: Invalid initialization value for constant 'c'

They fail as gate arguments too, where sqrt already works:

OPENQASM 3.0;
include "stdgates.inc";
qubit[1] q;
rx(sqrt(2.0)) q[0];   // OK today
rx(exp(1.0)) q[0];    // ValidationError: Invalid parameter 'exp(1.0)' for gate 'rx'

The spec's own example under Built-in constant expression functions exercises most of them:

const float[64] f2 = 2.0 * exp(f1);
const int[8] i2 = pow(i1, u1);
const bit[8] b2 = rotl(b1, 3);

Change Requested

  1. Add ceiling, floor, exp, log, mod to FUNCTION_MAP with the spec's signatures.
  2. Add popcount, rotl, rotr, which operate on bit[n] and uint[n] and must preserve
    the input width.
  3. Add pow(a, b) as a function. Note the parser caveat below — this one is not purely a
    FUNCTION_MAP entry.
  4. Report an unknown function name and an arity or type mismatch as a ValidationError naming
    the function, rather than the current generic "Invalid initialization value" message,
    which gives the user no indication that the function was the problem.

Implementation Details

  • FUNCTION_MAP is in src/pyqasm/maps/expressions.py:196. Most additions are one line each:
    "exp": np.exp, "log": np.log, "ceiling": np.ceil, "floor": np.floor,
    "mod": np.mod.
  • popcount / rotl / rotr are defined on bit[n] and depend on a width-carrying bit
    representation — see the companion issue on bit[n] operators. Widths must be preserved:
    rotl(a, n) == rotr(a, -n), and the output width equals the input width.
  • pow has a known blocker. const int c = pow(2, 3); fails at parse time in
    openqasm3 1.0.1 because pow is also the gate-modifier keyword. Verify against the
    current upstream release and, if it still reproduces, open an issue on
    openqasm/openqasm and link it here; the pyqasm-side change can land independently for the
    other eight functions.
  • Spec overload resolution matters for the error messages: pow(int, uint) -> int is
    preferred over pow(float, float) -> float, which is preferred over the complex overload.
    exp and sqrt each have float -> float and complex -> complex forms.
  • Tests: tests/qasm3/test_expressions.py — one case per function covering a const
    declaration and a gate argument, plus arity and type-error cases.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestllm-assistedUsed LLMs to fine tune issue description.qasm3Related to openqasm3qasm3-coverageAdding support for qasm3 constructs

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions