From 6eab43d77c27d9081d418ca7a206055d256f5f48 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 21 Aug 2024 15:38:04 +0100 Subject: [PATCH 1/6] feat!: int operations other than widen/narrow have only width arg BREAKING CHANGE: `idivmod_checked`, `idivmod`, `idiv`, `idiv_checked`, `imod`, `ishl`, `ishr`, `irotl`, `irotr` operations now only have one width argument for all inputs and outputs rather than two. --- .../src/std_extensions/arithmetic/int_ops.rs | 36 +++-- .../arithmetic/int_ops/const_fold.rs | 120 ++++++++--------- hugr-passes/src/const_fold/test.rs | 127 ++++++++---------- hugr-py/src/hugr/std/int.py | 15 +-- .../std_extensions/arithmetic/int.json | 112 ++++----------- 5 files changed, 162 insertions(+), 248 deletions(-) diff --git a/hugr-core/src/std_extensions/arithmetic/int_ops.rs b/hugr-core/src/std_extensions/arithmetic/int_ops.rs index 342a887ee..274d171c9 100644 --- a/hugr-core/src/std_extensions/arithmetic/int_ops.rs +++ b/hugr-core/src/std_extensions/arithmetic/int_ops.rs @@ -113,21 +113,22 @@ impl MakeOpDef for IntOpDef { fn signature(&self) -> SignatureFunc { use IntOpDef::*; + let tv0 = int_tv(0); match self { iwiden_s | iwiden_u => CustomValidator::new( - int_polytype(2, vec![int_tv(0)], vec![int_tv(1)]), + int_polytype(2, vec![tv0.clone()], vec![int_tv(1)]), IOValidator { f_ge_s: false }, ) .into(), inarrow_s | inarrow_u => CustomValidator::new( - int_polytype(2, int_tv(0), sum_ty_with_err(int_tv(1))), + int_polytype(2, tv0.clone(), sum_ty_with_err(int_tv(1))), IOValidator { f_ge_s: true }, ) .into(), itobool => int_polytype(0, vec![int_type(0)], type_row![BOOL_T]).into(), ifrombool => int_polytype(0, type_row![BOOL_T], vec![int_type(0)]).into(), ieq | ine | ilt_u | ilt_s | igt_u | igt_s | ile_u | ile_s | ige_u | ige_s => { - int_polytype(1, vec![int_tv(0); 2], type_row![BOOL_T]).into() + int_polytype(1, vec![tv0; 2], type_row![BOOL_T]).into() } imax_u | imax_s | imin_u | imin_s | iadd | isub | imul | iand | ior | ixor => { ibinop_sig().into() @@ -135,38 +136,31 @@ impl MakeOpDef for IntOpDef { ineg | iabs | inot => iunop_sig().into(), //TODO inline idivmod_checked_u | idivmod_checked_s => { - let intpair: TypeRowRV = vec![int_tv(0), int_tv(1)].into(); + let intpair: TypeRowRV = vec![tv0; 2].into(); int_polytype( - 2, + 1, intpair.clone(), sum_ty_with_err(Type::new_tuple(intpair)), ) } .into(), idivmod_u | idivmod_s => { - let intpair: TypeRowRV = vec![int_tv(0), int_tv(1)].into(); - int_polytype(2, intpair.clone(), intpair.clone()) + let intpair: TypeRowRV = vec![tv0; 2].into(); + int_polytype(1, intpair.clone(), intpair.clone()) } .into(), - idiv_u | idiv_s => int_polytype(2, vec![int_tv(0), int_tv(1)], vec![int_tv(0)]).into(), + idiv_u | idiv_s => int_polytype(1, vec![tv0.clone(); 2], vec![tv0]).into(), idiv_checked_u | idiv_checked_s => { - int_polytype(2, vec![int_tv(0), int_tv(1)], sum_ty_with_err(int_tv(0))).into() + int_polytype(1, vec![tv0.clone(); 2], sum_ty_with_err(tv0)).into() } - imod_checked_u | imod_checked_s => int_polytype( - 2, - vec![int_tv(0), int_tv(1).clone()], - sum_ty_with_err(int_tv(1)), - ) - .into(), - imod_u | imod_s => { - int_polytype(2, vec![int_tv(0), int_tv(1).clone()], vec![int_tv(1)]).into() - } - ishl | ishr | irotl | irotr => { - int_polytype(2, vec![int_tv(0), int_tv(1)], vec![int_tv(0)]).into() + imod_checked_u | imod_checked_s => { + int_polytype(1, vec![tv0.clone(); 2], sum_ty_with_err(tv0)).into() } + imod_u | imod_s => int_polytype(1, vec![tv0.clone(); 2], vec![tv0]).into(), + ishl | ishr | irotl | irotr => int_polytype(1, vec![tv0.clone(); 2], vec![tv0]).into(), itostring_u | itostring_s => PolyFuncTypeRV::new( vec![LOG_WIDTH_TYPE_PARAM], - FuncValueType::new(vec![int_tv(0)], vec![STRING_TYPE]), + FuncValueType::new(vec![tv0], vec![STRING_TYPE]), ) .into(), } diff --git a/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs b/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs index 4c520963d..34725677f 100644 --- a/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs +++ b/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs @@ -590,17 +590,16 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idivmod_checked_u => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n.log_width() != logwidth0 || m.log_width() != logwidth1 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 { None } else { let q_type = INT_TYPES[logwidth0 as usize].to_owned(); - let r_type = INT_TYPES[logwidth1 as usize].to_owned(); + let r_type = q_type.clone(); let qr_type: Type = Type::new_tuple(vec![q_type, r_type]); let sum_type: SumType = sum_with_error(qr_type); let err_value = || { @@ -620,7 +619,7 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { let rval = nval % mval; Value::tuple(vec![ Value::extension(ConstInt::new_u(logwidth0, qval).unwrap()), - Value::extension(ConstInt::new_u(logwidth1, rval).unwrap()), + Value::extension(ConstInt::new_u(logwidth0, rval).unwrap()), ]) }; Some(vec![(0.into(), out_const)]) @@ -631,21 +630,20 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idivmod_u => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; let nval = n.value_u(); let mval = m.value_u(); - if n.log_width() != logwidth0 || m.log_width() != logwidth1 || mval == 0 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 || mval == 0 { None } else { let qval = nval / mval; let rval = nval % mval; let q = Value::extension(ConstInt::new_u(logwidth0, qval).unwrap()); - let r = Value::extension(ConstInt::new_u(logwidth1, rval).unwrap()); + let r = Value::extension(ConstInt::new_u(logwidth0, rval).unwrap()); Some(vec![(0.into(), q), (1.into(), r)]) } }, @@ -654,17 +652,17 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idivmod_checked_s => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n.log_width() != logwidth0 || m.log_width() != logwidth1 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 { None } else { let q_type = INT_TYPES[logwidth0 as usize].to_owned(); - let r_type = INT_TYPES[logwidth1 as usize].to_owned(); + let r_type = INT_TYPES[logwidth0 as usize].to_owned(); let qr_type: Type = Type::new_tuple(vec![q_type, r_type]); let sum_type: SumType = sum_with_error(qr_type); let err_value = || { @@ -683,7 +681,7 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { let (qval, rval) = divmod_s(nval, mval); Value::tuple(vec![ Value::extension(ConstInt::new_s(logwidth0, qval).unwrap()), - Value::extension(ConstInt::new_u(logwidth1, rval).unwrap()), + Value::extension(ConstInt::new_u(logwidth0, rval).unwrap()), ]) }; Some(vec![(0.into(), out_const)]) @@ -694,20 +692,20 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idivmod_s => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; let nval = n.value_s(); let mval = m.value_u(); - if n.log_width() != logwidth0 || m.log_width() != logwidth1 || mval == 0 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 || mval == 0 { None } else { let (qval, rval) = divmod_s(nval, mval); let q = Value::extension(ConstInt::new_s(logwidth0, qval).unwrap()); - let r = Value::extension(ConstInt::new_u(logwidth1, rval).unwrap()); + let r = Value::extension(ConstInt::new_u(logwidth0, rval).unwrap()); Some(vec![(0.into(), q), (1.into(), r)]) } }, @@ -716,13 +714,13 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idiv_checked_u => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n.log_width() != logwidth0 || m.log_width() != logwidth1 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 { None } else { let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); @@ -750,15 +748,15 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idiv_u => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; let nval = n.value_u(); let mval = m.value_u(); - if n.log_width() != logwidth0 || m.log_width() != logwidth1 || mval == 0 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 || mval == 0 { None } else { let q = Value::extension(ConstInt::new_u(logwidth0, nval / mval).unwrap()); @@ -770,16 +768,16 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::imod_checked_u => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n.log_width() != logwidth0 || m.log_width() != logwidth1 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 { None } else { - let int_out_type = INT_TYPES[logwidth1 as usize].to_owned(); + let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); let sum_type = sum_with_error(int_out_type.clone()); let err_value = || { let err_val = ConstError { @@ -794,7 +792,7 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { let out_const: Value = if mval == 0 { err_value() } else { - Value::extension(ConstInt::new_u(logwidth1, nval % mval).unwrap()) + Value::extension(ConstInt::new_u(logwidth0, nval % mval).unwrap()) }; Some(vec![(0.into(), out_const)]) } @@ -804,18 +802,18 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::imod_u => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; let nval = n.value_u(); let mval = m.value_u(); - if n.log_width() != logwidth0 || m.log_width() != logwidth1 || mval == 0 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 || mval == 0 { None } else { - let r = Value::extension(ConstInt::new_u(logwidth1, nval % mval).unwrap()); + let r = Value::extension(ConstInt::new_u(logwidth0, nval % mval).unwrap()); Some(vec![(0.into(), r)]) } }, @@ -824,13 +822,13 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idiv_checked_s => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n.log_width() != logwidth0 || m.log_width() != logwidth1 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 { None } else { let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); @@ -849,7 +847,7 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { err_value() } else { let (qval, _) = divmod_s(nval, mval); - Value::extension(ConstInt::new_s(logwidth1, qval).unwrap()) + Value::extension(ConstInt::new_s(logwidth0, qval).unwrap()) }; Some(vec![(0.into(), out_const)]) } @@ -859,15 +857,15 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::idiv_s => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; let nval = n.value_s(); let mval = m.value_u(); - if n.log_width() != logwidth0 || m.log_width() != logwidth1 || mval == 0 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 || mval == 0 { None } else { let (qval, _) = divmod_s(nval, mval); @@ -880,16 +878,16 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::imod_checked_s => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n.log_width() != logwidth0 || m.log_width() != logwidth1 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 { None } else { - let int_out_type = INT_TYPES[logwidth1 as usize].to_owned(); + let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); let sum_type = sum_with_error(int_out_type.clone()); let err_value = || { let err_val = ConstError { @@ -905,7 +903,7 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { err_value() } else { let (_, rval) = divmod_s(nval, mval); - Value::extension(ConstInt::new_u(logwidth1, rval).unwrap()) + Value::extension(ConstInt::new_u(logwidth0, rval).unwrap()) }; Some(vec![(0.into(), out_const)]) } @@ -915,19 +913,19 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::imod_s => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n, m): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; let nval = n.value_s(); let mval = m.value_u(); - if n.log_width() != logwidth0 || m.log_width() != logwidth1 || mval == 0 { + if n.log_width() != logwidth0 || m.log_width() != logwidth0 || mval == 0 { None } else { let (_, rval) = divmod_s(nval, mval); - let r = Value::extension(ConstInt::new_u(logwidth1, rval).unwrap()); + let r = Value::extension(ConstInt::new_u(logwidth0, rval).unwrap()); Some(vec![(0.into(), r)]) } }, @@ -1052,13 +1050,13 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::ishl => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n0, n1): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n0.log_width() != logwidth0 || n1.log_width() != logwidth1 { + if n0.log_width() != logwidth0 || n1.log_width() != logwidth0 { None } else { Some(vec![( @@ -1079,13 +1077,13 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::ishr => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n0, n1): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n0.log_width() != logwidth0 || n1.log_width() != logwidth1 { + if n0.log_width() != logwidth0 || n1.log_width() != logwidth0 { None } else { Some(vec![( @@ -1101,13 +1099,13 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::irotl => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n0, n1): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n0.log_width() != logwidth0 || n1.log_width() != logwidth1 { + if n0.log_width() != logwidth0 || n1.log_width() != logwidth0 { None } else { let n = n0.value_u(); @@ -1130,13 +1128,13 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { IntOpDef::irotr => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg0, arg1] = type_args else { + let [arg0] = type_args else { return None; }; let logwidth0: u8 = get_log_width(arg0).ok()?; - let logwidth1: u8 = get_log_width(arg1).ok()?; + let (n0, n1): (&ConstInt, &ConstInt) = get_pair_of_input_values(consts)?; - if n0.log_width() != logwidth0 || n1.log_width() != logwidth1 { + if n0.log_width() != logwidth0 || n1.log_width() != logwidth0 { None } else { let n = n0.value_u(); diff --git a/hugr-passes/src/const_fold/test.rs b/hugr-passes/src/const_fold/test.rs index 68960591e..28f43f31e 100644 --- a/hugr-passes/src/const_fold/test.rs +++ b/hugr-passes/src/const_fold/test.rs @@ -885,19 +885,16 @@ fn test_fold_imul() { #[test] fn test_fold_idivmod_checked_u() { // pseudocode: - // x0, x1 := int_u<5>(20), int_u<3>(0) + // x0, x1 := int_u<5>(20), int_u<5>(0) // x2 := idivmod_checked_u(x0, x1) // output x2 == error - let intpair: TypeRowRV = vec![INT_TYPES[5].clone(), INT_TYPES[3].clone()].into(); + let intpair: TypeRowRV = vec![INT_TYPES[5].clone(), INT_TYPES[5].clone()].into(); let sum_type = sum_with_error(Type::new_tuple(intpair)); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 0).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); let x2 = build - .add_dataflow_op( - IntOpDef::idivmod_checked_u.with_two_log_widths(5, 3), - [x0, x1], - ) + .add_dataflow_op(IntOpDef::idivmod_checked_u.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -922,52 +919,44 @@ fn test_fold_idivmod_checked_u() { #[test] fn test_fold_idivmod_u() { // pseudocode: - // x0, x1 := int_u<5>(20), int_u<3>(3); + // x0, x1 := int_u<3>(20), int_u<3>(3); // x2, x3 := idivmod_u(x0, x1); // 6, 2 - // x4 := iwiden_u<3,5>(x3); // 2 - // x5 := iadd<5>(x2, x4); // 8 - // output x5 == int_u<5>(8); - let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); - let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 20).unwrap())); + // x4 := iadd<3>(x2, x3); // 8 + // output x4 == int_u<5>(8); + let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[3].clone()])).unwrap(); + let x0 = build.add_load_const(Value::extension(ConstInt::new_u(3, 20).unwrap())); let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); let [x2, x3] = build - .add_dataflow_op(IntOpDef::idivmod_u.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::idivmod_u.with_log_width(3), [x0, x1]) .unwrap() .outputs_arr(); - let [x4] = build - .add_dataflow_op(IntOpDef::iwiden_u.with_two_log_widths(3, 5), [x3]) - .unwrap() - .outputs_arr(); - let x5 = build - .add_dataflow_op(IntOpDef::iadd.with_log_width(5), [x2, x4]) + let x4 = build + .add_dataflow_op(IntOpDef::iadd.with_log_width(3), [x2, x3]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), arithmetic::int_types::EXTENSION.to_owned(), ]) .unwrap(); - let mut h = build.finish_hugr_with_outputs(x5.outputs(), ®).unwrap(); + let mut h = build.finish_hugr_with_outputs(x4.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::extension(ConstInt::new_u(5, 8).unwrap()); + let expected = Value::extension(ConstInt::new_u(3, 8).unwrap()); assert_fully_folded(&h, &expected); } #[test] fn test_fold_idivmod_checked_s() { // pseudocode: - // x0, x1 := int_s<5>(-20), int_u<3>(0) + // x0, x1 := int_s<5>(-20), int_u<5>(0) // x2 := idivmod_checked_s(x0, x1) // output x2 == error - let intpair: TypeRowRV = vec![INT_TYPES[5].clone(), INT_TYPES[3].clone()].into(); + let intpair: TypeRowRV = vec![INT_TYPES[5].clone(), INT_TYPES[5].clone()].into(); let sum_type = sum_with_error(Type::new_tuple(intpair)); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, -20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 0).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); let x2 = build - .add_dataflow_op( - IntOpDef::idivmod_checked_s.with_two_log_widths(5, 3), - [x0, x1], - ) + .add_dataflow_op(IntOpDef::idivmod_checked_s.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1002,7 +991,7 @@ fn test_fold_idivmod_s(#[case] a: i64, #[case] b: u64, #[case] c: i64) { let x0 = build.add_load_const(Value::extension(ConstInt::new_s(6, a).unwrap())); let x1 = build.add_load_const(Value::extension(ConstInt::new_u(6, b).unwrap())); let [x2, x3] = build - .add_dataflow_op(IntOpDef::idivmod_s.with_two_log_widths(6, 6), [x0, x1]) + .add_dataflow_op(IntOpDef::idivmod_s.with_log_width(6), [x0, x1]) .unwrap() .outputs_arr(); let x4 = build @@ -1022,15 +1011,15 @@ fn test_fold_idivmod_s(#[case] a: i64, #[case] b: u64, #[case] c: i64) { #[test] fn test_fold_idiv_checked_u() { // pseudocode: - // x0, x1 := int_u<5>(20), int_u<3>(0) + // x0, x1 := int_u<5>(20), int_u<5>(0) // x2 := idiv_checked_u(x0, x1) // output x2 == error let sum_type = sum_with_error(INT_TYPES[5].to_owned()); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 0).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::idiv_checked_u.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::idiv_checked_u.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1055,14 +1044,14 @@ fn test_fold_idiv_checked_u() { #[test] fn test_fold_idiv_u() { // pseudocode: - // x0, x1 := int_u<5>(20), int_u<3>(3); + // x0, x1 := int_u<5>(20), int_u<5>(3); // x2 := idiv_u(x0, x1); // output x2 == int_u<5>(6); let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 3).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::idiv_u.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::idiv_u.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1078,15 +1067,15 @@ fn test_fold_idiv_u() { #[test] fn test_fold_imod_checked_u() { // pseudocode: - // x0, x1 := int_u<5>(20), int_u<3>(0) + // x0, x1 := int_u<5>(20), int_u<5>(0) // x2 := imod_checked_u(x0, x1) // output x2 == error - let sum_type = sum_with_error(INT_TYPES[3].to_owned()); + let sum_type = sum_with_error(INT_TYPES[5].to_owned()); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 0).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::imod_checked_u.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::imod_checked_u.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1111,14 +1100,14 @@ fn test_fold_imod_checked_u() { #[test] fn test_fold_imod_u() { // pseudocode: - // x0, x1 := int_u<5>(20), int_u<3>(3); + // x0, x1 := int_u<5>(20), int_u<5>(3); // x2 := imod_u(x0, x1); // output x2 == int_u<3>(2); - let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[3].clone()])).unwrap(); + let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 3).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::imod_u.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::imod_u.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1127,22 +1116,22 @@ fn test_fold_imod_u() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::extension(ConstInt::new_u(3, 2).unwrap()); + let expected = Value::extension(ConstInt::new_u(5, 2).unwrap()); assert_fully_folded(&h, &expected); } #[test] fn test_fold_idiv_checked_s() { // pseudocode: - // x0, x1 := int_s<5>(-20), int_u<3>(0) + // x0, x1 := int_s<5>(-20), int_u<5>(0) // x2 := idiv_checked_s(x0, x1) // output x2 == error let sum_type = sum_with_error(INT_TYPES[5].to_owned()); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, -20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 0).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::idiv_checked_s.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::idiv_checked_s.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1167,14 +1156,14 @@ fn test_fold_idiv_checked_s() { #[test] fn test_fold_idiv_s() { // pseudocode: - // x0, x1 := int_s<5>(-20), int_u<3>(3); + // x0, x1 := int_s<5>(-20), int_u<5>(3); // x2 := idiv_s(x0, x1); // output x2 == int_s<5>(-7); let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, -20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 3).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::idiv_s.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::idiv_s.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1190,15 +1179,15 @@ fn test_fold_idiv_s() { #[test] fn test_fold_imod_checked_s() { // pseudocode: - // x0, x1 := int_s<5>(-20), int_u<3>(0) + // x0, x1 := int_s<5>(-20), int_u<5>(0) // x2 := imod_checked_u(x0, x1) // output x2 == error - let sum_type = sum_with_error(INT_TYPES[3].to_owned()); + let sum_type = sum_with_error(INT_TYPES[5].to_owned()); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, -20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 0).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::imod_checked_s.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::imod_checked_s.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1223,14 +1212,14 @@ fn test_fold_imod_checked_s() { #[test] fn test_fold_imod_s() { // pseudocode: - // x0, x1 := int_s<5>(-20), int_u<3>(3); + // x0, x1 := int_s<5>(-20), int_u<5>(3); // x2 := imod_s(x0, x1); - // output x2 == int_u<3>(1); - let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[3].clone()])).unwrap(); + // output x2 == int_u<5>(1); + let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, -20).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 3).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::imod_s.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::imod_s.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1239,7 +1228,7 @@ fn test_fold_imod_s() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::extension(ConstInt::new_u(3, 1).unwrap()); + let expected = Value::extension(ConstInt::new_u(5, 1).unwrap()); assert_fully_folded(&h, &expected); } @@ -1364,9 +1353,9 @@ fn test_fold_ishl() { // output x2 == int_u<5>(112); let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, 14).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 3).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::ishl.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::ishl.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1387,9 +1376,9 @@ fn test_fold_ishr() { // output x2 == int_u<5>(1); let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, 14).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 3).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::ishr.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::ishr.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1410,9 +1399,9 @@ fn test_fold_irotl() { // output x2 == int_u<5>(2^30 + 2^31 + 1); let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, 14).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 61).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 61).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::irotl.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::irotl.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1433,9 +1422,9 @@ fn test_fold_irotr() { // output x2 == int_u<5>(2^30 + 2^31 + 1); let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[5].clone()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, 14).unwrap())); - let x1 = build.add_load_const(Value::extension(ConstInt::new_u(3, 3).unwrap())); + let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 3).unwrap())); let x2 = build - .add_dataflow_op(IntOpDef::irotr.with_two_log_widths(5, 3), [x0, x1]) + .add_dataflow_op(IntOpDef::irotr.with_log_width(5), [x0, x1]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), diff --git a/hugr-py/src/hugr/std/int.py b/hugr-py/src/hugr/std/int.py index 779f35312..d3375ee53 100644 --- a/hugr-py/src/hugr/std/int.py +++ b/hugr-py/src/hugr/std/int.py @@ -76,22 +76,19 @@ def to_value(self) -> val.Extension: @INT_OPS_EXTENSION.register_op( - signature=ext.OpDefSig( - tys.FunctionType([_int_tv(0), _int_tv(1)], [_int_tv(0), _int_tv(1)]) - ), + signature=ext.OpDefSig(tys.FunctionType.endo([_int_tv(0)] * 2)), ) @dataclass(frozen=True) class idivmod_u(RegisteredOp): """DivMod operation, has two inputs and two outputs.""" - arg1: int = 5 - arg2: int = 5 + width: int = 5 def type_args(self) -> list[tys.TypeArg]: - return [tys.BoundedNatArg(n=self.arg1), tys.BoundedNatArg(n=self.arg2)] + return [tys.BoundedNatArg(n=self.width)] def cached_signature(self) -> tys.FunctionType | None: - row: list[tys.Type] = [int_t(self.arg1), int_t(self.arg2)] + row: list[tys.Type] = [int_t(self.width)] * 2 return tys.FunctionType.endo(row) @classmethod @@ -99,8 +96,8 @@ def from_ext(cls, custom: ExtOp) -> Self | None: if custom.op_def() != cls.const_op_def: return None match custom.args: - case [tys.BoundedNatArg(n=a1), tys.BoundedNatArg(n=a2)]: - return cls(arg1=a1, arg2=a2) + case [tys.BoundedNatArg(n=a1)]: + return cls(width=a1) case _: msg = f"Invalid args: {custom.args}" raise AsExtOp.InvalidExtOp(msg) diff --git a/specification/std_extensions/arithmetic/int.json b/specification/std_extensions/arithmetic/int.json index 944a57e5f..30c157024 100644 --- a/specification/std_extensions/arithmetic/int.json +++ b/specification/std_extensions/arithmetic/int.json @@ -204,10 +204,6 @@ "description": "as idivmod_checked_s but discarding the second output", "signature": { "params": [ - { - "tp": "BoundedNat", - "bound": 7 - }, { "tp": "BoundedNat", "bound": 7 @@ -238,7 +234,7 @@ "args": [ { "tya": "Variable", - "idx": 1, + "idx": 0, "cached_decl": { "tp": "BoundedNat", "bound": 7 @@ -294,10 +290,6 @@ "description": "as idivmod_checked_u but discarding the second output", "signature": { "params": [ - { - "tp": "BoundedNat", - "bound": 7 - }, { "tp": "BoundedNat", "bound": 7 @@ -328,7 +320,7 @@ "args": [ { "tya": "Variable", - "idx": 1, + "idx": 0, "cached_decl": { "tp": "BoundedNat", "bound": 7 @@ -384,10 +376,6 @@ "description": "as idivmod_s but discarding the second output", "signature": { "params": [ - { - "tp": "BoundedNat", - "bound": 7 - }, { "tp": "BoundedNat", "bound": 7 @@ -418,7 +406,7 @@ "args": [ { "tya": "Variable", - "idx": 1, + "idx": 0, "cached_decl": { "tp": "BoundedNat", "bound": 7 @@ -457,10 +445,6 @@ "description": "as idivmod_u but discarding the second output", "signature": { "params": [ - { - "tp": "BoundedNat", - "bound": 7 - }, { "tp": "BoundedNat", "bound": 7 @@ -491,7 +475,7 @@ "args": [ { "tya": "Variable", - "idx": 1, + "idx": 0, "cached_decl": { "tp": "BoundedNat", "bound": 7 @@ -530,10 +514,6 @@ "description": "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 Date: Wed, 21 Aug 2024 16:04:40 +0100 Subject: [PATCH 2/6] fix descriptions Co-authored-by: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> --- specification/std_extensions/arithmetic/int.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/std_extensions/arithmetic/int.json b/specification/std_extensions/arithmetic/int.json index 30c157024..2709dcfba 100644 --- a/specification/std_extensions/arithmetic/int.json +++ b/specification/std_extensions/arithmetic/int.json @@ -511,7 +511,7 @@ "idivmod_checked_s": { "extension": "arithmetic.int", "name": "idivmod_checked_s", - "description": "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 Date: Wed, 21 Aug 2024 15:43:14 +0100 Subject: [PATCH 3/6] remove redundant todo --- hugr-core/src/std_extensions/arithmetic/int_ops.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/hugr-core/src/std_extensions/arithmetic/int_ops.rs b/hugr-core/src/std_extensions/arithmetic/int_ops.rs index 274d171c9..0463799f6 100644 --- a/hugr-core/src/std_extensions/arithmetic/int_ops.rs +++ b/hugr-core/src/std_extensions/arithmetic/int_ops.rs @@ -134,7 +134,6 @@ impl MakeOpDef for IntOpDef { ibinop_sig().into() } ineg | iabs | inot => iunop_sig().into(), - //TODO inline idivmod_checked_u | idivmod_checked_s => { let intpair: TypeRowRV = vec![tv0; 2].into(); int_polytype( From fad3d787326d26418245a5d9a89376b6725b83d0 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 21 Aug 2024 16:08:12 +0100 Subject: [PATCH 4/6] fix descriptions --- hugr-core/src/std_extensions/arithmetic/int_ops.rs | 8 ++++---- specification/std_extensions/arithmetic/int.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hugr-core/src/std_extensions/arithmetic/int_ops.rs b/hugr-core/src/std_extensions/arithmetic/int_ops.rs index 0463799f6..c3785ca9a 100644 --- a/hugr-core/src/std_extensions/arithmetic/int_ops.rs +++ b/hugr-core/src/std_extensions/arithmetic/int_ops.rs @@ -193,13 +193,13 @@ impl MakeOpDef for IntOpDef { isub => "subtraction modulo 2^N (signed and unsigned versions are the same op)", ineg => "negation modulo 2^N (signed and unsigned versions are the same op)", imul => "multiplication modulo 2^N (signed and unsigned versions are the same op)", - idivmod_checked_u => "given unsigned integers 0 <= n < 2^N, 0 <= m < 2^M, generates unsigned q, r where \ + idivmod_checked_u => "given unsigned integers 0 <= n < 2^N, 0 <= m < 2^N, generates unsigned q, r where \ q*m+r=n, 0<=r "given unsigned integers 0 <= n < 2^N, 0 <= m < 2^M, generates unsigned q, r where \ + idivmod_u => "given unsigned integers 0 <= n < 2^N, 0 <= m < 2^N, generates unsigned q, r where \ q*m+r=n, 0<=r "given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^M, generates \ + idivmod_checked_s => "given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^N, generates \ signed q and unsigned r where q*m+r=n, 0<=r "given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^M, generates \ + idivmod_s => "given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^N, generates \ signed q and unsigned r where q*m+r=n, 0<=r "as idivmod_checked_u but discarding the second output", idiv_u => "as idivmod_u but discarding the second output", diff --git a/specification/std_extensions/arithmetic/int.json b/specification/std_extensions/arithmetic/int.json index 2709dcfba..6eb546736 100644 --- a/specification/std_extensions/arithmetic/int.json +++ b/specification/std_extensions/arithmetic/int.json @@ -816,7 +816,7 @@ "idivmod_u": { "extension": "arithmetic.int", "name": "idivmod_u", - "description": "given unsigned integers 0 <= n < 2^N, 0 <= m < 2^M, generates unsigned q, r where q*m+r=n, 0<=r Date: Wed, 21 Aug 2024 16:11:59 +0100 Subject: [PATCH 5/6] update spec table --- specification/hugr.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/specification/hugr.md b/specification/hugr.md index e2bc960ee..20ed03b4c 100644 --- a/specification/hugr.md +++ b/specification/hugr.md @@ -1771,27 +1771,27 @@ Other operations: | `isub` | `int`, `int` | `int` | subtraction modulo 2^N (signed and unsigned versions are the same op) | | `ineg` | `int` | `int` | negation modulo 2^N (signed and unsigned versions are the same op) | | `imul` | `int`, `int` | `int` | multiplication modulo 2^N (signed and unsigned versions are the same op) | -| `idivmod_checked_u`( \* ) | `int`, `int` | `Sum(#(int, int), #(ErrorType))` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^M, generates unsigned q, r where q\*m+r=n, 0\<=r\` | `int`, `int` | `(int, int)` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^M, generates unsigned q, r where q\*m+r=n, 0\<=r\`( \* ) | `int`, `int` | `Sum(#(int, int), #(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\`( \* ) | `int`, `int` | `(int, int)` | 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\` ( \* ) | `int`, `int` | `Sum(#(int),#( ErrorType))` | as `idivmod_checked_u` but discarding the second output | -| `idiv_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the second output | -| `imod_checked_u` ( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_u` but discarding the first output | -| `imod_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the first output | -| `idiv_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the second output | -| `idiv_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the second output | -| `imod_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the first output | -| `imod_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the first output | +| `idivmod_checked_u`( \* ) | `int`, `int` | `Sum(#(int, int), #(ErrorType))` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^N, generates unsigned q, r where q\*m+r=n, 0\<=r\` | `int`, `int` | `(int, int)` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^N, generates unsigned q, r where q\*m+r=n, 0\<=r\`( \* ) | `int`, `int` | `Sum(#(int, int), #(ErrorType))` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^N, generates signed q and unsigned r where q\*m+r=n, 0\<=r\`( \* ) | `int`, `int` | `(int, int)` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^N, generates signed q and unsigned r where q\*m+r=n, 0\<=r\` ( \* ) | `int`, `int` | `Sum(#(int),#( ErrorType))` | as `idivmod_checked_u` but discarding the second output | +| `idiv_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the second output | +| `imod_checked_u` ( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_u` but discarding the first output | +| `imod_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the first output | +| `idiv_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the second output | +| `idiv_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the second output | +| `imod_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the first output | +| `imod_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the first output | | `iabs` | `int` | `int` | convert signed to unsigned by taking absolute value | | `iand` | `int`, `int` | `int` | bitwise AND | | `ior` | `int`, `int` | `int` | bitwise OR | | `ixor` | `int`, `int` | `int` | bitwise XOR | | `inot` | `int` | `int` | bitwise NOT | -| `ishl`( \* ) | `int`, `int` | `int` | shift first input left by k bits where k is unsigned interpretation of second input (leftmost bits dropped, rightmost bits set to zero) | -| `ishr`( \* ) | `int`, `int` | `int` | shift first input right by k bits where k is unsigned interpretation of second input (rightmost bits dropped, leftmost bits set to zero) | -| `irotl`( \* ) | `int`, `int` | `int` | rotate first input left by k bits where k is unsigned interpretation of second input (leftmost bits replace rightmost bits) | -| `irotr`( \* ) | `int`, `int` | `int` | rotate first input right by k bits where k is unsigned interpretation of second input (rightmost bits replace leftmost bits) | +| `ishl`( \* ) | `int`, `int` | `int` | shift first input left by k bits where k is unsigned interpretation of second input (leftmost bits dropped, rightmost bits set to zero) | +| `ishr`( \* ) | `int`, `int` | `int` | shift first input right by k bits where k is unsigned interpretation of second input (rightmost bits dropped, leftmost bits set to zero) | +| `irotl`( \* ) | `int`, `int` | `int` | rotate first input left by k bits where k is unsigned interpretation of second input (leftmost bits replace rightmost bits) | +| `irotr`( \* ) | `int`, `int` | `int` | rotate first input right by k bits where k is unsigned interpretation of second input (rightmost bits replace leftmost bits) | | `itostring_u` | `int` | `string` | decimal string representation of unsigned integer | | `itostring_s` | `int` | `string` | decimal string representation of signed integer | From bc6fba6c0721270df3945cf0cb185d7173d735b5 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 21 Aug 2024 16:12:57 +0100 Subject: [PATCH 6/6] format table --- specification/hugr.md | 67 ++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/specification/hugr.md b/specification/hugr.md index 20ed03b4c..0de89e4cf 100644 --- a/specification/hugr.md +++ b/specification/hugr.md @@ -1761,39 +1761,40 @@ Comparisons: Other operations: -| Name | Inputs | Outputs | Meaning | -| ---------------------- | ------------------ | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `imax_u` | `int`, `int` | `int` | maximum of unsigned integers | -| `imax_s` | `int`, `int` | `int` | maximum of signed integers | -| `imin_u` | `int`, `int` | `int` | minimum of unsigned integers | -| `imin_s` | `int`, `int` | `int` | minimum of signed integers | -| `iadd` | `int`, `int` | `int` | addition modulo 2^N (signed and unsigned versions are the same op) | -| `isub` | `int`, `int` | `int` | subtraction modulo 2^N (signed and unsigned versions are the same op) | -| `ineg` | `int` | `int` | negation modulo 2^N (signed and unsigned versions are the same op) | -| `imul` | `int`, `int` | `int` | multiplication modulo 2^N (signed and unsigned versions are the same op) | -| `idivmod_checked_u`( \* ) | `int`, `int` | `Sum(#(int, int), #(ErrorType))` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^N, generates unsigned q, r where q\*m+r=n, 0\<=r\` | `int`, `int` | `(int, int)` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^N, generates unsigned q, r where q\*m+r=n, 0\<=r\`( \* ) | `int`, `int` | `Sum(#(int, int), #(ErrorType))` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^N, generates signed q and unsigned r where q\*m+r=n, 0\<=r\`( \* ) | `int`, `int` | `(int, int)` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^N, generates signed q and unsigned r where q\*m+r=n, 0\<=r\` ( \* ) | `int`, `int` | `Sum(#(int),#( ErrorType))` | as `idivmod_checked_u` but discarding the second output | -| `idiv_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the second output | -| `imod_checked_u` ( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_u` but discarding the first output | -| `imod_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the first output | -| `idiv_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the second output | -| `idiv_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the second output | -| `imod_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the first output | -| `imod_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the first output | -| `iabs` | `int` | `int` | convert signed to unsigned by taking absolute value | -| `iand` | `int`, `int` | `int` | bitwise AND | -| `ior` | `int`, `int` | `int` | bitwise OR | -| `ixor` | `int`, `int` | `int` | bitwise XOR | -| `inot` | `int` | `int` | bitwise NOT | -| `ishl`( \* ) | `int`, `int` | `int` | shift first input left by k bits where k is unsigned interpretation of second input (leftmost bits dropped, rightmost bits set to zero) | -| `ishr`( \* ) | `int`, `int` | `int` | shift first input right by k bits where k is unsigned interpretation of second input (rightmost bits dropped, leftmost bits set to zero) | -| `irotl`( \* ) | `int`, `int` | `int` | rotate first input left by k bits where k is unsigned interpretation of second input (leftmost bits replace rightmost bits) | -| `irotr`( \* ) | `int`, `int` | `int` | rotate first input right by k bits where k is unsigned interpretation of second input (rightmost bits replace leftmost bits) | -| `itostring_u` | `int` | `string` | decimal string representation of unsigned integer | -| `itostring_s` | `int` | `string` | decimal string representation of signed integer | +| Name | Inputs | Outputs | Meaning | +|------------------------------|--------------------|----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `imax_u` | `int`, `int` | `int` | maximum of unsigned integers | +| `imax_s` | `int`, `int` | `int` | maximum of signed integers | +| `imin_u` | `int`, `int` | `int` | minimum of unsigned integers | +| `imin_s` | `int`, `int` | `int` | minimum of signed integers | +| `iadd` | `int`, `int` | `int` | addition modulo 2^N (signed and unsigned versions are the same op) | +| `isub` | `int`, `int` | `int` | subtraction modulo 2^N (signed and unsigned versions are the same op) | +| `ineg` | `int` | `int` | negation modulo 2^N (signed and unsigned versions are the same op) | +| `imul` | `int`, `int` | `int` | multiplication modulo 2^N (signed and unsigned versions are the same op) | +| `idivmod_checked_u`( \* ) | `int`, `int` | `Sum(#(int, int), #(ErrorType))` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^N, generates unsigned q, r where q\*m+r=n, 0\<=r\` | `int`, `int` | `(int, int)` | given unsigned integers 0 \<= n \< 2^N, 0 \<= m \< 2^N, generates unsigned q, r where q\*m+r=n, 0\<=r\`( \* ) | `int`, `int` | `Sum(#(int, int), #(ErrorType))` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^N, generates signed q and unsigned r where q\*m+r=n, 0\<=r\`( \* ) | `int`, `int` | `(int, int)` | given signed integer -2^{N-1} \<= n \< 2^{N-1} and unsigned 0 \<= m \< 2^N, generates signed q and unsigned r where q\*m+r=n, 0\<=r\` ( \* ) | `int`, `int` | `Sum(#(int),#( ErrorType))` | as `idivmod_checked_u` but discarding the second output | +| `idiv_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the second output | +| `imod_checked_u` ( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_u` but discarding the first output | +| `imod_u` | `int`, `int` | `int` | as `idivmod_u` but discarding the first output | +| `idiv_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the second output | +| `idiv_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the second output | +| `imod_checked_s`( \* ) | `int`, `int` | `Sum(#(int), #(ErrorType))` | as `idivmod_checked_s` but discarding the first output | +| `imod_s` | `int`, `int` | `int` | as `idivmod_s` but discarding the first output | +| `iabs` | `int` | `int` | convert signed to unsigned by taking absolute value | +| `iand` | `int`, `int` | `int` | bitwise AND | +| `ior` | `int`, `int` | `int` | bitwise OR | +| `ixor` | `int`, `int` | `int` | bitwise XOR | +| `inot` | `int` | `int` | bitwise NOT | +| `ishl`( \* ) | `int`, `int` | `int` | shift first input left by k bits where k is unsigned interpretation of second input (leftmost bits dropped, rightmost bits set to zero) | +| `ishr`( \* ) | `int`, `int` | `int` | shift first input right by k bits where k is unsigned interpretation of second input (rightmost bits dropped, leftmost bits set to zero) | +| `irotl`( \* ) | `int`, `int` | `int` | rotate first input left by k bits where k is unsigned interpretation of second input (leftmost bits replace rightmost bits) | +| `irotr`( \* ) | `int`, `int` | `int` | rotate first input right by k bits where k is unsigned interpretation of second input (rightmost bits replace leftmost bits) | +| `itostring_u` | `int` | `string` | decimal string representation of unsigned integer | +| `itostring_s` | `int` | `string` | decimal string representation of signed integer | + #### `arithmetic.float.types`