# muldiv

x * y / z with a 512-bit product: no overflow before division. UINT256 rounds down, INT256 truncates toward zero, unless a rounding mode is given. Errors when z is zero or result does not fit its type. NULL propagates. Native integer arguments fit both forms: cast them to UINT256 or INT256.

Canonical HTML: <https://determica.com/docs/functions/muldiv>

- Kind: scalar function
- Category: [EVM utilities](/docs/category/evm-utilities.md)
- Tags: Types, EVM

x * y / z with a 512-bit product: no overflow before division. UINT256 rounds down, INT256 truncates toward zero, unless a rounding mode is given. Errors when z is zero or result does not fit its type. NULL propagates. Native integer arguments fit both forms: cast them to UINT256 or INT256.

## Overload 1: muldiv(UINT256, UINT256, UINT256)

```sql
muldiv(UINT256, UINT256, UINT256)
```

Forms the full 512-bit product x * y, divides it by z, and returns the floor as UINT256.

- Kind: scalar
- Execution context: Offline
- Behavior: Transform
- Execution modes: Offline
- Input shape: Scalar Arguments
- Planning contract: Runtime
- Cardinality: One Per Input
- Determinism: Deterministic
- Return shape: Scalar
- Schema stability: Fixed
- Stability: Stable
- Side effects: None documented

### Inputs

- `x` (UINT256; required; positional) — UINT256, or INT256 for a signed result, in the 512-bit product.
- `y` (UINT256; required; positional) — Same type as x, in the 512-bit product.
- `z` (UINT256; required; positional) — Non-zero, same type as x.

### Returns

Floor quotient

UINT256 floor(x * y / z), or NULL when any input is NULL.

- `result` (UINT256)

Floor quotient. UINT256 floor(x * y / z), or NULL when any input is NULL.

### Examples

_Local SQL · Local_

```sql
SELECT muldiv(7::UINT256, 6::UINT256, 4::UINT256)::VARCHAR AS result;
-- => [{"result":"10"}]
```

## Overload 2: muldiv(UINT256, UINT256, UINT256, TINYINT)

```sql
muldiv(UINT256, UINT256, UINT256, TINYINT)
```

Computes (x * y) / z for UINT256 inputs using the supplied rounding mode. Rounding modes: 0=floor, 1=ceil, 2=trunc, 3=expand, 4=half-up. Because UINT256 is unsigned, floor and trunc both round down, ceil and expand both round up, and half-up rounds to nearest with ties upward. Compatibility behavior for unsupported TINYINT values is parity-based: odd values round up and even values round down.

- Kind: scalar
- Execution context: Offline
- Behavior: Transform
- Execution modes: Offline
- Input shape: Scalar Arguments
- Planning contract: Runtime
- Cardinality: One Per Input
- Determinism: Deterministic
- Return shape: Scalar
- Schema stability: Fixed
- Stability: Stable
- Side effects: None documented

### Inputs

- `x` (UINT256; required; positional) — UINT256, or INT256 for a signed result, in the 512-bit product.
- `y` (UINT256; required; positional) — Same type as x, in the 512-bit product.
- `z` (UINT256; required; positional) — Non-zero, same type as x.
- `rounding` (TINYINT; required; positional) — TINYINT mode 0=floor, 1=ceil, 2=trunc, 3=expand, or 4=half-up.

### Returns

Rounded quotient

UINT256 rounded quotient; NULL when any input is NULL. Rounding can itself cause quotient overflow.

- `result` (UINT256)

Rounded quotient. UINT256 rounded quotient; NULL when any input is NULL. Rounding can itself cause quotient overflow.

### Examples

_Local SQL · Local_

```sql
SELECT muldiv(5::UINT256, 1::UINT256, 2::UINT256, 4::TINYINT)::VARCHAR AS result;
-- => [{"result":"3"}]
```

## Overload 3: muldiv(INT256, INT256, INT256)

```sql
muldiv(INT256, INT256, INT256)
```

512-bit product of INT256 magnitudes over |z|, sign carried separately, truncated toward zero as INT256 `/`.

- Kind: scalar
- Execution context: Offline
- Behavior: Transform
- Execution modes: Offline
- Input shape: Scalar Arguments
- Planning contract: Runtime
- Cardinality: One Per Input
- Determinism: Deterministic
- Return shape: Scalar
- Schema stability: Fixed
- Stability: Stable
- Side effects: None documented

### Inputs

- `x` (INT256; required; positional) — UINT256, or INT256 for a signed result, in the 512-bit product.
- `y` (INT256; required; positional) — Same type as x, in the 512-bit product.
- `z` (INT256; required; positional) — Non-zero, same type as x.

### Returns

Signed quotient

INT256 x * y / z truncated toward zero; NULL when any input is NULL. Quotient outside INT256 errors.

- `result` (INT256)

Signed quotient. INT256 x * y / z truncated toward zero; NULL when any input is NULL. Quotient outside INT256 errors.

### Examples

_Local SQL · Local_

```sql
-- A signed difference in basis points with two decimals: (a - b) * 1e6 / b
SELECT format_units(muldiv((2400::INT256 - 2410::INT256), 1000000::INT256, 2410::INT256), 2) AS bps;
-- => [{"bps":"-41.49"}]
```

## Overload 4: muldiv(INT256, INT256, INT256, TINYINT)

```sql
muldiv(INT256, INT256, INT256, TINYINT)
```

INT256 x * y / z, exact, rounded by mode. Rounding modes: 0=floor (toward -inf), 1=ceil (toward +inf), 2=trunc (toward zero), 3=expand (away from zero), 4=half-up (nearest, ties toward +inf). Other modes error.

- Kind: scalar
- Execution context: Offline
- Behavior: Transform
- Execution modes: Offline
- Input shape: Scalar Arguments
- Planning contract: Runtime
- Cardinality: One Per Input
- Determinism: Deterministic
- Return shape: Scalar
- Schema stability: Fixed
- Stability: Stable
- Side effects: None documented

### Inputs

- `x` (INT256; required; positional) — UINT256, or INT256 for a signed result, in the 512-bit product.
- `y` (INT256; required; positional) — Same type as x, in the 512-bit product.
- `z` (INT256; required; positional) — Non-zero, same type as x.
- `rounding` (TINYINT; required; positional) — TINYINT mode 0=floor, 1=ceil, 2=trunc, 3=expand, or 4=half-up (ties toward positive infinity).

### Returns

Rounded signed quotient

INT256 rounded quotient; NULL when any input is NULL. Quotient outside INT256 or unknown mode errors.

- `result` (INT256)

Rounded signed quotient. INT256 rounded quotient; NULL when any input is NULL. Quotient outside INT256 or unknown mode errors.

### Examples

_Local SQL · Local_

```sql
SELECT muldiv((-7)::INT256, 1::INT256, 2::INT256, 0::TINYINT)::VARCHAR AS floor_half, muldiv((-7)::INT256, 1::INT256, 2::INT256)::VARCHAR AS trunc_half;
-- => [{"floor_half":"-4","trunc_half":"-3"}]
```

## Related functions

- [fixed_mul](/docs/functions/fixed_mul.md) — See Also
- [fixed_div](/docs/functions/fixed_div.md) — See Also
- [try_mul](/docs/functions/try_mul.md) — See Also
- [evm_ceil_div](/docs/functions/evm_ceil_div.md) — See Also
