internal unsafe void Propagate(ManagedNeuralComputationContext context, float* valueBuffer, float* eVector)
        {
            Contract.Requires(valueBuffer != null);
            Contract.Requires(context != null);

            lock (context.SyncRoot)
            {
                EnsureInitialized(context);

                for (int compIndex = 0; compIndex < ForwardComputes.Length; compIndex++)
                {
                    var comp = ForwardComputes[compIndex];

                    int iLayerIndex = comp.ConnectedLayerIndex;
                    int compOutputBufferSize = comp.OutputBuffer.Size;
                    for (int iValueIndex = 0; iValueIndex < compOutputBufferSize; iValueIndex++)
                    {
                        // i: iLayerIndex, iValueIndex

                        // Compute for Weights:
                        var compPWeightBuffers = GetPWeights(context, compIndex);
                        for (int jLayerIndex = 0; jLayerIndex < compPWeightBuffers.Length; jLayerIndex++)
                        {
                            var layerRelatedPBuffs = compPWeightBuffers[jLayerIndex];
                            var layerRelatedPrevPBuffs = comp.PrevPWeightBuffers[jLayerIndex];
                            int inputLayerSize = comp.InputValueAccessItems[jLayerIndex].InputSize;

                            Debug.Assert(compOutputBufferSize * inputLayerSize == layerRelatedPBuffs.Length);
                            Debug.Assert(compOutputBufferSize * inputLayerSize == layerRelatedPrevPBuffs.Length);

                            for (int jValueIndex = 0; jValueIndex < inputLayerSize; jValueIndex++)
                            {
                                int ijValueIndex = WeightAccessor.GetWeightValueIndex(jValueIndex, iValueIndex, compOutputBufferSize);

                                var valueRelatedPBuffs = layerRelatedPBuffs[ijValueIndex];
                                var valueRelatedPrevPBuffs = layerRelatedPrevPBuffs[ijValueIndex];

                                // i: iLayerIndex, iValueIndex
                                // j: jLayerIndex, jValueIndex

                                FlipPWeights(context, compIndex);
                                ComputePValues(valueBuffer, comp, valueRelatedPBuffs, valueRelatedPrevPBuffs, iLayerIndex, iValueIndex, jLayerIndex, jValueIndex, eVector);
                            }
                        }

                        // Compute for Bias
                        if (comp.PBiasBuffers != null)
                        {
                            FlipPBias(context, compIndex);
                            ComputePValues(valueBuffer, comp, GetPBias(context, compIndex), comp.PrevPBiasBuffers, iLayerIndex, iValueIndex, -1, -1, eVector);
                        }
                    }
                }
            }
        }
 private void FlipPBias(ManagedNeuralComputationContext context, int compIndex)
 {
     context.PValuePropagator_PBiasBufferFlipped[compIndex] = !context.PValuePropagator_PBiasBufferFlipped[compIndex];
 }
 private IntRange[] GetPBias(ManagedNeuralComputationContext context, int compIndex)
 {
     if (!context.PValuePropagator_PBiasBufferFlipped[compIndex])
     {
         return ForwardComputes[compIndex].PBiasBuffers;
     }
     else
     {
         return ForwardComputes[compIndex].PrevPBiasBuffers;
     }
 }
 private void EnsureInitialized(ManagedNeuralComputationContext context)
 {
     if (context.PValuePropagator_PWeightBufferFlipped == null)
     {
         context.PValuePropagator_PWeightBufferFlipped = new bool[ForwardComputes.Length];
         context.PValuePropagator_PBiasBufferFlipped = new bool[ForwardComputes.Length];
     }
 }