Escolar Documentos
Profissional Documentos
Cultura Documentos
#i f n d e f vecteurT_hpp
#define vecteurT_hpp
// u t i l i t a i r e s
i n l i n e void s t o p ( const char ∗ msg ) // message d ’ a r r ê t
{ c o u t << "ERREUR␣ c l a s s e ␣ vecteurT , ␣ " << msg ; e x i t ( −1); }
i n l i n e void test_dim ( i n t d1 , i n t d2 , const char ∗ o r g ) // t e s t dimension
{
i f ( d1==d2 ) return ;
c o u t << o r g << " ␣ ( " << d1 << " , " << d2 << " ) ␣ d i m e n s i o n s ␣ i n c o m p a t i b l e s " ;
e x i t ( −1);
}
/∗−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
CLASSE GENERIQUE v e c t e u r <T>
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
− c o n s t r u c t e u r par d é f a u t , dimension e t v a l e u r e t par c o p i e
− a c c è s en l e c t u r e e t é c r i t u r e à un é l é m e n t
− i m p r e s s i o n du v e c t e u r
− somme e t d i f f é r e n c e de deux v e c t e u r s ( e x t e r n e s à l a c l a s s e )
− p r o d u i t par un s c a l a i r e ( e x t e r n e à l a c l a s s e )
− p r o d u i t s c a l a i r e e t norme e u c l i d i e n n e ( e x t e r n e à l a c l a s s e )
− o p é r a t e u r s : = s i m i l a i r e au c o n s t r u c t e u r par c o p i e
( i ) a c c è s au i ème é l é m e n t
+ − u n a i r e (U=−V)
+= −= ∗= /= d ’ un s c a l a i r e
+ − ∗ = un s c a l a i r e ( e x t e r n e )
+ − un v e c t e u r ( e x t e r n e )
== !=
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
template<typename T>
class vecteur
{
protected :
i n t dim_ ; // dimension du v e c t e u r
T ∗ val_ ; // t a b l e a u x de v a l e u r s
public :
v e c t e u r ( i n t d=0 , const T& v0=T ( ) ) ; // dim e t v a l c o n s t a n t e
v e c t e u r ( const v e c t e u r <T>& v ) ; // c o n s t r u c t e u r par c o p i e
~ vecteur ( ) ;
// t o o l s
void i n i t ( i n t d ) ; // a l l o c a t i o n
void c l e a r ( ) ; // d é s a l l o c a t i o n
// o p é r a t e u r d ’ a f f e c t a t i o n
v e c t e u r & operator=(const v e c t e u r <T>& v ) ; // a f f e c t a t i o n d ’ un v e c t e u r
v e c t e u r & operator=(const T& x ) ; // a f f e c t a t i o n d ’ une v a l e u r
// o p é r a t e u r s d ’ a c c è s
T operator ( ) ( i n t i ) const { return val_ [ i − 1 ] ; } // v a l e u r 1−>dim ( i n d i c e non t e s t é )
T& operator ( ) ( i n t i ) { return val_ [ i − 1 ] ; } // r é f é r e n c e 1−>dim ( i n d i c e non t e s t é )
i n t dim ( ) const { return dim_ ; } // a c c è s dimension
// o p é r a t e u r s a l g é b r i q u e s
v e c t e u r <T>& operator +=(const v e c t e u r <T>& v ) ; // u += v
v e c t e u r <T>& operator −=(const v e c t e u r <T>& v ) ; // u −= v
v e c t e u r <T>& operator +=(const T& x ) ; // u += x
v e c t e u r <T>& operator −=(const T& x ) ; // u −= x
v e c t e u r <T>& operator ∗=( const T& x ) ; // u ∗= x
v e c t e u r <T>& operator /=( const T& x ) ; // u /= x
} ; // f i n de d é f i n i t i o n de l a c l a s s e
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
2
// IMPLEMENTATION DES FONCTIONS MEMBRES
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// c o n s t r u c t e u r s −d e s t r u c t e u r
template<typename T>
v e c t e u r <T> : : v e c t e u r ( i n t d , const T& v0 ) //dim e t v a l c o n s t a n t e
{
i n i t (d ) ;
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]= v0 ;
}
template<typename T>
v e c t e u r <T> : : v e c t e u r ( const v e c t e u r <T>& v ) // c o n s t r u c t e u r par c o p i e
{
i n i t ( v . dim_ ) ;
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]=v . val_ [ i ] ;
}
template<typename T>
v e c t e u r <T> : : ~ v e c t e u r ( )
{ clear (); }
template<typename T>
void v e c t e u r <T> : : i n i t ( i n t d ) // i n i t i a l i s a t i o n a v e c a l l o c a t i o n dynamique
{
i f ( d<0) s t o p ( " i n i t ( ) ␣ : ␣ d i m e n s i o n ␣<0" ) ;
dim_=d ;
val_ =0;
i f ( d>0) val_ = new T [ d ] ;
}
template<typename T>
void v e c t e u r <T> : : c l e a r ( ) // d é s a l l o c a t i o n
{
i f ( val_ !=0) delete [ ] val_ ;
dim_=0;
}
// a f f e c t a t i o n
template<typename T>
v e c t e u r <T> & v e c t e u r <T> : : operator=(const v e c t e u r <T>& v ) // a f f e c t a t i o n d ’ un v e c t e u r <T>
{
i f ( dim_!=v . dim_ ) // redimensionnement
{
clear ();
i n i t ( v . dim_ ) ;
}
// r e c o p i e
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]=v . val_ [ i ] ;
return ∗ t h i s ;
}
template<typename T>
v e c t e u r <T> & v e c t e u r <T> : : operator=(const T& x ) // a f f e c t a t i o n d ’ une v a l e u r
{
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]=x ;
return ∗ t h i s ;
}
// o p é r a t e u r s a l g é b r i q u e s
template<typename T>
v e c t e u r <T>& v e c t e u r <T> : : operator +=(const v e c t e u r <T>& v )
{
test_dim ( dim_ , v . dim_ , " op ␣+=" ) ;
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]+=v . val_ [ i ] ;
return ∗ t h i s ;
}
template<typename T>
v e c t e u r <T>& v e c t e u r <T> : : operator −=(const v e c t e u r <T>& v )
{
test_dim ( dim_ , v . dim_ , " op ␣−=" ) ;
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]−=v . val_ [ i ] ;
return ∗ t h i s ;
}
template<typename T>
v e c t e u r <T>& v e c t e u r <T> : : operator +=(const T& x )
{
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]+=x ;
return ∗ t h i s ;
}
template<typename T>
v e c t e u r <T>& v e c t e u r <T> : : operator −=(const T& x )
3
{
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]−=x ;
return ∗ t h i s ;
}
template<typename T>
v e c t e u r <T>& v e c t e u r <T> : : operator ∗=( const T& x )
{
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]∗= x ;
return ∗ t h i s ;
}
template<typename T>
v e c t e u r <T>& v e c t e u r <T> : : operator /=( const T& x )
{
i f ( x==T ( ) ) s t o p ( " op ␣/=␣ : ␣ d i v i s i o n ␣ par ␣ 0 " ) ;
f o r ( i n t i =0; i <dim_ ; i ++) val_ [ i ]/= x ;
return ∗ t h i s ;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// DEFINITION ET IMPLEMENTATION DES FONCTIONS/OPERATEURS EXTERNES
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// o p é r a t e u r s e x t e r n e s
template<typename T> v e c t e u r <T> operator+(const v e c t e u r <T>& u ) // +u
{ return u ; }
template<typename T> v e c t e u r <T> operator −(const v e c t e u r <T>& u ) // −u
{ v e c t e u r <T> w=u ; return w∗= −1.; }
template<typename T> v e c t e u r <T> operator+(const v e c t e u r <T>& u , const v e c t e u r <T>& v ) // u+v
{ v e c t e u r <T> w=u ; return w+=v ; }
template<typename T> v e c t e u r <T> operator −(const v e c t e u r <T>& u , const v e c t e u r <T>& v ) // u−v
{ v e c t e u r <T> w=u ; return w−=v ; }
template<typename T> v e c t e u r <T> operator+(const v e c t e u r <T>& u , const T& x ) // u+x
{ v e c t e u r <T> w=u ; return w+=x ; }
template<typename T> v e c t e u r <T> operator −(const v e c t e u r <T>& u , const T& x ) // u−x
{ v e c t e u r <T> w=u ; return w−=x ; }
template<typename T> v e c t e u r <T> operator ∗ ( const v e c t e u r <T>& u , const T& x ) // u∗ x
{ v e c t e u r <T> w=u ; return w∗=x ; }
template<typename T> v e c t e u r <T> operator / ( const v e c t e u r <T>& u , const T& x ) // u/ x
{ v e c t e u r <T> w=u ; return w/=x ; }
template<typename T> v e c t e u r <T> operator+(const T& x , const v e c t e u r <T>& u ) // x+u
{ v e c t e u r <T> w=u ; return w+=x ; }
template<typename T> v e c t e u r <T> operator −(const T& x , const v e c t e u r <T>& u ) // x−u
{ v e c t e u r <T> w=−u ; return w−=x ; }
template<typename T> v e c t e u r <T> operator ∗ ( const T& x , const v e c t e u r <T>& u ) // x ∗u
{ v e c t e u r <T> w=u ; return w∗=x ; }
template<typename T> T operator | ( const v e c t e u r <T>& u , const v e c t e u r <T>& v ) // u | v
{
test_dim ( u . dim ( ) , v . dim ( ) , " op ␣ | " ) ;
T s =0;
f o r ( i n t i =1; i <=u . dim ( ) ; i ++) s+=u ( i ) ∗ v ( i ) ;
return s ;
}
template<typename T>
T norme ( const v e c t e u r <T>& u ) // s q r t ( u | u )
{ return s q r t ( u | u ) ; }
// o p é r a t e u r s de comparaison
template<typename T>
bool operator==(const v e c t e u r <T>& u , const v e c t e u r <T>& v )
{
i f ( u . dim ( ) ! = v . dim ( ) ) return f a l s e ;
f o r ( i n t i =1; i <=u . dim ( ) ; i ++)
i f ( u ( i )!= v ( i ) ) return f a l s e ;
return true ;
}
template<typename T>
bool operator !=( const v e c t e u r <T>& u , const v e c t e u r <T>& v )
{ return ! ( u==v ) ; }
// o p é r a t e u r de f l u x
template<typename T>
ostr ea m & operator<<(os tr ea m& os , const v e c t e u r <T>& u )
{
i f ( u . dim()<=0) { o s << " ( ) " ; return o s ; }
o s << " ( " ;
f o r ( i n t i =1; i <u . dim ( ) ; i ++) o s << u ( i ) << " , " ;
o s << u ( u . dim ( ) ) << " ) " ;
return o s ;
4
}
using namespace s t d ;
typedef complex<double> complexe ; // a l i a s
i n t main ( )
{
// t e s t a v e c d e s d o u b l e
//=====================
c o u t << " Test ␣ en ␣ r e e l \n " ;
// t e s t d e s c o n s t r u c t e u r s
v e c t e u r <double> V1 ;
v e c t e u r <double> V2 ( 3 ) ;
v e c t e u r <double> V3 ( 3 , 1 ) ;
v e c t e u r <double> V4(V3 ) ;
// t e s t i m p r e s s i o n
c o u t << "V1␣ : ␣ " << V1 << e n d l ;
c o u t << "V2␣ : ␣ " << V2 << e n d l ;
c o u t << "V3␣ : ␣ " << V3 << e n d l ;
c o u t << "V4␣ : ␣ " << V4 << e n d l ;
// t e s t a c c è s
V2 ( 1 ) = 1 . ; V2 ( 2 ) = 2 . ; V2 ( 3 ) = 3 . ;
c o u t << " a c c e s ␣ : ␣V2␣ : ␣ " << V2 << e n d l ;
v e c t e u r <double> V5 ;
V5=V2 ;
c o u t << "V5=V2␣ : ␣ " << V5 << e n d l ;
// t e s t de l a somme e t d i f f é r e n c e , p r o d u i t
v e c t e u r <double> V6 , V7 , V8 ;
V6=V2+V3 ;
c o u t << " somme␣V6=V2+V3␣ : ␣ " << V6 << e n d l ;
V7=V2−V3 ;
c o u t << " d i f f e r e n c e ␣V7=V2−V3␣ : ␣ " << V7 << e n d l ;
V8=V2 ∗ 5 . ;
c o u t << " p r o d u i t ␣V8=V2∗5 ␣ : ␣ " << V8 << e n d l ;
V8=5.∗V2 ;
c o u t << " p r o d u i t ␣V8=5∗V2␣ : ␣ " << V8 << e n d l ;
v e c t e u r <double> V9=3.∗V8+(2.∗V6−V5 ) / 2 . ;
c o u t << " c o m b i n a i s o n ␣V9=3.∗V8+(2.∗V6−V5 ) / 2 . ␣ : ␣ " << V9 << e n d l ;
V9=−V9 ;
c o u t << " oppose ␣V9=−V9␣ : ␣ " << V9 << e n d l ;
c o u t << "V2 | V3=" << (V2 | V3) << e n d l ;
c o u t << " norme (V2)= " << norme (V2) << e n d l ;
// t e s t a v e c d e s c o m p l e x e s
//=======================
c o u t << " \ nTest ␣ en ␣ complexe \n " ;
complexe i ( 0 . , 1 . ) ;
v e c t e u r <complexe> Z1 ( 3 , i ) ; c o u t << " v e c t e u r ␣Z1␣ : ␣ " << Z1 << e n d l ;
v e c t e u r <complexe> Z2 ( 3 , 1 ) ; c o u t << " v e c t e u r ␣Z2␣ : ␣ " << Z2 << e n d l ;
v e c t e u r <complexe> Z3 ( 3 ) ;
f o r ( i n t j =1; j <=3; j ++) Z3 ( j )= complexe ( j ) ;
c o u t << " v e c t e u r ␣Z3␣ : ␣ " << Z3 << e n d l ;
v e c t e u r <complexe> Z=Z1+Z2−Z3 ; c o u t << " v e c t e u r ␣Z=Z1+Z2−Z3␣ : ␣ " << Z << e n d l ;
Z=i ∗Z1−Z2∗ i ; c o u t << " v e c t e u r ␣Z=i ∗Z1−i ∗Z2␣ : ␣ " << Z << e n d l ;
c o u t << " ( Z1 | Z2)= " << ( Z1 | Z2 ) << e n d l ;
c o u t << " norme ( Z1)= " << norme ( Z1 ) << e n d l ;
return 0 ;
}
//============================= F I N ===================================
Résultats
Test en reel
V1 : ()
V2 : (0,0,0)
V3 : (1,1,1)
V4 : (1,1,1)
acces : V2 : (1,2,3)
5
V5=V2 : (1,2,3)
somme V6=V2+V3 : (2,3,4)
difference V7=V2-V3 : (0,1,2)
produit V8=V2*5 : (5,10,15)
produit V8=5*V2 : (5,10,15)
combinaison V9=3.*V8+(2.*V6-V5)/2. : (16.5,32,47.5)
oppose V9=-V9 : (-16.5,-32,-47.5)
V2|V3=6
norme(V2)=3.74166
Test en complexe
vecteur Z1 : ((0,1),(0,1),(0,1))
vecteur Z2 : ((1,0),(1,0),(1,0))
vecteur Z3 : ((1,0),(2,0),(3,0))
vecteur Z=Z1+Z2-Z3 : ((0,1),(-1,1),(-2,1))
vecteur Z=i*Z1-i*Z2 : ((-1,-1),(-1,-1),(-1,-1))
(Z1|Z2)=(0,3)
norme(Z1)=(0,1.73205)
Noter que le compilateur choisi toujours la version générique la mieux adaptée et donc ici l’opérateur | sur
des objets vecteur<complex<T> >.
6
// o p e r a t e u r s d ’ a c c e s
T operator ( ) ( i n t i ) const { return val_ [ i − 1 ] ; } // v a l e u r 1−>dim ( i n d i c e non t es t é )
T& operator ( ) ( i n t i ) { return val_ [ i − 1 ] ; } // référence 1−>dim ( i n d i c e non t es t é )
i n t dim ( ) const { return dim_ ; } // accès dimension
// o p e r a t e u r s a l g e b r i q u e s
template<typename C> v e c t e u r <T>& operator +=(const v e c t e u r <T>& v ) ; // u += v<C>
template<typename C> v e c t e u r <T>& operator −=(const v e c t e u r <T>& v ) ; // u −= v<C>
template<typename C> v e c t e u r <T>& operator +=(const T& x ) ; // u += c
template<typename C> v e c t e u r <T>& operator −=(const T& x ) ; // u −= c
template<typename C> v e c t e u r <T>& operator ∗=( const T& x ) ; // u ∗= c
template<typename C> v e c t e u r <T>& operator /=( const T& x ) ; // u /= c
};
Noter la syntaxe qui permet à une fonction membre de prendre un type d’argument différent :
template<typename C> v e c t e u r <T>& operator +=(const v e c t e u r <C>& v )
le premier template faisant référence à celui de la classe et le second à celui de la fonction membre.
Attention, cette approche suppose que la conversion du type C en type T soit permise. Ce qui est le cas pour
un double vers un complex<double> mais pas le cas complex<double> vers double. Par conséquent, il y
aura une erreur de compilation dès que cette fonction sera instanciée avec T=double et C=complex<double>,
par exemple avec les instructions suivantes dans le main :
Cette erreur de compilation est positive car elle prévient d’une utilisation abusive de type. Cependant, dans
certains cas, il peut y avoir une instanciation de ce type à la compilation même si de telles instructions
n’apparaissent pas et dans ce cas il y a une erreur de compilation qu’il y a moyen d’éviter en contrôlant
soi-même ces transtypages. Il suffit de produire les spécialisations pouvant poser problème. Ainsi on pourra
ajouter dans l’implémentation la spécialisation :
template <>
v e c t e u r <double>& v e c t e u r <double > : : operator +=(const complex<double>& z )
{ cout<<" v e c t e u r : : + = : t r a n s t y p a g e ␣ i n c o r r e c t ␣ de ␣ comple xe ␣ en ␣ r ï ¿ ½ e l " ; e x i t ( 1 ) ; }
On notera la syntaxe particulière template<> indiquant qu’il y a une spécialisation totale de la fonction.
7
T& operator ( ) ( i n t i , i n t j )
{ return this−>val_ [ ( i −1)∗d+j − 1 ] ; }
const T& operator ( ) ( i n t i , i n t j ) const
{ return this−>val_ [ ( i −1)∗d+j − 1 ] ; }
m a t r i c e <T>& operator+=(const m a t r i c e <T>& M) ;
m a t r i c e <T>& operator−=(const m a t r i c e <T>& M) ;
m a t r i c e <T>& operator∗=( const T& s ) ;
m a t r i c e <T>& operator/=( const T& s ) ;
};
// o p e r a t i o n s a l g é b r i q u e s i n t e r n e s
template<typename T> m a t r i c e <T>& m a t r i c e <T> : : operator+=(const m a t r i c e <T>& M)
{
test_dim ( d , M. d , " o p e r a t o r ␣+=" ) ;
v e c t e u r <T>& v=static_cast<v e c t e u r <T>&>(∗t h i s ) ;
const v e c t e u r <T>& vM=static_cast<const v e c t e u r <T>&>(M) ;
v+=vM;
return ∗ t h i s ;
}
template<typename T> m a t r i c e <T>& m a t r i c e <T> : : operator−=(const m a t r i c e <T>& M)
{
test_dim ( d , M. d , " o p e r a t o r ␣−=" )
v e c t e u r <T>& v=static_cast<v e c t e u r <T>&>(∗t h i s ) ;
const v e c t e u r <T>& vM=static_cast<const v e c t e u r <T>&>(M) ;
v−=vM;
return ∗ t h i s ;
}
template<typename T> m a t r i c e <T>& m a t r i c e <T> : : operator∗=( const T& s )
{
v e c t e u r <T>& v=static_cast<v e c t e u r <T>&>(∗t h i s ) ;
v∗=s ;
return ∗ t h i s ;
}
template<typename T> m a t r i c e <T>& m a t r i c e <T> : : operator/=( const T& s )
{
i f ( s==0) s t o p ( " o p e r a t o r ␣/=␣ : ␣ d i v i s i o n ␣ par ␣ 0 " ) ;
v e c t e u r <T>& v=static_cast<v e c t e u r <T>&>(∗t h i s ) ;
v/=s ;
return ∗ t h i s ;
}
// o p e r a t i o n s a l g é b r i q u e s e x t e r n e s
template<typename T> m a t r i c e <T> operator+(const m a t r i c e <T>& M)
{ return M; }
template<typename T> m a t r i c e <T> operator −(const m a t r i c e <T>& M)
{ m a t r i c e <T> R=M; return R∗=−1; }
template<typename T> m a t r i c e <T> operator+(const m a t r i c e <T>& M1, const m a t r i c e <T>& M2)
{ m a t r i c e <T> R=M1; return R+=M2; }
template<typename T> m a t r i c e <T> operator −(const m a t r i c e <T>& M1, const m a t r i c e <T>& M2)
{ m a t r i c e <T> R=M1; return R−=M2; }
template<typename T> m a t r i c e <T> operator ∗ ( const m a t r i c e <T>& M, const T& s )
{ m a t r i c e <T> R=M; return R∗=s ; }
template<typename T> m a t r i c e <T> operator ∗ ( const T& s , const m a t r i c e <T>& M)
{ m a t r i c e <T> R=M; return R∗=s ; }
template<typename T> m a t r i c e <T> operator / ( const m a t r i c e <T>& M, const T& s )
{ m a t r i c e <T> R=M; return R/=s ; }
// p r o d u i t m a t r i c e −v e c t e u r
template<typename T>
v e c t e u r <T> operator ∗ ( const m a t r i c e <T>& M, const v e c t e u r <T>& u )
{
i n t d=M. d ;
test_dim ( d , u . dim ( ) , " p r o d u i t ␣ m a t r i c e −v e c t e u r " ) ;
v e c t e u r <T> Mu( d ) ;
f o r ( i n t i =1; i <=d ; i ++)
f o r ( i n t j =1; j<=d ; j ++) Mu( i )+=M( i , j ) ∗ u ( j ) ;
return Mu;
}
// o p é r a t e u r de f l u x
template<typename T>
ostr ea m & operator<<(os tr ea m& os , const m a t r i c e <T>& M)
{
i f (M. d<=0) { o s << " [ ] " ; return o s ; }
f o r ( i n t i =1; i <=M. d ; i ++)
{
o s << " | " ;
f o r ( i n t j =1; j <M. d ; j ++) o s << M( i , j ) << " ␣ " ;
o s << M( i ,M. d ) << " | " << e n d l ;
8
}
return o s ;
}
#endif
Affichage du résultat :
Test matrice
M =
|11 12 13|
|21 22 23|
|31 32 33|
M+M =
|22 24 26|
|42 44 46|
|62 64 66|
M-M =
|0 0 0|
|0 0 0|
|0 0 0|
2*M =
|22 24 26|
|42 44 46|
|62 64 66|
M/2 =
|5.5 6 6.5|
|10.5 11 11.5|
|15.5 16 16.5|
M*V2 = (74,134,194)