Secure distributed GWAS computation
In this section we describe our approach to securely computing the task of distributed GWAS computation, namely, computing minor allele frequencies and chisquared statistics.
According to the task specification, the size of the input at each site, i.e., the number of SNPs and the number of individuals in the case and control groups, are treated as public and are not protected. This means that parameters P, {N}_{c}^{\left(1\right)}, {N}_{c}^{\left(2\right)}, {N}_{t}^{\left(1\right)} and {N}_{t}^{\left(2\right)} are known to all computation participants. All remaining data (i.e., the genotypes themselves) are private.
In what follows, we first describe a basic version of our solution and then provide optimization techniques that improve the runtime of program execution.
Basic solution
For each SNP in the input, the computation is identical (and independent of other SNPs) and thus it suffices to describe the computation for a single SNP.
We divide the overall computation into three phases: input preparation, computation execution, and output reconstruction, which proceed as follows. Observe that each input site i can locally compute {n}_{cA}^{\left(i\right)}, {n}_{tA}^{\left(i\right)}, {n}_{cB}^{\left(i\right)}, {n}_{tB}^{\left(i\right)} for each SNP. This is what is done as part of input preparation, after which each input site secret shares each of its computed values and distributes the shares among all three computational parties. We use notation [a] to denote that the value of a is secretshared among the computational parties (i.e., each party holds a different share of a).
During computation execution, the computation proceeds on the shares to compute MAF and chisquared statistics using equations 1 and 2 and secure building blocks from the previous section. We choose to perform only the private portion of the computation on secret shares, while postponing the computation with public constants to the output reconstruction phase. This is done for performance reasons to reduce the size of values used in the computation.
To calculate the MAF for each SNP in parallel, the computation follows equation 1 with provisions to make the computation dataoblivious. That is, each computational party performs the following steps: In this section we describe our approach to securely
1 \left[{n}_{A}\right]=\left[{n}_{cA}^{\left(1\right)}\right]+\left[{n}_{tA}^{\left(1\right)}\right]+\left[{n}_{cA}^{\left(2\right)}\right]+\left[{n}_{tA}^{\left(2\right)}\right];
2 \left[{n}_{B}\right]=\left[{n}_{cB}^{\left(1\right)}\right]+\left[{n}_{tB}^{\left(1\right)}\right]+\left[{n}_{cB}^{\left(2\right)}\right]+\left[{n}_{tB}^{\left(2\right)}\right];
3 \left[b\right]=\mathsf{\text{LT(}}\left[{n}_{A}\right],\left[{n}_{B}\right],{\ell}_{1}\mathsf{\text{);}}
4 \left[re{s}_{1}\right]=\mathsf{\text{Mult}}\left(\left[b\right],\left[{n}_{A}\right]\left[{n}_{B}\right]\right)+\left[{n}_{B}\right];
The first two steps that aggregate the input values are local to each computational party, but steps 3 and 4 that produce the minimum of n_{
A
} and n_{
B
} involve joint computation by all of them. We subsequently discuss the choice of the parameter ℓ _{1}.
To compute the chisquared statistics for each SNP in parallel, we similarly follow the computation in equation 2 using the following steps:
1 \left[{n}_{cA}\right]=\left[{n}_{cA}^{\left(1\right)}\right]+\left[{n}_{cA}^{\left(2\right)}\right];
2 \left[{n}_{tA}\right]=\left[{n}_{tA}^{\left(1\right)}\right]+\left[{n}_{tA}^{\left(2\right)}\right];
3 \left[{n}_{cB}\right]=\left[{n}_{cB}^{\left(1\right)}\right]+\left[{n}_{cB}^{\left(2\right)}\right];
4 \left[{n}_{tB}\right]=\left[{n}_{tB}^{\left(1\right)}\right]+\left[{n}_{tB}^{\left(2\right)}\right];
5 [a] = Mul([n_{
cA
}], [n_{
tB
}]);
6 [b] = Mul([n_{
cB
}], [n_{
tA
}]);
7 [c] = Mul([n_{
cA
}] + [n_{
tA
}], [n_{
cB
}] + [n_{
tB
}]);
8 [d] = Mul([a] − [b], [a] − [b]);
9 [res_{2}] = Div(k · [d], [c], ℓ _{2});
Lines 5, 6, and 8 compute the numerator in equation 2 and line 7 its denominator (multiplication by public N , N_{
c
}, and N_{
t
} is omitted). The numerator is then scaled up by a factor of k to ensure that using integer division will provide sufficient precision of the result. The bitlength of k will be on the order of the precision of the answer in bits. We defer discussion of the choice of ℓ _{2} to the next section.
At the end of the computation, all computational parties send their shares of the result res_{1} and res_{2} for each SNP to one of the input sites who reconstruct the values. The output party then sets the result of MAF computation to res_{1}/N^{'}and the result of the chisquared computation to \left(re{s}_{2}\cdot {N}^{\prime}\right)/\left(k{N}_{c}^{\prime}{N}_{t}^{\prime}\right).
Optimizations
We applied several optimizations to the computation to improve its runtime.

1
The nature of the computation in this task allows all interactive operations to run in parallel in a single batch for all SNPs. That is, all P comparisons corresponding to line 3 of MAF computation are executed simultaneously. The same applies to line 4 of MAF computation and lines 59 of chisquared computation.
We can further reduce the number of rounds in chisquared computation by running interactive independent operations at the same time. In particular, this means that lines 57 of the computation can be executed in a single round.

2
We modify chisquared computation to use floating point instead of integer division after converting both operands d and c to floating point representation. This is primarily driven by the fact that performance of division we rely on (described in [15, 9]) depends on the maximum of the bitlengths of its arguments and we can use substantially shorter values with floating point division compared to integer division (i.e., the bitlength can be comparable to that of k instead of the sum of the bitlengths of d and k). The savings noticeably outweigh the cost of integertofloating point conversion, or normalization (to use floating point division we need to normalize two values, while integer division needs to compute normalization of one of its arguments). We additionally slightly optimize integer to floating point conversion and floating point division compared to those given in [9] using information known about d and c (e.g., the fact that they are positive).

3
For performance reasons, we want to set parameters ℓ _{1} and ℓ _{2} (as well as the bitlength of secret shared values) to their minimum values that guarantee correctness. When the bitlength of the arguments to both comparison and division differ, the larger value is to be used. In particular, for ℓ _{1}, the largest value of n_{
A
} or n_{
B
} in the LT protocol appears when only one nucleotide is present in all genotypes in both case and control groups (i.e., max(n_{
A
}, n_{
B
}) = N^{'}and min(n_{
A
}, n_{
B
}) = 0), and we set ℓ_{1} = ⌈log N^{'}⌉ (where the extra 1 is due to the specifics of the LT operation). For ℓ _{2}, the largest value of d or c appears when n_{
cB
} = n_{
tA
} = 0, which leads to {n}_{cA}={N}_{c}^{\prime}, {n}_{tB}={N}_{t}^{\prime}, and d={\left({N}_{c}^{\prime}\right)}^{2}{\left({N}_{t}^{\prime}\right)}^{2}, and we set {n}_{tB}={N}_{t}^{\prime}, and d={\left({N}_{c}^{\prime}\right)}^{2}{\left({N}_{t}^{\prime}\right)}^{2}, and we set {\ell}_{2}=\u23082\left(\mathsf{\text{log}}{{N}^{\prime}}_{c}+\mathsf{\text{log}}{{N}^{\prime}}_{t}\right)\u2309. For integer division, this value of ℓ _{2} needs to be additionally incremented by the bitlength of precision k, but fortunately after we switch to floating point representation, we can reduce the bitlength to the desired precision of the result because the values are represented in a normalized form.
Secure distributed genomic Hamming distance computation
We next concentrate on the second task of securely computing the Hamming distance between a pair of genomic datasets in a distributed setting.
According to the task specification, the number of records in each of the two datasets are known to all parties and we denote them as N_{1} and N_{2}, respectively. The content of the records, however, is private (in particular, the values that fields CHROM, POS, REF, ALT, and SVTYPE take). Because only records with SVTYPE equal to SUB and SNP are relevant for the computation, for ease of notation we refer to them as SUB and SNP records, respectively.
The highlevel idea behind our solution is as follows: we first let each input site extract SUB and SNP records from its dataset and pad the resulting set with dummy records to hide its size. After each input site secret shares its records across all computational parties, the parties then run a set operation to identify all records that appear in both dataset (conceptually similar to set intersection) using ⟨CHROM, POS⟩ as the key as well as all records that appear only in one dataset (conceptually similar to symmetric difference). We accomplish this by obliviously sorting all records from both datasets using Batcher's mergesort [2] and scanning the sorted set examining every two adjacent elements in it to determine if the Hamming distance needs to be incremented by one for that pair.
At the time of competition preparation, Batcher's mergesort was available to us as one of the best options for oblivious sorting (based on the overall amount work as well as its round complexity). It is particularly well suited to this task because it is a recursive algorithm that works by first sorting the first and the second half of its input set and then merging the sorted halves. In our setup this means that the input datasets can be presorted by each input site locally and only the merge step needs to be run jointly. Unfortunately, Batcher's mergesort (including the merge step) has the drawback that the number of elements in the input set has to be a power of 2, which may unnecessarily increase the runtime.
In what follows, we start by describing in detail a basic solution in the first subsection and then discuss two optimizations in the two consecutive subsections.
Basic solution
As before, we divide the overall computation into three phases: input preparation, joint computation execution, and output reconstruction.
Input preparation. Each input site i extracts all SUB and SNP records from its dataset and pads them with dummy records to size N_{
i
} + 1 (we require at least one dummy record). (If the combined fraction of SUB and SNP records is guaranteed to be within a certain fraction α < 1 of the total size for typical genomic datasets, then the datasets can be padded to αN_{
i
} + 1 records. For this competition, α could not be lower than 1.) Furthermore, to meet Batcher's mergesort requirements, the input parties additionally pad the sets with dummy records so that the combined size of the two datasets is 2^{q}, where q = ⌈log2(N1 + N2 + 2)⌉. We use this newly formed dataset as the input into the computation and refer to it as a "dataset".
Next, the values in each record need to be converted to integers, which we accomplish as follows:

1
The location ⟨CHROM, POS⟩ is represented as V_{1} = CHROM · L + POS, where L is the maximum length of any existing human chromosome. CHROM ranges from 1 to 24 (22 autosomes, plus × and Y), and for dummy records we set V1 = 25L + 1 to avoid overlap with real records.

2
REF and ALT fields are represented as strings of nucleotides in the input. To produce their numeric counterparts, we map each nucleotide value to a twobit integer (e.g., A = 0, C = 1, G = 2, and T = 3) and concatenate twobit integers from a string to form a single number. To hide information about the size of the fields, the values need to be represented using the same bitlength for all records based on the maximum string length M. Because shorter strings need to be padded to the maximum size, we need to ensure that strings of different sizes will always be different (i.e., the padding character cannot be one of 03).
Instead of introducing a separate padding character, which increases the bitlength of one character from 2 to 3 bits, we append the string length in bits at the end of the string and use 0 for padding. Thus, all strings are represented using 2M +log M bits. Let V_{2} and V_{3} denote numeric values of REF and ALT fields in a record. V_{2} and V_{3} are set to 0 for dummy records.
In our implementation with M = 100, we partition representation of V_{2} and V_{3} into three blocks of size (2M + log M )/3 each. This still requires comparing all 2M + log M bits when two such values need to be compared, but reduces the size of secret shared values and thus the cost of the corresponding arithmetic. When M is large, V_{2} and V_{3} can instead be set to the hash of REF and ALT strings. This would guarantee constant size representation regardless of the value of M.
After computing a 3tuple (V_{1}, V_{2}, V_{3}) for each record in its dataset, an input site i sorts the records by the V_{1} field to form set S_{
i
}, generates shares of all records in S_{
i
}, and distributes them to the computational parties (we slightly abuse notation and use [S_{
i
}] to denote shares of all values in S_{
i
}). It also distributes shares of the number of dummy records d_{
i
} in S_{
i
}.
Computation execution. After receiving two sorted sets of ([V_{1}], [V_{2}], [V_{3}]) triples from both input sites, the computational parties run oblivious merge using [V1] as the key. The algorithm is built using an inputindependent sequence of compareandexchange operations. Each operation takes two integers and either swaps them or leaves them unchanged so that the first output (min) is always smaller than the second (max). In our framework, it is implemented as follows:
1 [c] = LT([a], [b], ℓ );
2 [min] = [c]([a] − [b]) + [b];
3 [max] = [c]([b] − [a]) + [a];
Note that lines 2 and 3 involve only a single multiplication (i.e., first compute [c]([a] − [b]) and then set [min] and [max] with no additional interaction). When applying this operation to our setting, comparisons on line 1 are performed using [V_{1}]'s, but the entire records ([V_{1}], [V_{2}], [V_{3}]) are swapped (or left unchanged) using comparison results [c].
The computational parties next compute the Hamming distance as specified in Algorithm 2. Sets S_{1} and S_{2} represent sorted input triples of the input parties and parameters ℓ_{1} and ℓ_{2} correspond to the bitlengths of fields V_{1} and V_{2} (or V_{3}), as discussed previously.
Because a specific location V_{1} appears only once in each of the input datasets (except for dummy records), there will be at most two records with the same V_{1} in the combined set. The algorithm works by looking at each pair of two consecutive elements in the combined sorted set and adds 1 to dist if this is the first time the location appears on the list (i.e., a_{
i
} = 0 on line 4). The distance is incremented automatically for the first record (dist = 1 on line 2). Then, if a location appears for the second time (a_{
i
} = 1 on line 4), the algorithm examines the values of V_{2} and V_{3} fields (lines 56) to determine whether the condition for incrementing the distance is satisfied (i.e., b_{
i
} = 1 and c_{
i
} = 0). If not (b_{
i
} = 0 or c_{
i
} = 1), dist is decremented by 1 to compensate for the fact that it was increased during previous loop iteration. All dummy records collectively contribute distance −d_{1}−d_{2} +2 (i.e., 0 for the first two records and −1 for each additional record) and this is why we adjust the computed distance at the end (line 9). We note that all loop iterations and all comparisons within a loop iteration can be carried out in parallel.
Algorithm 2 SecureHD([S_{1}], [S_{2}], [d_{1}], [d_{2}])
1: {\left(\left[{V}_{1}^{\left(i\right)}\right],\left[{V}_{2}^{\left(i\right)}\right],\left[{V}_{3}^{\left(i\right)}\right]\right)}_{i=1}^{{2}^{q}}=\mathsf{\text{Merge}}\left(\left[{S}_{1}\right],\left[{S}_{2}\right]\right)
2: dist = 1
3: for i = 2 to 2^{q} do
4: \left[{a}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{1}^{\left(i1\right)}\right],\left[{V}_{1}^{\left(i\right)}\right],{\ell}_{1}\right)
5: \left[{b}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{2}^{\left(i1\right)}\right],\left[{V}_{2}^{\left(i\right)}\right],{\ell}_{2}\right)
6: \left[{c}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{3}^{\left(i1\right)}\right],\left[{V}_{3}^{\left(i\right)}\right],{\ell}_{2}\right)
7: dist = dist + (1 − [a_{
i
}]) + [a_{
i
}]([b_{
i
}](1 − [c_{
i
}]) − 1)
8: end for
9: dist = dist + [d_{1}] + [d_{2}] −2
10: return dist
Output reconstruction is straightforward and consists only of receiving and combining shares of the computed Hamming distance.
Separating SUB and SNP records
As the first significant optimization, we separate computation of the distance for SNP and SUB records and consequently reconstruct the overall distance from the two values. The main reason for this is to reduce the time comparisons of V_{2} and V_{3} take. Recall that SNP records contain a single character in REF and ALT fields, while SUB records can contain longer strings. In the genomic datasets we worked with, a great majority of all records were SNP records that can be processed using 2bit comparisons for V_{2} and V_{3} (i.e., ℓ_{2} = 2). In the basic solution, however, the bitlength had to be unnecessarily increased by two orders of magnitude for most records to meet privacy requirements. Thus, the idea consists of extracting two sets from each input dataset: one consisting of SNP records and another consisting of SUB records. Then the distance for SUB records is computed separately from the distance for SNP records and the sum is returned as the result.
This strategy works well if all records with the same ⟨CHROM, POS⟩ pair are always marked with the same type across all datasets. It is, however, possible for two datasets to contain SUB and SNP records corresponding to the same location. Because of the existence of such records, the Hamming distance will not be computed correctly if we simply add the two distances together. That is, if one record appears in the SUB set and another with the same location appears in the SNP set, they collectively will contribute 2 to the overall distance instead of correct 0 or 1 (depending on other attributes). To address this, we need to find all such pairs and compensate for the difference they introduced, which is the most subtle part of our solution. We next provide more detail about the solution and highlight the differences from the basic scheme.
Input preparation. Given a dataset, an input entity produces two subsets: one composed of SUB records and one composed of both SUB and SNP records from the dataset. As before, both sets need to be padded with dummy records to hide their number and make the size to be a power of 2 to the combined size of 2^{qs} and 2^{q}, where q_{
s
} = ⌈log(α_{
s
}(N_{1} + N_{2}) + 2)⌉ and q = ⌈log(α(N_{1} + N_{2}) + 2⌉ and α_{
s
} (α) denotes the maximum fraction of SUB (resp., SNP and SUB) records in genomic datasets (we were given α = 1 and α_{
s
} = 0.3). All records in the SUB set are converted to (V_{1}, V_{2}, V_{3}) triples as before. For the SNP&SUB set, onecharacter REF and ALT fields in SNP or SUB records are represented using integers 03, while these fields of longer length in SUB records are represented using integer 4 (i.e., V_{2} and V_{3} fields are 3 bits long). This will guarantee that comparison of a onecharacter long REF or ALT field in a SNP record with a longer REF or ALT field in a SUB record will result in their inequality. We also add another binary attribute V_{4} to each record of the SNP&SUB set that indicates whether the record is of SUB type (V_{4} = 0) or SNP type (V_{4} = 1). We set V_{4} = 0 in dummy records.
Each input entity now produces shares of (V_{1}, V_{2}, V_{3}) in its SUB set and (V_{1}, V_{2}, V_{3}, V_{4}) in its SNP&SUB set (together with the number of dummy records in each set) and distributes them to the computational parties. We note that computation with SNP&SUB sets can be performed on shorter bitlengths, which results in faster arithmetic, and thus we setup two different instances of the secret sharing scheme and process SUB sets separately from SNP&SUB sets.
Computation execution. To compute the Hamming distance correctly, we now distinguish between different cases: (i) SUB records that don't have a SNP record with identical location in the other dataset, (ii) SNP records that don't have a SUB record with identical location in the other dataset, and (iii) records that have another record with identical location but different type present in the other dataset. Let N0 denote the number of records in the third category.
Algorithm 3 SecureHD2([S_{1}], [S_{2}])
1: {\left(\left[{V}_{1}^{\left(i\right)}\right],\left[{V}_{2}^{\left(i\right)}\right],\left[{V}_{3}^{\left(i\right)}\right],\left[{V}_{4}^{\left(i\right)}\right]\right)}_{i=1}^{{2}^{q}}=\mathsf{\text{Merge}}\left(\left[{S}_{1}\right],\left[{S}_{2}\right]\right)
2: \mathsf{\text{dist}}=\left[{V}_{4}^{\left(1\right)}\right]
3: for i = 2 to 2^{q} do
4: \left[{a}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{1}^{\left(i1\right)}\right],\left[{V}_{1}^{\left(i\right)}\right]\right)
5: \left[{b}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{2}^{\left(i1\right)}\right],\left[{V}_{2}^{\left(i\right)}\right]\right)
6: \left[{c}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{3}^{\left(i1\right)}\right],\left[{V}_{3}^{\left(i\right)}\right]\right)
7: \left[{d}_{i}\right]=\mathsf{\text{OR}}\left(\left[{V}_{4}^{\left(i1\right)}\right],\left[{V}_{4}^{\left(i\right)}\right]\right)
8: \left[{e}_{i}\right]=\mathsf{\text{XOR}}\left(\left[{V}_{4}^{\left(i1\right)}\right],\left[{V}_{4}^{\left(i\right)}\right]\right)
9: \mathsf{\text{dist}}+=\left[{d}_{i}\right]\left(\left(1\left[{a}_{i}\right]\right)\left[{V}_{4}^{\left(i\right)}\right]+\left[{a}_{i}\right]\left(\left[{b}_{i}\right]\left(1\left[{c}_{i}\right]\right)\left[{V}_{4}^{\left(i1\right)}\right]\right)\right)\left[{a}_{i}\right]\left[{e}_{i}\right]
10: end for
11: return dist
The computational parties execute Algorithm 2 on two SUB datasets. This computes the distance corresponding to the records in category 1, but also introduces offset N_{0}. The parties then execute Algorithm 3 on two SNP&SUB sets that computes the distance corresponding to categories 2 and 3 and additionally compensates for the offset. The output will then be the sum of the distances computed by both algorithms.
In Algorithm 3, when examining each pair of consecutive records, we only consider those that contain at least one SNP record within the pair (d_{
i
} = 1 on line 9). Furthermore, similar Algorithm 2, when observing a location for the first time, we add 1 to the Hamming distance, but only if it is a SNP record ({V}_{4}^{\left(1\right)}=1 on line 2 and {V}_{4}^{\left(i\right)}=1 on line 9). If a location appears for the second time, we undo the previous increment if b_{
i
} = 0 or c_{
i
} = 1 as before, but only if the record preceding the current one is of type SNP (i.e., {V}_{4}^{\left(i1\right)}=1 on line 9). By doing that, we are able compute the distance corresponding to records of second and third types without introducing errors. The offset N_{0} is compensated by the last term a_{
i
}e_{
i
} on line 9, that counts the number of pairs of consecutive records that have the same location (a_{
i
} = 1), but different types (e_{
i
} = 1). OR([x], [y]) and XOR([x], [y]) are implemented as [x]+[y]−Mult([x], [y]) and [x]+[y]−2Mult([x], [y]), respectively (computation of d_{
i
} and e_{
i
} reuses the same multiplication result).
Note that dummy records do not introduce any error in Algorithm 3. That is, d_{
i
} = 0 and e_{
i
} = 0 when both records i and i − 1 are dummy and the expression on line 9 evaluates to 0. Similarly, when record i−1 is real while record i is fake that expression also evaluates to 0 because a_{
i
} = 0 and {V}_{4}^{\left(i\right)}=0.
After computing the distances corresponding to SUB and SNP&SUB sets, the parties need to convert shares of one of them into shares of the same value in the secret sharing setup used by the other algorithm. Then the distances can be locally added to compute the overall result. Output reconstruction is performed as before by exchanging the shares and recovering the result.
The performance gain achieved by this optimization highly depends on the values of public parameters α_{
s
}, α, and M. While the gain stems from using shorter values for V_{2} and V_{3} with SNP&SUB sets, the total number of records processed using this solution \left({2}^{q}+{2}^{{q}_{s}}\right) is greater than in the basic scheme (2_{
q
}). Therefore, this optimization is recommended with relatively small α_{
s
} and large M. In our experiments with α_{
s
} = 0.3, α = 1, and M = 100, we observed approximately 30% performance improvement compared to the basic scheme.
Reducing set size
Our second optimization is with respect to oblivious sort and removing the requirement that the input size has to be a power of 2 for the merge step of Batcher's mergesort. To explain how our optimization works, we need to provide additional details about Batcher's mergesort algorithm.
Recall that the merge step takes two sorted sets L_{1} = (a_{1}, a_{2}, ..., a_{
m
}) and L_{2} = (b_{1}, b_{2},..., b_{
n
}), where m + n is a power of 2. It first combines them into a single sequence that first monotonically increases and then decreases as L = (a_{1}, a_{2}, ..., a_{
m
}, b_{
n
}, ..., b_{2}, b_{1}), after which a sequence of compareandexchange operation is executed as specified by the following pseudocode:
\begin{array}{c}\mathsf{\text{for}}\left(r=\left(m+n\right)/2;r0;r=r/2\right)\\ \phantom{\rule{1em}{0ex}}\mathsf{\text{for}}\left(j=0;jm+n;j=j+2r\right)\\ \phantom{\rule{1em}{0ex}}\phantom{\rule{1em}{0ex}}\mathsf{\text{for}}\left(k=j;kj+r;k=k+1\right)\\ \phantom{\rule{1em}{0ex}}\phantom{\rule{1em}{0ex}}\phantom{\rule{2em}{0ex}}\phantom{\rule{2em}{0ex}}\phantom{\rule{2em}{0ex}}\mathsf{\text{compareandexchange}}\left(L\left[k\right],L\left[k+r\right]\right)\end{array}
After executing the first iteration of the outer loop, the first (second) half of L will contain (m + n)/2 smallest (resp., largest) elements of L although they are not necessarily sorted. After its second iteration, the ith quarter of L will contain the ith quarter of elements in the final sorted list for i = 1, ..., 4. This process continues until each sublist contains one element and L becomes sorted. Notice that the algorithm uses log(m + n) iterations of the outer loop, and in each iteration every element in the list is used in a compareandexchange operation, which is the reason for requiring the size of the list to be a power of 2.
Consider an example with input L_{1} = (3, 4, 6, 9, 12) and L_{2} = (2, 5, 10), which is combined into L = (3, 4, 6, 9, 12, 10, 5, 2). In the first iteration of the outer loop, compareandexchange operations are performed on pairs (3, 12), (4, 10), (6, 5), and (9, 2), and the resulting list is (3, 4, 5, 2, 12, 10, 6, 9). In the second iteration, comparisons are performed on (3, 5), (4, 2), (12, 6), (10, 9) and produce (3, 2, 5, 4, 6, 9, 12, 10). In the last iteration, we compare every pair of consecutive elements (3, 2), (5, 4), (6, 9), (12, 10), which results in the final sorted list (2, 3, 4, 5, 6, 9, 10, 12). If L2 = (2, 5) instead, after all iterations 2 will remain at the end of the list making it unsorted, as the element does not have any pair to use in a comparison.
We next proceed with describing our strategy for generalizing the merge operation to work with inputs of arbitrary sizes, which might be of independent interest. There will be no need to pad the input in the beginning to make the overall input size to be a power of 2, but dummy records are now added throughout algorithm execution as needed. This means that earlier loop iterations use a smaller number of elements and are therefore faster than in the original algorithm. In particular, at each loop iteration, if the size of a sublist is odd, we append a copy of its last element to the end. This will ensure that comparisons can be performed at the current level while still preserving the necessary properties of the (partially) sorted list. For example, suppose we want to merge (3, 6, 8) and (5, 7). Before the first iteration 5 will be added to the list (3, 6, 8, 7, 5) because the number of elements in it is odd, and we obtain (3, 5, 5, 7, 6, 8) at the end of that iteration. At the time of second iteration, the size of sublists (3, 5, 5) and (7, 6, 8) is also odd and they are modified to be (3, 5, 5, 5) and (7, 6, 8, 8). In the next iteration no additional padding is used and we obtain (3, 5, 5, 5, 6, 7, 8, 8) at the end of the algorithm.
In the context of Hamming distance computation, we similarly make a copy of the entire last record of a subset as needed during the merge step. More importantly, after having the list sorted, we need to ensure the Hamming distance is computed correctly because the introduction of repeated records creates inaccuracies in Algorithm 2. Now two consecutive records with the same location in the sorted set may correspond to (i) two records in the original datasets, (ii) two copied records, or (iii) one original and one copied record. Let a_{
i
} and a_{
j
} be two different records with the same location in the original datasets. If they get copied during the merge as {a}_{i}^{\prime} and {a}_{j}^{\prime}, the relative order of these records in the sorted list can be arbitrary (e.g., \left({a}_{i}^{\prime},{a}_{i},{a}_{j},{a}_{j}^{\prime}\right), \left({a}_{i}^{\prime},{a}_{j},{a}_{i},{a}_{j}^{\prime}\right), etc.) and they may contribute more than 1 to the computed distance.
We address the problem by modifying locations of records in the datasets so that (i) two records originally with the same location are assigned locations that differ by 1 and (ii) two records originally with different locations are assigned locations that differ by more than 1. By doing that, a pair of consecutive records with the same location in the sorted set is guaranteed to correspond to either two copied records or one original record and its copy. In either case, the Hamming distance should not get affected. We implement this change by setting the location to 4V_{1}, where V_{1} is the original location, for records from the first input site and to 4V_{1} + 1 for records from the second input site.
Algorithm 4 SecureHD3([S_{1}], [S_{2}])
1: {\left(\left[{V}_{1}^{\left(i\right)}\right],\left[{V}_{2}^{\left(i\right)}\right],\left[{V}_{3}^{\left(i\right)}\right]\right)}_{i=1}^{{2}^{q}}=\mathsf{\text{NewMerge}}\left(\left[{S}_{1}\right],\left[{S}_{2}\right]\right)
2: dist = 1
3: for i = 2 to 2^{q} do
4: \left[{a}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{1}^{\left(i1\right)}\right],\left[{V}_{1}^{\left(i\right)}\right]\right)
5: \left[{b}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{2}^{\left(i1\right)}\right],\left[{V}_{2}^{\left(i\right)}\right]\right)
6: \left[{c}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{3}^{\left(i1\right)}\right],\left[{V}_{3}^{\left(i\right)}\right]\right)
7: \left[{d}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{1}^{\left(i1\right)}\right]+1,\left[{V}_{1}^{\left(i\right)}\right]\right)
8: \mathsf{\text{dist}}+=\left(1\left[{a}_{i}\right]\right)\left(1\left[{d}_{i}\right]+\left[{d}_{i}\right]\left(\left[{b}_{i}\right]\left(1\left[{c}_{i}\right]\right)1\right)\right)
9: end for
10: return dist
With this solution, the input sites prepare their input datasets as in the basic scheme, but pad a set to size N_{
i
} + 1 instead of requiring the combined size to be a power of 2. The computational parties can locally modify V_{1}'s in the input records run the improved merge and compute the Hamming distance as specified in Algorithm 4. The algorithm has two major differences compared to Algorithm 2: (i) when examining each pair of consecutive records, only pairs with different locations can contribute to the distance (a_{
i
} = 0 on line 8) and (ii) when locations of two consecutive records differ by 1 (d_{
i
} = 1 on line 8), they are treated as having the same location in Algorithm 2, and when the locations differ by neither 1 nor 0 (d_{
i
} = 0 and a_{
i
} = 0 on line 8), they are treated as having different locations in Algorithm 2.
Dummy records inserted by each input site into their input datasets do not affect correctness of the Hamming distance that uses this optimization (including the combined solution in Algorithm 5). This is because the first dummy record from the first input set will result in the distance incremented by 1, while the first dummy record from the second input set will result in the distance decremented by 1. All consecutive dummy records from the first or the second input datasets do not modify the distance (because all records with the same V_{1} are ignored).
We recently became aware of a sorting algorithm [16] that generalizes Batcher's bitonic sort to input sizes which are not a power of 2 without adding extra records during the sorting procedure. The algorithm results in the same asymptotic complexity as our solution, but performs fewer compareandexchange operations in each iteration (because dummy records are not added), which is expected to lead to better performance than our algorithm. We plan to provide both theoretical and empirical comparison of this algorithm with our solution as future work.
Our final solution consists of using both optimizations from the previous and current subsections, and we summarize it in Algorithm 5. We omit its explanation due to space considerations.
Algorithm 5 SecureHD4 \left(\left[{S}_{1}^{\mathsf{\text{SUB}}}\right],\left[{S}_{1}^{\mathsf{\text{SNP}}}\right],\left[{S}_{2}^{\mathsf{\text{SUB}}}\right],\left[{S}_{2}^{\mathsf{\text{SNP}}}\right]\right)
1: dist_{1} = SecureHD3\left(\left[{S}_{1}^{\mathsf{\text{SUB}}}\right],\left[{S}_{2}^{\mathsf{\text{SUB}}}\right]\right)
2: {\left(\left[{V}_{1}^{\left(i\right)}\right],\left[{V}_{2}^{\left(i\right)}\right],\left[{V}_{3}^{\left(i\right)}\right],\left[{V}_{4}^{\left(i\right)}\right]\right)}_{i=1}^{{2}^{q}}=\mathsf{\text{NewMerge}}\left(\left[{S}_{1}^{\mathsf{\text{SNP}}}\right],\left[{S}_{2}^{\mathsf{\text{SNP}}}\right]\right)
3: \mathsf{\text{dis}}{\mathsf{\text{t}}}_{2}=\left[{V}_{4}^{\left(0\right)}\right]
4: for i = 2 to 2^{q} do
5: \left[{a}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{1}^{\left(i1\right)}\right],\left[{V}_{1}^{\left(i\right)}\right]\right)
6: \left[{b}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{2}^{\left(i1\right)}\right],\left[{V}_{2}^{\left(i\right)}\right]\right)
7: \left[{c}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{3}^{\left(i1\right)}\right],\left[{V}_{3}^{\left(i\right)}\right]\right)
8: \left[{d}_{i}\right]=\mathsf{\text{OR}}\left(\left[{V}_{4}^{\left(i1\right)}\right],\left[{V}_{4}^{\left(i\right)}\right]\right)
9: \left[{e}_{i}\right]=\mathsf{\text{XOR}}\left(\left[{V}_{4}^{\left(i1\right)}\right],\left[{V}_{4}^{\left(i\right)}\right]\right)
10: \left[{g}_{i}\right]=\mathsf{\text{EQ}}\left(\left[{V}_{1}^{\left(i1\right)}\right]+1,\left[{V}_{1}^{\left(i\right)}\right]\right)
11: \mathsf{\text{dis}}{\mathsf{\text{t}}}_{2}+=\left(1\left[{a}_{i}\right]\right)\left(\left[{d}_{i}\right]\left(\left(1\left[{g}_{i}\right]\right)\left[{V}_{4}^{\left(i\right)}\right]+\left[{g}_{i}\right]\left(\left[{b}_{i}\right]\left(1\left[{c}_{i}\right]\right){V}_{4}^{\left(i1\right)}\right)\right)\left[{g}_{i}\right]\left[{e}_{i}\right]\right)
12: end for
13: return dist_{1} + Convert(dist_{2})