<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
// Copyright (C) 2008 Xtensive LLC.
// All rights reserved.
// For conditions of distribution and use, see license.
// Created by: Alexey Gamzov
// Created:    2008.01.22

using System;
using Xtensive.Arithmetic;


namespace Xtensive.Arithmetic
{
<#
var types = new[] { 
  typeof(byte), 
  typeof(sbyte), 
  typeof(char),
  typeof(short),
  typeof(ushort),
  typeof(int),
  typeof(uint),
  typeof(long),
  typeof(ulong),
  typeof(decimal),
  typeof(float),
  typeof(double),
  };
foreach (var type in types) {
  var primitiveName = type.Name;
  var className = type.Name + "Arithmetic";
#>
  [Serializable]
  internal sealed class <#= className #>
    : ArithmeticBase<<#= primitiveName #>>
  {
    private const <#= primitiveName #> zero     = (<#= primitiveName #>) 0;
    private const <#= primitiveName #> one      = (<#= primitiveName #>) 1;
    private const <#= primitiveName #> minusOne = unchecked ((<#= primitiveName #>) (-1));

    /// <inheritdoc/>
    public override <#= primitiveName #> Zero
    {
      get { return zero; }
    }

    /// <inheritdoc/>
    public override <#= primitiveName #> One
    {
      get { return one; }
    }

	/// <inheritdoc/>
    public override <#= primitiveName #> MaxValue
    {
      get { return <#= primitiveName #>.MaxValue; }
    }
    
    /// <inheritdoc/>
    public override <#= primitiveName #> MinValue
    {
      get { return <#= primitiveName #>.MinValue; }
    }
    
    /// <inheritdoc/>
    public override bool IsSigned
    {
      get { return <#= primitiveName #>.MinValue != zero; }
    }

    /// <inheritdoc/>
    public override <#= primitiveName #> Add(<#= primitiveName #> value1, <#= primitiveName #> value2)
    {
      if (OverflowAllowed) {
        unchecked{
          return (<#= primitiveName #>)(value1 + value2);
        }
      }
      else {
        checked{
          return (<#= primitiveName #>)(value1 + value2);
        }
      }
    }

    /// <inheritdoc/>
    public override <#= primitiveName #> Negation(<#= primitiveName #> value)
    {
      if (OverflowAllowed) {
        unchecked{
          return (<#= primitiveName #>)(minusOne*value);
        }
      }
      else {
        checked{
          return (<#= primitiveName #>)(minusOne*value);
        }
      }
    }

    /// <inheritdoc/>
    public override <#= primitiveName #> Subtract(<#= primitiveName #> value1, <#= primitiveName #> value2)
    {
      if (OverflowAllowed) {
        unchecked{
          return (<#= primitiveName #>)(value1 - value2);
        }
      }
      else {
        checked{
          return (<#= primitiveName #>)(value1 - value2);
        }
      }
    }

    /// <inheritdoc/>
    public override <#= primitiveName #> Multiply(<#= primitiveName #> value, double factor)
    {
      if (OverflowAllowed) {
        unchecked{
          return (<#= primitiveName #>)((double)value*factor);
        }
      }
      else {
        checked{
          return (<#= primitiveName #>)((double)value*factor);
        }
      }
    }

    /// <inheritdoc/>
    public override <#= primitiveName #> Divide(<#= primitiveName #> value, double factor)
    {
      if (OverflowAllowed) {
        unchecked{
          return (<#= primitiveName #>)((double)value/factor);
        }
      }
      else {
        checked{
          return (<#= primitiveName #>)((double)value/factor);
        }
      }
    }

    /// <inheritdoc/>
    protected override IArithmetic<<#= primitiveName #>> CreateNew(ArithmeticRules rules)
    {
      return new <#= className #>(Provider, rules);
    }


    // Constructors

    /// <summary>
    /// Initializes a new instance of this type.
    /// </summary>
    public <#= className #>(IArithmeticProvider provider, ArithmeticRules rule)
      : base(provider, rule)
    {
    }
  }
  
<#
  }
#>
}