text:
using System;
using System.Numerics;
using DiffSharp.Backend;
using Microsoft.FSharp.Core;
using Sigma.Core.MathAbstract;
using Sigma.Core.Utils;
using static DiffSharp.Util;

namespace Sigma.Core.Handlers.Backends.SigmaDiff
{
	/// <summary>
	/// A DiffSharp backend handle for 32-bit floats as passed to the underlying DiffSharp implementation.
	/// </summary>
	public unsafe class DiffSharpFloat32BackendHandle : DiffSharpBackendHandle<float>
	{
		public IBlasBackend BlasBackend { get; }
		public ILapackBackend LapackBackend { get; }

		/// <summary>
		/// Create a DiffSharpFloat32BackendHandle with a certain BLAS and LAPACK backend and an associated handle tag.
		/// </summary>
		/// <param name="blasBackend">The BLAS backend to use (must use 32-bit floats).</param>
		/// <param name="lapackBackend">The LAPACK backend to use (must use 32-bit floats).</param>
		/// <param name="backendTag">The backend tag to use.</param>
		public DiffSharpFloat32BackendHandle(IBlasBackend blasBackend, ILapackBackend lapackBackend, long backendTag) : base(backendTag)
		{
			if (blasBackend == null) throw new ArgumentNullException(nameof(blasBackend));
			if (lapackBackend == null) throw new ArgumentNullException(nameof(lapackBackend));

			BlasBackend = blasBackend;
			LapackBackend = lapackBackend;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.CreateDataBuffer"/>
		public override ISigmaDiffDataBuffer<float> CreateDataBuffer(float[] values)
		{
			return new SigmaDiffDataBuffer<float>(values, backendTag: BackendTag);
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.L1Norm_V"/>
		public override float L1Norm_V(ISigmaDiffDataBuffer<float> value)
		{
			if (value.Length == 0)
			{
				return 0.0f;
			}

			fixed (float* aref = &value.Data[value.Offset])
			{
				int len = value.Length;
				int inca = 1;

				return BlasBackend.Sasum(&len, aref, &inca);
			}
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.L2Norm_V"/>
		public override float L2Norm_V(ISigmaDiffDataBuffer<float> value)
		{
			if (value.Length == 0)
			{
				return 0.0f;
			}

			fixed (float* aref = &value.Data[value.Offset])
			{
				int len = value.Length;
				int inca = 1;

				return BlasBackend.Snrm2(&len, aref, &inca);
			}
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.SupNorm_V"/>
		public override float SupNorm_V(ISigmaDiffDataBuffer<float> value)
		{
			if (value.Length == 0)
			{
				return 0.0f;
			}

			fixed (float* aref = &value.Data[value.Offset])
			{
				int len = value.Length;
				int inca = 1;

				int i = BlasBackend.Isamax(&len, aref, &inca);

				return value.Data[value.Offset + i - 1];
			}
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sum_V"/>
		public override float Sum_V(ISigmaDiffDataBuffer<float> a)
		{
			if (a.Length == 0)
			{
				return 0.0f;
			}

			int simdLength = Vector<float>.Count, len = a.Length;
			float[] aData = a.Data;
			int aOffset = a.Offset;
			float result = 0.0f;

			// Use SIMD instructions to sum all elements into a temporary vector vt, then sum that and the remaining items to result.
			fixed (float* aref = &aData[aOffset])
			{
				Vector<float> vt = Vector<float>.Zero;

				int i;
				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					vt += va;
				}

				for (; i < len; ++i)
				{
					result += aref[i];
				}

				result += Vector.Dot<float>(vt, Vector<float>.One);
			}

			return result;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sum_M"/>
		public override float Sum_M(ISigmaDiffDataBuffer<float> value)
		{
			return Sum_V(value);
		}

		public override int MaxIndex_V(ISigmaDiffDataBuffer<float> a)
		{
			if (a.Length == 0)
			{
				return 0;
			}

			int simdLength = Vector<float>.Count, len = a.Length;
			float[] aData = a.Data;
			int aOffset = a.Offset, maxIndex = 0;
			float maxValue = float.NegativeInfinity;

			// Pick between per-item (for smaller arrays) and SIMD max index search (for larger arrays).
			fixed (float* aref = &aData[aOffset])
			{
				// In case of smaller array, use standard manual max index search.
				if (len < simdLength * 4)
				{
					for (int k = 0; k < len; k++)
					{
						if (aref[k] > maxValue)
						{
							maxValue = aref[k];
							maxIndex = k;
						}
					}
				}
				// In case of larger array, use SIMD max index search.
				// In an optimal case, this should perform around 4-5x times faster for large enough arrays with evenly distributed values.
				else
				{
					Vector<float> vt = new Vector<float>(float.NegativeInfinity);

					// Find the maximum values for each simdLength vector slot.
					int i = 0;
					for (; i <= len - simdLength; i += simdLength)
					{
						Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
						vt = Vector.Max(va, vt);
					}

					// Find the maximum value within the remaining data.
					for (; i < len; ++i)
					{
						if (aref[i] > maxValue)
						{
							maxValue = aref[i];
							maxIndex = i;
						}
					}

					// If any of the maximum value slots of the SIMD vector is larger than the already picked value, set the mod max index (slot index within the SIMD vector).
					int modMaxIndex = -1;
					for (int y = 0; y < simdLength; y++)
					{
						if (vt[y] > maxValue)
						{
							maxValue = vt[y];
							modMaxIndex = y;
						}
					}

					// If the slot ("mod") index was set, find the actual max index in simdLength increments.
					if (modMaxIndex != -1)
					{
						for (i = modMaxIndex; i < len; i += simdLength)
						{
							if (aref[i] == maxValue)
							{
								maxIndex = i;

								break;
							}
						}
					}
				}
			}

			return maxIndex;
		}

		public override int MinIndex_V(ISigmaDiffDataBuffer<float> a)
		{
			if (a.Length == 0)
			{
				return 0;
			}

			int simdLength = Vector<float>.Count, len = a.Length;
			float[] aData = a.Data;
			int aOffset = a.Offset, minIndex = 0;
			float minValue = float.PositiveInfinity;

			// Pick between per-item (for smaller arrays) and SIMD min index search (for larger arrays).
			fixed (float* aref = &aData[aOffset])
			{
				// In case of smaller array, use standard manual max index search.
				if (len < simdLength * 4)
				{
					for (int k = 0; k < len; k++)
					{
						if (aref[k] < minValue)
						{
							minValue = aref[k];
							minIndex = k;
						}
					}
				}
				// In case of larger array, use SIMD min index search.
				// In an optimal case, this should perform around 4-5x times faster for large enough arrays with evenly distributed values.
				else
				{
					Vector<float> vt = new Vector<float>(float.PositiveInfinity);

					// Find the minimum values for each simdLength vector slot.
					int i = 0;
					for (; i <= len - simdLength; i += simdLength)
					{
						Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
						vt = Vector.Min(va, vt);
					}

					// Find the minimum value within the remaining data.
					for (; i < len; ++i)
					{
						if (aref[i] < minValue)
						{
							minValue = aref[i];
							minIndex = i;
						}
					}

					// If any of the minimum value slots of the SIMD vector is smaller than the already picked value, set the mod min index (slot index within the SIMD vector).
					int modMinIndex = -1;
					for (int y = 0; y < simdLength; y++)
					{
						if (vt[y] < minValue)
						{
							minValue = vt[y];
							modMinIndex = y;
						}
					}

					// If the slot ("mod") index was set, find the actual min index in simdLength increments.
					if (modMinIndex != -1)
					{
						for (i = modMinIndex; i < len; i += simdLength)
						{
							if (aref[i] == minValue)
							{
								minIndex = i;

								break;
							}
						}
					}
				}
			}

			return minIndex;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Add_V_V"/>
		public override ISigmaDiffDataBuffer<float> Add_V_V(ISigmaDiffDataBuffer<float> a, ISigmaDiffDataBuffer<float> b)
		{
			if (a.Length == 0)
			{
				return b.DeepCopy();
			}
			if (b.Length == 0)
			{
				return a.DeepCopy();
			}

			b = b.DeepCopy();
			fixed (float* aref = &a.Data[a.Offset])
			fixed (float* bref = &b.Data[b.Offset])
			{
				int len = Math.Min(a.Length, b.Length);
				int inca = 1, incb = 1;
				float alpha = 1.0f;

				BlasBackend.Saxpy(&len, &alpha, aref, &inca, bref, &incb);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Add_V_V_InPlace"/>
		public override ISigmaDiffDataBuffer<float> Add_V_V_InPlace(ISigmaDiffDataBuffer<float> a, int aOffset, ISigmaDiffDataBuffer<float> b, int bOffset, int len)
		{
			if (len == 0)
			{
				return b;
			}

			fixed (float* aref = &a.Data[a.Offset + aOffset])
			fixed (float* bref = &b.Data[b.Offset + bOffset])
			{
				int inca = 1, incb = 1;
				float alpha = 1.0f;

				BlasBackend.Saxpy(&len, &alpha, aref, &inca, bref, &incb);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Add_S_V"/>
		public override ISigmaDiffDataBuffer<float> Add_S_V(float a, ISigmaDiffDataBuffer<float> b)
		{
			if (b.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			b = b.DeepCopy();
			fixed (float* bref = &b.Data[b.Offset])
			{
				int len = Math.Min(1, b.Length);
				int inca = 0, incb = 1;
				float alpha = 1.0f;

				BlasBackend.Saxpy(&len, &alpha, &a, &inca, bref, &incb);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sub_V_V"/>
		public override ISigmaDiffDataBuffer<float> Sub_V_V(ISigmaDiffDataBuffer<float> a, ISigmaDiffDataBuffer<float> b)
		{
			if (a.Length == 0)
			{
				return b.DeepCopy();
			}
			if (b.Length == 0)
			{
				return a.DeepCopy();
			}

			b = b.DeepCopy();
			fixed (float* aref = &a.Data[a.Offset])
			fixed (float* bref = &b.Data[b.Offset])
			{
				int len = Math.Min(a.Length, b.Length);
				int inca = 1, incb = 1;
				float alpha = -1.0f;

				BlasBackend.Saxpy(&len, &alpha, bref, &incb, aref, &inca);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sub_S_V"/>
		public override ISigmaDiffDataBuffer<float> Sub_S_V(float a, ISigmaDiffDataBuffer<float> b)
		{
			if (b.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			b = b.DeepCopy();
			fixed (float* bref = &b.Data[b.Offset])
			{
				int len = b.Length;
				int inca = 0, incb = 1;
				float alpha = -1.0f;

				BlasBackend.Saxpy(&len, &alpha, &a, &inca, bref, &incb);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sub_V_S"/>
		public override ISigmaDiffDataBuffer<float> Sub_V_S(ISigmaDiffDataBuffer<float> a, float b)
		{
			if (a.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			a = a.DeepCopy();
			fixed (float* aref = &a.Data[a.Offset])
			{
				int len = a.Length;
				int inca = 1, incb = 0;
				float alpha = -1.0f;

				BlasBackend.Saxpy(&len, &alpha, aref, &inca, &b, &incb);
			}

			return a;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_S_V"/>
		public override ISigmaDiffDataBuffer<float> Mul_S_V(float a, ISigmaDiffDataBuffer<float> b)
		{
			if (b.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			b = b.DeepCopy();
			fixed (float* bref = &b.Data[b.Offset])
			{
				int len = b.Length;
				int incx = 1;

				BlasBackend.Sscal(&len, &a, bref, &incx);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_M_V"/>
		public override ISigmaDiffDataBuffer<float> Mul_M_V(ShapedDataBufferView<float> a, ISigmaDiffDataBuffer<float> b)
		{
			if (a.Length * b.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			ISigmaDiffDataBuffer<float> z = CreateDataBuffer(CreateZeroArray(a.Rows));

			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			fixed (float* bref = &b.Data[b.Offset])
			fixed (float* zref = &z.Data[z.Offset])
			{
				char trans = 'T';
				int m = a.Cols, n = a.Rows;
				int incb = 1, incz = 1;
				float alpha = 1.0f, beta = 0.0f;

				BlasBackend.Sgemv(&trans, &m, &n, &alpha, aref, &m, bref, &incb, &beta, zref, &incz);
			}

			return z;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_M_V_Add_V"/>
		public override ISigmaDiffDataBuffer<float> Mul_M_V_Add_V(ShapedDataBufferView<float> a, ISigmaDiffDataBuffer<float> b, ISigmaDiffDataBuffer<float> obj2)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_Dot_V_V"/>
		public override float Mul_Dot_V_V(ISigmaDiffDataBuffer<float> a, ISigmaDiffDataBuffer<float> n)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_V_M"/>
		public override ISigmaDiffDataBuffer<float> Mul_V_M(ISigmaDiffDataBuffer<float> a, ShapedDataBufferView<float> b)
		{
			if (a.Length * b.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			ISigmaDiffDataBuffer<float> z = CreateDataBuffer(CreateZeroArray(b.Rows));

			fixed (float* aref = &a.Data[a.Offset])
			fixed (float* bref = &b.DataBuffer.Data[b.DataBuffer.Offset])
			fixed (float* zref = &z.Data[z.Offset])
			{
				char trans = 'T';
				int m = b.Cols, n = b.Rows;
				int incb = 1, incz = 1;
				float alpha = 1.0f, beta = 0.0f;

				BlasBackend.Sgemv(&trans, &m, &n, &alpha, aref, &m, bref, &incb, &beta, zref, &incz);
			}

			return z;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Solve_M_V"/>
		public override FSharpOption<ISigmaDiffDataBuffer<float>> Solve_M_V(ShapedDataBufferView<float> a, ISigmaDiffDataBuffer<float> b)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.SolveSymmetric_M_V"/>
		public override FSharpOption<ISigmaDiffDataBuffer<float>> SolveSymmetric_M_V(ShapedDataBufferView<float> a, ISigmaDiffDataBuffer<float> b)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Diagonal_M"/>
		public override ISigmaDiffDataBuffer<float> Diagonal_M(ShapedDataBufferView<float> a)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Map_F_V"/>
		public override ISigmaDiffDataBuffer<float> Map_F_V(MapOp mapOp, FSharpFunc<float, float> a, ISigmaDiffDataBuffer<float> b)
		{
			if (b.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			b = b.DeepCopy();

			int upper = b.Offset + b.Length;
			for (int i = b.Offset; i < upper; i++)
			{
				b.Data[i] = a.Invoke(b.Data[i]);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Map_F_S_V"/>
		public override ISigmaDiffDataBuffer<float> Map_F_S_V(float other, MapOp mapOp, FSharpFunc<float, float> function, ISigmaDiffDataBuffer<float> value)
		{
			return Map_F_V(mapOp, function, value);
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Map2_F_V_V"/>
		public override ISigmaDiffDataBuffer<float> Map2_F_V_V(MapOp mapOp, FSharpFunc<float, FSharpFunc<float, float>> function, ISigmaDiffDataBuffer<float> a, ISigmaDiffDataBuffer<float> b)
		{
			if (a.Length == 0)
			{
				return Map2_F_V_V(mapOp, function, CreateDataBuffer(CreateZeroArray(b.Length)), b);
			}
			if (b.Length == 0)
			{
				return Map2_F_V_V(mapOp, function, a, CreateDataBuffer(CreateZeroArray(a.Length)));
			}

			b = b.DeepCopy();

			for (int i = 0; i < a.Length; i++)
			{
				b.Data[i] = function.Invoke(a.Data[i + a.Offset]).Invoke(b.Data[i + b.Offset]);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_Out_V_V"/>
		public override ShapedDataBufferView<float> Mul_Out_V_V(ISigmaDiffDataBuffer<float> a, ISigmaDiffDataBuffer<float> b)
		{
			if (a.Length * b.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			ISigmaDiffDataBuffer<float> z = CreateDataBuffer(CreateZeroArray(a.Length * b.Length));
			int m = b.Length, n = a.Length;

			fixed (float* aref = &a.Data[a.Offset])
			fixed (float* bref = &b.Data[b.Offset])
			fixed (float* zref = &z.Data[z.Offset])
			{
				int inca = 1, incb = 1;
				float alpha = 1.0f;

				BlasBackend.Sger(&m, &n, &alpha, aref, &inca, bref, &incb, zref, &m);
			}

			return new ShapedDataBufferView<float>(z, m, n);
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Add_M_M"/>
		public override ShapedDataBufferView<float> Add_M_M(ShapedDataBufferView<float> a, ShapedDataBufferView<float> b)
		{
			if (a.Length == 0)
			{
				return b.DeepCopy();
			}
			if (b.Length == 0)
			{
				return a.DeepCopy();
			}

			b = b.DeepCopy();
			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			fixed (float* bref = &b.DataBuffer.Data[b.DataBuffer.Offset])
			{
				int len = Math.Min(a.Length, b.Length);
				int inca = 1, incb = 1;
				float alpha = 1.0f;

				BlasBackend.Saxpy(&len, &alpha, aref, &inca, bref, &incb);
			}

			return b;
		}

		public override ShapedDataBufferView<float> Add_M_M_InPlace(ShapedDataBufferView<float> a, ShapedDataBufferView<float> b)
		{
			if (a.Length == 0)
			{
				return b;
			}
			if (b.Length == 0)
			{
				return a;
			}

			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			fixed (float* bref = &b.DataBuffer.Data[b.DataBuffer.Offset])
			{
				int len = Math.Min(a.Length, b.Length);
				int inca = 1, incb = 1;
				float alpha = 1.0f;

				BlasBackend.Saxpy(&len, &alpha, aref, &inca, bref, &incb);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Add_S_M"/>
		public override ShapedDataBufferView<float> Add_S_M(float a, ShapedDataBufferView<float> b)
		{
			if (b.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			b = b.DeepCopy();
			fixed (float* bref = &b.DataBuffer.Data[b.DataBuffer.Offset])
			{
				int len = b.Length;
				int inca = 0, incb = 1;
				float alpha = 1.0f;

				BlasBackend.Saxpy(&len, &alpha, &a, &inca, bref, &incb);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Add_V_MCols"/>
		public override ShapedDataBufferView<float> Add_V_MCols(ISigmaDiffDataBuffer<float> a, ShapedDataBufferView<float> b)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sub_M_M"/>
		public override ShapedDataBufferView<float> Sub_M_M(ShapedDataBufferView<float> a, ShapedDataBufferView<float> b)
		{
			if (a.Length == 0)
			{
				return b.DeepCopy();
			}
			if (b.Length == 0)
			{
				return a.DeepCopy();
			}

			a = a.DeepCopy();
			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			fixed (float* bref = &b.DataBuffer.Data[b.DataBuffer.Offset])
			{
				int len = Math.Min(a.Length, b.Length);
				int inca = 1, incb = 1;
				float alpha = -1.0f;

				BlasBackend.Saxpy(&len, &alpha, bref, &incb, aref, &inca);
			}

			return a;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sub_M_S"/>
		public override ShapedDataBufferView<float> Sub_M_S(ShapedDataBufferView<float> a, float b)
		{
			if (a.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			a = a.DeepCopy();
			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			{
				int len = a.Length;
				int inca = 1, incb = 0;
				float alpha = -1.0f;

				BlasBackend.Saxpy(&len, &alpha, &b, &incb, aref, &inca);
			}

			return a;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Sub_S_M"/>
		public override ShapedDataBufferView<float> Sub_S_M(float other, ShapedDataBufferView<float> a)
		{
			if (a.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			a = a.DeepCopy();

			int simdLength = Vector<float>.Count;
			int len = a.Length;
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(len)), (long[])a.Shape.Clone());
			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;
			Vector<float> vc = new Vector<float>(other); // filled with constant value of other

			// Use SIMD instructions to subtract an array from a constant factor (using a vc array filled with the constant a).
			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int i;
				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					(vc - va).CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = other - aref[i];
				}
			}

			return result;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_M_M"/>
		public override ShapedDataBufferView<float> Mul_M_M(ShapedDataBufferView<float> a, ShapedDataBufferView<float> b)
		{
			if (a.Length * b.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			ISigmaDiffDataBuffer<float> z = CreateDataBuffer(new float[a.Rows * b.Cols]);

			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			fixed (float* bref = &b.DataBuffer.Data[b.DataBuffer.Offset])
			fixed (float* zref = &z.Data[z.Offset])
			{
				char transa = 'N', transb = 'N';
				float alpha = 1.0f, beta = 0.0f;
				int m = a.Rows, n = b.Cols, k = b.Rows;

				BlasBackend.Sgemm(&transa, &transb, &n, &m, &k, &alpha, bref, &n, aref, &k, &beta, zref, &n);
			}

			return new ShapedDataBufferView<float>(z, a.Rows, b.Cols);
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_S_M"/>
		public override ShapedDataBufferView<float> Mul_S_M(float a, ShapedDataBufferView<float> b)
		{
			if (b.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			b = b.DeepCopy();
			fixed (float* bref = &b.DataBuffer.Data[b.DataBuffer.Offset])
			{
				int len = b.Length;
				int incx = 1;

				BlasBackend.Sscal(&len, &a, bref, &incx);
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_M_M_Add_V_MCols"/>
		public override ShapedDataBufferView<float> Mul_M_M_Add_V_MCols(ShapedDataBufferView<float> a, ShapedDataBufferView<float> b, ISigmaDiffDataBuffer<float> c)
		{
			throw new NotImplementedException();
		}

		public override ISigmaDiffDataBuffer<float> Add_M_Colwise_V_InPlace(ShapedDataBufferView<float> a, ISigmaDiffDataBuffer<float> b)
		{
			float[] aData = a.DataBuffer.Data, bData = b.Data;
			int aOffset = a.DataBuffer.Offset, bOffset = b.Offset;
			int cols = a.Cols, len = b.Length;

			// Use SIMD instructions to multiply two arrays element-wise.
			fixed (float* aref = &aData[aOffset])
			fixed (float* bref = &bData[bOffset])
			{
				int simdLength = Vector<float>.Count, i;

				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> vb = new Vector<float>(bData, i + bOffset);

					for (int y = 0; y < a.Rows; y++)
					{
						vb += new Vector<float>(aData, i + aOffset + y * cols);
					}

					vb.CopyTo(bData, i + bOffset);
				}

				for (; i < len; ++i)
				{
					for (int y = 0; y < a.Rows; y++)
					{
						bref[i] += aref[i + y * cols];
					}
				}
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Mul_Had_M_M"/>
		public override unsafe ShapedDataBufferView<float> Mul_Had_M_M(ShapedDataBufferView<float> a, ShapedDataBufferView<float> b)
		{
			if (a.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(CreateZeroArray(b.Length)), b.Shape);
			}
			if (b.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(CreateZeroArray(a.Length)), a.Shape);
			}

			int len = Math.Min(a.Length, b.Length);
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(len)), (long[])b.Shape.Clone());

			float[] aData = a.DataBuffer.Data, bData = b.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, bOffset = b.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;

			// Use SIMD instructions to multiply two arrays element-wise.
			fixed (float* aref = &aData[aOffset])
			fixed (float* bref = &bData[bOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int simdLength = Vector<float>.Count, i;

				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					Vector<float> vb = new Vector<float>(bData, i + bOffset);
					(va * vb).CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = aref[i] * bref[i];
				}
			}

			return result;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Inverse_M"/>
		public override FSharpOption<ShapedDataBufferView<float>> Inverse_M(ShapedDataBufferView<float> a)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Det_M"/>
		public override FSharpOption<float> Det_M(ShapedDataBufferView<float> a)
		{
			if (a.Length == 0)
			{
				return FSharpOption<float>.Some(0.0f);
			}

			a = a.DeepCopy();

			int info = 0;
			int[] ipiv = new int[Math.Min(a.Rows, a.Cols)];

			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			fixed (int* ipivref = &ipiv[0])
			{
				int m = a.Rows, n = a.Cols;

				LapackBackend.Sgetrf_(&m, &n, aref, &m, ipivref, &info);
			}

			if (info != 0)
			{
				return FSharpOption<float>.None;
			}

			float det = 1.0f;

			for (int i = 0; i < ipiv.Length; i++)
			{
				det *= ipiv[i] != i + 1 ? -a[i, i] : a[i, i];
			}

			return FSharpOption<float>.Some(det);
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Transpose_M"/>
		public override ShapedDataBufferView<float> Transpose_M(ShapedDataBufferView<float> a)
		{
			if (a.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			ShapedDataBufferView<float> transposed = a.DeepCopy();

			for (int i = 0; i < transposed.Shape.Length; i++)
			{
				transposed.Shape[i] = a.Shape[a.Shape.Length - 1 - i];
			}

			fixed (float* aref = &a.DataBuffer.Data[a.DataBuffer.Offset])
			fixed (float* bref = &transposed.DataBuffer.Data[transposed.DataBuffer.Offset])
			{
				int ordering = 101; // CBLAS_LAYOUT - CblasRowMajor
				int trans = 112; // CBLAS_TRANSPOSE - CblasTrans
				int rows = a.Rows, cols = a.Cols;
				int lda = a.Cols, ldb = a.Rows;
				float alpha = 1.0f;

				BlasBackend.Somatcopy(ordering, trans, rows, cols, alpha, aref, lda, bref, ldb);
			}

			return transposed;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Permute_M"/>
		public override ShapedDataBufferView<float> Permute_M(ShapedDataBufferView<float> a, int[] permutedDimensions)
		{
			long[] originalShape = a.Shape;
			long[] permutedShape = ArrayUtils.PermuteArray(originalShape, permutedDimensions);
			long[] originalStrides = NDArrayUtils.GetStrides(originalShape), permutedStrides = NDArrayUtils.GetStrides(permutedShape);
			int rank = originalShape.Length, unitSize = 1;

			for (int i = permutedDimensions.Length - 1; i >= 0; i--)
			{
				if (permutedDimensions[i] != i)
				{
					break;
				}

				unitSize = checked(unitSize * (int)originalShape[i]);
			}

			int unitSizeBytes = unitSize * sizeof(float), len = a.Length;
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(len)), permutedShape);
			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;

			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				long[] bufferIndices = new long[rank];

				if (unitSize > 1) // TODO maybe set a limit for when block copy outperforms manual copy (don't forget to change i++ in else branch)
				{
					for (int i = 0; i < len; i += unitSize)
					{
						NDArrayUtils.GetIndices(i, originalShape, originalStrides, bufferIndices);

						bufferIndices = ArrayUtils.PermuteArray(bufferIndices, permutedDimensions);

						int resultIndex = (int)NDArrayUtils.GetFlatIndex(permutedShape, permutedStrides, bufferIndices);

						Buffer.BlockCopy(aData, (i + aOffset) * sizeof(float), resData, (resultIndex + resOffset) * sizeof(float), unitSizeBytes);
					}
				}
				else
				{
					for (int i = 0; i < len; i++)
					{
						NDArrayUtils.GetIndices(i, originalShape, originalStrides, bufferIndices);

						bufferIndices = ArrayUtils.PermuteArray(bufferIndices, permutedDimensions);

						int resultIndex = (int)NDArrayUtils.GetFlatIndex(permutedShape, permutedStrides, bufferIndices);

						resref[resultIndex] = aref[i];
					}
				}
			}

			return result;
		}

		public override ShapedDataBufferView<float> Reshape_M(ShapedDataBufferView<float> array, long[] newShape)
		{
			ShapedDataBufferView<float> reshaped = new ShapedDataBufferView<float>(array.DataBuffer, newShape);

			return reshaped;
		}

		private bool _InternalOptimisedMapOp_F_M(MapOp mapOp, ref ShapedDataBufferView<float> a)
		{
			if (mapOp.IsExp)
			{
				_InternalOptimisedExp(ref a);

				return true;
			}
			else if (mapOp.IsSqrt)
			{
				_InternalOptimisedSqrt(ref a);

				return true;
			}
			else if (mapOp.IsSign)
			{
				_InternalOptimisedSign(ref a);

				return true;
			}
			else if (mapOp.IsReL)
			{
				_InternalOptimisedRel(ref a);

				return true;
			}
			else if (mapOp.IsSigmoid)
			{
				_InternalOptimisedSigmoid(ref a);

				return true;
			}
			else if (mapOp.IsLog)
			{
				_InternalOptimisedLog(ref a);

				return true;
			}

			return false;
		}

		private unsafe void _InternalOptimisedSign(ref ShapedDataBufferView<float> a)
		{
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(a.Length)), (long[])a.Shape.Clone());

			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;
			int len = a.Length;

			uint signFlag = 0x80000000;
			Vector<float> vf = new Vector<float>(*(float*)&signFlag);

			// Use SIMD instructions with a few bit-twiddling "hacks" to quickly get the sign for each element in a large array.
			// This works because the sign if the first bit in the binary floating point representation which can be easily extracted using bitwise operations.
			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int simdLength = Vector<float>.Count, i;

				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					Vector<float> vr = Vector<float>.One;
					(vr | (va & vf)).CopyTo(resData, i + resOffset); // TODO should zero be considered as well? (right now it's 1 / -1 only)
				}

				for (; i < len; ++i)
				{
					resref[i] = 1.0f;
					resref[i] = *(uint*)&resref[i] | (*(uint*)&aref[i] & signFlag);
				}
			}

			a = result;
		}

		private void _InternalOptimisedSqrt(ref ShapedDataBufferView<float> a)
		{
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(a.Length)), (long[])a.Shape.Clone());

			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;
			int len = a.Length;

			// Use SIMD instructions to quickly get the square root of each element of an array.
			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int simdLength = Vector<float>.Count, i;

				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					Vector.SquareRoot(va).CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = (float)Math.Sqrt(aref[i]);
				}
			}

			a = result; // write out result to ref
		}

		private static void _InternalOptimisedExp(ref ShapedDataBufferView<float> a)
		{
			a = a.DeepCopy();
			float[] aData = a.DataBuffer.Data;
			Vector<float> vf = new Vector<float>(1.0f / 256.0f);
			Vector<float> vc = Vector<float>.One;
			int len = a.Length, simdLength = Vector<float>.Count, aOffset = a.DataBuffer.Offset;

			// Use SIMD instructions and an exponent estimation to quickly get the exponent of each element of an array.
			// This works because the exponential function e^x can be considered as the limit of (1 + x/n)^n for n -> infinity.
			// For any reasonably small value for machine learning (< ~7) the error is extremely small when approximated with
			//  x = 1 + x / 256
			//	x *= x; x *= x; x *= x; x *= x; x *= x; x *= x; x *= x; x *= x; // 8 times, because 2^8 is 256 and that's reasonably accurate.
			fixed (float* aref = &aData[aOffset])
			{
				int i;
				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> vres = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					vres = vc + vres * vf;

					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;

					vres.CopyTo(aData, i + aOffset);
				}

				for (; i < len; ++i)
				{
					aref[i] = (float)Math.Exp(aref[i]);
				}
			}
		}

		private void _InternalOptimisedRel(ref ShapedDataBufferView<float> a)
		{
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(a.Length)), (long[])a.Shape.Clone());

			int simdLength = Vector<float>.Count;
			int len = a.Length;
			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;
			Vector<float> vc = Vector<float>.Zero;

			// Use SIMD instructions and an exponent estimation to quickly get the exponent of each element of an array.
			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int i;
				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					Vector.Max(va, vc).CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = Math.Max(aref[i], 0.0f);
				}
			}

			a = result;
		}

		// number1 / (number1 + exp -v))
		private void _InternalOptimisedSigmoid(ref ShapedDataBufferView<float> a)
		{
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(a.Length)), (long[])a.Shape.Clone());

			int simdLength = Vector<float>.Count;
			int len = a.Length;
			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;
			Vector<float> vc = Vector<float>.One;
			Vector<float> vf = new Vector<float>(1.0f / 256.0f);

			// Use SIMD instructions and an exponent estimation to quickly get the sigmoid of each element of an array.
			// The exponent estimation works because the exponential function e^x can be considered as the limit of (1 + x/n)^n for n -> infinity.
			// For any reasonably small value for machine learning (< ~7) the error is extremely small when approximated with
			//  x = 1 + x / 256
			//	x *= x; x *= x; x *= x; x *= x; x *= x; x *= x; x *= x; x *= x; // 8 times, because 2^8 is 256 and that's reasonably accurate.
			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int i;
				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> vres = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					vres = vc - vres * vf;

					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;
					vres *= vres;

					vres = vres + vc;
					(vc / vres).CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = 1.0f / (1.0f + (float)Math.Exp(-aref[i]));
				}
			}

			a = result;
		}

		private void _InternalOptimisedLog(ref ShapedDataBufferView<float> a)
		{
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(a.Length)), (long[])a.Shape.Clone());

			int simdLength = Vector<float>.Count;
			int len = a.Length;
			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;

			// Using SIMD instructions, bit-twiddling and rational approximation to quickly get the log of each element of an array.
			// Quite frankly, I'm not quite sure yet just why this works, it just does, and with quite high accuracy (avg error of 1.60712e-05 for [0, 20])
			// See https://github.com/etheory/fastapprox/blob/master/fastapprox/src/fastlog.h
			uint exponentMask = 0x3f000000, mantissaMask = 0x007fffff;
			Vector<float> vf1 = new Vector<float>(*(float*) &exponentMask);
			Vector<float> vf2 = new Vector<float>(*(float*) &mantissaMask);
			Vector<float> vc1 = new Vector<float>(1.1920928955078125e-7f);
			Vector<float> vc2 = new Vector<float>(124.22551499f);
			Vector<float> vc3 = new Vector<float>(1.498030302f);
			Vector<float> vc4 = new Vector<float>(1.72587999f);
			Vector<float> vc5 = new Vector<float>(0.3520887068f);
			Vector<float> vc6 = new Vector<float>(0.69314718f);
			float[] vaiBuffer = CreateUninitialisedArray(simdLength);

			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int i;
				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets

					// TODO the manual float bits as int then back cast to float conversion is taking a lot of time (~70% of the entire method)
					for (int y = 0; y < simdLength; y++)
					{
						vaiBuffer[y] = *(uint*) &aref[i + y];
					}

					Vector<float> vai = new Vector<float>(vaiBuffer);
					Vector<float> vt1 = (va & vf2) | vf1;
					Vector<float> vres = vc1 * vai;
					Vector<float> vt2 = (vc3 * vt1);
					Vector<float> vt3 = (vc4 / (vc5 + vt1));
					vres = (vres - vc2 - vt2 - vt3) * vc6;

					vres.CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = (float)Math.Log(aref[i]);
				}
			}

			a = result;
		}

		private bool _InternalOptimisedMapOp_F_S_M(float other, MapOp mapOp, ref ShapedDataBufferView<float> a)
		{
			if (mapOp.IsDiv)
			{
				_InternalOptimisedDiv(other, ref a);

				return true;
			}

			return false;
		}

		private void _InternalOptimisedDiv(float other, ref ShapedDataBufferView<float> a)
		{
			int simdLength = Vector<float>.Count;
			int len = a.Length;
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(len)), (long[])a.Shape.Clone());
			float[] aData = a.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;
			Vector<float> vc = new Vector<float>(other); // filled with constant value of other

			// Use SIMD instructions to divide an array by a constant factor (using a vc array filled with the constant a).
			fixed (float* aref = &aData[aOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int i;
				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					(vc / va).CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = other / aref[i];
				}
			}

			a = result;
		}

		private bool _InternalOptimisedMapOp_F_M_M(MapOp mapOp, ShapedDataBufferView<float> a, ref ShapedDataBufferView<float> b)
		{
			if (mapOp.IsDiv)
			{
				_InternalOptimisedDiv(a, ref b);

				return true;
			}

			return false;
		}

		private void _InternalOptimisedDiv(ShapedDataBufferView<float> a, ref ShapedDataBufferView<float> b)
		{
			int len = Math.Min(a.Length, b.Length);
			ShapedDataBufferView<float> result = new ShapedDataBufferView<float>(CreateDataBuffer(CreateUninitialisedArray(len)), (long[])b.Shape.Clone());

			float[] aData = a.DataBuffer.Data, bData = b.DataBuffer.Data, resData = result.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, bOffset = b.DataBuffer.Offset, resOffset = result.DataBuffer.Offset;

			// Use SIMD instructions to divide an array by another array.
			fixed (float* aref = &aData[aOffset])
			fixed (float* bref = &bData[bOffset])
			fixed (float* resref = &resData[resOffset])
			{
				int simdLength = Vector<float>.Count, i;

				for (i = 0; i <= len - simdLength; i += simdLength)
				{
					Vector<float> va = new Vector<float>(aData, i + aOffset); // TODO optimise offsets
					Vector<float> vb = new Vector<float>(bData, i + bOffset);
					(va / vb).CopyTo(resData, i + resOffset);
				}

				for (; i < len; ++i)
				{
					resref[i] = aref[i] / bref[i];
				}
			}

			b = result;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Map_F_M"/>
		public override ShapedDataBufferView<float> Map_F_M(MapOp mapOp, FSharpFunc<float, float> f, ShapedDataBufferView<float> a)
		{
			if (a.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			if (_InternalOptimisedMapOp_F_M(mapOp, ref a))
			{
				return a;
			}

			a = a.DeepCopy();

			int upper = a.DataBuffer.Offset + a.DataBuffer.Length;
			float[] data = a.DataBuffer.Data;

			for (int i = a.DataBuffer.Offset; i < upper; i++)
			{
				data[i] = f.Invoke(data[i]);
			}

			return a;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Map_F_S_M"/>
		public override ShapedDataBufferView<float> Map_F_S_M(float other, MapOp mapOp, FSharpFunc<float, float> function, ShapedDataBufferView<float> value)
		{
			if (_InternalOptimisedMapOp_F_S_M(other, mapOp, ref value))
			{
				return value;
			}

			return Map_F_M(mapOp, function, value); // this is correct, the "other" constant is only passed to speed up computation in optimised versions without using the lambda
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.Map2_F_M_M"/>
		public override ShapedDataBufferView<float> Map2_F_M_M(MapOp mapOp, FSharpFunc<float, FSharpFunc<float, float>> f, ShapedDataBufferView<float> a, ShapedDataBufferView<float> b)
		{
			if (a.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}
			if (b.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			if (_InternalOptimisedMapOp_F_M_M(mapOp, a, ref b))
			{
				return b;
			}

			// If no optimised versions exist for the given map operation, manually invoke the given function for each element (slow).
			b = b.DeepCopy();

			float[] aData = a.DataBuffer.Data, bData = b.DataBuffer.Data;
			int aOffset = a.DataBuffer.Offset, bOffset = b.DataBuffer.Offset;

			fixed (float* aref = &aData[aOffset])
			fixed (float* bref = &bData[bOffset])
			{
				for (int i = 0; i < a.Length; i++)
				{
					bref[i] = f.Invoke(aref[i]).Invoke(bData[i]);
				}
			}

			return b;
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.ReshapeCopy_MRows_V"/>
		public override ISigmaDiffDataBuffer<float> ReshapeCopy_MRows_V(ShapedDataBufferView<float> value)
		{
			if (value.Length == 0)
			{
				return CreateDataBuffer(new float[0]);
			}

			return value.DataBuffer.DeepCopy();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.ReshapeCopy_V_MRows"/>
		public override ShapedDataBufferView<float> ReshapeCopy_V_MRows(int rows, ISigmaDiffDataBuffer<float> value)
		{
			if (value.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			int n = value.Length / rows;

			return new ShapedDataBufferView<float>(value.DeepCopy(), rows, n);
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.RepeatReshapeCopy_V_MRows"/>
		public override ShapedDataBufferView<float> RepeatReshapeCopy_V_MRows(int rows, ISigmaDiffDataBuffer<float> row)
		{
			if (row.Length == 0)
			{
				return new ShapedDataBufferView<float>(CreateDataBuffer(new float[0]), 0L, 0L);
			}

			int rowLength = row.Length;
			float[] result = CreateUninitialisedArray(rows * rowLength);
			float[] rowData = row.Data;
			int sourceOffset = row.Offset;
			int destinationOffset = 0;

			for (int i = 0; i < rows; i++)
			{
				Buffer.BlockCopy(rowData, sourceOffset * sizeof(float), result, destinationOffset * sizeof(float), rowLength * sizeof(float));

				destinationOffset += rowLength;
			}

			return new ShapedDataBufferView<float>(CreateDataBuffer(result), rows, rowLength);
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.RepeatReshapeCopy_V_MCols"/>
		public override ShapedDataBufferView<float> RepeatReshapeCopy_V_MCols(int cols, ISigmaDiffDataBuffer<float> value)
		{
			throw new NotImplementedException();
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.CustomOp_DM_Forward"/>
		public override ShapedDataBufferView<float> CustomOp_DM_Forward(ShapedDataBufferView<float> value, object customInfo)
		{
			throw new NotImplementedException($"Custom DM ops are not supported in default {nameof(DiffSharpFloat32BackendHandle)} implementation.");
		}

		/// <inheritdoc cref="DiffSharpBackendHandle{T}.CustomOp_DM_Backward"/>
		public override ShapedDataBufferView<float> CustomOp_DM_Backward(ShapedDataBufferView<float> origin,
			ShapedDataBufferView<float> adjoint, ShapedDataBufferView<float> primal, object customInfo)
		{
			throw new NotImplementedException($"Custom DM ops are not supported in default {nameof(DiffSharpFloat32BackendHandle)} implementation.");
		}
	}
}


text:
layout: post
title: Diplomatura en Sistemas Operativos Linux (Universidad Nacional de Córdoba)
date: '2014-02-11T15:36:00.004-02:00'
author: Filly
tags:
- software libre
- eventos
modified_time: '2014-02-11T15:38:26.978-02:00'
thumbnail: http://1.bp.blogspot.com/-Fd2lTIaVrZ0/UvpeU4e0nMI/AAAAAAAAA-M/u203J2a87d0/s72-c/diplomatura.png
blogger_id: tag:blogger.com,1999:blog-6145090415061302130.post-2204896400317976795
blogger_orig_url: http://missfillys.blogspot.com/2014/02/diplomatura-en-sistemas-operativos.html
---

[![](http://1.bp.blogspot.com/-Fd2lTIaVrZ0/UvpeU4e0nMI/AAAAAAAAA-M/u203J2a87d0/s1600/diplomatura.png)][0]

Dejo el link que llegó por la lista de correo de [GrULiC][1], sobre una **Diplomatura en Sistemas Operativos Linux** que
ofrece el Departamento Universitario de Informática de la UNC. Tiene una duración de 2 años, inicia el **13 de Marzo**,
y las preinscripciones están abiertas a partir del **16 de Febrero**.

Toda la información en [este link][2].

[0]: http://1.bp.blogspot.com/-Fd2lTIaVrZ0/UvpeU4e0nMI/AAAAAAAAA-M/u203J2a87d0/s1600/diplomatura.png
[1]: http://www.grulic.org.ar/
[2]: http://www.di.unc.edu.ar/cursosy-eventos/diplomatura-en-sistema-operativo-linux

redpajama_set_name: RedPajamaGithub


text:
package com.obsidian.compiler.StaticCodeAnalyzer.Errors;

import com.obsidian.compiler.Lava.LvRangeInFile;
import com.obsidian.compiler.StaticCodeAnalyzer.ScaErrorSource;

/**
 * Created by Jonathon on 5/17/2017.
 */
public class NonsensicalToTakeValueTypeWarning extends CompileWarning {

	public String type;
	public LvRangeInFile source;

	public NonsensicalToTakeValueTypeWarning(String type, LvRangeInFile source) {
		this.type = type;
		this.source = source;
	}

	@Override
	public String getTitle() {
		return "Cannot take ownership of value type \"" + this.type + "\", values of this type are always pass-by-copy.";
	}

	@Override
	public ScaErrorSource getFirstSource() {
		return new ScaErrorSource(this.source,
								  "Function attempts to take ownership of value type \"" + this.type + "\" here");
	}

}


text:
from gurobipy import *

def modelling():
    m = Model("versatech_problem")
    # === Modify codes below using above variable m ===

    return m

if __name__ == "__main__":
    model_object = modelling()
    for v in model_object.getVars():
        print(v.varName, v.x)

    print('Obj:', model_object.objVal)


text:
FOUNDATION_EXPORT double MonoidVersionNumber;

//! Project version string for Monoid.
FOUNDATION_EXPORT const unsigned char MonoidVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <Monoid/PublicHeader.h>


text:
import acspytest__POA
from Acspy.Servants.ContainerServices  import ContainerServices
from Acspy.Servants.ComponentLifecycle import ComponentLifecycle
from Acspy.Servants.ACSComponent       import ACSComponent
from CORBA import TRUE, FALSE
#*******************************************************************************
# ALMA - Atacama Large Millimiter Array
# (c) Associated Universities Inc., 2002
# (c) European Southern Observatory, 2002
# Copyright by ESO (in the framework of the ALMA collaboration)
# and Cosylab 2002, All rights reserved
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307  USA
#
#------------------------------------------------------------------------------
'''
Module designed to test the full functionality of the Python Container.  Since
Python is not a compiled language, its vital that everything be tested.
'''
#------------------------------------------------------------------------------
print "#*# Inside acspytest.testSubPackage.PyTest #*#"

class PyTest(acspytest__POA.PyTest,
             ACSComponent,  #Base IDL interface
             ContainerServices,  #Developer niceties
             ComponentLifecycle):

    def __init__(self):
        ACSComponent.__init__(self)
        ContainerServices.__init__(self)
        return

    def sayHello(self):
        return
    #------------------------------------------------------------------------------
    def invokeSayHello(self, compName):
        return
    #------------------------------------------------------------------------------
    def testMount(self, compName):
        return
    #------------------------------------------------------------------------------
    def testAnything(self, compName, methodName, params):
        return
    #------------------------------------------------------------------------------
    def testServices(self):
        return TRUE
    #------------------------------------------------------------------------------
#------------------------------------------------------------------------------


text:
You can use time-delta.js to display a live countdown to a date/ time. The project was made specifically with countdowns to events in mind, and allows you to display the time difference between the specified date/ time and now in a completely customizable way.

## Deprecated

When I started to implement time zone support, I realized how weird Javascript is with time zones and dates in general. Moment.js could help in dealing with this, but that already has relative time support, which is a big part of the problem time-delta.js was trying to solve.

So I'm deprecating this project; it was a fun way to get into JavaScript a little more, but ultimately won't be very useful in the future. Some aspects, like the Format String, might be cool to fork into Moment.js, which is something I'll look into more in the future.

## Getting Started

Here's a short example that shows a basic time-delta.js countdown on an HTML page:

```html
<script type="text/javascript" src="path/to/time-delta.js"></script>
<p>The concert starts <span id="time-delta-1">on April 18th, 2020, at 2 pm</span></p>
<script type="text/javascript">
display(
	"time-delta-1",
	new Date("2020-04-18T14:00:00"),
	"in {day-c} day[{day-c}!=1:s] and {hr} hour[{hr}!=1:s]",
	"{day-c} day[{day-c}!=1:s] and {hr} hour[{hr}!=1:s] ago"
);
</script>
```

Make sure you change `path/to/time-delta.js` to point to where `time-delta.js` is, relative to the HTML page.

See `demo/demo.html` for more advanced examples.

## Format string

Generally, the format string consists of a combination of text that will be displayed as-is and tags that time-delta.js replaces with the entities specified below. You can also use conditionals to change what is displayed depending on the value of different parts of the date delta.

In the most common use cases, your largest time unit should use a complete tag, and your other time units should use a partial tag.

### Partial tags

Partial tags display only their respective part of the time delta.

The tags are:
- `{mil}` - the milliseconds part of the time delta (0 - 999)
- `{sec}` - the seconds part of the time delta (0 - 59)
- `{min}` - the minutes part of the time delta (0 - 59)
- `{hr}` - the hours part of the time delta (0 - 23)
- `{day}` - the days part of the time delta (0 - 6)
- `{wk}` - the weeks part of the time delta (0 - infinity)

For a date that is 1 hour and 150 seconds away, for example, `{hr}` will be 1, `{min}` will be 2, and `{sec}` will be 30.

### Complete tags

Complete tags display the full time delta, precise to rounded-down full units of their respective type. They are formed by appending `-c` to the end of a partial tag.

The tags are:
- `{mil-c}` - the time delta in milliseconds (0 - infinity)
- `{sec-c}` - the time delta in seconds (0 - infinity)
- `{min-c}` - the time delta in minutes (0 - infinity)
- `{hr-c}` - the time delta in hours (0 - infinity)
- `{day-c}` - the time delta in days (0 - infinity)
- `{wk-c}` - the time delta in weeks (0 - infinity)

For a date that is 1 hour and 150 seconds away, for example, `{hr}` will be 1, `{min}` will be 62, and `{sec}` will be 3750.

### Conditionals

Conditionals allow you to change whether something is displayed depending on the values of different parts of the time delta. This allows you to, for example, automatically change names of time units to be singular if only that time unit is equal to 1.

The basic construction of conditionals is: `[condition:result]`, where the `condition` can use any of the variables from the partial and complete tags (such as `{day}` and `{hr-c}`) combined with constants and any one of the following comparators: `==`, `>`, `<`, `>=`, `<=`, `!=`. The result will only be shown if the condition is evaluated as true.

Examples:
- `{day} day[{day}!=1:s]` would display "2 days", "1 day" or "0 days" depending on the value of `{day}`
- `The number of days until my birthday is: {day-c}.[{day-c}<7: That's in less than one week!]` would display "The number of days until my birthday is: 20." or "The number of days until my birthday is: 4. That's in less than one week!"


text:
namespace feature_guide {
namespace features {

BASE_FEATURE(kFeatureNotificationGuide,
             "FeatureNotificationGuide",
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kSegmentationModelLowEngagedUsers,
             "SegmentationModelLowEngagedUsers",
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kSkipCheckForLowEngagedUsers,
             "FeatureNotificationGuideSkipCheckForLowEngagedUsers",
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kUseFeatureEngagementForUserTargeting,
             "UseFeatureEngagementForUserTargeting",
             base::FEATURE_DISABLED_BY_DEFAULT);

}  // namespace features

FeatureNotificationGuideService::FeatureNotificationGuideService() = default;

FeatureNotificationGuideService::~FeatureNotificationGuideService() = default;

FeatureNotificationGuideService::Delegate::~Delegate() = default;

void FeatureNotificationGuideService::Delegate::SetService(
    FeatureNotificationGuideService* service) {
  service_ = service;
}

FeatureNotificationGuideService*
FeatureNotificationGuideService::Delegate::GetService() {
  return service_;
}

}  // namespace feature_guide


text:
'use strict';
var copyUrlsExpert;

(function() {

  /**
   * Installs the toolbar button with the given ID into the given
   * toolbar, if it is not already present in the document.
   *
   * Source: https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Toolbar
   *
   * @param {string} toolbarId The ID of the toolbar to install to.
   * @param {string} id The ID of the button to install.
   * @param {string} afterId The ID of the element to insert after. @optional
   */
  function installButton(toolbarId, id, afterId) {
    try {
      if (document.getElementById(id)) {
        return;
      }

      var toolbar = document.getElementById(toolbarId);

      // If no afterId is given, then append the item to the toolbar
      var before = null;
      if (afterId) {
          let elem = document.getElementById(afterId);
          if (elem /* && elem.parentNode == toolbar */) {
              before = elem.nextElementSibling;
          }
      }

      toolbar.insertItem(id, before);
      toolbar.setAttribute('currentset', toolbar.currentSet);
      document.persist(toolbar.id, 'currentset');

      if (toolbarId == 'addon-bar') {
          toolbar.collapsed = false;
      }
    }
    catch(ex) {
      Components.utils.reportError(ex);
    }
  }

  function _isDuplicate(entries, url) {
    url = url.toLowerCase();
    for (var i = 0; i < entries.length; i++) {
      var entryUrl = entries[i];
      if (entryUrl.toLowerCase() == url) {
        return true;
      }
    }
    return false;
  }

  function setupMainRef() {
    copyUrlsExpert = {
      _prefService: null,
      TBB_ACTION_ACTIVE_WIN: 'active-win',
      TBB_ACTION_ACTIVE_TAB: 'active-tab',
      TBB_ACTION_ACTIVE_TABGROUP: 'active-tabgroup',
      TBB_ACTION_ALL_WIN: 'all-win',
      TBB_ACTION_OPEN_TABS: 'open-tabs',
      TBB_ACTION_ADVANCED_COPY: 'advanced-copy',
      TBB_ACTION_SELECTION_LINKS: 'selection-links',
      TBB_ACTION_SELECTION_IMAGES: 'selection-images',

      defaultPattern: null,

      /* Following props are initialized by common.jsm */
      SORT_BY_TAB_ORDER: null,
      SORT_BY_DOMAIN: null,
      SORT_BY_TITLE: null,
      LINE_FEED: null,

      /* documentHandler is initialized by imported document handler module */
      documentHandler: null,

      init: function () {
        const Cu = Components.utils;
        Cu.import('resource://copy-urls-expert/common.jsm', this);

        this._prefService = this.getPrefService();
        this._handleStartup();

        Cu.import('resource://copy-urls-expert/chrome-utils.jsm', this);
        Cu.import('resource://copy-urls-expert/copy-task.jsm', this);
        Cu.import('resource://copy-urls-expert/keyboardshortcut.jsm');
        Cu.import('resource://copy-urls-expert/modifiers.jsm');

        // Use a document handler depending on messageManager feature
        let resourceUrl = 'resource://copy-urls-expert/document-handler-legacy.jsm';
        if (window.messageManager) {
          resourceUrl = 'resource://copy-urls-expert/document-handler-modern.jsm';
        }

        //Components.utils.reportError('document-handler: ' + resourceUrl.substr(resourceUrl.lastIndexOf('/') + 1));
        Cu.import(resourceUrl, this);

        this.documentHandler.init({
          messageManager: window.messageManager,
        });

        try {
          this._updateShortcutsForDocument(document, this.getCustomShortcuts());
        }
        catch (ex) {
          //ignore any exception in new feature and let the init complete
          Cu.reportError(ex);
        }

        Cu.import('resource://copy-urls-expert/cue-classes.jsm', this);

        this.readTemplatesFile(function (result) {

          var target = result.templates;
          var index = result.defaultTemplateId;

          if (target === null) {

            if (result.errorStatus === null) {

              if (!copyUrlsExpert.isFirstRun) {
                alert('Copy Urls Expert: templates list file is missing.\nRestoring to default values.'); // TODO: localize it
              }

              target = [];
              index = copyUrlsExpert._setupDefaultModel(target);

              // attempt to update file
              var defaultContent = '0' + copyUrlsExpert.LINE_FEED + target.join(copyUrlsExpert.LINE_FEED);
              copyUrlsExpert.updateUrlListFile(defaultContent);

            }
            else {
              // Handle error!
              alert('Copy Urls Expert: Error reading templates list file.\n' + result.errorStatus); // TODO: localize it
            }

          }

          copyUrlsExpert._updateFuelAppData(target, index);

        });
      },

      onUnload: function (evt) {
        this.documentHandler.uninit({
          messageManager: window.messageManager
        });
      },

      _handleStartup: function () {
        var oldVersion = '___version___';
        var currVersion = '___version___';

        try {
          oldVersion = this._prefService.getCharPref('version');
        }
        catch (e) {
        }

        if (oldVersion != currVersion) {
          this._prefService.setCharPref('version', currVersion);
        }

        if (oldVersion === '') {
          this.isFirstRun = true;
          // extension is installed for the first time
          installButton('nav-bar', 'copyurlsexpert-toolbar-btnmain', 'urlbar-container');
          // The "addon-bar" is available since Firefox 4
          installButton('addon-bar', 'copyurlsexpert-toolbar-btnmain');
        }
      },

      getUrlEntry: function (title, url) {
        return {
          title: title,
          url: url
        };
      },

      _getEntriesFromTabs: function (aBrowsers, filterHidden, filterDuplicates, filterPinnedTabs) {
        var title = '',
            url = '',
            urls = [],
            entries = [];

        for (var i = 0; i < aBrowsers.length; i++) {
          var tabbrowser = aBrowsers[i].gBrowser;
          var tabHistory = aBrowsers[i].sessionHistory;

          // Check each tab of this tabbrowser instance
          var numTabs = tabbrowser.browsers.length,
              tabContainer = tabbrowser.tabContainer;

          for (var index = 0; index < numTabs; index++) {
            var targetBrwsr = tabbrowser.getBrowserAtIndex(index),
                targetTab = tabContainer.getItemAtIndex(index);

            if (filterHidden && targetTab.hidden) continue;

            if (filterPinnedTabs && targetTab.pinned) continue;

            if (filterDuplicates && _isDuplicate(urls, targetBrwsr.currentURI.spec)) {
              continue;
            }

            var auxTemp = this._getEntryForTab(targetBrwsr, targetTab);
            entries.push(auxTemp);
            urls.push(auxTemp.url);
          }
        }

        return entries;
      },

      _getEntryForTab: function (brwsr, tab) {
        var url = brwsr.currentURI.spec;

        var useContentTitle = this._prefService.getBoolPref("usecontenttitle");

        var title = useContentTitle && brwsr.contentTitle ? brwsr.contentTitle : tab.label;

        var entry = this.getUrlEntry(title, url);
        return entry;
      },

      performCopyActiveTabUrl: function (opts) {
        opts = opts || {};
        opts.contextTab = opts.contextTab || this.getGBrowser().selectedTab;

        this._performCopyOfSingleTabUrl(opts);
      },

      performCopyTabUnderMouseUrl: function (opts) {
        opts = opts || {};

        let _g = this.getGBrowser();
        opts.contextTab = _g.mContextTab || _g.selectedTab;

        this._performCopyOfSingleTabUrl(opts);
      },

      _performCopyOfSingleTabUrl: function (opts) {

        let templateToUse = opts.template || this.defaultPattern;
        let sortBy = opts.sortBy || this._prefService.getCharPref('sortby');

        var entries = [this._getEntryForTab(this.getGBrowser().getBrowserForTab(opts.contextTab), opts.contextTab)];
        this.copyEntriesToClipBoard(entries, sortBy, templateToUse);
      },

      _getBrowsers: function (onlyActiveWindow) {
        var aBrowsers = [];

        var winMediator = copyUrlsExpert.getWindowMediator();
        if (onlyActiveWindow) {
          aBrowsers.push(winMediator.getMostRecentWindow('navigator:browser'));
        }
        else {
          var browserEnumerator = winMediator.getEnumerator('navigator:browser');
          // Iterate all open windows
          while (browserEnumerator.hasMoreElements()) {
            aBrowsers.push(browserEnumerator.getNext());
          }
        }

        return aBrowsers;
      },

      performCopyTabsUrl: function (onlyActiveWindow, filterHidden) {
        this.performCopyTabsUrlWithOptions({
          onlyActiveWindow: onlyActiveWindow,
          filterHidden: filterHidden
        });
      },

      performCopyTabsUrlWithOptions: function (opts) {

        let options = {
          onlyActiveWindow: true,
          filterHidden: false,
          filterDuplicates: this._prefService.getBoolPref('filterduplicates'),
          filterPinnedTabs: this._prefService.getBoolPref('excludepinnedtabs'),
          sortBy: this._prefService.getCharPref('sortby'),
          template: this.defaultPattern
        };

        // override default options with the opts
        for (let prop in opts) {
          if (opts.hasOwnProperty(prop)) {
            options[prop] = opts[prop];
          }
        }

        // This function must be called awith all three arguments
        var aBrowsers = this._getBrowsers(options.onlyActiveWindow);

        var entries = this._getEntriesFromTabs(aBrowsers, options.filterHidden, options.filterDuplicates, options.filterPinnedTabs);

        this.copyEntriesToClipBoard(entries, options.sortBy, options.template);
      },

      performOpenUrlsInSelection: function () {
        copyUrlsExpert.documentHandler.openUrlsInSelection({
          filterDuplicates: this._prefService.getBoolPref('filterduplicates')
        });
      },

      performCopyUrlsInSelection: function (opts) {
        opts = opts || {};

        opts.tagName = 'a';
        copyUrlsExpert._performCopyUrlsInSelection(opts);
      },

      performCopyUrlsOfImagesInSelection: function (opts) {
        opts = opts || {};

        opts.tagName = 'img';

        copyUrlsExpert._performCopyUrlsInSelection(opts);
      },

      _performCopyUrlsInSelection: function (opts) {

        let options = {
          filterDuplicates: this._prefService.getBoolPref('filterduplicates'),
          sortBy: this._prefService.getCharPref('sortby'),
          tagName: '',
          template: opts.template || this.defaultPattern
        };

        for (let prop in opts) {
          if (opts.hasOwnProperty(prop)) {
            options[prop] = opts[prop];
          }
        }

        this.documentHandler.extractAndCopyUrlsFromSelection(options);
      },

      _isEmptySelection: function () {
        // Check if there is some text selected

        var sel = content.getSelection();

        return sel & sel.length > 0;
      },

      performDefaultAction: function () {
        copyUrlsExpert._doAction(copyUrlsExpert._prefService.getCharPref('toolbaraction'), {});
      },

      _doAction: function (action, options) {

        switch (action) {
          case this.TBB_ACTION_ACTIVE_WIN:
            options.onlyActiveWindow = true;
            options.filterHidden = false;
            this.performCopyTabsUrlWithOptions(options);
            break;

          case this.TBB_ACTION_ACTIVE_TABGROUP:
            options.onlyActiveWindow = true;
            options.filterHidden = true;
            this.performCopyTabsUrlWithOptions(options);
            break;

          case this.TBB_ACTION_ACTIVE_TAB:
            this.performCopyActiveTabUrl(options);
            break;

          case this.TBB_ACTION_ALL_WIN:
            options.onlyActiveWindow = false;
            options.filterHidden = false;
            this.performCopyTabsUrlWithOptions(options);
            break;

          case this.TBB_ACTION_SELECTION_LINKS:
            this.performCopyUrlsInSelection(options);
            break;

          case this.TBB_ACTION_SELECTION_IMAGES:
            this.performCopyUrlsOfImagesInSelection(options);
            break;

          case this.TBB_ACTION_ADVANCED_COPY:
            this.showAdvancedCopyWindow();
            break;

          case this.TBB_ACTION_OPEN_TABS:
            document.getElementById('cmd_cue_openTabs').doCommand();
            break;
        }
      },

      showOptionsWindow: function () {
        //window.open('chrome://copy-urls-expert/content/dialogs/options.xul', 'copyUrlsExpertOptionsWindow', 'addressbar=no, modal');

        var features = "chrome,titlebar,toolbar,centerscreen";
        try {
          var instantApply = Services.prefs.getBoolPref('browser.preferences.instantApply');
          features += instantApply ? ",dialog=no" : ",modal";
        }
        catch (e) {
          features += ",modal";
        }
        openDialog('chrome://copy-urls-expert/content/dialogs/options.xul', '', features);
      },

      showAdvancedCopyWindow: function () {
        var features = "chrome,titlebar,toolbar,centerscreen";
        try {
          var instantApply = Services.prefs.getBoolPref('browser.preferences.instantApply');
          features += instantApply ? ",dialog=no" : ",modal";
        }
        catch (e) {
          features += ",modal";
        }

        let dialogArgs = {
          contextTab: null
        };

        // If the context menu was invoked on a tab other than active tab, Let the dialog know the contextTab
        let _g = this.getGBrowser();
        dialogArgs.contextTab = _g.mContextTab;

        openDialog('chrome://copy-urls-expert/content/dialogs/advanced.xul', '', features, dialogArgs);
      },

      _getClipboardText: function () {
        var clip = Components.classes['@mozilla.org/widget/clipboard;1'].getService(Components.interfaces.nsIClipboard);
        if (!clip) return null;

        var trans = copyUrlsExpert.createTransferable(window);

        clip.getData(trans, clip.kGlobalClipboard);

        var str = new Object();
        var strLength = new Object();

        trans.getTransferData("text/unicode", str, strLength);

        if (str) {
          str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
          str = str.data.substring(0, strLength.value / 2);
        }

        return str;
      },

      /**
       This function is called for 'Open Tabs from Clipboard'
       */
      openTabs: function () {
        var sUrl = this._getClipboardText(),
        // the following regex is extracting urls from any text
            myRe = /((https?):\/\/((?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::((?:[0-9]*)))?(\/(((?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,^#]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,^#]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,^#]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,^#]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?]((?:(?:[;\/?:@&=+$,^#a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/ig,
            myArray = null,
            urls = [],
            filterDuplicates = this._prefService.getBoolPref('filterduplicates');

        while ((myArray = myRe.exec(sUrl))) {
          var newUrl = String(myArray[0]);

          if (filterDuplicates && _isDuplicate(urls, newUrl)) {
            continue;
          }

          urls.push(newUrl);
        }

        if (typeof this.openAllUrls === 'undefined') {
          Cu.import('resource://copy-urls-expert/open-urls-task.jsm', this);
        }

        return this.openAllUrls(urls);
      },

      _updateFuelAppData: function (target, defaultIndex) {
        // FUEL DEPRECIATED - update local data of all windows

        const Cc = Components.classes,
            Ci = Components.interfaces;

        let defaultPattern = target[defaultIndex];

        let wm = this.getWindowMediator();

        // Get the list of browser windows already open
        let windows = wm.getEnumerator('navigator:browser');
        while (windows.hasMoreElements()) {
          let xulWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);

          xulWindow.copyUrlsExpert.defaultPattern = defaultPattern;
        }
      },

      updateCustomShortcuts: function (shortcutsMap) {
        this._prefService.setCharPref('shortcuts', JSON.stringify(shortcutsMap));
        this._loadCustomShortcuts(shortcutsMap);

      },

      _loadCustomShortcuts: function (shortcutsMap) {

        let wm = this.getWindowMediator();

        // Get the list of browser windows already open
        let windows = wm.getEnumerator('navigator:browser');
        while (windows.hasMoreElements()) {
          let domWindow = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);

          this._updateShortcutsForDocument(domWindow.document, shortcutsMap);
        }
      },

      _updateShortcutsForDocument: function (document, shortcutsMap) {

        // Add keyset to XUL document for all the defined shortcuts

        let CUE_KEYSET_ID = 'copyUrlsExpert-keyset',
            keysetParent = document.getElementById('mainKeyset');

        if (keysetParent == null) {
          // loaded in a non-browser window
          return;
        }
        else {
          keysetParent = keysetParent.parentNode;
        }

        let keyset = keysetParent.querySelector('#' + CUE_KEYSET_ID);

        // Remove the old keyset to remove the old key bindings
        if (keyset != null) {
          keyset.remove();
        }

        // Create a new keyset for new shortcuts defined
        keyset = document.createElement('keyset');
        keyset.setAttribute('id', CUE_KEYSET_ID);

        for (let commandId in shortcutsMap) {
          let keyElemId = 'key-' + commandId,
              targetKey = null,
              shortcut = shortcutsMap[commandId];

          if (!shortcut) {
            // shortcut is not defined
            continue;
          }

          targetKey = document.createElement('key');
          targetKey.setAttribute('id', keyElemId);
          targetKey.setAttribute('command', commandId);

          var shortcutKeyConfig = shortcut.getKeyConfig();

          if (shortcutKeyConfig.hasOwnProperty('keycode')) {
            targetKey.setAttribute('keycode', shortcutKeyConfig.keycode);
            targetKey.setAttribute('keytext', shortcutKeyConfig.keytext);
          }
          else {
            targetKey.setAttribute('key', shortcutKeyConfig.keytext);
          }

          if (shortcut.modifiers) {
            targetKey.setAttribute('modifiers', shortcut.modifiers.toXulModifiersString());
          }

          keyset.appendChild(targetKey);
        }

        keysetParent.appendChild(keyset);

      },

      updateUrlListFile: function (theContent) {
        // Write to prefs
        // get profile directory
        var file = Components.classes['@mozilla.org/file/directory_service;1'].getService(Components.interfaces.nsIProperties).get('ProfD', Components.interfaces.nsIFile);
        file.append('copyurlsexpert');
        if (!file.exists() || !file.isDirectory()) {
          // if it doesn't exist, create
          file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0x1FF);   // 0x1FF = 0777
        }

        file.append('urls.templates');

        var updateHandler = new copyUrlsExpert._AsynHandler(file, copyUrlsExpert._prefService);
        copyUrlsExpert._writeDataToFile(theContent, file, function (inputStream, status) {
          updateHandler.handleUpdate(inputStream, status);
        });
      },

      _writeDataToFile: function (content, file, fptr) {
        // file is nsIFile, content is a string

        Components.utils.import('resource://gre/modules/NetUtil.jsm');
        Components.utils.import('resource://gre/modules/FileUtils.jsm');
        // You can also optionally pass a flags parameter here. It defaults to
        // FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE;
        var ostream = FileUtils.openSafeFileOutputStream(file)

        var converter = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
        converter.charset = 'UTF-8';
        var istream = converter.convertToInputStream(content);

        // The last argument (the callback) is optional.
        NetUtil.asyncCopy(istream, ostream, fptr);
      },

      /*
       Fills the 'templates' by parsing the contents of 'data'
       @param: data - Contents of file.
       @param: templates - target array object that would be populated.
       @returns: int representing the index of default pattern.
       */
      _updateModel: function (data, templates) {
        var index = this.convertStringToModel(data, templates);

        if (index == -1) {
          index = copyUrlsExpert._setupDefaultModel(templates);
        }

        return index;

      },

      _setupDefaultModel: function (templates) {
        templates.push(new this._FormatPattern(0, 'Default', '$url$n'));
        templates.push(new this._FormatPattern(1, 'html', '<a href="$url">$title</a>$n'));
        templates.push(new this._FormatPattern(2, 'forum', '[a=$url]$title[/a]$n'));
        return 0;
      }

    };
  }

  function init() {
    window.removeEventListener('load', init);

    window.setTimeout(function () {
      setupMainRef();

      window.addEventListener('unload', function onUnload(evt){
        copyUrlsExpert.onUnload(evt);
      }, false);

      // @ifdef DEBUG
      var consoleSvc = Components.classes["@mozilla.org/consoleservice;1"]
          .getService(Components.interfaces.nsIConsoleService);

      copyUrlsExpert.log = function() {
        consoleSvc.logStringMessage.call(consoleSvc, "Copy Urls Expert: " + Array.prototype.join.call(arguments, ' '));
      };
      // @endif

      copyUrlsExpert.init();
    }, 50);
  }

  window.addEventListener('load', init, false);
})();


text:
FROM node:8-jessie
RUN apt update
USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
COPY . /home/node/app
RUN npm install
CMD npm start && sleep infinity


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">

<title>DummyStopTermHandler Properties</title>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <meta name="generator" content="Doc-O-Matic">
    <link rel="STYLESHEET" href="default.css" type="text/css">

SimMetrics library v 1.5 for .NET 2.0

Contents | Index | Reference

DummyStopTermHandler Properties

DummyStopTermHandler | Legend

Properties

Property
Description

 NumberOfWords
gets the number of stopwords in the list.

 ShortDescriptionString
displays the stopWordHandler method.

 WordsAsBuffer
gets the stopwords as a stringBuffer.

Copyright (c) 2006. All rights reserved.

Contents | Index | Reference


text:
@class Picture;

@interface User : NSManagedObject

@property (nonatomic, retain) NSString * fullname;
@property (nonatomic, retain) NSString * id;
@property (nonatomic, retain) NSString * profileImageURLString;
@property (nonatomic, retain) NSString * username;
@property (nonatomic, retain) NSSet *pictures;
@end

@interface User (CoreDataGeneratedAccessors)

- (void)addPicturesObject:(Picture *)value;
- (void)removePicturesObject:(Picture *)value;
- (void)addPictures:(NSSet *)values;
- (void)removePictures:(NSSet *)values;

@end


text:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

/**
 * The unique ID of the installation.
 */
 export const InstallationId = "X-ZUMO-INSTALLATION-ID";

 /**
  * Some clients cannot adjust `User-Agent`, so we provide a secondary user-agent.
  */
 export const InternalUserAgent = "X-ZUMO-VERSION";

 /**
  * The version of the protocol being used.
  */
 export const ProtocolVersion = "ZUMO-API-VERSION";

 /**
  * The user agent header name.
  */
 export const UserAgent = "User-Agent";


text:
namespace Core {
    class cConfigFactory : public cFactory<cConfig> {
    protected:
    public:

        cConfigFactory(Paranoia::Engine *engine);
        virtual ~cConfigFactory();

        virtual void AddObject(cConfig* newObj) override;
        virtual cConfig* AddObject(std::string cfName, int id = 0, bool lock = false);
        //virtual cConfig* AddObject(std::string afName, std::string cfName, int id = 0, bool lock = false);
        //virtual cConfig* CreateObject(std::string config, std::string name, int id = 0, bool lock = false);

        // Сохраняет файл конфигурации в файл
        void SaveToFile(std::string cfName);
    };
}

#endif //PROJECT_CCONFIGFACTORY_H


text:
import Ember from 'ember';
import Application from '../../app';
import Router from '../../router';
import config from '../../config/environment';

export default function startApp(attrs) {
  var App;

  var attributes = Ember.merge({}, config.APP);
  attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;

  Router.reopen({
    location: 'none'
  });

  Ember.run(function() {
    App = Application.create(attributes);
    App.setupForTesting();
    App.injectTestHelpers();
  });

  App.reset(); // this shouldn't be needed, i want to be able to "start an app at a specific URL"

  return App;
}


text:
using System;
using System.Text;
using JetBrains.Annotations;

namespace fNbt {
    /// <summary> A tag containing an array of signed 32-bit integers. </summary>
    public sealed class NbtIntArray : NbtTag {
        /// <summary> Type of this tag (ByteArray). </summary>
        public override NbtTagType TagType {
            get {
                return NbtTagType.IntArray;
            }
        }

        /// <summary> Value/payload of this tag (an array of signed 32-bit integers). May not be <c>null</c>. </summary>
        /// <exception cref="ArgumentNullException"> <paramref name="value"/> is <c>null</c>. </exception>
        [NotNull]
        public int[] Value {
            get {
                return ints;
            }
            set {
                if( value == null ) {
                    throw new ArgumentNullException( "value" );
                }
                ints = value;
            }
        }

        [NotNull]
        int[] ints;

        /// <summary> Creates an unnamed NbtIntArray tag, containing an empty array of ints. </summary>
        public NbtIntArray()
            : this( null, new int[0] ) {}

        /// <summary> Creates an unnamed NbtIntArray tag, containing the given array of ints. </summary>
        /// <param name="value"> Int array to assign to this tag's Value. May not be <c>null</c>. </param>
        /// <exception cref="ArgumentNullException"> <paramref name="value"/> is <c>null</c>. </exception>
        public NbtIntArray( [NotNull] int[] value )
            : this( null, value ) {}

        /// <summary> Creates an NbtIntArray tag with the given name, containing an empty array of ints. </summary>
        /// <param name="tagName"> Name to assign to this tag. May be <c>null</c>. </param>
        public NbtIntArray( [CanBeNull] string tagName )
            : this( tagName, new int[0] ) {}

        /// <summary> Creates an NbtIntArray tag with the given name, containing the given array of ints. </summary>
        /// <param name="tagName"> Name to assign to this tag. May be <c>null</c>. </param>
        /// <param name="value"> Int array to assign to this tag's Value. May not be <c>null</c>. </param>
        /// <exception cref="ArgumentNullException"> <paramref name="value"/> is <c>null</c>. </exception>
        public NbtIntArray( [CanBeNull] string tagName, [NotNull] int[] value ) {
            if( value == null )
                throw new ArgumentNullException( "value" );
            Name = tagName;
            Value = (int[])value.Clone();
        }

        /// <summary> Gets or sets an integer at the given index. </summary>
        /// <param name="tagIndex"> The zero-based index of the element to get or set. </param>
        /// <returns> The integer at the specified index. </returns>
        /// <exception cref="IndexOutOfRangeException"> <paramref name="tagIndex"/> is outside the array bounds. </exception>
        public new int this[ int tagIndex ] {
            get {
                return Value[tagIndex];
            }
            set {
                Value[tagIndex] = value;
            }
        }

        internal override bool ReadTag( NbtBinaryReader readStream ) {
            int length = readStream.ReadInt32();
            if( length < 0 ) {
                throw new NbtFormatException( "Negative length given in TAG_Int_Array" );
            }

            if( readStream.Selector != null && !readStream.Selector( this ) ) {
                readStream.Skip( length * sizeof( int ) );
                return false;
            }

            Value = new int[length];
            for( int i = 0; i < length; i++ ) {
                Value[i] = readStream.ReadInt32();
            }
            return true;
        }

        internal override void SkipTag( NbtBinaryReader readStream ) {
            int length = readStream.ReadInt32();
            if( length < 0 ) {
                throw new NbtFormatException( "Negative length given in TAG_Int_Array" );
            }
            readStream.Skip( length * sizeof( int ) );
        }

        internal override void WriteTag( NbtBinaryWriter writeStream, bool writeName ) {
            writeStream.Write( NbtTagType.IntArray );
            if( writeName ) {
                if( Name == null )
                    throw new NbtFormatException( "Name is null" );
                writeStream.Write( Name );
            }
            WriteData( writeStream );
        }

        internal override void WriteData( NbtBinaryWriter writeStream ) {
            writeStream.Write( Value.Length );
            for( int i = 0; i < Value.Length; i++ ) {
                writeStream.Write( Value[i] );
            }
        }

        /// <summary> Returns a String that represents the current NbtIntArray object.
        /// Format: TAG_Int_Array("Name"): [N ints] </summary>
        /// <returns> A String that represents the current NbtIntArray object. </returns>
        public override string ToString() {
            var sb = new StringBuilder();
            PrettyPrint( sb, null, 0 );
            return sb.ToString();
        }

        internal override void PrettyPrint( StringBuilder sb, string indentString, int indentLevel ) {
            for( int i = 0; i < indentLevel; i++ ) {
                sb.Append( indentString );
            }
            sb.Append( "TAG_Int_Array" );
            if( !String.IsNullOrEmpty( Name ) ) {
                sb.AppendFormat( "(\"{0}\")", Name );
            }
            sb.AppendFormat( ": [{0} ints]", ints.Length );
        }
    }
}


text:
package io.quarkus.qute.deployment.inject;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import javax.enterprise.context.Dependent;
import javax.inject.Inject;

import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.qute.Engine;
import io.quarkus.qute.Location;
import io.quarkus.qute.Template;
import io.quarkus.test.QuarkusUnitTest;

public class InjectionTest {

    @RegisterExtension
    static final QuarkusUnitTest config = new QuarkusUnitTest()
            .withApplicationRoot((jar) -> jar
                    .addClasses(SimpleBean.class)
                    .addAsResource(new StringAsset("quarkus.qute.suffixes=txt"), "application.properties")
                    .addAsResource(new StringAsset("{this}"), "templates/foo.txt")
                    .addAsResource(new StringAsset("{this}"), "templates/foo.qute.html")
                    .addAsResource(new StringAsset("{@String foo}{this}"), "templates/bars/bar.txt"));

    @Inject
    SimpleBean simpleBean;

    @Test
    public void testInjection() {
        assertNotNull(simpleBean.engine);
        assertEquals("bar", simpleBean.foo.render("bar"));
        assertEquals("bar", simpleBean.foo2.render("bar"));
        assertEquals("bar", simpleBean.bar.render("bar"));

        // Some operations are only allowed for unambiguous templates
        assertThrows(UnsupportedOperationException.class, () -> simpleBean.foo.getId());
        assertThrows(UnsupportedOperationException.class, () -> simpleBean.foo.getExpressions());
        assertThrows(UnsupportedOperationException.class, () -> simpleBean.foo.getGeneratedId());
        assertThrows(UnsupportedOperationException.class, () -> simpleBean.foo.getParameterDeclarations());
        assertThrows(UnsupportedOperationException.class, () -> simpleBean.foo.getVariant());
        assertThrows(UnsupportedOperationException.class, () -> simpleBean.foo.findExpression(null));
        assertEquals(1, simpleBean.bar.getExpressions().size());
        assertEquals("this", simpleBean.bar.findExpression(e -> e.getParts().size() == 1).getParts().get(0).getName());
        assertEquals("bars/bar.txt", simpleBean.bar.getId());
        assertEquals(1, simpleBean.bar.getParameterDeclarations().size());
        assertEquals("UTF-8", simpleBean.bar.getVariant().get().getEncoding());
        assertNotNull(simpleBean.bar.getGeneratedId());
        assertEquals("foo.qute.html", simpleBean.foo2.getId());
    }

    @Dependent
    public static class SimpleBean {

        @Inject
        Engine engine;

        @Inject
        Template foo;

        @Location("foo.qute.html")
        Template foo2;

        @Location("bars/bar")
        Template bar;

    }

}


text:
/**
* @file vtol_type.h
*
* @author Roman Bapst 		<bapstroman@gmail.com>
* @author Sander Smeets		<sander@droneslab.com>
* @author Andreas Antener	<andreas@uaventure.com>
*
*/

#ifndef VTOL_TYPE_H
#define VTOL_TYPE_H

#include <lib/mathlib/mathlib.h>
#include <drivers/drv_hrt.h>

struct Params {
	int32_t idle_pwm_mc;			// pwm value for idle in mc mode
	int32_t vtol_motor_count;		// number of motors
	float fw_pitch_trim;		// trim for neutral elevon position in fw mode
	int32_t vtol_type;
	bool elevons_mc_lock;		// lock elevons in multicopter mode
	float fw_min_alt;			// minimum relative altitude for FW mode (QuadChute)
	float fw_alt_err;			// maximum negative altitude error for FW mode (Adaptive QuadChute)
	float fw_qc_max_pitch;		// maximum pitch angle FW mode (QuadChute)
	float fw_qc_max_roll;		// maximum roll angle FW mode (QuadChute)
	float front_trans_time_openloop;
	float front_trans_time_min;
	bool wv_takeoff;
	bool wv_loiter;
	bool wv_land;
};

// Has to match 1:1 msg/vtol_vehicle_status.msg
enum mode {
	TRANSITION_TO_FW = 1,
	TRANSITION_TO_MC = 2,
	ROTARY_WING = 3,
	FIXED_WING = 4
};

enum vtol_type {
	TAILSITTER = 0,
	TILTROTOR,
	STANDARD
};

class VtolAttitudeControl;

class VtolType
{
public:

	VtolType(VtolAttitudeControl *att_controller);
	VtolType(const VtolType &) = delete;
	VtolType &operator=(const VtolType &) = delete;

	virtual ~VtolType();

	/**
	 * Update vtol state.
	 */
	virtual void update_vtol_state() = 0;

	/**
	 * Update transition state.
	 */
	virtual void update_transition_state() = 0;

	/**
	 * Update multicopter state.
	 */
	virtual void update_mc_state();

	/**
	 * Update fixed wing state.
	 */
	virtual void update_fw_state();

	/**
	 * Write control values to actuator output topics.
	 */
	virtual void fill_actuator_outputs() = 0;

	/**
	 * Special handling opportunity for the time right after transition to FW
	 * before TECS is running.
	 */
	virtual void waiting_on_tecs() {}

	/**
	 * Checks for fixed-wing failsafe condition and issues abort request if needed.
	 */
	void check_quadchute_condition();

	/**
	 * Returns true if we're allowed to do a mode transition on the ground.
	 */
	bool can_transition_on_ground();

	void set_idle_mc();
	void set_idle_fw();

	mode get_mode() {return _vtol_mode;}

	virtual void parameters_update() = 0;

protected:
	VtolAttitudeControl *_attc;
	mode _vtol_mode;

	struct vehicle_attitude_s		*_v_att;				//vehicle attitude
	struct vehicle_attitude_setpoint_s	*_v_att_sp;			//vehicle attitude setpoint
	struct vehicle_attitude_setpoint_s *_mc_virtual_att_sp;	// virtual mc attitude setpoint
	struct vehicle_attitude_setpoint_s *_fw_virtual_att_sp;	// virtual fw attitude setpoint
	struct vehicle_control_mode_s		*_v_control_mode;	//vehicle control mode
	struct vtol_vehicle_status_s 		*_vtol_vehicle_status;
	struct actuator_controls_s			*_actuators_out_0;			//actuator controls going to the mc mixer
	struct actuator_controls_s			*_actuators_out_1;			//actuator controls going to the fw mixer (used for elevons)
	struct actuator_controls_s			*_actuators_mc_in;			//actuator controls from mc_att_control
	struct actuator_controls_s			*_actuators_fw_in;			//actuator controls from fw_att_control
	struct vehicle_local_position_s			*_local_pos;
	struct vehicle_local_position_setpoint_s	*_local_pos_sp;
	struct airspeed_s 				*_airspeed;					// airspeed
	struct tecs_status_s				*_tecs_status;
	struct vehicle_land_detected_s			*_land_detected;

	struct Params 					*_params;

	bool flag_idle_mc = true;		//false = "idle is set for fixed wing mode"; true = "idle is set for multicopter mode"

	bool _pusher_active = false;
	float _mc_roll_weight = 1.0f;	// weight for multicopter attitude controller roll output
	float _mc_pitch_weight = 1.0f;	// weight for multicopter attitude controller pitch output
	float _mc_yaw_weight = 1.0f;	// weight for multicopter attitude controller yaw output
	float _mc_throttle_weight = 1.0f;	// weight for multicopter throttle command. Used to avoid

	// motors spinning up or cutting too fast when doing transitions.
	float _thrust_transition = 0.0f;	// thrust value applied during a front transition (tailsitter & tiltrotor only)

	float _ra_hrate = 0.0f;			// rolling average on height rate for quadchute condition
	float _ra_hrate_sp = 0.0f;		// rolling average on height rate setpoint for quadchute condition

	bool _flag_was_in_trans_mode = false;	// true if mode has just switched to transition
	hrt_abstime _trans_finished_ts = 0;
	bool _tecs_running = false;
	hrt_abstime _tecs_running_ts = 0;

};

#endif


text:
@interface TouchChainDesController : UIViewController

@end


text:
var gulp = require('gulp');
var gulpsync = require('gulp-sync')(gulp);
var shell = require('gulp-shell');
var typescript = require('gulp-typescript');
var sourcemaps = require('gulp-sourcemaps');
var mocha = require('gulp-mocha');
var fs = require('fs');
var merge2 = require('merge2');
var child_process = require('child_process');
var configs = require('./building/loadConfigs');
var config = configs['config'];

function requireFromString(src, filename) {
	var Module = module.constructor;
	var m = new Module();
	m._compile(src, filename);
	return m.exports;
}

gulp.task('prepareSymlinks', function() {
	fs.exists('node_modules/', function(exist) {
		if (!exist) {
			fs.mkdirSync('node_modules')
		}
	})
	fs.exists('v/0.0.0/', function(exist) {
		if(!exist) {
			fs.mkdirSync('v/0.0.0')
			fs.link('lib', 'v/0.0.0/lib');
			fs.link('app', 'v/0.0.0/app');
		}
	})
})

gulp.task('saveConfigToTs', function() {
	fs.writeFile("./app/rogsit/config.ts", 'export var config = ' + JSON.stringify(config) + ';', function(err) {});
})

gulp.task('processTypesChanges', function() {
	var processor = require('./building/processTypesChanges')
	processor.processTypes()
})

gulp.task('transpilateTypescript', function () {
	var tsResult = gulp.src(['app/*/*.ts'])
		.pipe(sourcemaps.init())
		.pipe(typescript({
			sortOutput: true,
			target: 'ES5',
			emitDecoratorMetadata: true,
			experimentalDecorators: true,
			declaration: true,
			moduleResolution: 'node',
			module: 'system',
		}))

	return merge2([
		tsResult.dts
			.pipe(gulp.dest('app/')),
		tsResult.js
			.pipe(sourcemaps.write('./'))
			.pipe(gulp.dest('app/'))
	])
})

function requireFromString(src, filename) {
	var Module = module.constructor;
	var m = new Module();
	m._compile(src, filename);
	return m.exports;
}

var buildBackendCommandsByLang = {
	'go': 'go install github.com/rogallic/rogsit',
}
gulp.task('buildBackend', shell.task([
	buildBackendCommandsByLang[config['BackendProgrammingLanguage']],
]))

var testBackendCommandsByLang = {
	'go': 'go test github.com/rogallic/rogsit',
}
gulp.task('testBackend', shell.task([
	testBackendCommandsByLang[config['BackendProgrammingLanguage']],
]))

gulp.task('applyDBTest', function() {
	return gulp.src(['building/applyDB_' + config['DBLang'] + '_test.js'], {read: false})
		.pipe(mocha())
		.once('end', function() {
		})
})

gulp.task('applyDB', function() {
	return require('./building/applyDB.js').runApplyDB();
})

var createFirstUserCommandsByLang = {
	'go': ['$GOPATH/bin/rogsit createFirstUser', '$GOPATH/bin/rogsit test createFirstUser'],
}
gulp.task('createFirstUser', shell.task(createFirstUserCommandsByLang[config['BackendProgrammingLanguage']]))

var runTestServCommandsByLang = {
	'go': ['/home/rogallic/go/bin/rogsit', ['test', 'serv']],
}
gulp.task('commonBackendTests', function() {
	var testServerSpawn;
	var servCommand = runTestServCommandsByLang[config['BackendProgrammingLanguage']];
	if (servCommand) {
		testServerSpawn = child_process.spawn(servCommand[0], servCommand[1], {})
	}

	return gulp.src(['building/commonBackendTests/*.js'], {
			read: false
		})
		.pipe(mocha())
		.once('end', function() {
			if (testServerSpawn) {
				setTimeout(function() {
					testServerSpawn.kill()
				}, 10)
			}
		})
})

var servCommandsByLang = {
	'go': '$GOPATH/bin/rogsit serv',
}
gulp.task('serv', shell.task([
	servCommandsByLang[config['BackendProgrammingLanguage']],
]))

gulp.task('frontend', gulpsync.sync(['prepareSymlinks', 'saveConfigToTs', 'processTypesChanges', 'transpilateTypescript']))
gulp.task('backend', gulpsync.sync(['buildBackend', 'testBackend', 'applyDB', 'createFirstUser', 'commonBackendTests']))
gulp.task('backendBuildTest', gulpsync.sync(['buildBackend', 'testBackend']))
gulp.task('devserv', gulpsync.sync['buildBackend', 'serv'])

gulp.task('default', gulpsync.sync(['frontend', 'backend']))


text:
@interface ASDetailViewController : UIViewController

@end