diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index f9f3af1a1e85ed98f196ea538d67974fc6e5716e..ea9f998733c0f05294342c7811f9ca197e3bdd25 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -22829,15 +22829,56 @@ void IntraPrediction::initEipParams(const PredictionUnit& pu, const ComponentID
   CPelBuf recoLeft(piReco + refPosPicX + (refPosPicY + refSizeY) * picStride, picStride, refSizeX, refHeight - refSizeY);
   PelBuf refLeft(m_eipBuffer + refWidth * refSizeY, refWidth, refSizeX, refHeight - refSizeY);
   refLeft.copyFrom(recoLeft);
+
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+  int min = MAX_INT;
+  int max = 0;
+  int startY = refPosPicY < 0 ? -refPosPicY : 0;
+  const int startX = refPosPicX < 0 ? -refPosPicX : 0;
+  for(int y=startY;y<refTopAndTopLeft.height;y++)
+  {
+    for(int x=startX;x<refTopAndTopLeft.width;x++)
+    {
+      int sample = refTopAndTopLeft.at(x,y);
+      min = sample < min ? sample : min;
+      max = sample > max ? sample : max;
+    }
+  }
+  startY = (refPosPicY + refSizeY) < 0 ? -(refPosPicY + refSizeY) : 0;
+  for(int y=startY;y<refLeft.height;y++)
+  {
+    for(int x=startX;x<refLeft.width;x++)
+    {
+      int sample = refLeft.at(x,y);
+      min = sample < min ? sample : min;
+      max = sample > max ? sample : max;
+    }
+  }
+  m_eipClipMin = min;
+  m_eipClipMax = max;
+  m_eipBias    = 1 << (pu.cu->slice->getSPS()->getBitDepth(chType) - 1);
+#endif
 }
 
-void setInputsVec(Pel *inputs, PelBuf &reco, int w, int h, int filterShape) 
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+void IntraPrediction::setInputsVec(Pel *inputs, PelBuf &reco, int w, int h, int filterShape)
+{
+  inputs[EIP_FILTER_TAP - 1] = m_eipBias;
+  
+  for(int idx = 0; idx < EIP_FILTER_TAP - 1; idx++)
+  {
+    inputs[idx] = reco.at(w + g_eipFilter[filterShape][idx].x, h + g_eipFilter[filterShape][idx].y);
+  }
+}
+#else
+void setInputsVec(Pel *inputs, PelBuf &reco, int w, int h, int filterShape)
 {
   for(int idx = 0; idx < EIP_FILTER_TAP; idx++)
   {
     inputs[idx] = reco.at(w + g_eipFilter[filterShape][idx].x, h + g_eipFilter[filterShape][idx].y);
   }
 }
+#endif
 
 void IntraPrediction::getCurEipCands(const PredictionUnit& pu, static_vector<EipModelCandidate, NUM_DERIVED_EIP>& candList, const ComponentID compId, const bool fastTest)
 {
@@ -22933,7 +22974,13 @@ void IntraPrediction::getCurEipCands(const PredictionUnit& pu, static_vector<Eip
         {
           for (int x = startX; x < endX; x++)
           {
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+            m_a[numInputs - 1][numSamples] = m_eipBias;
+            
+            for (int inputIdx = 0; inputIdx < numInputs - 1; inputIdx++)
+#else
             for (int inputIdx = 0; inputIdx < numInputs; inputIdx++)
+#endif
             {
               m_a[inputIdx][numSamples] = refBuf.at(x + g_eipFilter[filterShape][inputIdx].x, y + g_eipFilter[filterShape][inputIdx].y);
             }
@@ -23019,7 +23066,13 @@ void IntraPrediction::eipPred(const PredictionUnit& pu, PelBuf& piPred, const Co
   const ScanElement* scan = g_scanOrder[SCAN_UNGROUPED][SCAN_DIAG][gp_sizeIdxInfo->idxFrom(blockWidth)][gp_sizeIdxInfo->idxFrom(blockHeight)];
   const int num = blockWidth * blockHeight;
   Pel inputs[EIP_FILTER_TAP];
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+  ClpRng clipRng = pu.cu->slice->clpRngs().comp[compId];
+  clipRng.min = std::max( clipRng.min, m_eipClipMin);
+  clipRng.max = std::min( clipRng.max, m_eipClipMax);
+#else
   const ClpRng clipRng = pu.cu->slice->clpRngs().comp[compId];
+#endif
   for (int scanIdx = 0; scanIdx < num; scanIdx++)
   {
     setInputsVec(inputs, predBuf, scan[scanIdx].x, scan[scanIdx].y, model.filterShape);
@@ -23510,7 +23563,13 @@ void IntraPrediction::reorderEipCands(const PredictionUnit& pu, static_vector<Ei
   static_vector<EipModelCandidate, MAX_MERGE_EIP> tmpCandList;
   Pel inputs[EIP_FILTER_TAP];
   const ChannelType chType = toChannelType(compId);
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+  ClpRng clipRng = pu.cu->slice->clpRngs().comp[compId];
+  clipRng.min = std::max( clipRng.min, m_eipClipMin);
+  clipRng.max = std::min( clipRng.max, m_eipClipMax);
+#else
   const ClpRng clipRng = pu.cu->slice->clpRngs().comp[compId];
+#endif
   for(auto model: candList)
   {
     CccmModel cand(EIP_FILTER_TAP, pu.cu->slice->getSPS()->getBitDepth(toChannelType(compId)));
diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h
index e732808434c96a3e8aad304da1542ad12d51ce3c..bca6799e8daab922a474a0417521a290a471a70e 100644
--- a/source/Lib/CommonLib/IntraPrediction.h
+++ b/source/Lib/CommonLib/IntraPrediction.h
@@ -272,6 +272,11 @@ protected:
   bool       bSrcBufFilled[NUM_EIP_SHAPE * NUM_EIP_BASE_RECOTYPE];
   bool       bDstBufFilled[NUM_EIP_BASE_RECOTYPE];
   int        numSamplesBuf[NUM_EIP_BASE_RECOTYPE];
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+  Pel        m_eipBias;
+  int        m_eipClipMin;
+  int        m_eipClipMax;
+#endif
 #endif
 private:
 #if JVET_AG0136_INTRA_TMP_LIC
@@ -849,6 +854,9 @@ public:
 
   void getNeiEipCands(const PredictionUnit &pu, static_vector<EipModelCandidate, MAX_MERGE_EIP> &candList, const ComponentID compId = COMPONENT_Y);
   void reorderEipCands(const PredictionUnit &pu, static_vector<EipModelCandidate, MAX_MERGE_EIP> &candList, const ComponentID compId = COMPONENT_Y);
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+  void setInputsVec(Pel *inputs, PelBuf &reco, int w, int h, int filterShape);
+#endif
 #endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING && JVET_Y0065_GPM_INTRA
 protected:
diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index 5468f1c270b6bcdaeb3a8d08ca64f9c368563cd3..7d5826cbf5679bf76ba4856e30629da943a8b8ba 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -4266,14 +4266,23 @@ const uint8_t g_aucTrSet[80][4] =
 #endif
 
 #if JVET_AG0058_EIP
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+// Note: Positions here are identical to the definition in the #else branch, just omitting the last position from each array
+const Position g_eipFilter[NUM_EIP_SHAPE][EIP_FILTER_TAP - 1] =
+{
+  { Position(-1,  0), Position(-2,  0), Position(-3,  0), Position( 0, -1), Position(-1, -1), Position(-2, -1), Position(-3, -1), Position( 0, -2), Position(-1, -2), Position(-2, -2), Position(-3, -2), Position( 0, -3), Position(-1, -3), Position(-2, -3) },
+  { Position(-1,  0), Position( 0, -1), Position(-1, -1), Position( 0, -2), Position(-1, -2), Position( 0, -3), Position(-1, -3), Position( 0, -4), Position(-1, -4), Position( 0, -5), Position(-1, -5), Position( 0, -6), Position(-1, -6), Position( 0, -7) },
+  { Position( 0, -1), Position(-1,  0), Position(-1, -1), Position(-2,  0), Position(-2, -1), Position(-3,  0), Position(-3, -1), Position(-4,  0), Position(-4, -1), Position(-5,  0), Position(-5, -1), Position(-6,  0), Position(-6, -1), Position(-7,  0) },
+};
+#else
 const Position g_eipFilter[NUM_EIP_SHAPE][EIP_FILTER_TAP] =
 {
   { Position(-1,  0), Position(-2,  0), Position(-3,  0), Position( 0, -1), Position(-1, -1), Position(-2, -1), Position(-3, -1), Position( 0, -2), Position(-1, -2), Position(-2, -2), Position(-3, -2), Position( 0, -3), Position(-1, -3), Position(-2, -3), Position(-3, -3) },
   { Position(-1,  0), Position( 0, -1), Position(-1, -1), Position( 0, -2), Position(-1, -2), Position( 0, -3), Position(-1, -3), Position( 0, -4), Position(-1, -4), Position( 0, -5), Position(-1, -5), Position( 0, -6), Position(-1, -6), Position( 0, -7), Position(-1, -7) },
   { Position( 0, -1), Position(-1,  0), Position(-1, -1), Position(-2,  0), Position(-2, -1), Position(-3,  0), Position(-3, -1), Position(-4,  0), Position(-4, -1), Position(-5,  0), Position(-5, -1), Position(-6,  0), Position(-6, -1), Position(-7,  0), Position(-7, -1) },
 };
-
-const EIPInfo g_eipInfoLut[4][4][9] = 
+#endif
+const EIPInfo g_eipInfoLut[4][4][9] =
 {
   {
     { EIPInfo(EIP_AL_A_L, EIP_FILTER_S), EIPInfo(EIP_AL_A_L, EIP_FILTER_V), EIPInfo(EIP_AL_A_L, EIP_FILTER_H), EIPInfo(), EIPInfo(), EIPInfo(), EIPInfo(), EIPInfo(), EIPInfo() }, // 4x4, 3modes
diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h
index 575cf0f82a32bcc4753e746cf9be3c8bef254df0..976e949ab4c90c66ac4902b8365c3487d03c0048 100644
--- a/source/Lib/CommonLib/Rom.h
+++ b/source/Lib/CommonLib/Rom.h
@@ -447,7 +447,11 @@ extern const int8_t g_amvpSbTmvp_mvd_offset[6];
 extern uint32_t g_picAmvpSbTmvpEnabledArea;
 #endif
 #if JVET_AG0058_EIP
+#if JVET_AH0086_EIP_BIAS_AND_CLIP
+extern const Position g_eipFilter[NUM_EIP_SHAPE][EIP_FILTER_TAP - 1];
+#else
 extern const Position g_eipFilter[NUM_EIP_SHAPE][EIP_FILTER_TAP];
+#endif
 extern const EIPInfo  g_eipInfoLut[4][4][9];
 #endif
 #if JVET_AG0276_LIC_SLOPE_ADJUST
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 9a48f57775bfa9445b07ca0c22eb1e7e425aa23a..e95c92f46b0e434024ef02d9862f73e39d2de677 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -204,6 +204,7 @@
 #define JVET_AG0154_DECODER_DERIVED_CCP_FUSION            1 // JVET-AG0154: Decoder derived CCP mode with fusion candidates
 #define JVET_AG0059_CCP_MERGE_ENHANCEMENT                 1 // JVET-AG0059: Enhancements on CCP merge for chroma intra coding
 #define JVET_AH0065_RELAX_LINE_BUFFER                     1 // JVET-AH0065: Relaxing line buffer restriction
+#define JVET_AH0086_EIP_BIAS_AND_CLIP                     1 // JVET-AH0086: EIP with bias and clipping
 
 //IBC
 #define JVET_Y0058_IBC_LIST_MODIFY                        1 // JVET-Y0058: Modifications of IBC merge/AMVP list construction, ARMC-TM-IBC part is included under JVET_W0090_ARMC_TM