public void AggregateLevel(ISimpleLevelState childLevel, ILevelState parentLevel, ILevelAtomicRITEInfo aRITEINfo)
        {
            int             childlevelsize = aRITEINfo.NumOfARITEs;
            IAggPatternInfo patterinInfo   = aRITEINfo.GetARitePatternInfo();

            int[]         partitions = aRITEINfo.GetARiteAggregationPartitions();
            float[]       factors    = childLevel.GetFactors(); //aRITEINfo.GetaRiteInfo().Factors;
            FactorPattern fPattern   = aRITEINfo.GetaRiteInfo().ApplyFactorPattern;

            //pre-process for factor
            float[] childrenLoss;
            if (fPattern == FactorPattern.AllOnes)
            {
                childrenLoss = childLevel.GetSubjectLoss();
            }
            else
            {
                childrenLoss = childLevel.GetSubjectLoss().Zip(factors, (x1, x2) => x1 * x2).ToArray();
            }

            switch (patterinInfo.GetLevelRelation)
            {
            case AggRelationship.OneToOne:
                Array.Copy(childrenLoss, parentLevel.GetSubjectLoss(), childlevelsize);
                break;

            case AggRelationship.RepeatedPattern:
                int groupSize = patterinInfo.RepeatedPartitionSize;
                SumArrayByPattern(childrenLoss, parentLevel.GetSubjectLoss(), groupSize);
                break;

            case AggRelationship.NoPattern:
                SumArrayByPartition(childrenLoss, parentLevel.GetSubjectLoss(), partitions);
                break;
            }
        }
        public void AggregateLevel(ILevelState childLevel, ISimpleLevelState childARITELevel, ILevelState parentLevel, ILevelNodeAggInfo childAggInfo, ILevelAtomicRITEInfo aRITEINfo, Stopwatch aggregation1)
        {
            int             childlevelsize = childAggInfo.NumOfNodes;
            IAggPatternInfo patterinInfo   = childAggInfo.GetNodePatternInfo();

            int[] partitions = childAggInfo.GetNodeAggregationPartitions();

            IAggPatternInfo aRITEpatterinInfo = aRITEINfo.GetARitePatternInfo();

            int[] aRITEpartitions = aRITEINfo.GetARiteAggregationPartitions();

            float[]       nodeFactors  = childLevel.GetFactors();      //childAggInfo.GetSimpleLevelInfo().Factors;
            float[]       riteFactor   = childARITELevel.GetFactors(); //aRITEINfo.GetaRiteInfo().Factors;
            FactorPattern nodeFPattern = childAggInfo.GetSimpleLevelInfo().ApplyFactorPattern;
            FactorPattern riteFPattern = aRITEINfo.GetaRiteInfo().ApplyFactorPattern;

            float[] childrenDed;
            float[] childrenExcess;

            //pre-process to multiply the Factor array
            if (nodeFPattern == FactorPattern.AllOnes)
            {
                childrenDed    = childLevel.GetDeductible();
                childrenExcess = childLevel.GetExcess();
            }
            else
            {
                childrenDed    = childLevel.GetDeductible().Zip(nodeFactors, (x1, x2) => x1 * x2).ToArray();
                childrenExcess = childLevel.GetExcess().Zip(nodeFactors, (x1, x2) => x1 * x2).ToArray();
            }

            //Aggregate D and X (ARITEs do not have D, X)
            switch (patterinInfo.GetLevelRelation)
            {
            case AggRelationship.OneToOne:
                Array.Copy(childrenDed, parentLevel.GetDeductible(), childlevelsize);
                Array.Copy(childrenExcess, parentLevel.GetExcess(), childlevelsize);
                break;

            case AggRelationship.RepeatedPattern:
                int groupSize = patterinInfo.RepeatedPartitionSize;
                SumArrayByPattern(childrenDed, parentLevel.GetDeductible(), groupSize);
                SumArrayByPattern(childrenExcess, parentLevel.GetExcess(), groupSize);
                break;

            case AggRelationship.NoPattern:
                SumArrayByPartition(childrenDed, parentLevel.GetDeductible(), partitions);

                aggregation1.Start();
                SumArrayByPartition(childrenExcess, parentLevel.GetExcess(), partitions);
                aggregation1.Stop();
                break;
            }

            // Aggregate S in case with Atomic Rites & Aggregate R for allocation
            float[] childrenNodeSubLoss;
            float[] childrenRiteSubLoss;
            float[] childrenRecov;

            if (nodeFPattern == FactorPattern.AllOnes)
            {
                childrenNodeSubLoss = childLevel.GetSubjectLoss();
                childrenRecov       = childLevel.GetRecoverable();
            }
            else
            {
                childrenNodeSubLoss = childLevel.GetSubjectLoss().Zip(nodeFactors, (x1, x2) => x1 * x2).ToArray();
                childrenRecov       = childLevel.GetRecoverable().Zip(nodeFactors, (x1, x2) => x1 * x2).ToArray();
            }

            if (aRITEINfo.HasAtomicRITEs)
            {
                //pre-process
                if (riteFPattern == FactorPattern.AllOnes)
                {
                    childrenRiteSubLoss = childARITELevel.GetSubjectLoss();
                }
                else
                {
                    childrenRiteSubLoss = childARITELevel.GetSubjectLoss().Zip(riteFactor, (x1, x2) => x1 * x2).ToArray();
                }

                if (aRITEpatterinInfo.GetLevelRelation == AggRelationship.NoPattern ||
                    patterinInfo.GetLevelRelation == AggRelationship.NoPattern)
                {
                    SumTwoArrayByPartition(childrenNodeSubLoss, childrenRiteSubLoss, parentLevel.GetSubjectLoss(), partitions, aRITEpartitions);
                    SumTwoArrayByPartition(childrenRecov, childrenRiteSubLoss, parentLevel.GetRecoverable(), partitions, aRITEpartitions);
                }
                else
                {
                    int termgroupsize;
                    int aRITEgroupsize;

                    switch (patterinInfo.GetLevelRelation)
                    {
                    case AggRelationship.OneToOne:
                        termgroupsize = 1;
                        break;

                    case AggRelationship.RepeatedPattern:
                        termgroupsize = aRITEpatterinInfo.RepeatedPartitionSize;
                        break;

                    default:
                        throw new NotSupportedException("The Level realtion " + patterinInfo.GetLevelRelation + " is currently not supported");
                    }

                    switch (aRITEpatterinInfo.GetLevelRelation)
                    {
                    case AggRelationship.OneToOne:
                        aRITEgroupsize = 1;
                        break;

                    case AggRelationship.RepeatedPattern:
                        aRITEgroupsize = aRITEpatterinInfo.RepeatedPartitionSize;
                        break;

                    default:
                        throw new NotSupportedException("The Level realtion " + patterinInfo.GetLevelRelation + " is currently not supported");
                    }

                    SumTwoArrayByPatternNew(childrenNodeSubLoss, childrenRiteSubLoss, parentLevel.GetSubjectLoss(), termgroupsize, aRITEgroupsize);
                    SumTwoArrayByPatternNew(childrenRecov, childrenRiteSubLoss, parentLevel.GetRecoverable(), termgroupsize, aRITEgroupsize);
                }
            }
            // Aggregate S in case with no Atomic Rites
            else
            {
                switch (patterinInfo.GetLevelRelation)
                {
                case AggRelationship.OneToOne:
                    Array.Copy(childrenNodeSubLoss, parentLevel.GetSubjectLoss(), childlevelsize);
                    Array.Copy(childrenRecov, parentLevel.GetRecoverable(), childlevelsize);
                    break;

                case AggRelationship.RepeatedPattern:
                    int groupSize = patterinInfo.RepeatedPartitionSize;
                    SumArrayByPattern(childrenNodeSubLoss, parentLevel.GetSubjectLoss(), groupSize);
                    SumArrayByPattern(childrenRecov, parentLevel.GetRecoverable(), groupSize);
                    break;

                case AggRelationship.NoPattern:
                    SumArrayByPartition(childrenNodeSubLoss, parentLevel.GetSubjectLoss(), partitions);
                    SumArrayByPartition(childrenRecov, parentLevel.GetRecoverable(), partitions);
                    break;
                }
            }
        }