diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 3e308c6a698c1b3482d9bec4feb3d015b32c1fcc..06e1f2a8a55745ccc93ade2e9d6d5d336cd3804d 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -12302,6 +12302,35 @@ bool IntraPrediction::generateTMPrediction(Pel *piPred, unsigned int uiStride, i
         m_if.m_filterVer[3][true][true](clpRng, tmp, tmpStride, piPred, uiStride, uiWidth, uiHeight, p, false);
       }
     }
+#if JVET_AF0079_STORING_INTRATMP
+    if (tmpIsSubPel != 0)   
+    {
+      int absDistance = (tmpIsSubPel == 1) ? 8 : (tmpIsSubPel == 2) ? 4 : 12;
+      int xDistance = 0, yDistance = 0;
+      if ((tmpSubPelIdx == LEFT_POS) || (tmpSubPelIdx == ABOVE_LEFT_POS) || (tmpSubPelIdx == LEFT_BOTTOM_POS))
+      {
+        xDistance = -absDistance;
+      }
+      if ((tmpSubPelIdx == RIGHT_POS) || (tmpSubPelIdx == ABOVE_RIGHT_POS) || (tmpSubPelIdx == RIGHT_BOTTOM_POS))
+      {
+        xDistance = absDistance;
+      }
+      if ((tmpSubPelIdx == ABOVE_POS) || (tmpSubPelIdx == ABOVE_LEFT_POS) || (tmpSubPelIdx == ABOVE_RIGHT_POS))
+      {
+        yDistance = -absDistance;
+      }
+      if ((tmpSubPelIdx == BOTTOM_POS) || (tmpSubPelIdx == LEFT_BOTTOM_POS) || (tmpSubPelIdx == RIGHT_BOTTOM_POS))
+      {
+        yDistance = absDistance;
+      }
+      const int iHor = (pX << MV_FRACTIONAL_BITS_INTERNAL) + xDistance;
+      const int iVer = (pY << MV_FRACTIONAL_BITS_INTERNAL) + yDistance;
+      pu.mv[0].set(iHor, iVer);
+
+      pu.bv = pu.mv[0];
+      pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
+    }
+#endif
   }
 #else
 #if TMP_FAST_ENC
@@ -12347,8 +12376,16 @@ bool IntraPrediction::generateTMPrediction(Pel *piPred, unsigned int uiStride, i
 
   pu.interDir               = 1;
   pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF;
+#if JVET_AF0079_STORING_INTRATMP
+  if ((cu->tmpIsSubPel == 0) || (cu->tmpIsSubPel == -1))
+  {
+    pu.mv[0].set(pX << MV_FRACTIONAL_BITS_INTERNAL, pY << MV_FRACTIONAL_BITS_INTERNAL);
+    pu.bv.set(pX, pY);
+  }
+#else
   pu.mv->set(pX << MV_FRACTIONAL_BITS_INTERNAL, pY << MV_FRACTIONAL_BITS_INTERNAL);
   pu.bv.set(pX, pY);
+#endif
 
 #if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST
 #if JVET_AD0086_ENHANCED_INTRA_TMP
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 6f2f2db70ca5c765f31369b87d0b914a8ccc7050..ed1323c8e2012aecd93bb79c41c82ed83eb16f42 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -136,6 +136,7 @@
 #define JVET_AB0061_ITMP_BV_FOR_IBC                       1 // JVET-AB0061: Storing IntraTMP BV for IBC BV prediction
 #define JVET_AD0086_ENHANCED_INTRA_TMP                    1 // JVET-AD0086: Enhanced intra TMP
 #define JVET_AE0077_EXT_INTRATMP                          1 // JVET-AE0077: Extended search areas for intraTMP
+#define JVET_AF0079_STORING_INTRATMP                      1 // JVET-AF0079: Storing fractional-pel intraTMP BV
 #endif
 
 #define JVET_W0123_TIMD_FUSION                            1 // JVET-W0123: Template based intra mode derivation and fusion
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index ab6dafaa08cc3076a6936fbf320e89ab8a3d59d5..5d585baae96dd928dde1183a9fde4665e03c8432 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -473,7 +473,11 @@ void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone )
     mi.addHypData = pu.addHypData;
 #endif
 #if JVET_AA0070_RRIBC
+#if JVET_AF0079_STORING_INTRATMP
+    if (CU::isIBC(cu) || cu.tmpFlag)
+#else
     if(CU::isIBC(cu))
+#endif
     {
       mi.centerPos.x = cu.lx() + (cu.lwidth() >> 1);
       mi.centerPos.y = cu.ly() + (cu.lheight() >> 1);
@@ -486,14 +490,22 @@ void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone )
     const unsigned xBr = pu.cu->Y().width + pu.cu->Y().x;
     const unsigned yBr = pu.cu->Y().height + pu.cu->Y().y;
     bool enableHmvp = ((xBr >> log2ParallelMergeLevel) > (pu.cu->Y().x >> log2ParallelMergeLevel)) && ((yBr >> log2ParallelMergeLevel) > (pu.cu->Y().y >> log2ParallelMergeLevel));
+#if JVET_AF0079_STORING_INTRATMP
+    bool enableInsertion = CU::isIBC(cu) || enableHmvp || cu.tmpFlag;
+#else
     bool enableInsertion = CU::isIBC(cu) || enableHmvp;
+#endif
     if (enableInsertion)
     {
 #if JVET_Z0075_IBC_HMVP_ENLARGE
 #if JVET_Z0118_GDR
       if (isClean)
       {
+#if JVET_AF0079_STORING_INTRATMP
+        if (CU::isIBC(cu) || cu.tmpFlag)
+#else
         if (CU::isIBC(cu))
+#endif
         {
           cu.cs->addMiToLutIBC(cu.cs->motionLut.lutIbc1, mi);
         }
@@ -503,7 +515,11 @@ void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone )
         }
       }
 
+#if JVET_AF0079_STORING_INTRATMP
+      if (CU::isIBC(cu) || cu.tmpFlag)
+#else
       if (CU::isIBC(cu))
+#endif
       {
         cu.cs->addMiToLutIBC(cu.cs->motionLut.lutIbc0, mi);
       }
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 39981e2061cdb0b42dc30f1367819db805223c8f..d0dec55d29f508376f5cb496bf5741c144e30b4c 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -513,6 +513,13 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
 #endif
 #endif
         xReconIntraQT( currCU );
+#if JVET_AF0079_STORING_INTRATMP
+        if (currCU.tmpFlag)
+        {
+          bool isIbcSmallBlk = false;
+          CU::saveMotionInHMVP(currCU, isIbcSmallBlk);
+        }
+#endif
 #if JVET_AD0188_CCP_MERGE
         CU::saveModelsInHCCP(currCU);
 #endif
@@ -1725,12 +1732,17 @@ void DecCu::xReconInter(CodingUnit &cu)
       }
     }
 #endif
+#if JVET_AF0079_STORING_INTRATMP
+    bool isIbcSmallBlk = false;
+#else
     bool isIbcSmallBlk = CU::isIBC(cu) && (cu.lwidth() * cu.lheight() <= 16);
+
 #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES
     if (cu.cs->sps->getUseIbcNonAdjCand())
     {
       isIbcSmallBlk = false;
     }
+#endif
 #endif
     CU::saveMotionInHMVP( cu, isIbcSmallBlk );
   }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 10295dffe12fe2a8bcf30c726ddcbaf822cea225..483ff802eb9a75d82b01704500cd94e2ee8d2059 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -1588,23 +1588,36 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par
   }
 #endif
 #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
+#if JVET_AF0079_STORING_INTRATMP
+  if ((!slice.isIntra() || slice.getUseIBC() || slice.getSPS()->getUseIntraTMP())
+#else
   if ((!slice.isIntra() || slice.getUseIBC())
+#endif
 #else
   if ((!slice.isIntra() || slice.getSPS()->getIBCFlag())
 #endif
     && partitioner.chType == CHANNEL_TYPE_LUMA
-    && bestCS->cus.size() == 1 && (bestCS->cus.back()->predMode == MODE_INTER || bestCS->cus.back()->predMode == MODE_IBC)
+    && bestCS->cus.size() == 1 && (bestCS->cus.back()->predMode == MODE_INTER || bestCS->cus.back()->predMode == MODE_IBC
+#if JVET_AF0079_STORING_INTRATMP
+          || bestCS->cus.back()->tmpFlag
+#endif
+      )
     && bestCS->area.Y() == (*bestCS->cus.back()).Y()
     )
   {
     const CodingUnit&     cu = *bestCS->cus.front();
 
+#if JVET_AF0079_STORING_INTRATMP
+    bool isIbcSmallBlk = false;
+#else
     bool isIbcSmallBlk = CU::isIBC(cu) && (cu.lwidth() * cu.lheight() <= 16);
+
 #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES
     if(cu.cs->sps->getUseIbcNonAdjCand())
     {
       isIbcSmallBlk = false;
     }
+#endif
 #endif
     CU::saveMotionInHMVP( cu, isIbcSmallBlk );
   }
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index 98a067d2dbf5c7bcd437e8d2b2255ff5c91cf9b2..8f0926fdd03ce667a07c92cda6b00ed771cf1422 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -7336,11 +7336,21 @@ void IntraSearch::xSelectAMTForFullRD(TransformUnit &tu)
 #if JVET_AD0086_ENHANCED_INTRA_TMP
       CodingUnit *cu         = pu.cu;
       int         pX, pY;
+
       int tmpIdx = cu->tmpFusionFlag ? m_tmpFusionInfo[cu->tmpIdx].tmpFusionIdx : cu->tmpIdx;
       pX = m_tmpXdisp[tmpIdx];
       pY = m_tmpYdisp[tmpIdx];
+#if JVET_AF0079_STORING_INTRATMP
+      if (cu->tmpFusionFlag
+          && ((m_tmpFusionInfo[cu->tmpIdx].tmpFusionNumber < 1) || m_tmpFusionInfo[cu->tmpIdx].bFilter))
+      {
+        pu.mv[0].set(pX << MV_FRACTIONAL_BITS_INTERNAL, pY << MV_FRACTIONAL_BITS_INTERNAL);
+        pu.bv.set(pX, pY);
+      }
+#else
       pu.mv->set(pX << MV_FRACTIONAL_BITS_INTERNAL, pY << MV_FRACTIONAL_BITS_INTERNAL);
       pu.bv.set(pX, pY);
+#endif
 #else
       pu.mv->set(m_tempLibFast.getX() << MV_FRACTIONAL_BITS_INTERNAL, m_tempLibFast.getY() << MV_FRACTIONAL_BITS_INTERNAL);
       pu.bv.set(m_tempLibFast.getX(), m_tempLibFast.getY());
@@ -7586,11 +7596,22 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
 #if JVET_AD0086_ENHANCED_INTRA_TMP
             CodingUnit *cu = pu.cu;
             int pX, pY;
+
             int tmpIdx = cu->tmpFusionFlag ? m_tmpFusionInfo[cu->tmpIdx].tmpFusionIdx : cu->tmpIdx;
             pX = m_tmpXdisp[tmpIdx];
             pY = m_tmpYdisp[tmpIdx];
+#if JVET_AF0079_STORING_INTRATMP
+            if (cu->tmpFusionFlag
+                && ((m_tmpFusionInfo[cu->tmpIdx].tmpFusionNumber < 1) || m_tmpFusionInfo[cu->tmpIdx].bFilter))
+            {
+              pu.mv[0].set(pX << MV_FRACTIONAL_BITS_INTERNAL, pY << MV_FRACTIONAL_BITS_INTERNAL);
+              pu.bv.set(pX, pY);
+            }
+#else
+
             pu.mv->set(pX << MV_FRACTIONAL_BITS_INTERNAL, pY << MV_FRACTIONAL_BITS_INTERNAL);
             pu.bv.set(pX, pY);
+#endif
 #else
             pu.mv->set(m_tempLibFast.getX() << MV_FRACTIONAL_BITS_INTERNAL, m_tempLibFast.getY() << MV_FRACTIONAL_BITS_INTERNAL);
             pu.bv.set(m_tempLibFast.getX(), m_tempLibFast.getY());