Skip to content

Commit

Permalink
feat!: Add panicking integer division ops
Browse files Browse the repository at this point in the history
We rename the existing sumtype-returning ops using the `_checked`
scheme.

The new ops, matching the semantics of webassembly ops, are given the
existing names.
  • Loading branch information
doug-q committed Oct 31, 2023
1 parent 46d5017 commit f201ff1
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 13 deletions.
18 changes: 12 additions & 6 deletions specification/hugr.md
Original file line number Diff line number Diff line change
Expand Up @@ -1659,12 +1659,18 @@ Other operations:
| `isub<N>` | `int<N>`, `int<N>` | `int<N>` | subtraction modulo 2^N (signed and unsigned versions are the same op) |
| `ineg<N>` | `int<N>` | `int<N>` | negation modulo 2^N (signed and unsigned versions are the same op) |
| `imul<N>` | `int<N>`, `int<N>` | `int<N>` | multiplication modulo 2^N (signed and unsigned versions are the same op) |
| `idivmod_u<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum((int<N>, int<M>), ErrorType)` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^M, generates unsigned q, r where q\*m+r=n, 0\<=r\<m (m=0 is an error) |
| `idivmod_s<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum((int<N>, int<M>), ErrorType)` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^M, generates signed q and unsigned r where q\*m+r=n, 0\<=r\<m (m=0 is an error) |
| `idiv_u<N,M>` | `int<N>`, `int<M>` | `Sum(int<N>, ErrorType)` | as `idivmod_u` but discarding the second output |
| `imod_u<N,M>` | `int<N>`, `int<M>` | `Sum(int<M>, ErrorType)` | as `idivmod_u` but discarding the first output |
| `idiv_s<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum(int<N>, ErrorType)` | as `idivmod_s` but discarding the second output |
| `imod_s<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum(int<M>, ErrorType)` | as `idivmod_s` but discarding the first output |
| `idivmod_checked_u<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum((int<N>, int<M>), ErrorType)` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^M, generates unsigned q, r where q\*m+r=n, 0\<=r\<m (m=0 is an error) |
| `idivmod_u<N,M>` | `int<N>`, `int<M>` | `(int<N>, int<M>)` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^M, generates unsigned q, r where q\*m+r=n, 0\<=r\<m (m=0 will call panic) |
| `idivmod_checked_s<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum((int<N>, int<M>), ErrorType)` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^M, generates signed q and unsigned r where q\*m+r=n, 0\<=r\<m (m=0 is an error) |
| `idivmod_s<N,M>`( \* ) | `int<N>`, `int<M>` | `(int<N>, int<M>)` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^M, generates signed q and unsigned r where q\*m+r=n, 0\<=r\<m (m=0 will call panic) |
| `idiv_checked_u<N,M>` ( \* ) | `int<N>`, `int<M>` | `Sum(int<N>, ErrorType)` | as `idivmod_checked_u` but discarding the second output |
| `idiv_u<N,M>` | `int<N>`, `int<M>` | `int<N>` | as `idivmod_u` but discarding the second output |
| `imod_checked_u<N,M>` ( \* ) | `int<N>`, `int<M>` | `Sum(int<M>, ErrorType)` | as `idivmod_checked_u` but discarding the first output |
| `imod_u<N,M>` | `int<N>`, `int<M>` | `int<M>` | as `idivmod_u` but discarding the first output |
| `idiv_checked_s<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum(int<N>, ErrorType)` | as `idivmod_checked_s` but discarding the second output |
| `idiv_s<N,M>` | `int<N>`, `int<M>` | `int<N>` | as `idivmod_s` but discarding the second output |
| `imod_checked_s<N,M>`( \* ) | `int<N>`, `int<M>` | `Sum(int<M>, ErrorType)` | as `idivmod_checked_s` but discarding the first output |
| `imod_s<N,M>` | `int<N>`, `int<M>` | `int<M>` | as `idivmod_s` but discarding the first output |
| `iabs<N>` | `int<N>` | `int<N>` | convert signed to unsigned by taking absolute value |
| `iand<N>` | `int<N>`, `int<N>` | `int<N>` | bitwise AND |
| `ior<N>` | `int<N>`, `int<N>` | `int<N>` | bitwise OR |
Expand Down
91 changes: 84 additions & 7 deletions src/std_extensions/arithmetic/int_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn iunop_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
))
}

fn idivmod_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
fn idivmod_checked_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
let [arg0, arg1] = collect_array(arg_values);
let intpair: TypeRow = vec![int_type(arg0.clone()), int_type(arg1.clone())].into();
Ok(FunctionType::new(
Expand All @@ -87,22 +87,47 @@ fn idivmod_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
))
}

fn idiv_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
fn idivmod_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
let [arg0, arg1] = collect_array(arg_values);
let intpair: TypeRow = vec![int_type(arg0.clone()), int_type(arg1.clone())].into();
Ok(FunctionType::new(
intpair.clone(),
vec![Type::new_tuple(intpair)],
))
}

fn idiv_checked_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
let [arg0, arg1] = collect_array(arg_values);
Ok(FunctionType::new(
vec![int_type(arg0.clone()), int_type(arg1.clone())],
vec![Type::new_sum(vec![int_type(arg0.clone()), ERROR_TYPE])],
))
}

fn imod_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
fn idiv_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
let [arg0, arg1] = collect_array(arg_values);
Ok(FunctionType::new(
vec![int_type(arg0.clone()), int_type(arg1.clone())],
vec![int_type(arg0.clone())],
))
}

fn imod_checked_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
let [arg0, arg1] = collect_array(arg_values);
Ok(FunctionType::new(
vec![int_type(arg0.clone()), int_type(arg1.clone())],
vec![Type::new_sum(vec![int_type(arg1.clone()), ERROR_TYPE])],
))
}

fn imod_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
let [arg0, arg1] = collect_array(arg_values);
Ok(FunctionType::new(
vec![int_type(arg0.clone()), int_type(arg1.clone())],
vec![int_type(arg1.clone())],
))
}

fn ish_sig(arg_values: &[TypeArg]) -> Result<FunctionType, SignatureError> {
let [arg0, arg1] = collect_array(arg_values);
Ok(FunctionType::new(
Expand Down Expand Up @@ -313,24 +338,52 @@ pub fn extension() -> Extension {
.unwrap();
extension
.add_op_custom_sig_simple(
"idivmod_u".into(),
"idivmod_checked_u".into(),
"given unsigned integers 0 <= n < 2^N, 0 <= m < 2^M, generates unsigned q, r where \
q*m+r=n, 0<=r<m (m=0 is an error)"
.to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
idivmod_checked_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"idivmod_u".into(),
"given unsigned integers 0 <= n < 2^N, 0 <= m < 2^M, generates unsigned q, r where \
q*m+r=n, 0<=r<m (m=0 will call panic)"
.to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
idivmod_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"idivmod_s".into(),
"idivmod_checked_s".into(),
"given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^M, generates \
signed q and unsigned r where q*m+r=n, 0<=r<m (m=0 is an error)"
.to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
idivmod_checked_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"idivmod_s".into(),
"given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^M, generates \
signed q and unsigned r where q*m+r=n, 0<=r<m (m=0 will call panic)"
.to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
idivmod_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"idiv_checked_u".into(),
"as idivmod_checked_u but discarding the second output".to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
idiv_checked_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"idiv_u".into(),
Expand All @@ -339,20 +392,44 @@ pub fn extension() -> Extension {
idiv_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"imod_checked_u".into(),
"as idivmod_checked_u but discarding the first output".to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
imod_checked_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"imod_u".into(),
"as idivmod_u but discarding the first output".to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
idiv_sig,
imod_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"idiv_checked_s".into(),
"as idivmod_checked_s but discarding the second output".to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
idiv_checked_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"idiv_s".into(),
"as idivmod_s but discarding the second output".to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
imod_sig,
idiv_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"imod_checked_s".into(),
"as idivmod_checked_s but discarding the first output".to_owned(),
vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM],
imod_checked_sig,
)
.unwrap();
extension
Expand Down

0 comments on commit f201ff1

Please sign in to comment.