/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2002/X/X - 2016/11/25
/// 
/// @brief  基本的なベクトルクラス
/// 
/// ****************************************************************************

#pragma once

#include "CPL_Core_Traits.h"

namespace CPL {
namespace Core {

/// @cond
namespace zzz_ {


// _____________________________________________________________________________
/// @brief 
// *****************************************************************************
template<bool F_Arithmetic, int IDX>
struct vec_getter_
{
  template<class T, int N, class D, template<class, int, class> class T_Vec>
  const T operator()( T_Vec<T, N, D> const& pt ) const
  {
    if( N > IDX )
    {
      return ((T*)&pt)[IDX];
    }
    return 0;
  }
  template<class T, int N>
  auto operator()( T const (&v)[N] ) const -> decltype( v[N] )
  {
    static decltype( v[N] ) const nullobj = 0;
    return (N > IDX) ? v[IDX] : nullobj;
  }
  template<class T_Point>
  typename T_Point::td_element operator()( T_Point const& pt )
  {
    static constexpr int N = T_Point::kELEMENTS_NUM;
    if( N > IDX )
    {
      return ((typename T_Point::td_element*)&pt)[IDX];
    }
    return 0;
  }
};
template<int IDX>
struct vec_getter_<true,IDX>
{
  template<class T>
  const T operator()( T in_value ) const
  {
    return in_value;
  }
};




// _____________________________________________________________________________
/// @brief 複数の値を格納するクラスの共通機能。
///
/// @note 
/// T_Numは２以上にしなければならない。
///
// *****************************************************************************
template<class T_Type, int T_Num, class T_Derived>
class Vector_
  : public Vector_<T_Type, T_Num-1, T_Derived>
{
public:
private:
  using td_self = Vector_<T_Type, T_Num,   T_Derived>;
  using td_base = Vector_<T_Type, T_Num-1, T_Derived>;
  using PriorityPoint  = typename td_base::PriorityPoint;
  using PriorityVector = typename td_base::PriorityVector;
  using PriorityArray  = typename td_base::PriorityArray;
  using PriorityUnary  = typename td_base::PriorityUnary;

  friend td_self;
  friend td_base;
  template<class T, int N, class D>
  friend class Vector_;

  // 
  template<class T> int zzf_arg_size( T* adr )
  {
    return (sizeof(T) + (sizeof(int)-1)) & ~(sizeof(int)-1);
  }

  template<class T> T*  zzf_arg_prev( T* adr )
  {
    return reinterpret_cast<T*>((char*)adr - zzf_arg_size(adr));
  }

  template<class T> T*  zzf_arg_end( T* adr )
  {
    return reinterpret_cast<T*>((char*)adr + zzf_arg_size(adr) * (T_Num-1));
  }
public:

  static constexpr int kELEMENTS_NUM = T_Num;
  using td_element = T_Type;

protected:
  template<class T>
  void zzf_copy( const T* adr )
  {
    td_base::get(T_Num-1) = static_cast<T_Type>(*adr);
    td_base::zzf_copy( adr - 1 );
  }
  T_Type zzf_min( T_Type n ) const
  {
    return zzf_min( n, td_base::zzf_min( td_base::get(T_Num-1) ) );
  }
  T_Type zzf_max( T_Type n ) const
  {
    return zzf_max( n, td_base::zzf_max( td_base::get(T_Num-1) ) );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // ＋
  template<class T_Derived, class T>
  T_Derived& zzf_add_eq( T const& vec )
  {
    td_base::get(T_Num-1) +=
      vec_getter_<std::is_arithmetic<T>::value, T_Num-1>()( vec );
    return td_base::template zzf_add_eq<T_Derived>( vec );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // −
  template<class T_Derived, class T>
  T_Derived& zzf_sub_eq( T const& vec )
  {
    td_base::get(T_Num-1) -=
      vec_getter_<std::is_arithmetic<T>::value, T_Num-1>()( vec );
    return td_base::template zzf_sub_eq<T_Derived>( vec );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // ×
  template<class T_Derived, class T>
  T_Derived& zzf_multiply_eq( T const& vec )
  {
    td_base::get(T_Num-1) *=
      vec_getter_<std::is_arithmetic<T>::value, T_Num-1>()( vec );
    return td_base::template zzf_multiply_eq<T_Derived>( vec );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // ÷
  template<class T_Derived, class T>
  T_Derived& zzf_division_eq( T const& vec )
  {
    td_base::get(T_Num-1) /=
      vec_getter_<std::is_arithmetic<T>::value, T_Num-1>()( vec );
    return td_base::template zzf_division_eq<T_Derived>( vec );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 交換
  void zzf_swap( td_self& vec )
  {
    CPL::Swap<T_Type, T_Type>( td_base::get(T_Num-1), vec.get(T_Num-1) );
    td_base::zzf_swap( vec );
  }


  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  constexpr Vector_() = default;
  Vector_( Vector_ const& ) = default;
  ~Vector_() = default;
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  constexpr Vector_( T_Type n )
    : td_base( n )
  {
    td_base::get(T_Num-1) = n;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Vector_( T const* in_ptr )
  {
    zzf_copy( in_ptr + T_Num - 1 );
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<template<class> class T, class U>
  Vector_( T<U> const& vs )
  {
    zzf_copy( &vs.get(T_Num-1) );
  }
  
public:
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  T_Type GetMin()
  {
    return td_base::zzf_min( td_base::get(T_Num-1) );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  T_Type GetMax()
  {
    return td_base::zzf_max( td_base::get(T_Num-1) );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void Swap( T_Derived& in_vset )
  {
    zzf_swap( in_vset );
  }

//  template<class T0> operator T0(){
//    T0 tmp(static_cast<T_Type*>(*this));
//    return tmp; } // 変換用

  // 継承されないので意味がない
//  template<class T0> T0& operator = ( const T0& d ){
//                                                   zzf_copy( &d.get(T_Num-1) );
//                                                   return *reinterpret_cast<T0*>(this); }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T0>
  bool operator == ( const T0& vs ) const
  {
    return
      (td_base::get(T_Num-1) == vs.get(T_Num-1))  &&
      ((td_base const&)*this == (typename T0::td_base const&)vs);
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T0> bool operator != ( const T0& vs ) const
  {
    return !((*this) == vs);
  }

};




// _____________________________________________________________________________
/// @brief Vector_クラスの１による特殊化。
///
// *****************************************************************************
template<class T_Type, class T_Derived>
class Vector_<T_Type, 1, T_Derived> {
protected:
  typedef Priority<3>* PriorityPoint;
  typedef Priority<2>* PriorityVector;
  typedef Priority<1>* PriorityArray;
  typedef Priority<0>* PriorityUnary;

  template<class T>
  void zzf_copy( const T* in_adr )
  {
    get(0) = static_cast<T_Type>(*in_adr);
  }

  T_Type zzf_min( T_Type n )
  {
    return Min( get(0), n );
  }

  T_Type zzf_max( T_Type n )
  {
    return Max( get(0), n );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // ＋
  template<class T_Derived, class T>
  T_Derived& zzf_add_eq( T const& vec )
  {
    get(0) += vec_getter_<std::is_arithmetic<T>::value, 0>()( vec );
    return static_cast<T_Derived&>(*this);
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // －
  template<class T_Derived, class T>
  T_Derived& zzf_sub_eq( T const& vec )
  {
    get(0) -= vec_getter_<std::is_arithmetic<T>::value, 0>()( vec );
    return static_cast<T_Derived&>(*this);
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // ×
  template<class T_Derived, class T>
  T_Derived& zzf_multiply_eq( T const& vec )
  {
    get(0) *= vec_getter_<std::is_arithmetic<T>::value, 0>()( vec );
    return static_cast<T_Derived&>(*this);
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // ÷
  template<class T_Derived, class T>
  T_Derived& zzf_division_eq( T const& vec )
  {
    get(0) /= vec_getter_<std::is_arithmetic<T>::value, 0>()( vec );
    return static_cast<T_Derived&>(*this);
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void zzf_swap( Vector_<T_Type,1, T_Derived>& pt )
  {
    CPL::Swap<T_Type, T_Type>( get(0), pt.get(0) );
  }

  T_Type*          base_()          { return (T_Type*)this; }
  T_Type const*    base_() const    { return (T_Type const*)this; }
  T_Type volatile* base_() volatile { return (T_Type volatile*)this; }
  T_Type cpl_cv*   base_() cpl_cv   { return (T_Type cpl_cv*)this; }

public:
  constexpr Vector_() = default;
  constexpr Vector_( T_Type n ){
                       get(0) = n; }

  T_Type&          get()                   { return *base_(); }
  T_Type const&    get()          const    { return *base_(); }
  T_Type volatile& get()          volatile { return *base_(); }
  T_Type cpl_cv&   get()          cpl_cv   { return *base_(); }
  T_Type&          get( int idx )          { return base_()[ idx ]; }
  T_Type const&    get( int idx ) const    { return base_()[ idx ]; }
  T_Type volatile& get( int idx ) volatile { return base_()[ idx ]; }
  T_Type cpl_cv&   get( int idx ) cpl_cv   { return base_()[ idx ]; }
  
  template<class Idx> T_Type&          operator[]( Idx idx )          { return base_()[ idx ]; }
  template<class Idx> T_Type const&    operator[]( Idx idx ) const    { return base_()[ idx ]; }
  template<class Idx> T_Type volatile& operator[]( Idx idx ) volatile { return base_()[ idx ]; }
  template<class Idx> T_Type cpl_cv&   operator[]( Idx idx ) cpl_cv   { return base_()[ idx ]; }

  template<class T0> bool operator == ( T0 const& vs ) const
  {
    return get(0) == vs.get(0);
  }
  template<class T0> bool operator == ( T0 cpl_cv& vs ) cpl_cv
  {
    return get(0) == vs.get(0);
  }

  operator T_Type*      ()       { return base_(); }
  operator T_Type const*() const { return base_(); }

};

} // namespace zzz_
/// @endcond

//// _____________________________________________________________________________
//// 
//#define CPL_CORE_BASICVECTOR_POINT_OPERATOR_ARITHMETIC( T_CLASS, OP_TYPE, FUNC, DEFTYPE, NEWTYPE )\
//  T_CLASS<typename Traits::Accurate<DEFTYPE,NEWTYPE>::type>\
//    operator OP_TYPE ( NEWTYPE value ) const\
//  {\
//    return\
//      T_CLASS<typename Traits::Accurate<DEFTYPE,NEWTYPE>::type>( base_() )\
//        OP_TYPE= value;\
//  }

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 算術オペレータ簡易化用マクロ
#define CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( OP_TYPE, FUNC )\
  td_self& operator OP_TYPE ( td_self const& vec )\
  {\
    return FUNC<td_self>( vec );\
  }\
  template<class T>\
  td_self& operator OP_TYPE ( T const& vec )\
  {\
    return FUNC<td_self>( vec );\
  }



#define CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( POINT_X, TYPE_OP )\
  template<class T>\
  POINT_X<typename Traits::Accurate<T_Type, T>::type> const\
    operator TYPE_OP ( POINT_X<T> const& rhs ) const\
  {\
    using type_res = POINT_X<typename Traits::Accurate<T_Type, T>::type>;\
    return type_res( *this ) TYPE_OP##= rhs;\
  }\
  template<class T>\
  POINT_X<typename Traits::Accurate<T_Type, T>::type> const\
    operator TYPE_OP ( T const& rhs ) const\
  {\
    using type_res = POINT_X<typename Traits::Accurate<T_Type, T>::type>;\
    return type_res( *this ) TYPE_OP##= rhs;\
  }

//template<class T, class U>\
//POINT_X<typename Traits::Accurate<T, U>::type> const\
//  FUNC(POINT_X<T> const& lhs, POINT_X<U> const& rhs)\
//{\
//  typedef POINT_X<typename Traits::Accurate<T, U>::type> type_res;\
//  return type_res( lhs ) TYPE_OP= rhs;\
//}


//template<class T> struct Point2;
//
///// @cond
//namespace zzz_
//{
//  namespace point_arithmetic
//  {
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, +, add_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, -, sub_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, *, multiply_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, /, division_ );
//  }
//}
///// @endcond

// _____________________________________________________________________________
/// @brief ２点保持用クラス
///
// *****************************************************************************
template<class T_Type>
struct Point2
  : public zzz_::Vector_< T_Type, 2, Point2<T_Type> >
{
  typedef Point2 TypeDerivedT;

  using td_base = zzz_::Vector_< T_Type, 2, Point2<T_Type> >;
  using td_self = Point2<T_Type>;

  union {
  struct { T_Type x, y; };
  struct { T_Type r, g; };
  T_Type p[2];
  T_Type xy[2];
  T_Type rg[2];
  };

  // コンストラクタ
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  constexpr Point2() = default;
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  explicit
  Point2( T_Type val_ )
    : x(val_), y(val_)
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point2( Nothing_    ) : x(0), y(0) {}
  Point2( Default_    ) : x(0), y(0) {}
  Point2( Initialize_ ) : x(0), y(0) {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point2( T_Type x_, T_Type y_ )
    : x(x_), y(y_)
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point2( td_self const& p2 )
    : td_base( p2 )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point2( Point2<T> const& p2 )
    : td_base( &p2.x )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T, int N>
  Point2( T const (&v)[N] )
  {
    static constexpr int idx = Traits::NumComp<td_base::kELEMENTS_NUM, N>::min - 1;
    zzz_::Vector_<T_Type, idx, td_self>::zzf_copy( v + idx );
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point2( T const* p )
    : td_base( p )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<template<class T0,int N,class T1> class T_Vec, class U, class V>
  Point2( T_Vec<U, 2, V> const& p2 )
    : x( p2.get(0) ), y( p2.get(1) )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point2( sem::t_X<T> in_X ) : x(in_X.val){}
  template<class T>
  Point2( sem::t_Y<T> in_Y ) : y(in_Y.val){}
  template<class T, class... Ts>
  Point2( sem::t_X<T> in_X, Ts... args )
    : x(in_X.val)
    , Point2( args... )
  {}
  template<class T, class... Ts>
  Point2( sem::t_Y<T> in_Y, Ts... args )
    : y(in_Y.val)
    , Point2( args... )
  {}

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 代入
  template<class T> td_self& operator = ( const T& d )
  {
    this->zzf_copy( &d.get( Traits::NumComp<td_base::kELEMENTS_NUM-1,T::kELEMENTS_NUM-1>::min ) );
    return *this;
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( +=, td_base::template zzf_add_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( -=, td_base::template zzf_sub_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( *=, td_base::template zzf_multiply_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( /=, td_base::template zzf_division_eq )

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, + )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, - )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, * )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point2, / )

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  operator T_Type*      ()       { return reinterpret_cast<T_Type*      >(this); }
  operator T_Type const*() const { return reinterpret_cast<T_Type const*>(this); }

  //// _____________________________________________________________________________
  //operator td_base&      ()       { return static_cast<td_base&>(*this); }
  //operator td_base const&() const { return static_cast<td_base const&>(*this); }

  //typedef Point2<T_Type>*        ptr;
  //typedef Point2<T_Type> const* cptr;
  //typedef Point2<T_Type>&        ref;
  //typedef Point2<T_Type> const& cref;

};



//template<class T> struct Point3;
//
///// @cond
//namespace zzz_
//{
//  namespace point_arithmetic
//  {
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, +, add_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, -, sub_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, *, multiply_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, /, division_ );
//  }
//}
///// @endcond

// _____________________________________________________________________________
/// @brief ３点保持用クラス
///
// *****************************************************************************
template<class T_Type>
struct Point3
  : public zzz_::Vector_< T_Type, 3, Point3<T_Type> >
{
  typedef zzz_::Vector_< T_Type, 3, Point3<T_Type> > td_base;
  typedef Point3<T_Type> td_self;
  
  union {
  struct { T_Type x, y, z; };
  struct { T_Type r, g, b; };
  T_Type p[3];
  T_Type xyz[3];
  T_Type rgb[3];
  T_Type xy[2];
  T_Type rg[2];
  };

  // コンストラクタ。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  constexpr Point3() = default;
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  explicit
  Point3( T_Type val_ )
    : x(val_), y(val_), z(val_)
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  explicit Point3( Nothing_    ) : x(0), y(0), z(0) {}
  explicit Point3( Default_    ) : x(0), y(0), z(0) {}
  explicit Point3( Initialize_ ) : x(0), y(0), z(0) {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point3( T_Type x_, T_Type y_, T_Type z_ )
    : x(x_), y(y_), z(z_)
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point3( Point3<T_Type> const& p3 )
    : td_base( p3 )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point3( Point3<T> const& p3 )
    : td_base( &p3.x )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T, int N>
  Point3( T const (&v)[N] )
  {
    static const int idx = Traits::NumComp<td_base::kELEMENTS_NUM, N>::min - 1;
    zzz_::Vector_<T_Type, idx, td_self>::zzf_copy( v + idx );
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point3( T const* p )
    : td_base( p )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point3( Point2<T> const& p2, T_Type z_ )
  {
    x = static_cast<T_Type>(p2.x);
    y = static_cast<T_Type>(p2.y);
    z = z_;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point3( T const xy_[2], T_Type z_ )
  {
    x = static_cast<T_Type>(xy_[0]);
    y = static_cast<T_Type>(xy_[1]);
    z = z_;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<template<class,int,class> class T, class U, class V>
  Point3( T<U, 2, V> const& p2, U z_ )
    : x( p2.x ), y( p2.y ), z( z_ )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<template<class,int,class> class T, class U, class V>
  Point3( T<U, 3, V> const& p3 )
    : x( p3.x ), y( p3.y ), z( p3.z )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point3( sem::t_X<T> in_X ) : x(in_X.val){}
  template<class T>
  Point3( sem::t_Y<T> in_Y ) : y(in_Y.val){}
  template<class T>
  Point3( sem::t_Z<T> in_Z ) : z(in_Z.val){}
  template<class T, class... Ts>
  Point3( sem::t_X<T> in_X, Ts... args )
    : x(in_X.val)
    , Point3( args... )
  {}
  template<class T, class... Ts>
  Point3( sem::t_Y<T> in_Y, Ts... args )
    : y(in_Y.val)
    , Point3( args... )
  {}
  template<class T, class... Ts>
  Point3( sem::t_Z<T> in_Z, Ts... args )
    : z(in_Z.val)
    , Point3( args... )
  {}

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 代入。
  template<class T> td_self& operator = ( const T& d )
  {
    zzf_copy( &d.get( Traits::NumComp<td_base::kELEMENTS_NUM-1,T::kELEMENTS_NUM-1>::min ) );
    return *this;
  }
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( +=, td_base::template zzf_add_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( -=, td_base::template zzf_sub_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( *=, td_base::template zzf_multiply_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( /=, td_base::template zzf_division_eq )

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, + )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, - )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, * )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point3, / )

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  operator T_Type*      ()       { return reinterpret_cast<T_Type*      >(this); }
  operator T_Type const*() const { return reinterpret_cast<T_Type const*>(this); }

  //// _____________________________________________________________________________
  //operator td_base&      ()       { return static_cast<td_base&>(*this); }
  //operator td_base const&() const { return static_cast<td_base const&>(*this); }

  //typedef Point3<T_Type>*        ptr;
  //typedef Point3<T_Type> const* cptr;
  //typedef Point3<T_Type>&        ref;
  //typedef Point3<T_Type> const& cref;
};




//template<class T> struct Point4;
//
///// @cond
//namespace zzz_
//{
//  namespace point_arithmetic
//  {
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, +, add_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, -, sub_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, *, multiply_ );
//    CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, /, division_ );
//  }
//}
///// @endcond

// _____________________________________________________________________________
/// @brief ４点保持用クラス
///
// *****************************************************************************
template<class T_Type>
struct Point4
  : public zzz_::Vector_< T_Type, 4, Point4<T_Type> >
{
  typedef zzz_::Vector_< T_Type, 4, Point4<T_Type> > td_base;
  typedef Point4<T_Type> td_self;

  union {
  struct { T_Type x, y, z, w; };
  struct { T_Type r, g, b, a; };
  struct { T_Type left, top, right, bottom; };
  T_Type p[4];
  T_Type xyzw[4];
  T_Type rgba[4];
  T_Type xyz[3];
  T_Type rgb[3];
  T_Type xy[2];
  T_Type rg[2];
  };

  // コンストラクタ。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  constexpr Point4() = default;
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  explicit
  Point4( T_Type val_ )
    : x(val_), y(val_), z(val_), w(val_)
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  explicit Point4( Nothing_    ) : x(0), y(0), z(0), w(0) {}
  explicit Point4( Default_    ) : x(0), y(0), z(0), w(0) {}
  explicit Point4( Initialize_ ) : x(0), y(0), z(0), w(0) {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point4( T_Type x_, T_Type y_, T_Type z_, T_Type w_ )
    : x(x_), y(y_), z(z_), w(w_)
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point4( Point4<T_Type> const& p4 )
    : td_base( p4 )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( Point4<T> const& p4 )
    : td_base( &p4.x )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T, int N>
  Point4( T const (&v)[N] )
  {
    static const int idx = Traits::NumComp<td_base::kELEMENTS_NUM, N>::min - 1;
    zzz_::Vector_<T_Type, idx, td_self>::zzf_copy( v + idx );
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( T const* p )
    : td_base( p )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( Point3<T> const& p3, T_Type w_ )
  {
    x = static_cast<T_Type>(p3.x);
    y = static_cast<T_Type>(p3.y);
    z = static_cast<T_Type>(p3.z);
    w = w_;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( T const xyz_[3], T_Type w_ )
  {
    x = static_cast<T_Type>(xyz_[0]);
    y = static_cast<T_Type>(xyz_[1]);
    z = static_cast<T_Type>(xyz_[2]);
    w = w_;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( Point2<T> const& p2, T_Type z_, T_Type w_ )
  {
    x = static_cast<T_Type>(p2.x);
    y = static_cast<T_Type>(p2.y);
    z = z_;
    w = w_;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( Point2<T> const& p2a, Point2<T> const& p2b )
  {
    x = static_cast<T_Type>(p2a.x);
    y = static_cast<T_Type>(p2a.y);
    z = static_cast<T_Type>(p2b.x);
    w = static_cast<T_Type>(p2b.y);
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( T const xy_[2], T_Type z_, T_Type w_ )
  {
    x = static_cast<T_Type>(xy_[0]);
    y = static_cast<T_Type>(xy_[1]);
    z = z_;
    w = w_;
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<template<class,int,class> class T, class U, class V>
  Point4( T<U, 2, V> const& p2, U z_, U w_ )
    : x( p2.get(0) ), y( p2.get(1) ), z( z_ ), w( w_ )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<template<class,int,class> class T, class U, class V>
  Point4( T<U, 3, V> const& p3, U w_ )
    : x( p3.get(0) ), y( p3.get(1) ), z( p3.get(2) ), w( w_ )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<template<class,int,class> class T, class U, class V>
  Point4( T<U, 4, V> const& p4 )
    : x( p4.get(0) ), y( p4.get(1) ), z( p4.get(2) ), w( p4.get(3) )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  Point4( sem::t_X<T> in_X ) : x(in_X.val){}
  template<class T>
  Point4( sem::t_Y<T> in_Y ) : y(in_Y.val){}
  template<class T>
  Point4( sem::t_Z<T> in_Z ) : z(in_Z.val){}
  template<class T>
  Point4( sem::t_W<T> in_W ) : w(in_W.val){}
  template<class T, class... Ts>
  Point4( sem::t_X<T> in_X, Ts... args )
    : x(in_X.val)
    , Point4( args... )
  {}
  template<class T, class... Ts>
  Point4( sem::t_Y<T> in_Y, Ts... args )
    : y(in_Y.val)
    , Point4( args... )
  {}
  template<class T, class... Ts>
  Point4( sem::t_Z<T> in_Z, Ts... args )
    : z(in_Z.val)
    , Point4( args... )
  {}
  template<class T, class... Ts>
  Point4( sem::t_W<T> in_W, Ts... args )
    : w(in_W.val)
    , Point4( args... )
  {}

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  T_Type Width()  const { return z - x; }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  T_Type Height() const { return w - y; }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Point2<T_Type> Size() const { return Point2<T_Type>( Width(), Height() ); }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /// @brief 2D当たり判定用。
  bool IsHit( T_Type x_, T_Type y_ ) const
  {
    return (x <= x_  &&  x_ <= z)  &&  (y <= y_  &&  y_ <= w);
  }

  // _____________________________________________________________________________
  /// @brief 矩形内補正
  /// 
  /// @param[in] in_p4 : 外矩形座標を指定する。
  /// @param[in] in_type_corner
  ///   : 角の優先度を指定する。\n
  ///   : 0 - 左上              \n
  ///   : 1 - 右上              \n
  ///   : 2 - 左下              \n
  ///   : 3 - 右下
  /// 
  /// @return なし。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T>
  void Revise( cref<Point4<T>> in_p4, _in<int> in_type_corner )
  {
    T sx = Width(), sy = Height();
    T x_ = in_p4.x, y_ = in_p4.y, z_ = in_p4.z - sx, w_ = in_p4.w - sy;
    x = (in_type_corner & 1)
      ? Min( Max( x, x_ ), z_ )  // 右優先
      : Max( Min( x, z_ ), x_ ); // 左優先
    y = ( in_type_corner & 2 )
      ? Min( Max( y, y_ ), w_ )  // 下優先
      : Max( Min( y, w_ ), y_ ); // 上優先
    z = x + sx;
    w = y + sy;
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 代入。
  template<class T> td_self& operator = ( const T& d )
  {
    this->zzf_copy( &d.get( Traits::NumComp<td_base::kELEMENTS_NUM-1,T::kELEMENTS_NUM-1>::min ) );
    return *this;
  }
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( +=, td_base::template zzf_add_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( -=, td_base::template zzf_sub_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( *=, td_base::template zzf_multiply_eq )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC_EQ( /=, td_base::template zzf_division_eq )

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, + )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, - )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, * )
  CPL_DEF_CORE_BASIC_VECTOR_POINT_ARITHMETIC( Point4, / )

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  operator T_Type*      ()       { return reinterpret_cast<T_Type*      >(this); }
  operator T_Type const*() const { return reinterpret_cast<T_Type const*>(this); }

  //// _____________________________________________________________________________
  //operator td_base&      ()       { return static_cast<td_base&>(*this); }
  //operator td_base const&() const { return static_cast<td_base const&>(*this); }

  //typedef Point4<T_Type>*        ptr;
  //typedef Point4<T_Type> const* cptr;
  //typedef Point4<T_Type>&        ref;
  //typedef Point4<T_Type> const& cref;
};



} // namespace Core


// 別名定義 ----------------------------
#define CPL_DEF_CORE_BASICVECTOR_POINT_N_SET_(N)\
typedef CPL::Core::Point##N<char>            char##N,  S8x##N;\
typedef CPL::Core::Point##N<short>           short##N, S16x##N;\
typedef CPL::Core::Point##N<int>             int##N,   S32x##N;\
typedef CPL::Core::Point##N<long>            long##N;\
typedef CPL::Core::Point##N<S64>             S64x##N;\
typedef CPL::Core::Point##N<unsigned char>   u_char##N,  U8x##N;\
typedef CPL::Core::Point##N<unsigned short>  u_short##N, U16x##N;\
typedef CPL::Core::Point##N<unsigned int>    u_int##N,   U32x##N;\
typedef CPL::Core::Point##N<unsigned long>   u_long##N;\
typedef CPL::Core::Point##N<U64>             U64x##N;\
typedef CPL::Core::Point##N<float>           float##N;\
typedef CPL::Core::Point##N<double>          double##N;\
typedef CPL::Core::Point##N<SDEF>            SDEF##N;\
typedef CPL::Core::Point##N<UDEF>            UDEF##N


CPL_DEF_CORE_BASICVECTOR_POINT_N_SET_(2);
CPL_DEF_CORE_BASICVECTOR_POINT_N_SET_(3);
CPL_DEF_CORE_BASICVECTOR_POINT_N_SET_(4);


#define CPL_TYPE_PTR_REF_VALUE_SET_N_(N)\
CPL_DEF_TYPE_PTR_REF1_(char##N);\
CPL_DEF_TYPE_PTR_REF1_(short##N);\
CPL_DEF_TYPE_PTR_REF1_(int##N);\
CPL_DEF_TYPE_PTR_REF1_(long##N);\
CPL_DEF_TYPE_PTR_REF1_(S64x##N);\
CPL_DEF_TYPE_PTR_REF1_(u_char##N);\
CPL_DEF_TYPE_PTR_REF1_(u_short##N);\
CPL_DEF_TYPE_PTR_REF1_(u_int##N);\
CPL_DEF_TYPE_PTR_REF1_(u_long##N);\
CPL_DEF_TYPE_PTR_REF1_(float##N);\
CPL_DEF_TYPE_PTR_REF1_(double##N);\
CPL_DEF_TYPE_PTR_REF1_(U64x##N);\
CPL_DEF_TYPE_PTR_REF1_(SDEF##N);\
CPL_DEF_TYPE_PTR_REF1_(UDEF##N)

CPL_TYPE_PTR_REF_VALUE_SET_N_(2);
CPL_TYPE_PTR_REF_VALUE_SET_N_(3);
CPL_TYPE_PTR_REF_VALUE_SET_N_(4);


//namespace sem {
//
//  CPL_DEF_ARG_SEMANTICS_T( Rect )
//
//}


} // namespace CPL
