/// <summary> /// Reshape the bottom (input) and top (output) blobs. /// </summary> /// <param name="colBottom">Specifies the collection of bottom (input) Blobs.</param> /// <param name="colTop">Specifies the collection of top (output) Blobs.</param> public override void Reshape(BlobCollection <T> colBottom, BlobCollection <T> colTop) { T[] rgOldSteps = new T[m_nNumAxes]; T[] rgNewSteps = new T[m_nNumAxes]; T[] rgOrder1 = m_blobPermuteOrder.mutable_cpu_data; List <int> rgOrder = new List <int>(); for (int i = 0; i < rgOrder1.Length; i++) { if (i < m_nNumAxes) { if (i == m_nNumAxes - 1) { rgOldSteps[i] = m_tOne; } else { rgOldSteps[i] = Utility.ConvertVal <T>(colBottom[0].count(i + 1)); } } rgOrder.Add((int)Utility.ConvertVal <T>(rgOrder1[i])); } m_blobOldSteps.mutable_cpu_data = rgOldSteps; List <int> rgTopShape = PermuteParameter.Reshape(rgOrder, colBottom[0].shape(), colBottom[0].num_axes); colTop[0].Reshape(rgTopShape); for (int i = 0; i < m_nNumAxes; i++) { if (i == m_nNumAxes - 1) { rgNewSteps[i] = m_tOne; } else { rgNewSteps[i] = Utility.ConvertVal <T>(colTop[0].count(i + 1)); } } m_blobNewSteps.mutable_cpu_data = rgNewSteps; }
/// <summary> /// Setup the layer. /// </summary> /// <param name="colBottom">Specifies the collection of bottom (input) Blobs.</param> /// <param name="colTop">Specifies the collection of top (output) Blobs.</param> public override void LayerSetUp(BlobCollection <T> colBottom, BlobCollection <T> colTop) { m_log.CHECK_EQ(colBottom.Count, 1, "There should only be one botom blob."); PermuteParameter permute_param = layer_param.permute_param; m_nNumAxes = colBottom[0].num_axes; // Push the specified new orders List <int> rgOrders = new List <int>(); foreach (int nOrder in permute_param.order) { m_log.CHECK_LT(nOrder, m_nNumAxes, "The order should be less than the input dimension '" + m_nNumAxes.ToString() + "'!"); if (rgOrders.Contains(nOrder)) { m_log.FAIL("The order '" + nOrder.ToString() + "' is a duplicate order!"); } rgOrders.Add(nOrder); } // Push the rest of the orders and save the orginal step sizes for each axis. for (int i = 0; i < m_nNumAxes; i++) { if (!rgOrders.Contains(i)) { rgOrders.Add(i); } } m_log.CHECK_EQ(rgOrders.Count, m_nNumAxes, "The order count should be the same as the input dimension of '" + m_nNumAxes.ToString() + "'!"); // Check if we need to reorder the data or keep it. m_bNeedPermute = false; for (int i = 0; i < m_nNumAxes; i++) { if (rgOrders[i] != i) { // As long as there is one order which is different from the natural order // of the data, we need to permute. Otherwise, we share the data and diff. m_bNeedPermute = true; break; } } List <int> rgTopShape = Utility.Create <int>(m_nNumAxes, 1); m_blobPermuteOrder.Reshape(m_nNumAxes, 1, 1, 1); m_blobOldSteps.ReshapeLike(m_blobPermuteOrder); m_blobNewSteps.ReshapeLike(m_blobPermuteOrder); T[] rgOrder1 = new T[m_nNumAxes]; for (int i = 0; i < m_nNumAxes; i++) { int nOrder = rgOrders[i]; rgOrder1[i] = Utility.ConvertVal <T>(nOrder); int nShape = colBottom[0].shape(nOrder); rgTopShape[i] = nShape; } m_blobPermuteOrder.mutable_cpu_data = rgOrder1; colTop[0].Reshape(rgTopShape); }