-- Listing 16.14

using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;
namespace Helion.Examples
{
   [Serializable]
   [Microsoft.SqlServer.Server.SqlUserDefinedType
      (
         Format.Native,
         IsByteOrdered = true
      )]
   public struct Complex : INullable
   {
      #region "Complex Number UDT Fields/Components"
      private bool m_Null;
      public Double real;
      public Double imaginary;
      #endregion
      #region "Complex Number Parsing, Constructor, and Methods/Properties"
      private static readonly Regex rx = new Regex(
         "^(?<Imaginary>[+-]?([0-9]+|[0-9]*\\.[0-9]+))[i|I]$|" +
         "^(?<Real>[+-]?([0-9]+|[0-9]*\\.[0-9]+))$|" +
         "^(?<Real>[+-]?([0-9]+|[0-9]*\\.[0-9]+))" +
         "(?<Imaginary>[+-]?([0-9]+|[0-9]*\\.[0-9]+))[i|I]$");
   public static Complex Parse(SqlString s)
   {
      Complex u = new Complex();
      if (s.IsNull)
          u = Null;
      else
      {
         MatchCollection m = rx.Matches(s.Value);
         if (m.Count == 0)
             throw (new FormatException("Invalid Complex Number Format."));
         String real_str = m[0].Groups["Real"].Value;
         String imaginary_str = m[0].Groups["Imaginary"].Value;
         if (real_str == "" && imaginary_str == "")
             throw (new FormatException("Invalid Complex Number Format."));
         if (real_str == "")
             u.real = 0.0;
         else
             u.real = Convert.ToDouble(real_str);
         if (imaginary_str == "")
             u.imaginary = 0.0;
         else
             u.imaginary = Convert.ToDouble(imaginary_str);
      }
      return u;
   }
   public override String ToString()
   {
      String sign = "";
      if (this.imaginary >= 0.0)
          sign = "+";
      return this.real.ToString() + sign + this.imaginary.ToString() + "i";
   }
   public bool IsNull
   {
      get
      {
         return m_Null;
      }
   }
   public static Complex Null
   {
      get
      {
         Complex h = new Complex();
         h.m_Null = true;
         return h;
      }
   }
   public Complex(Double r, Double i)
   {
      this.real = r;
      this.imaginary = i;
      this.m_Null = false;
   }
   #endregion
   #region "Complex Number Basic Operators"
   // Dodawanie liczb zespolonych.
      public static Complex operator +(Complex n1, Complex n2)
      {
         Complex u;
         if (n1.IsNull || n2.IsNull)
             u = Null;
         else
             u = new Complex(n1.real + n2.real, n1.imaginary + n2.imaginary);
         return u;
      }
      #endregion
      #region "Exposed Mathematical Basic Operator Methods"
      // Dodaj liczb zespolon n2 do n1.
      public static Complex CAdd(Complex n1, Complex n2)
      {
         return n1 + n2;
      }
      // Odejmij liczb zespolon n2 od n1.
      public static Complex Sub(Complex n1, Complex n2)
      {
         return n1 - n2;
      }
      #endregion
      // Inne operacje na liczbach zespolonych znajduj si w zaczonych kodach rdowych.
      }
}
