code: def _lsb_private(prot, x: PondPrivateTensor):
      """
      Logic for finding the least significant bit of a private tensor
      in binary representation.
      """
  
      # TODO[Morten] in the refactor these could be type parameters
      odd_dtype = x.backing_dtype
      out_dtype = prot.tensor_factory
      prime_dtype = prot.prime_factory
  
      assert odd_dtype.modulus % 2 == 1
  
      # needed for security because of `r` masking
      assert x.backing_dtype.native_type == odd_dtype.native_type
  
      with tf.name_scope("lsb"):
          with tf.name_scope("blind"):
              # ask server2 to generate r mask and its bits
              with tf.device(prot.server_2.device_name):
                  r0 = odd_dtype.sample_uniform(x.shape)
                  r1 = odd_dtype.sample_uniform(x.shape)
              with tf.device(prot.server_0.device_name):
                  r0 = r0.identity()
              with tf.device(prot.server_1.device_name):
                  r1 = r1.identity()
              r = PondPrivateTensor(prot, r0, r1, False)
  
              with tf.device(prot.server_2.device_name):
                  r_raw = r0 + r1
                  rbits_raw = r_raw.bits(factory=prime_dtype)
                  rbits = prot._share_and_wrap(rbits_raw, False)
  
                  # TODO[Morten] once .bits() is cached then call .lsb() here instead
                  rlsb_raw = rbits_raw[..., 0].cast(out_dtype)
                  rlsb = prot._share_and_wrap(rlsb_raw, False)
  
              # blind and reveal
              c = (x + r).reveal()
              c = prot.cast_backing(c, out_dtype)
              c.is_scaled = False
  
          with tf.name_scope("compare"):
              # ask either server0 and server1 to generate beta (distributing load)
              if random.random() < 0.5:
                  with tf.device(prot.server_0.device_name):
                      beta_raw0 = prime_dtype.sample_bits(x.shape)
                  with tf.device(prot.server_1.device_name):
                      beta_raw1 = beta_raw0.identity()
              else:
                  with tf.device(prot.server_1.device_name):
                      beta_raw1 = prime_dtype.sample_bits(x.shape)
                  with tf.device(prot.server_0.device_name):
                      beta_raw0 = beta_raw1.identity()
              beta = PondPublicTensor(
                  prot, beta_raw0, beta_raw1, is_scaled=False
              )
  
              greater_xor_beta = _private_compare(prot, rbits, c, beta)
              clsb = prot.lsb(c)
  
          with tf.name_scope("unblind"):
              gamma = prot.bitwise_xor(
                  greater_xor_beta, prot.cast_backing(beta, out_dtype)
              )
              delta = prot.bitwise_xor(rlsb, clsb)
              alpha = prot.bitwise_xor(gamma, delta)
  
          assert alpha.backing_dtype is out_dtype
          return alpha
  
imports: from __future__ import absolute_import
  import math
  import random
  import sys
  from typing import Optional
  from typing import Tuple
  import numpy
  import tensorflow
  from tf_encrypted.config import get_config
  from tf_encrypted.player import Player
  from tf_encrypted.protocol import memoize
  from tf_encrypted.protocol.pond import Pond
  from tf_encrypted.protocol.pond import PondMaskedTensor
  from tf_encrypted.protocol.pond import PondPrivateTensor
  from tf_encrypted.protocol.pond import PondPublicTensor
  from tf_encrypted.protocol.pond import PondTensor
  from tf_encrypted.protocol.pond import _type
  from tf_encrypted.protocol.protocol import nodes
  from tf_encrypted.protocol.securenn.odd_tensor import oddint64_factory
  from tf_encrypted.tensor import int64factory
  from tf_encrypted.tensor import native_factory
  from tf_encrypted.tensor.factory import AbstractFactory
  from tf_encrypted.tensor.factory import AbstractTensor
label_desc: Use image node_id 3 for calling a global function with example usage: _lsb_private(prot, x) and returns: alpha