123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- package com.oblivm.backend.circuits.arithmetic;
- import java.util.Arrays;
- import com.oblivm.backend.flexsc.CompEnv;
- import com.oblivm.backend.util.Utils;
- public class FloatLib<T> implements ArithmeticLib<T> {
- CompEnv<T> env;
- IntegerLib<T> lib;
- public int VLength;
- public int PLength;
- public FloatLib(CompEnv<T> e, int VLength, int PLength) {
- this.env = e;
- lib = new IntegerLib<>(e);
- this.VLength = VLength;
- this.PLength = PLength;
- }
- public T[] inputOfAlice(double d) {
- return env.inputOfAlice(Utils.fromFloat(d, VLength, PLength));
- }
- public T[] inputOfBob(double d) {
- return env.inputOfBob(Utils.fromFloat(d, VLength, PLength));
- }
- public T[] pack(Representation<T> f) {
- assert (f.v.length == VLength && f.p.length == PLength) : "pack: not compatiable";
- T[] res = env.newTArray(1 + f.v.length + f.p.length);
- res[0] = f.s;
- System.arraycopy(f.v, 0, res, 1, f.v.length);
- System.arraycopy(f.p, 0, res, 1 + f.v.length, f.p.length);
- return res;
- }
- public Representation<T> unpack(T[] data) {
- assert (data.length == VLength + PLength + 1) : "unpack: not compatiable";
- T[] v = Arrays.copyOfRange(data, 1, 1 + VLength);
- T[] p = Arrays.copyOfRange(data, 1 + VLength, data.length);
- return new Representation<T>(data[0], v, p);
- }
- public static class Representation<T> {
- public T s;
- public T[] v;
- public T[] p;
- public Representation(T sign, T[] v, T[] p) {
- this.s = sign;
- this.p = p;
- this.v = v;
- }
- }
- public T[] multiply(T[] fa, T[] fb) {
- Representation<T> a = unpack(fa);
- Representation<T> b = unpack(fb);
- T new_s = lib.xor(a.s, b.s);
- T[] a_multi_b = lib.karatsubaMultiply(a.v, b.v);// length 2*v.length
- T[] a_add_b = lib.add(a.p, b.p);
- T toShift = lib.not(a_multi_b[a_multi_b.length - 1]);
- T[] Shifted = lib.conditionalLeftPublicShift(a_multi_b, 1, toShift);
- T[] new_v = Arrays.copyOfRange(Shifted, a.v.length, a.v.length * 2);
- T[] new_p = lib.add(a_add_b, lib.toSignals(a.v.length, a_add_b.length));
- T[] decrement = lib.zeros(new_p.length);
- decrement[0] = toShift;
- new_p = lib.sub(new_p, decrement);
- Representation<T> res = new Representation<T>(new_s, new_v, new_p);
- return pack(res);
- }
- public T[] div(T[] fa, T[] fb) {
- Representation<T> a = unpack(fa);
- Representation<T> b = unpack(fb);
- T new_s = lib.xor(a.s, b.s);
- int length = a.v.length;
- int newLength = a.v.length * 2;
- T[] padded_av = lib.padSignal(a.v, newLength);
- T[] padded_bv = lib.padSignal(b.v, b.v.length + 1);
- T[] shifted_av = lib.leftPublicShift(padded_av, newLength - length - 1);
- // must be postive number div. so avoid div(shifted_av, padded_bv);
- T[] a_div_b = Arrays.copyOf(lib.divInternal(shifted_av, padded_bv), shifted_av.length);
- T[] leadingzero = lib.leadingZeros(a_div_b);
- T[] sh = lib.leftPrivateShift(a_div_b, leadingzero);
- sh = lib.rightPublicShift(sh, newLength - length);
- T[] new_v = Arrays.copyOf(sh, length);
- T[] new_p = lib.add(lib.sub(a.p, b.p), lib.toSignals(1, a.p.length));
- new_p = lib.sub(lib.padSignal(new_p, leadingzero.length), leadingzero);
- new_p = lib.padSignedSignal(new_p, a.p.length);
- Representation<T> res = new Representation<T>(new_s, new_v, new_p);
- return pack(res);
- }
- public T[] publicValue(double d) {
- boolean[] b = Utils.fromFloat(d, VLength, PLength);
- T[] res = env.newTArray(PLength + VLength + 1);
- for (int i = 0; i < b.length; ++i)
- res[i] = b[i] ? lib.SIGNAL_ONE : lib.SIGNAL_ZERO;
- return res;
- }
- // assuming na = va*2^p, nb = vb*2^(p+pDiff)
- private T[] addInternal(T sa, T sb, T[] va, T[] vb, T[] p, T[] pDiff) {
- int temp_length = 2 * VLength + 1;
- T[] signedVa = lib.padSignal(va, temp_length);
- T[] signedVb = lib.padSignal(vb, temp_length);
- signedVb = lib.leftPrivateShift(signedVb, pDiff);
- signedVa = lib.addSign(signedVa, sa);
- signedVb = lib.addSign(signedVb, sb);
- T[] new_v = lib.add(signedVa, signedVb);
- T new_s = new_v[new_v.length - 1];
- new_v = lib.absolute(new_v);
- T[] leadingzero = lib.leadingZeros(new_v);
- T[] sh = lib.leftPrivateShift(new_v, leadingzero);
- sh = lib.rightPublicShift(sh, temp_length - VLength);
- new_v = Arrays.copyOf(sh, VLength);
- T[] new_p = lib.sub(lib.padSignal(p, leadingzero.length), leadingzero);
- new_p = lib.add(new_p, lib.toSignals(temp_length - VLength, new_p.length));
- new_p = lib.padSignedSignal(new_p, PLength);
- Representation<T> res = new Representation<T>(new_s, new_v, new_p);
- return pack(res);
- }
- public T[] add(T[] fa, T[] fb) {
- T[] va = Arrays.copyOfRange(fa, 1, 1 + VLength);
- T[] vb = Arrays.copyOfRange(fb, 1, 1 + VLength);
- T[] pa = Arrays.copyOfRange(fa, 1 + VLength, fa.length);
- T[] pb = Arrays.copyOfRange(fb, 1 + VLength, fb.length);
- T[] pDifference = lib.sub(pa, pb);
- T[] pDiffAbs = lib.absolute(pDifference);
- T paGreater = lib.not(pDifference[pDifference.length - 1]);
- T[] pToUse = lib.mux(pa, pb, paGreater);
- T[] normalCase = addInternal(lib.mux(fa[0], fb[0], paGreater), lib.mux(fb[0], fa[0], paGreater),
- lib.mux(va, vb, paGreater), lib.mux(vb, va, paGreater), pToUse, pDiffAbs);
- T underFlowHappen = lib.not(lib.leq(pDiffAbs, lib.toSignals(VLength, pDiffAbs.length)));
- T[] underFlowResult = lib.mux(fb, fa, paGreater);
- return lib.mux(normalCase, underFlowResult, underFlowHappen);
- }
- // (v*s^p)^(1/2) =
- public T[] sqrt(T[] fa) {
- int newLength = VLength + 2 + 1;
- T[] va = Arrays.copyOfRange(fa, 1, 1 + VLength);
- T[] pa = Arrays.copyOfRange(fa, 1 + VLength, fa.length);
- va = lib.padSignal(va, newLength);
- va = lib.leftPublicShift(va, 1);
- pa = lib.sub(pa, lib.toSignals(1, PLength));
- va = lib.conditionalLeftPublicShift(va, 1, pa[0]);
- va = lib.sqrt(va);
- pa = lib.rightPublicShift(pa, 1);
- pa[pa.length - 1] = pa[pa.length - 2];
- T[] leadingzero = lib.leadingZeros(va);
- T[] sh = lib.leftPrivateShift(va, leadingzero);
- sh = lib.rightPublicShift(sh, newLength - VLength);
- T[] new_v = Arrays.copyOf(sh, VLength);
- pa = lib.sub(pa, lib.padSignal(leadingzero, pa.length));
- pa = lib.add(pa, lib.toSignals(newLength - VLength, PLength));
- return pack(new Representation<T>(lib.SIGNAL_ZERO, new_v, pa));
- }
- public T[] sub(T[] a, T[] b) {
- T[] negB = Arrays.copyOf(b, b.length);
- negB[0] = lib.not(negB[0]);
- return add(a, negB);
- }
- public T leq(T[] a, T[] b) {
- T[] res = sub(a, b);
- return lib.not(res[0]);
- }
- public T eq(T[] a, T[] b) {
- return lib.eq(a, b);
- }
- @Override
- public CompEnv<T> getEnv() {
- return env;
- }
- @Override
- public T[] toSecureInt(T[] a, IntegerLib<T> lib) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public T[] toSecureFloat(T[] a, FloatLib<T> lib) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public T[] toSecureFixPoint(T[] a, FixedPointLib<T> lib) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public double outputToAlice(T[] a) {
- return Utils.toFloat(env.outputToAlice(a), VLength, PLength);
- }
- @Override
- public int numBits() {
- return VLength + PLength + 1;
- }
- }
|