Skip to content

Commit

Permalink
Long division algorithm.
Browse files Browse the repository at this point in the history
  • Loading branch information
markkurossi committed May 10, 2024
1 parent 6507331 commit c47a01d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 12 deletions.
26 changes: 15 additions & 11 deletions benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -678,14 +678,18 @@ BenchmarkGarbleINV-8 14924721 77.97 ns/op

Optimized circuits from [pkg/math/](pkg/math/):

| Implementation | XOR gates | XOR % | !XOR gates | !XOR % |
|:---------------|----------:|------:|-----------:|-------:|
| add64.circ | 313 | | 63 | |
| sub64.circ | 313 | | 126 | |
| mul64.circ | 9642 | | 4033 | |
| div64.circ | 24817 | | 5109 | |
| MPCL a+b | 251 | 80.2 | 63 | 100.0 |
| MPCL a-b | 252 | 80.5 | 65 | 51.6 |
| MPCL a*b | 8261 | 85.7 | 4007 | 99.4 |
| MPCL int a/b | 25274 | 101.8 | 8574 | 167.8 |
| MPCL uint a/b | 24515 | 98.8 | 8194 | 160.4 |
| Implementation | XOR gates | XOR % | !XOR gates | !XOR % |
|:----------------|----------:|------:|-----------:|-------:|
| add64.circ | 313 | | 63 | |
| sub64.circ | 313 | | 126 | |
| mul64.circ | 9642 | | 4033 | |
| div64.circ | 24817 | | 5109 | |
| MPCL a+b | 251 | 80.2 | 63 | 100.0 |
| MPCL a-b | 252 | 80.5 | 65 | 51.6 |
| MPCL a*b | 8261 | 85.7 | 4007 | 99.4 |
| MPCL R int a/b | 33273 | 134.1 | 10463 | 204.8 |
| MPCL R uint a/b | 32133 | 129.5 | 10084 | 197.4 |
| MPCL A int a/b | 25655 | 103.4 | 8574 | 167.8 |
| MPCL A uint a/b | 24515 | 98.8 | 8194 | 160.4 |
| MPCL L int a/b | 25209 | 101.6 | 8447 | 165.3 |
| MPCL L uint a/b | 24069 | 97.0 | 8068 | 160.0 |
54 changes: 53 additions & 1 deletion compiler/circuits/circ_divider.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,58 @@

package circuits

// NewUDividerLong creates an unsigned integer division circuit
// computing r=a/b, q=a%b. This function uses Long Division algorithm.
func NewUDividerLong(cc *Compiler, a, b, q, rret []*Wire) error {
a, b = cc.ZeroPad(a, b)

r := make([]*Wire, len(a))
for i := 0; i < len(r); i++ {
r[i] = cc.ZeroWire()
}

for i := len(a) - 1; i >= 0; i-- {
// r << 1
for j := len(r) - 1; j > 0; j-- {
r[j] = r[j-1]
}
r[0] = a[i]

// r-d, overlow: r < d
diff := make([]*Wire, len(r)+1)
for j := 0; j < len(diff); j++ {
diff[j] = cc.Calloc.Wire()
}
err := NewSubtractor(cc, r, b, diff)
if err != nil {
return err
}
if i < len(q) {
err = NewMUX(cc, diff[len(diff)-1:], []*Wire{cc.ZeroWire()},
[]*Wire{cc.OneWire()}, q[i:i+1])
if err != nil {
return err
}
}
nr := make([]*Wire, len(r))
for j := 0; j < len(nr); j++ {
if i == 0 && j < len(rret) {
nr[j] = rret[j]
} else {
nr[j] = cc.Calloc.Wire()
}
}

err = NewMUX(cc, diff[len(diff)-1:], r, diff[:len(diff)-1], nr)
if err != nil {
return err
}
r = nr
}

return nil
}

// NewUDividerRestoring creates an unsigned integer division circuit
// computing r=a/b, q=a%b. This function uses Restoring Division
// algorithm.
Expand Down Expand Up @@ -154,7 +206,7 @@ func NewUDividerArray(cc *Compiler, a, b, q, r []*Wire) error {
// NewUDivider creates an unsigned integer division circuit computing
// r=a/b, q=a%b.
func NewUDivider(cc *Compiler, a, b, q, r []*Wire) error {
return NewUDividerArray(cc, a, b, q, r)
return NewUDividerLong(cc, a, b, q, r)
}

// NewIDivider creates a signed integer division circuit computing
Expand Down

0 comments on commit c47a01d

Please sign in to comment.