code: def __SPK_circuit(S, P):
      """
      Computes the Set-Propagate-Kill Tree circuit for a set (S, P)
      (K is implied by S, P since (SPK) is one-hot)
  
      (See section 6.3 of Damgard, "Unconditionally Secure Constant-Rounds
      Multi-Party Computation for Equality, Comparison, Bits and Exponentiation")
  
      At each stage:
          S <- S0 ^ (P0 & S1)
          P <- P0 & P1
          K <- K0 ^ (P0 & K1) <- don't need K since it is implied by S and P
      """
      from .binary import BinarySharedTensor
  
      # Vectorize private AND calls to reduce rounds:
      SP = BinarySharedTensor.stack([S, P])
  
      __MASKS, __OUT_MASKS, __MULTIPLIERS = __SPK_circuit_constants(
          SP.device
      )
  
      # fmt: off
      # Tree reduction circuit
      for i in range(__LOG_BITS):
          in_mask = __MASKS[i]                # Start of arrows
          out_mask = __OUT_MASKS[i]           # End of arrows
          not_out_mask = out_mask ^ -1        # Not (end of arrows)
  
          # Set up S0, S1, P0, and P1
          P0 = SP[1] & out_mask               # Mask P0 from P
          S1P1 = SP & in_mask                 # Mask S1P1 from SP
          S1P1._tensor *= __MULTIPLIERS[i]    # Fan out S1P1 along arrows
  
          # Update S and P
          update = P0 & S1P1                  # S0 ^= P0 & S1, P0 = P0 & P1
          SP[1] &= not_out_mask
          SP ^= update
      # fmt: on
      return SP[0], SP[1]
  
file_path: CrypTen/crypten/mpc/primitives/circuit.py
imports: import functools
  import math
  import torch
label_desc: Use image node_id 2 for calling a global function with example usage: __SPK_circuit(S, P) and returns: SP,  SP