code: def _g_h_process(self, grad_and_hess: DataFrame):
      en_grad_hess = grad_and_hess.create_frame()
  
      def make_long_tensor(
          s: pd.Series,
          coder,
          pk,
          offset,
          shift_bit,
          precision,
          encryptor,
          pack_num=2,
      ):
          pack_tensor = t.Tensor(s.values)
          pack_tensor[0] = pack_tensor[0] + offset
          pack_vec = coder.pack_floats(
              pack_tensor, shift_bit, pack_num, precision
          )
          en = pk.encrypt_encoded(pack_vec, obfuscate=True)
          ret = encryptor.lift(
              en, (len(en), 1), pack_tensor.dtype, pack_tensor.device
          )
          return ret
  
      def compute_offset_bit(sample_num, g_max, h_max):
          g_bit = int(
              math.log2(2**FIX_POINT_PRECISION * sample_num * g_max)
              + 1
          )  # add 1 more bit for safety
          h_bit = int(
              math.log2(2**FIX_POINT_PRECISION * sample_num * h_max)
              + 1
          )
          return max(g_bit, h_bit)
  
      if self._gh_pack:
          task_type = get_task_info(self._objective)
  
          if task_type == BINARY or task_type == MULTI:
              self._g_offset = 1
              self._g_abs_max = 2
              self._h_abs_max = 1
  
          elif task_type == REGRESSION:
              self._g_offset = abs(float(grad_and_hess["g"].min()["g"]))
              self._g_abs_max = (
                  abs(float(grad_and_hess["g"].max()["g"]))
                  + self._g_offset
              )
              self._h_abs_max = 2
  
          pack_num = 2
          shift_bit = compute_offset_bit(
              len(grad_and_hess), self._g_abs_max, self._h_abs_max
          )
          total_pack_num = (self._en_key_length - 2) // (
              shift_bit * pack_num
          )  # -2 in case overflow
          partial_func = functools.partial(
              make_long_tensor,
              coder=self._coder,
              offset=self._g_offset,
              pk=self._pk,
              shift_bit=shift_bit,
              pack_num=2,
              precision=FIX_POINT_PRECISION,
              encryptor=self._encryptor,
          )
          en_grad_hess["gh"] = grad_and_hess.apply_row(partial_func)
  
          # record pack info
          self._pack_info["g_offset"] = self._g_offset
          self._pack_info["shift_bit"] = shift_bit
          self._pack_info["precision"] = FIX_POINT_PRECISION
          self._pack_info["pack_num"] = pack_num
          self._pack_info["total_pack_num"] = total_pack_num
          self._pack_info["split_point_shift_bit"] = (
              shift_bit * pack_num
          )
          logger.info("gh are packed")
      else:
          en_grad_hess["g"] = self._encryptor.encrypt_tensor(
              grad_and_hess["g"].as_tensor()
          )
          en_grad_hess["h"] = self._encryptor.encrypt_tensor(
              grad_and_hess["h"].as_tensor()
          )
          logger.info("not using gh pack")
  
      return en_grad_hess
  
imports: from fate.ml.ensemble.learner.decision_tree.tree_core.decision_tree import DecisionTree, Node, _update_sample_pos_on_local_nodes, _merge_sample_pos
  from fate.ml.ensemble.learner.decision_tree.tree_core.hist import SBTHistogramBuilder
  from fate.ml.ensemble.learner.decision_tree.tree_core.splitter import SBTSplitter
  from fate.ml.ensemble.learner.decision_tree.tree_core.loss import get_task_info
  from fate.ml.ensemble.learner.decision_tree.tree_core.decision_tree import ALL_FEAT, GUEST_FEAT_ONLY
  from fate.ml.utils.predict_tools import BINARY, MULTI, REGRESSION
  from fate.arch import Context
  from fate.arch.dataframe import DataFrame
  from typing import List
  import functools
  import logging
  import pandas
  import torch
  import math
label_desc: Use image node_id 6 for calling the HeteroDecisionTreeGuest obj's underlying member method code with example usage: obj._g_h_process(grad_and_hess) and returns: en_grad_hess, ret, max