Skip to content

Commit

Permalink
Issue intel#336: Added power functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Sanchit-kumar committed May 6, 2023
1 parent 834fec6 commit c6df19c
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ a_xor_b <= a ^ b; // xor
and_a <= a.and(); // unary and
or_a <= a.or(); // unary or
xor_a <= a.xor(); // unary xor
a_pow_b <= a.pow(b);// power
a_plus_b <= a + b; // addition
a_sub_b <= a - b; // subtraction
a_times_b <= a * b; // multiplication
Expand Down
1 change: 1 addition & 0 deletions doc/tutorials/chapter_2/00_basic_logic.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ a_xor_b <= a ^ b; // xor
and_a <= a.and(); // unary and
or_a <= a.or(); // unary or
xor_a <= a.xor(); // unary xor
a_pow_b <= a.pow(b);// power
a_plus_b <= a + b; // addition
a_sub_b <= a - b; // subtraction
a_times_b <= a * b; // multiplication
Expand Down
3 changes: 3 additions & 0 deletions lib/src/logic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,9 @@ class Logic {
/// Logical bitwise XOR.
Logic operator ^(Logic other) => Xor2Gate(this, other).out;

/// Power operation
Logic pow(dynamic other) => Power(this, other).out;

/// Addition.
///
/// WARNING: Signed math is not fully tested.
Expand Down
9 changes: 9 additions & 0 deletions lib/src/modules/gates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,15 @@ class Xor2Gate extends _TwoInputBitwiseGate {
: super((a, b) => a ^ b, '^', in0, in1, name: name);
}

/// A two-input power module.
class Power extends _TwoInputBitwiseGate {
/// Calculates [in0] raise to power of [in1].
///
/// [in1] can be either a [Logic] or [int].
Power(Logic in0, dynamic in1, {String name = 'power'})
: super((a, b) => a.pow(b), '**', in0, in1, name: name);
}

/// A two-input addition module.
class Add extends _TwoInputBitwiseGate {
/// Calculates the sum of [in0] and [in1].
Expand Down
36 changes: 36 additions & 0 deletions lib/src/values/logic_value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,13 @@ abstract class LogicValue {
/// invalid, [neq] will return `x`.
LogicValue neq(dynamic other) => _doCompare(other, (a, b) => a != b);

/// Power operation.
///
/// This will return a [LogicValue] of some input 'base' to the power of other
/// input 'exponent'. If one of the two input values is invalid, [pow] will
/// return ‘x’ of input size width.
LogicValue pow(dynamic other) => _doMath(other, _binPower);

/// Less-than operation.
///
/// WARNING: Signed math is not fully tested.
Expand Down Expand Up @@ -761,6 +768,35 @@ abstract class LogicValue {
// ignore: avoid_dynamic_calls
_doCompare(other, (a, b) => (a >= b) as bool);

/// Binary Power
///
/// Both inputs [a] and [b] are either of type [int] or [BigInt].
/// Returns [a] raise to the power [b] of input type.
dynamic _binPower(dynamic a, dynamic b) {
dynamic x = a;
dynamic y = b;
dynamic zero = 0;
dynamic res = 1;
if (x is BigInt) {
res = BigInt.from(1);
zero = BigInt.zero;
}

// ignore: avoid_dynamic_calls
while ((y > zero) as bool) {
// ignore: avoid_dynamic_calls
if (y.isOdd as bool) {
// ignore: avoid_dynamic_calls
res = res * x;
}
// ignore: avoid_dynamic_calls
x = x * x;
// ignore: avoid_dynamic_calls
y = y >> 1;
}
return res;
}

/// Executes comparison operations between two [LogicValue]s
///
/// Handles width and bounds checks as well as proper conversion between
Expand Down
37 changes: 37 additions & 0 deletions test/logic_value_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,43 @@ void main() {
});
});
group('arithmetic operations', () {
test('power', () {
expect(
// test ofInt
LogicValue.ofInt(2, 32).pow(LogicValue.ofInt(0, 32)),
equals(LogicValue.ofInt(1, 32)));
expect(
// test ofInt
LogicValue.ofInt(2, 32).pow(LogicValue.ofInt(12, 32)),
equals(LogicValue.ofInt(4096, 32)));
expect(
// test ofInt
LogicValue.ofInt(3, 32).pow(LogicValue.ofInt(5, 32)),
equals(LogicValue.ofInt(243, 32)));
expect(
// test ofBigInt
LogicValue.ofBigInt(BigInt.from(31), 128)
.pow(LogicValue.ofBigInt(BigInt.from(21), 128)),
equals(LogicValue.ofBigInt(
BigInt.parse('20825506393391550743120420649631'), 128)));
expect(
// test ofBigInt
LogicValue.ofBigInt(BigInt.parse('111234234231234523412665554'), 256)
.pow(LogicValue.ofBigInt(BigInt.from(2), 256)),
equals(LogicValue.ofBigInt(
BigInt.parse(
'12373054865009146225795242412633846245734343458126916'),
256)));
expect(
//test string
LogicValue.ofString('000010').pow(LogicValue.ofString('000100')),
equals(LogicValue.ofString('010000')));
expect(
//test invalid input
LogicValue.ofString('0001').pow(LogicValue.ofString('000x')),
equals(LogicValue.filled(4, LogicValue.x)));
});

test('addsub', () {
expect(
// + normal
Expand Down
17 changes: 17 additions & 0 deletions test/math_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ class MathTestModule extends Module {
a = addInput('a', a, width: a.width);
b = addInput('b', b, width: b.width);

final aPowerB = addOutput('a_power_b', width: a.width);
final aPlusB = addOutput('a_plus_b', width: a.width);
final aMinusB = addOutput('a_minus_b', width: a.width);
final aTimesB = addOutput('a_times_b', width: a.width);
final aDividedByB = addOutput('a_dividedby_b', width: a.width);
final aModuloB = addOutput('a_modulo_b', width: a.width);
final aModuloConst = addOutput('a_modulo_const', width: a.width);

final aPowerConst = addOutput('a_power_const', width: a.width);
final aPlusConst = addOutput('a_plus_const', width: a.width);
final aMinusConst = addOutput('a_minus_const', width: a.width);
final aTimesConst = addOutput('a_times_const', width: a.width);
Expand All @@ -43,13 +45,15 @@ class MathTestModule extends Module {
final aSrlConst = addOutput('a_srl_const', width: a.width);
final aSraConst = addOutput('a_sra_const', width: a.width);

aPowerB <= a.pow(b);
aPlusB <= a + b;
aMinusB <= a - b;
aTimesB <= a * b;
aDividedByB <= a / b;
aModuloB <= a % b;
aModuloConst <= a % c;

aPowerConst <= a.pow(c);
aPlusConst <= a + c;
aMinusConst <= a - c;
aTimesConst <= a * c;
Expand Down Expand Up @@ -79,6 +83,19 @@ void main() {
expect(simResult, equals(true));
}

test('power', () async {
await runMathVectors([
Vector({'a': 1, 'b': 100}, {'a_power_b': 1}),
Vector({'a': 1043, 'b': 0}, {'a_power_b': 1}),
Vector({'a': 3, 'b': 3}, {'a_power_b': 27}),
Vector({'a': 2, 'b': 1}, {'a_power_b': 2}),
Vector({'a': 2, 'b': 7}, {'a_power_b': 128}),
Vector({'a': 2}, {'a_power_const': 32}),
Vector({'a': 5, 'b': 3}, {'a_power_b': 125}),
Vector({'a': 7, 'b': 2}, {'a_power_b': 49}),
]);
});

test('addition', () async {
await runMathVectors([
Vector({'a': 0, 'b': 0}, {'a_plus_b': 0}),
Expand Down

0 comments on commit c6df19c

Please sign in to comment.