void mexFunction(int nlhs, mxArray *plhs[], /* Output variables */ int nrhs, const mxArray *prhs[]) /* Input variables */ { #define ccr(ai,bi) (ccr[ai+Nss[0]*bi]) #define cci(ai,bi) (cci[ai+Nss[0]*bi]) #define kk1(ai,bi) (kk1[ai+Nss[0]*bi]) #define kk2(ai,bi) (kk2[ai+Nss[0]*bi]) #define kb(loc1,loc2,ai,bi) kb[loc1+NB1*(loc2+NB2*(ai+Nss[0]*bi))] #define avgdx(loc1,loc2,ai,bi) avgdx[loc1+NB1*(loc2+NB2*(ai+Nss[0]*bi))] #define avgdy(loc1,loc2,ai,bi) avgdy[loc1+NB1*(loc2+NB2*(ai+Nss[0]*bi))] size_t ai, bi; int NB1, NB2, loc1, loc2, di = 0; double *kk1, *kk2, *ccr, *cci, *kb, *avgdx, *avgdy; double EXT, num_dir, da, dr, r, agl, R_low; double temp_energy; ccr = mxGetPr(prhs[0]); cci = mxGetPi(prhs[0]); kk1 = mxGetPr(prhs[1]); kk2 = mxGetPr(prhs[2]); EXT = mxGetScalar(prhs[3]); num_dir = mxGetScalar(prhs[4]); da = mxGetScalar(prhs[5]); dr = mxGetScalar(prhs[6]); NB1 = mxGetScalar(prhs[7]); NB2 = mxGetScalar(prhs[8]); R_low = mxGetScalar(prhs[9]); const mwSize *Nss = mxGetDimensions(prhs[0]); kb = mxGetPr(prhs[10]); avgdx = mxGetPr(prhs[11]); avgdy = mxGetPr(prhs[12]); nrhs = 13; nlhs = 0; for (ai=0;ai<Nss[0];ai++) { for (bi=0;bi<Nss[1];bi++) { if (kk1(ai,bi)<EXT) { r = sqrt(kk1(ai,bi)*kk1(ai,bi)+kk2(ai,bi)*kk2(ai,bi)); if (kk1(ai,bi)>=0) { agl = fmod(acos(kk2(ai,bi)/r),num_dir); } else agl = fmod(3.1415926-acos(kk2(ai,bi)/r),num_dir); loc1 = round((r-R_low)/dr); loc2 = round(agl/da); temp_energy = ccr(ai,bi)*ccr(ai,bi) + cci(ai,bi)*cci(ai,bi); kb(loc1,loc2,ai,bi) = kb(loc1,loc2,ai,bi) + temp_energy; avgdx(loc1,loc2,ai,bi) = avgdx(loc1,loc2,ai,bi) + r * cos(agl) * temp_energy; avgdy(loc1,loc2,ai,bi) = avgdy(loc1,loc2,ai,bi) + r * sin(agl) * temp_energy; /* cannot use kk since those are symmetric */ } } } return; }
void DrrnPsiClient::recv(Channel s0, Channel s1, span<block> inputs) { if (inputs.size() != mClientSetSize) throw std::runtime_error(LOCATION); Matrix<u64> bins(mNumSimpleBins, mBinSize); std::vector<u64> binSizes(mNumSimpleBins); u64 cuckooSlotsPerBin = (mCuckooParams.numBins() + mNumSimpleBins) / mNumSimpleBins; // Simple hashing with a PRP std::vector<block> hashs(inputs.size()); AES hasher(mHashingSeed); u64 numCuckooBins = mCuckooParams.numBins(); for (u64 i = 0; i < u64(inputs.size());) { auto min = std::min<u64>(inputs.size() - i, 8); auto end = i + min; hasher.ecbEncBlocks(inputs.data() + i, min, hashs.data() + i); for (; i < end; ++i) { hashs[i] = hashs[i] ^ inputs[i]; for (u64 j = 0; j < mCuckooParams.mNumHashes; ++j) { u64 idx = CuckooIndex<>::getHash(hashs[i], j, numCuckooBins) * mNumSimpleBins / mCuckooParams.numBins(); // insert this item in this bin. pack together the hash index and input index bins(idx, binSizes[idx]++) = (j << 56) | i; } //if (!i) //{ // ostreamLock(std::cout) << "cinput[" << i << "] = " << inputs[i] << " -> " << hashs[i] << " (" // << CuckooIndex<>::getHash(hashs[i], 0, numCuckooBins) << ", " // << CuckooIndex<>::getHash(hashs[i], 1, numCuckooBins) << ", " // << CuckooIndex<>::getHash(hashs[i], 2, numCuckooBins) << ")" // << std::endl; //} } } // power of 2 u64 numLeafBlocks = (cuckooSlotsPerBin + mBigBlockSize * 128 - 1) / (mBigBlockSize * 128); u64 gDepth = 2; u64 kDepth = std::max<u64>(gDepth, log2floor(numLeafBlocks)) - gDepth; u64 groupSize = (numLeafBlocks + (u64(1) << kDepth) - 1) / (u64(1) << kDepth); if (groupSize > 8) throw std::runtime_error(LOCATION); //std::cout << "kDepth: " << kDepth << std::endl; //std::cout << "mBinSize: " << mBinSize << std::endl; u64 numQueries = mNumSimpleBins * mBinSize; auto permSize = numQueries * mBigBlockSize; // mask generation block rSeed = CCBlock;// mPrng.get<block>(); AES rGen(rSeed); std::vector<block> shares(mClientSetSize * mCuckooParams.mNumHashes), r(permSize), piS1(permSize), s(permSize); //std::vector<u32> rIdxs(numQueries); //std::vector<u64> sharesIdx(shares.size()); //TODO("use real masks"); //memset(r.data(), 0, r.size() * sizeof(block)); rGen.ecbEncCounterMode(r.size() * 0, r.size(), r.data()); rGen.ecbEncCounterMode(r.size() * 1, r.size(), piS1.data()); rGen.ecbEncCounterMode(r.size() * 2, r.size(), s.data()); //auto encIter = enc.begin(); auto shareIter = shares.begin(); //auto shareIdxIter = sharesIdx.begin(); u64 queryIdx = 0, dummyPermIdx = mClientSetSize * mCuckooParams.mNumHashes; std::unordered_map<u64, u64> inputMap; inputMap.reserve(mClientSetSize * mCuckooParams.mNumHashes); std::vector<u32> pi(permSize); auto piIter = pi.begin(); u64 keySize = kDepth + 1 + groupSize; u64 mask = (u64(1) << 56) - 1; auto binIter = bins.begin(); for (u64 bIdx = 0; bIdx < mNumSimpleBins; ++bIdx) { u64 i = 0; auto binOffset = (bIdx * numCuckooBins + mNumSimpleBins - 1) / mNumSimpleBins; std::vector<block> k0(keySize * mBinSize), k1(keySize * mBinSize); //std::vector<u64> idx0(mBinSize), idx1(mBinSize); auto k0Iter = k0.data(), k1Iter = k1.data(); //auto idx0Iter = idx0.data(), idx1Iter = idx1.data(); for (; i < binSizes[bIdx]; ++i) { span<block> kk0(k0Iter, kDepth + 1), g0(k0Iter + kDepth + 1, groupSize), kk1(k1Iter, kDepth + 1), g1(k1Iter + kDepth + 1, groupSize); k0Iter += keySize; k1Iter += keySize; u8 hashIdx = *binIter >> 56; u64 itemIdx = *binIter & mask; u64 cuckooIdx = CuckooIndex<>::getHash(hashs[itemIdx], hashIdx, numCuckooBins) - binOffset; ++binIter; auto bigBlockoffset = cuckooIdx % mBigBlockSize; auto bigBlockIdx = cuckooIdx / mBigBlockSize; BgiPirClient::keyGen(bigBlockIdx, mPrng.get<block>(), kk0, g0, kk1, g1); // the index of the mask that will mask this item auto rIdx = *piIter = itemIdx * mCuckooParams.mNumHashes + hashIdx * mBigBlockSize + bigBlockoffset; // the masked value that will be inputted into the PSI *shareIter = r[rIdx] ^ inputs[itemIdx]; //*shareIter = inputs[itemIdx]; //if (itemIdx == 0) // ostreamLock(std::cout) // << "item[" << i << "] bin " << bIdx // << " block " << bigBlockIdx // << " offset " << bigBlockoffset // << " psi " << *shareIter << std::endl; // This will be used to map itemed items in the intersection back to their input item inputMap.insert({ queryIdx, itemIdx }); ++shareIter; ++piIter; ++queryIdx; } u64 rem = mBinSize - i; binIter += rem; for (u64 i = 0; i < rem; ++i) { *piIter++ = dummyPermIdx++; } //s0.asyncSendCopy(k0); //s0.asyncSendCopy(k1); //s1.asyncSendCopy(k1); //s1.asyncSendCopy(k0); s0.asyncSend(std::move(k0)); s1.asyncSend(std::move(k1)); } std::vector<u32> pi1(permSize), pi0(permSize), pi1Inv(permSize); for (u32 i = 0; i < pi1.size(); ++i) pi1[i] = i; PRNG prng(rSeed ^ OneBlock); std::random_shuffle(pi1.begin(), pi1.end(), prng); //std::vector<block> pi1RS(pi.size()); for (u64 i = 0; i < permSize; ++i) { //auto pi1i = pi1[i]; //pi1RS[i] = r[pi1i] ^ s[pi1i]; pi1Inv[pi1[i]] = i; //std::cout << "pi1(r + s)[" << i << "] " << pi1RS[i] << std::endl; } std::vector<block> piS0(r.size()); for (u64 i = 0; i < permSize; ++i) { //std::cout << "r[" << i << "] " << r[i] << std::endl; //std::cout << "pi(r + s)[" << i << "]=" << (r[pi[i]] ^ s[pi[i]]) << std::endl; pi0[i] = pi1Inv[pi[i]]; piS0[i] = piS1[i] ^ s[pi[i]]; //std::cout << "pi (r + s)[" << i << "] = " << (r[pi[i]] ^ s[pi[i]]) << " = " << r[pi[i]] << " ^ " << s[pi[i]] << " c " << pi[i] << std::endl; //std::cout << "pi`(r + s)[" << i << "] = " << pi1RS[pi0[i]] <<" c " << pi0[pi1[i]] << std::endl; } s0.asyncSend(std::move(pi0)); s0.asyncSend(std::move(piS0)); //rGen.ecbEncBlocks(r.data(), r.size(), r.data()); //for (u64 i = 0; i < shares.size(); ++i) //{ // std::cout << IoStream::lock << "cshares[" << i << "] " << shares[i] << " input[" << sharesIdx[i]<<"]" << std::endl << IoStream::unlock; //} mPsi.sendInput(shares, s0); mIntersection.reserve(mPsi.mIntersection.size()); for (u64 i = 0; i < mPsi.mIntersection.size(); ++i) { // divide index by #hashes mIntersection.emplace(inputMap[mPsi.mIntersection[i]]); } }