public static bool IsFourthType(Multioperation6 op)
        {
            if (ArrSet6.IsConst(op) == true)
            {
                return(false);
            }
            var first = op & Multioperation6.E;

            if (first != Multioperation6.E)
            {
                return(false);
            }
            var second = (!op) & op;

            if (second != Multioperation6.E)
            {
                return(false);
            }
            var third1 = op * (!op);
            var third2 = (!op) * op;

            if (third1 != Multioperation6.All || third2 != Multioperation6.All)
            {
                return(false);
            }

            var fourth = op * op;

            if (fourth != Multioperation6.All)
            {
                return(false);
            }
            return(true);
        }
        public static bool IsSecondType(Multioperation6 op)
        {
            if (ArrSet6.IsConst(op) == true)
            {
                return(false);
            }
            var first = op & Multioperation6.E;

            if (first != Multioperation6.E)
            {
                return(false);
            }
            var mu = !op;

            if (mu != op)
            {
                return(false);
            }
            var op2 = op * op;

            if (op2 != Multioperation6.All)
            {
                return(false);
            }
            return(true);
        }
        public static bool IsFifthType(Multioperation6 op)
        {
            if (ArrSet6.IsConst(op) == true)
            {
                return(false);
            }
            var first = op & Multioperation6.E;

            if (first != Multioperation6.Zero)
            {
                return(false);
            }
            if (!op != op)
            {
                return(false);
            }
            var third = op * op;

            if (third != Multioperation6.All)
            {
                return(false);
            }
            return(true);
        }
        /// <summary>
        /// Main function
        /// </summary>
        /// <param name="args"></param>
        private static void Main(string[] args)
        {
            // generate all multioperations of rank 4 (count = 2^16 = 65536)
            var gen6 = (from a in Enumerable.Range(1, 2)
                        from b in Enumerable.Range(1, 64)
                        from c in Enumerable.Range(1, 64)
                        from d in Enumerable.Range(1, 64)
                        from e in Enumerable.Range(1, 64)
                        from f in Enumerable.Range(1, 64)
                        select new Multioperation6(a, b, c, d, e, f)).ToArray();

            // contents multioperation f and number of elements
            // in corresponging algebra of unary multioperations
            //var results = new ConcurrentBag<Tuple<Multioperation4, int>>();
            //var finished = new bool[1] { false };

            //var thread = new Thread((obj) =>
            //{
            //    var fin = (bool[])obj;

            //    using (var file = new FileStream("ops.txt", FileMode.Append, FileAccess.Write, FileShare.Read))
            //    using (var wr = new StreamWriter(file))
            //    {
            //        while (!fin[0])
            //        {
            //            Tuple<Multioperation4, int> tpl;
            //            while (results.TryTake(out tpl))
            //            {
            //                wr.WriteLine(tpl);
            //                Console.Out.WriteLine("Tuple = {0}, count = ", tpl.Item1, tpl.Item2);
            //            }
            //            wr.Flush();
            //            //Thread.Sleep(500);
            //        }
            //    }
            //});

            //thread.Priority = ThreadPriority.BelowNormal;
            //thread.Start(finished);


            //Parallel.ForEach(gen4, new ParallelOptions() { MaxDegreeOfParallelism = 8 }, op =>
            //{
            //    var opCnt = ArrSet4.CheckOp4Arr(op);
            //    results.Add(new Tuple<Multioperation4, int>(op, opCnt));
            //});
            //finished[0] = true;

            //Console.ReadKey();
            Dictionary <Multioperation6, Multioperation6> dict = new Dictionary <Multioperation6, Multioperation6>();

            int count = 0;

            foreach (Multioperation6 op in gen6)
            {
                //if (dict.ContainsKey(op)) {
                //    continue;
                //}
                var isFirst = ArrSet6.IsFirstType(op);
                if (isFirst)
                {
                    count++;
                    //dict[!op] = op;
                    Console.WriteLine("{0}", op);
                }
            }
            Console.WriteLine("{0}", count);
            return;
        }
        /// <summary>
        /// Generate the whole algebra
        /// </summary>
        /// <returns>Number of multioperations in algebra</returns>
        /// <param name="op">Multioperation generator</param>
        public static int CheckOp4Arr(Multioperation6 op)
        {
            var set = new ArrSet6(op);

            if (set.Count <= 3)
            {
                return(set.Count);
            }

            var prevCount = 0;

            // generate new multioperation while it is possible
            while (set.Count < 65536 && prevCount != set.Count)
            {
                prevCount = set.Count;

                // add mu(f) multioperations
                for (int i = 0; i < set.Count; i++)
                {
                    set.Add(!set[i]);
                }

                for (int i = 0; i < set.Count; i++)
                {
                    var op1 = set[i];

                    // For multioperation tetha: (tetha * x)(x) = (tetha)
                    // and (tetha intersection f)(x) = (tetha)
                    // so we could skip this step
                    if (op1 == Multioperation6.Zero)
                    {
                        continue;
                    }
                    for (int j = 0; j < set.Count; j++)
                    {
                        var op2 = set[j];
                        // For multioperation tetha: (f * tetha)(x) = (tetha)
                        // and (f intersection tetha)(x) = (tetha)
                        // so we could skip this step too
                        if (op2 == Multioperation6.Zero)
                        {
                            continue;
                        }
                        // (f * g)(x)
                        var opSup = op1 * op2;
                        // (f intersection g)(x)
                        var opUn = op1 & op2;
                        set.Add(opSup);
                        set.Add(opUn);
                        if (op1 == op2)
                        {
                            continue;
                        }
                        // (g * f)(x)
                        opSup = op2 * op1;
                        set.Add(opSup);
                    }
                }
            }
            return(set.Count);
        }