// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: math.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Math {

  namespace Proto {

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Math {

      #region Descriptor
      public static pbr::FileDescriptor Descriptor {
        get { return descriptor; }
      }
      private static pbr::FileDescriptor descriptor;

      static Math() {
        byte[] descriptorData = global::System.Convert.FromBase64String(
            string.Concat(
              "CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB", 
              "KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB", 
              "IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB", 
              "IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50", 
              "GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu", 
              "RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E", 
              "aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51", 
              "bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAFiBnByb3Rv", 
              "Mw=="));
        descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
            new pbr::FileDescriptor[] { },
            new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
              new pbr::GeneratedCodeInfo(typeof(global::Math.DivArgs), new[]{ "Dividend", "Divisor" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.DivReply), new[]{ "Quotient", "Remainder" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.FibArgs), new[]{ "Limit" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.Num), new[]{ "Num_" }, null, null, null),
              new pbr::GeneratedCodeInfo(typeof(global::Math.FibReply), new[]{ "Count" }, null, null, null)
            }));
      }
      #endregion

    }
  }
  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class DivArgs : pb::IMessage<DivArgs> {
    private static readonly pb::MessageParser<DivArgs> _parser = new pb::MessageParser<DivArgs>(() => new DivArgs());
    public static pb::MessageParser<DivArgs> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[0]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public DivArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    public DivArgs(DivArgs other) : this() {
      dividend_ = other.dividend_;
      divisor_ = other.divisor_;
    }

    public DivArgs Clone() {
      return new DivArgs(this);
    }

    public const int DividendFieldNumber = 1;
    private long dividend_;
    public long Dividend {
      get { return dividend_; }
      set {
        dividend_ = value;
      }
    }

    public const int DivisorFieldNumber = 2;
    private long divisor_;
    public long Divisor {
      get { return divisor_; }
      set {
        divisor_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as DivArgs);
    }

    public bool Equals(DivArgs other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Dividend != other.Dividend) return false;
      if (Divisor != other.Divisor) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Dividend != 0L) hash ^= Dividend.GetHashCode();
      if (Divisor != 0L) hash ^= Divisor.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Dividend != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Dividend);
      }
      if (Divisor != 0L) {
        output.WriteRawTag(16);
        output.WriteInt64(Divisor);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Dividend != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Dividend);
      }
      if (Divisor != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor);
      }
      return size;
    }

    public void MergeFrom(DivArgs other) {
      if (other == null) {
        return;
      }
      if (other.Dividend != 0L) {
        Dividend = other.Dividend;
      }
      if (other.Divisor != 0L) {
        Divisor = other.Divisor;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            Dividend = input.ReadInt64();
            break;
          }
          case 16: {
            Divisor = input.ReadInt64();
            break;
          }
        }
      }
    }

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class DivReply : pb::IMessage<DivReply> {
    private static readonly pb::MessageParser<DivReply> _parser = new pb::MessageParser<DivReply>(() => new DivReply());
    public static pb::MessageParser<DivReply> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[1]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public DivReply() {
      OnConstruction();
    }

    partial void OnConstruction();

    public DivReply(DivReply other) : this() {
      quotient_ = other.quotient_;
      remainder_ = other.remainder_;
    }

    public DivReply Clone() {
      return new DivReply(this);
    }

    public const int QuotientFieldNumber = 1;
    private long quotient_;
    public long Quotient {
      get { return quotient_; }
      set {
        quotient_ = value;
      }
    }

    public const int RemainderFieldNumber = 2;
    private long remainder_;
    public long Remainder {
      get { return remainder_; }
      set {
        remainder_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as DivReply);
    }

    public bool Equals(DivReply other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Quotient != other.Quotient) return false;
      if (Remainder != other.Remainder) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Quotient != 0L) hash ^= Quotient.GetHashCode();
      if (Remainder != 0L) hash ^= Remainder.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Quotient != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Quotient);
      }
      if (Remainder != 0L) {
        output.WriteRawTag(16);
        output.WriteInt64(Remainder);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Quotient != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Quotient);
      }
      if (Remainder != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Remainder);
      }
      return size;
    }

    public void MergeFrom(DivReply other) {
      if (other == null) {
        return;
      }
      if (other.Quotient != 0L) {
        Quotient = other.Quotient;
      }
      if (other.Remainder != 0L) {
        Remainder = other.Remainder;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            Quotient = input.ReadInt64();
            break;
          }
          case 16: {
            Remainder = input.ReadInt64();
            break;
          }
        }
      }
    }

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class FibArgs : pb::IMessage<FibArgs> {
    private static readonly pb::MessageParser<FibArgs> _parser = new pb::MessageParser<FibArgs>(() => new FibArgs());
    public static pb::MessageParser<FibArgs> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[2]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public FibArgs() {
      OnConstruction();
    }

    partial void OnConstruction();

    public FibArgs(FibArgs other) : this() {
      limit_ = other.limit_;
    }

    public FibArgs Clone() {
      return new FibArgs(this);
    }

    public const int LimitFieldNumber = 1;
    private long limit_;
    public long Limit {
      get { return limit_; }
      set {
        limit_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as FibArgs);
    }

    public bool Equals(FibArgs other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Limit != other.Limit) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Limit != 0L) hash ^= Limit.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Limit != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Limit);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Limit != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Limit);
      }
      return size;
    }

    public void MergeFrom(FibArgs other) {
      if (other == null) {
        return;
      }
      if (other.Limit != 0L) {
        Limit = other.Limit;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            Limit = input.ReadInt64();
            break;
          }
        }
      }
    }

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Num : pb::IMessage<Num> {
    private static readonly pb::MessageParser<Num> _parser = new pb::MessageParser<Num>(() => new Num());
    public static pb::MessageParser<Num> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[3]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public Num() {
      OnConstruction();
    }

    partial void OnConstruction();

    public Num(Num other) : this() {
      num_ = other.num_;
    }

    public Num Clone() {
      return new Num(this);
    }

    public const int Num_FieldNumber = 1;
    private long num_;
    public long Num_ {
      get { return num_; }
      set {
        num_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as Num);
    }

    public bool Equals(Num other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Num_ != other.Num_) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Num_ != 0L) hash ^= Num_.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Num_ != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Num_);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Num_ != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Num_);
      }
      return size;
    }

    public void MergeFrom(Num other) {
      if (other == null) {
        return;
      }
      if (other.Num_ != 0L) {
        Num_ = other.Num_;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            Num_ = input.ReadInt64();
            break;
          }
        }
      }
    }

  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class FibReply : pb::IMessage<FibReply> {
    private static readonly pb::MessageParser<FibReply> _parser = new pb::MessageParser<FibReply>(() => new FibReply());
    public static pb::MessageParser<FibReply> Parser { get { return _parser; } }

    public static pbr::MessageDescriptor Descriptor {
      get { return global::Math.Proto.Math.Descriptor.MessageTypes[4]; }
    }

    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    public FibReply() {
      OnConstruction();
    }

    partial void OnConstruction();

    public FibReply(FibReply other) : this() {
      count_ = other.count_;
    }

    public FibReply Clone() {
      return new FibReply(this);
    }

    public const int CountFieldNumber = 1;
    private long count_;
    public long Count {
      get { return count_; }
      set {
        count_ = value;
      }
    }

    public override bool Equals(object other) {
      return Equals(other as FibReply);
    }

    public bool Equals(FibReply other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Count != other.Count) return false;
      return true;
    }

    public override int GetHashCode() {
      int hash = 1;
      if (Count != 0L) hash ^= Count.GetHashCode();
      return hash;
    }

    public override string ToString() {
      return pb::JsonFormatter.Default.Format(this);
    }

    public void WriteTo(pb::CodedOutputStream output) {
      if (Count != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(Count);
      }
    }

    public int CalculateSize() {
      int size = 0;
      if (Count != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count);
      }
      return size;
    }

    public void MergeFrom(FibReply other) {
      if (other == null) {
        return;
      }
      if (other.Count != 0L) {
        Count = other.Count;
      }
    }

    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while (input.ReadTag(out tag)) {
        switch(tag) {
          case 0:
            throw pb::InvalidProtocolBufferException.InvalidTag();
          default:
            if (pb::WireFormat.IsEndGroupTag(tag)) {
              return;
            }
            break;
          case 8: {
            Count = input.ReadInt64();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
