HIRASE CONNECTION WK

programming collection

目次

Blog 利用状況

ニュース

書庫

日記カテゴリ

Link Collection

[C#] 複素数型を作る。

元ネタ:[C#]コンプレックスと戦う

C# ジェネリクスの制限に打ち勝つ

型制約として値型を用いることができない、operator+-*/ をGetMethod()できない、そんな C# ジェネリックでも、複素数型を定義してみました。

namespace Sample
{
    using System;
    using System.ComponentModel;

    struct Complex<TValue>
    {
        public TValue Real { get; set; }
        public TValue Imaginary { get; set; }

        public static Complex<TValue> operator +(Complex<TValue> lft, Complex<TValue> rgt)
        {
            return new Complex<TValue>() { Real = Adder(lft.Real, rgt.Real), Imaginary = Adder(lft.Imaginary, rgt.Imaginary) };
        }

        public static Complex<TValue> operator -(Complex<TValue> lft, Complex<TValue> rgt)
        {
            return new Complex<TValue>() { Real = Subtractor(lft.Real, rgt.Real), Imaginary = Subtractor(lft.Imaginary, rgt.Imaginary) };
        }

        public static Complex<TValue> operator *(Complex<TValue> lft, Complex<TValue> rgt)
        {
            return new Complex<TValue>() { Real = Multiplier(lft.Real, rgt.Real), Imaginary = Multiplier(lft.Imaginary, rgt.Imaginary) };
        }

        public static Complex<TValue> operator /(Complex<TValue> lft, Complex<TValue> rgt)
        {
            return new Complex<TValue>() { Real = Divider(lft.Real, rgt.Real), Imaginary = Divider(lft.Imaginary, rgt.Imaginary) };
        }

        static Complex()
        {
            var tvalue_type = typeof(TValue);
            if (tvalue_type == typeof(sbyte))
            {
                Complex<sbyte>.Adder = (x, y) => (sbyte)(x + y);
                Complex<sbyte>.Subtractor = (x, y) => (sbyte)(x - y);
                Complex<sbyte>.Multiplier = (x, y) => (sbyte)(x * y);
                Complex<sbyte>.Divider = (x, y) => (sbyte)(x / y);
            }
            else if (tvalue_type == typeof(byte))
            {
                Complex<byte>.Adder = (x, y) => (byte)(x + y);
                Complex<byte>.Subtractor = (x, y) => (byte)(x - y);
                Complex<byte>.Multiplier = (x, y) => (byte)(x * y);
                Complex<byte>.Divider = (x, y) => (byte)(x / y);
            }
            else if (tvalue_type == typeof(short))
            {
                Complex<short>.Adder = (x, y) => (short)(x + y);
                Complex<short>.Subtractor = (x, y) => (short)(x - y);
                Complex<short>.Multiplier = (x, y) => (short)(x * y);
                Complex<short>.Divider = (x, y) => (short)(x / y);
            }
            else if (tvalue_type == typeof(ushort))
            {
                Complex<ushort>.Adder = (x, y) => (ushort)(x + y);
                Complex<ushort>.Subtractor = (x, y) => (ushort)(x - y);
                Complex<ushort>.Multiplier = (x, y) => (ushort)(x * y);
                Complex<ushort>.Divider = (x, y) => (ushort)(x / y);
            }
            else if (tvalue_type == typeof(int))
            {
                Complex<int>.Adder = (x, y) => (int)(x + y);
                Complex<int>.Subtractor = (x, y) => (int)(x - y);
                Complex<int>.Multiplier = (x, y) => (int)(x * y);
                Complex<int>.Divider = (x, y) => (int)(x / y);
            }
            else if (tvalue_type == typeof(uint))
            {
                Complex<uint>.Adder = (x, y) => (uint)(x + y);
                Complex<uint>.Subtractor = (x, y) => (uint)(x - y);
                Complex<uint>.Multiplier = (x, y) => (uint)(x * y);
                Complex<uint>.Divider = (x, y) => (uint)(x / y);
            }
            else if (tvalue_type == typeof(long))
            {
                Complex<long>.Adder = (x, y) => (long)(x + y);
                Complex<long>.Subtractor = (x, y) => (long)(x - y);
                Complex<long>.Multiplier = (x, y) => (long)(x * y);
                Complex<long>.Divider = (x, y) => (long)(x / y);
            }
            else if (tvalue_type == typeof(ulong))
            {
                Complex<ulong>.Adder = (x, y) => (ulong)(x + y);
                Complex<ulong>.Subtractor = (x, y) => (ulong)(x - y);
                Complex<ulong>.Multiplier = (x, y) => (ulong)(x * y);
                Complex<ulong>.Divider = (x, y) => (ulong)(x / y);
            }
            else if (tvalue_type == typeof(float))
            {
                Complex<float>.Adder = (x, y) => (float)(x + y);
                Complex<float>.Subtractor = (x, y) => (float)(x - y);
                Complex<float>.Multiplier = (x, y) => (float)(x * y);
                Complex<float>.Divider = (x, y) => (float)(x / y);
            }
            else if (tvalue_type == typeof(double))
            {
                Complex<double>.Adder = (x, y) => (double)(x + y);
                Complex<double>.Subtractor = (x, y) => (double)(x - y);
                Complex<double>.Multiplier = (x, y) => (double)(x * y);
                Complex<double>.Divider = (x, y) => (double)(x / y);
            }
            else if (tvalue_type == typeof(decimal))
            {
                Complex<decimal>.Adder = (x, y) => (decimal)(x + y);
                Complex<decimal>.Subtractor = (x, y) => (decimal)(x - y);
                Complex<decimal>.Multiplier = (x, y) => (decimal)(x * y);
                Complex<decimal>.Divider = (x, y) => (decimal)(x / y);
            }
            else
            {
                throw new NotSupportedException();
            }
        }

        private static Func<TValue, TValue, TValue> Adder { get; set; }
        private static Func<TValue, TValue, TValue> Subtractor { get; set; }
        private static Func<TValue, TValue, TValue> Multiplier { get; set; }
        private static Func<TValue, TValue, TValue> Divider { get; set; }

        public override string ToString()
        {
            return String.Format("({0}) + ({1})i", Real.ToString(), Imaginary.ToString());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            #region +
            Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } + new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } + new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } + new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } + new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } + new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } + new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } + new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } + new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } + new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } + new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } + new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
            #endregion
            #region -
            Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } - new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } - new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } - new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } - new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } - new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } - new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } - new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } - new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } - new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } - new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } - new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
            #endregion
            #region *
            Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } * new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } * new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } * new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } * new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } * new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } * new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } * new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } * new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } * new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } * new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } * new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
            #endregion
            #region /
            Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } / new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } / new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } / new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } / new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } / new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } / new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } / new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } / new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } / new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } / new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
            Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } / new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
            #endregion
        }
    }
}

ちなみに、string でも Adder だけは定義可能なので、επιστημη氏の「あらあらあら」も C# で可能。

投稿日時 : 2009年2月5日 10:37

コメントを追加

# re: [C#] 複素数型を作る。 2009/02/05 11:49 επιστημη

どひゃー

# re: [C#] 複素数型を作る。 2009/02/05 12:25 T.Hirase

力業すぎます?

そういえば昼ラーメン食べ終わったときに思ったのですが、
別に静的コンストラクタでif-elseしなくても全部実体化しちゃえば良かったです。。

# re: [C#] 複素数型を作る。 2009/02/05 12:53 NyaRuRu

Expression.Add を使えばもうちょっと短かく書けますよ.
http://msdn.microsoft.com/ja-jp/library/bb354402.aspx

# [.NET]Expression trees と .NET 風メタプログラミング 2009/02/05 14:34 NyaRuRuの日記

あらあらあら - 東方算程譚 コンプレックスと戦う - Garbage Collection 複素数型を作る。 - HIRASE CONNECTION WK そういえば昔似たようなことをやっていた. 演算子に関するセマンティクスが保存される Generic 型生成 ― Expression Tree による実行時コード生成 ― - Ny

# re: [C#] 複素数型を作る。 2009/02/05 17:10 ufcpp

NyaRuRu さんが 言うように Expression.Add を使うなら、以下のように簡素に書けますね。

static Func<T, T, T> GetAdder<T>()
{
var x = Expression.Parameter(typeof(T), "x");
var y = Expression.Parameter(typeof(T), "y");

var ex = Expression.Lambda<Func<T, T, T>>(
Expression.Add(x, y),
new[] { x, y });

return ex.Compile();
}

# re: [C#] 複素数型を作る。 2009/02/06 0:24 よねけん

こりゃすごい!!!
Complex<TValue>の定義の中でComplex<float>といった具体的な型を使えるとは目から鱗ですね。

# make money easy 2010/08/11 0:04 personal finance software

i have enjoyed reading thank for sharing your story Greeting.

# buy a transit van 2011/04/02 1:28 used suv accesories

Awesome Post. I add this Post to my bookmarks.

# VHGGIaEzzYmBfQzRCg 2011/09/29 6:53 http://oemfinder.com

xv1XMN I serched through the internet and got here. What a wonderful invention of the mankind. With the help of the network you communicate, learn, read !... That helped us to get acquainted!...

# APCyraEJkkGLz 2011/10/05 1:07 http://altynetsoft.com/flash-player-pro-3.6.html

It's pleasant sitting at work to distract from it?to relax and read the information written here:D

# QtvOMgHoWYLhp 2011/10/22 22:44 http://www.discountwatchstore.com/Invicta-Watches_

It`s really useful! Looking through the Internet you can mostly observe watered down information, something like bla bla bla, but not here to my deep surprise. It makes me happy..!

# ixWDpgqOYVush 2011/11/02 5:28 http://www.pharmaciecambier.com/

Gripping! I would like to listen to the experts` views on the subject!!...

# UavbpmiJvfpcirRoObA 2011/11/02 6:22 http://optclinic.com/

Yeah, now it's clear !... And firstly I did not understand very much where there was the link with the title itself !!...

# ZKtEoONqfjEhslbWdL 2011/11/16 3:38 http://www.catalinabiosolutions.com/index.php/pond

I serched through the internet and got here. What a wonderful invention of the mankind. With the help of the network you communicate, learn, read !... That helped us to get acquainted!...

# mEzLuuqfbC 2011/11/16 3:59 http://www.laurenslinens.com/teenbedding.html

I read online (computer problems) positive feedback about your resource. Didnt even believe it, and now saw myself. It turned out that I was not fooled!...

タイトル  
名前  
URL
コメント