/// <summary>
        ///     Selects a <see cref="DoubleArray"/> to a <see cref="double"/>. The result is stored in a <see cref="Identity"/>.
        /// </summary>
        /// <param name="input">The indicator that sends data via <see cref="IUpdatable.Updated"/></param>
        /// <param name="selector">A selector to choose a <see cref="double"/>. </param>
        /// <param name="waitForFirstToReady">Input must be ready in order to push the updates forward.</param>
        /// <param name="name">Name of the new returned <see cref="Identity"/>.</param>
        public static Identity Select(this IUpdatable input, SelectorFunctionHandler selector, bool waitForFirstToReady = true, string name = null)
        {
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }
            var idn = new Identity(ResolveName(input, name), setReady: true);

            if (input.OutputCount > 1)
            {
                unsafe {
                    if (waitForFirstToReady)
                    {
                        input.Updated += (time, updated) => {
                            if (input.IsReady)
                            {
                                var ret = new DoubleArray2DManaged(updated.Count, 1);

                                fixed(double *dst = ret, src = updated)
                                for (int i = 0; i < updated.Count; i++)
                                {
                                    dst[i] = selector(src[i * updated.Properties]);
                                }

                                idn.Update(time, ret);
                            }
                        };
                    }
                    else
                    {
                        input.Updated += (time, updated) => {
                            var ret = new DoubleArray2DManaged(updated.Count, 1);

                            fixed(double *dst = ret, src = updated)
                            for (int i = 0; i < updated.Count; i++)
                            {
                                dst[i] = selector(src[i * updated.Properties]);
                            }

                            idn.Update(time, ret);
                        };
                    }

                    input.Resetted += sender => idn.Reset();
                }
            }
            else
            {
                if (waitForFirstToReady)
                {
                    input.Updated += (time, updated) => {
                        if (input.IsReady)
                        {
                            idn.Update(time, new DoubleArrayScalar(selector(updated)));
                        }
                    };
                }
                else
                {
                    input.Updated += (time, updated) => idn.Update(time, new DoubleArrayScalar(selector(updated)));
                }

                input.Resetted += sender => idn.Reset();
            }

            return(idn);
        }
        /// <summary>
        ///     Performs a math <paramref name="op"/> over <see cref="DoubleArray.Value"/> or value from <paramref name="selector"/>. The result is stored in a <see cref="Identity"/>.
        /// </summary>
        /// <param name="first">The indicator that sends data via <see cref="IUpdatable.Updated"/> even to the math <paramref name="op"/></param>
        /// <param name="op">The operation to perform on <see cref="DoubleArray.Value"/>.</param>
        /// <param name="selector">A selector to choose what <see cref="double"/> to pass to math <paramref name="op"/>. By default <see cref="DoubleArray.Value"/> is used.</param>
        /// <param name="waitForFirstToReady">First must be ready in order to push the updates forward.</param>
        /// <param name="name">Name of the new returned <see cref="Identity"/> representing the <paramref name="op"/>.</param>
        public static Identity Function(this IUpdatable first, UnaryFunctionHandler op, SelectorFunctionHandler selector = null, bool waitForFirstToReady = true, string name = null)
        {
            if (op == null)
            {
                throw new ArgumentNullException(nameof(op));
            }

            var idn = new Identity(ResolveName(first, name));


            if (selector == null)
            {
                if (waitForFirstToReady)
                {
                    first.Updated += (time, updated) => {
                        if (first.IsReady)
                        {
                            idn.Update(time, op(updated.Value));
                        }
                    };
                }
                else
                {
                    first.Updated += (time, updated) => idn.Update(time, op(updated.Value));
                }
            }
            else
            {
                if (waitForFirstToReady)
                {
                    first.Updated += (time, updated) => {
                        if (first.IsReady)
                        {
                            idn.Update(time, new DoubleArrayScalar(op(selector(updated))));
                        }
                    };
                }
                else
                {
                    first.Updated += (time, updated) => idn.Update(time, new DoubleArrayScalar(op(selector(updated))));
                }
            }

            first.Resetted += sender => idn.Reset();

            return(idn);
        }