code: def encode_positions(self,
                           positions: mx.sym.Symbol,
                           data: mx.sym.Symbol) -> mx.sym.Symbol:
          
          # (batch_size, 1)
          positions = mx.sym.expand_dims(positions, axis=1)
          # (num_embed,)
          channels = mx.sym.arange(0, self.num_embed // 2)
          # (1, num_embed,)
          scaling = mx.sym.expand_dims(1. / mx.sym.pow(10000, (2 * channels) / self.num_embed), axis=0)
  
          # (batch_size, num_embed/2)
          scaled_positions = mx.sym.dot(positions, scaling)
  
          sin = mx.sym.sin(scaled_positions)
          cos = mx.sym.cos(scaled_positions)
  
          # (batch_size, num_embed)
          pos_embedding = mx.sym.concat(sin, cos, dim=1)
  
          if self.scale_up_input:
              data = data * (self.num_embed ** 0.5)
  
          if self.scale_down_positions:
              pos_embedding = pos_embedding * (self.num_embed ** -0.5)
  
          pos_embedding = mx.sym.BlockGrad(pos_embedding)
  
          return mx.sym.broadcast_add(data, pos_embedding, name="%s_add" % self.prefix)
docs: :param positions: (batch_size,)
          :param data: (batch_size, num_embed)
          :return: (batch_size, num_embed)