Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
b1d56ec1
Commit
b1d56ec1
authored
Sep 20, 2011
by
Vladimir Ur
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Just a new draft of length units
parent
726d772c
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
243 additions
and
153 deletions
+243
-153
length.h
include/length.h
+243
-153
No files found.
include/length.h
View file @
b1d56ec1
...
@@ -3,140 +3,215 @@
...
@@ -3,140 +3,215 @@
* @file length.h
* @file length.h
*/
*/
/* sorry it is not style
s
correctly, i'll work on it further */
/* sorry it is not style
d
correctly, i'll work on it further */
#ifndef LENGTH_H_INCLUDED
#ifndef LENGTH_H_INCLUDED
#define LENGTH_H_INCLUDED 1
#define LENGTH_H_INCLUDED 1
/* type to be used by length units by default */
typedef
int
DEF_LENGTH_VALUE
;
typedef
int
DEF_LENGTH_VALUE
;
template
<
typename
T
=
DEF_LENGTH_VALUE
,
int
P
=
1
>
class
LENGTH
;
/**
* Length template class
* @param T actual type holding a value (be aware of precision and range!)
* @param P power of length unit: 1 - length, 2 - area, 3 - volume, -1 - lin. density etc...
* This class check length dimension in compile time. In runtime it behaves
* exactly like contained type t (which should be numeric type, like int or double)
* This class can be replaced with its contained type or simple stub.
* Check rules:
* - comparisons (< = etc.), addition, subtraction require values of same dimension
* e. g. length with length, area with area etc.
* - multiplication and division result have appropriate dimension (powers
* added and subtracted respectively)
* - sqrt and cbrt have appropriate dimensions (P/2 and P/3).
* Limitations:
* - functions which should not be applied to dimensioned values are not implemeted:
* they include algebraic (exp, log...), trigo (sin, cos...), hyperbolic (sinh, cosh..)
* - pow function is not implemented as it is require dimension check in runtime
* you should use multiplication, division, sqrt and cbrt functions instead.
* - sqrt and cbrt result type should be instantiated before they used
* Be aware when using them in complex formulae, e. g.
* LENGTH< double, 1 > len = cbrt(vol) - is ok, but
* LENGTH< double, 2 > vol = sqrt(area*area*area*area)/length - will fail
* if LENGTH<..., 4> is not instantiated
* - non-integer power values do not supported
* they should be implemented carefully using natural fractions, not floats, to be exact
* but they are very rare so you should not worry about.
* e. g. linear electric noise density should be in mV/sqrt(m)
* - automatic numeric type casts are not performed. You even have to manually
* cast LENGTH< short > to LENGTH< int > or LENGTH< float >
* to LENGTH< double >. Anyway it is not such trouble as progremmer should be
* very careful when mixing numeric types and avoid automatic casts.
*
*/
template
<
typename
T
=
DEF_LENGTH_VALUE
,
int
P
=
1
>
class
LENGTH
;
/**
* Length units contained in this class
*/
template
<
typename
T
>
class
LENGTH_UNITS
;
template
<
typename
T
>
class
LENGTH_UNITS
;
template
<
typename
T
,
int
P
>
struct
LENGTH_TRAITS
{
/**
* For internal needs
*/
template
<
typename
T
,
int
P
>
struct
LENGTH_TRAITS
{
typedef
LENGTH
<
T
,
P
>
flat
;
typedef
LENGTH
<
T
,
P
>
flat
;
};
};
template
<
typename
T
>
struct
LENGTH_TRAITS
<
T
,
0
>
{
template
<
typename
T
>
struct
LENGTH_TRAITS
<
T
,
0
>
{
/* length dimension to power 0 is just a number, so LENGTH<T, 0> should be automatically converted to T */
typedef
T
flat
;
typedef
T
flat
;
};
};
template
<
typename
T
,
int
P
>
class
LENGTH
{
template
<
typename
T
,
int
P
>
class
LENGTH
friend
class
LENGTH_UNITS
<
T
>
;
{
friend
class
LENGTH_TRAITS
<
T
,
P
>
;
friend
class
LENGTH_UNITS
<
T
>
;
template
<
typename
Y
,
int
R
>
friend
class
LENGTH
;
friend
class
LENGTH_TRAITS
<
T
,
P
>
;
template
<
typename
Y
,
int
R
>
friend
class
LENGTH
;
protected
:
protected
:
T
m_U
;
T
m_U
;
LENGTH
(
T
units
)
:
m_U
(
units
)
{
LENGTH
(
T
units
)
:
m_U
(
units
)
{
}
}
static
T
RawValue
(
const
LENGTH
<
T
,
P
>
&
x
)
{
static
T
RawValue
(
const
LENGTH
<
T
,
P
>
&
x
)
{
return
x
.
m_U
;
return
x
.
m_U
;
}
}
static
T
RawValue
(
const
T
&
x
)
{
static
T
RawValue
(
const
T
&
x
)
{
return
x
;
return
x
;
}
}
public
:
public
:
typedef
LENGTH
<
T
,
P
>
flat
;
typedef
T
value_type
;
typedef
T
value_type
;
enum
{
enum
{
dimension
=
P
dimension
=
P
};
};
LENGTH
(
const
LENGTH
<
T
,
P
>
&
orig
)
:
m_U
(
orig
.
m_U
)
{
LENGTH
(
const
LENGTH
<
T
,
P
>
&
orig
)
:
m_U
(
orig
.
m_U
)
{
}
}
LENGTH
(
void
)
:
m_U
()
{
LENGTH
(
void
)
:
m_U
()
{
}
}
static
LENGTH
<
T
,
P
>
zero
(
void
)
{
static
LENGTH
<
T
,
P
>
zero
(
void
)
{
return
T
(
0
);
return
T
(
0
);
}
}
LENGTH
<
T
,
P
>
&
operator
=
(
const
LENGTH
<
T
,
P
>
&
y
)
{
LENGTH
<
T
,
P
>
&
operator
=
(
const
LENGTH
<
T
,
P
>
&
y
)
{
this
->
m_U
=
y
.
m_U
;
this
->
m_U
=
y
.
m_U
;
return
*
this
;
return
*
this
;
}
}
template
<
typename
Y
>
template
<
typename
Y
>
operator
LENGTH
<
Y
,
P
>
(
void
)
operator
LENGTH
<
Y
,
P
>
(
void
)
{
{
return
this
->
m_U
;
return
this
->
m_U
;
}
}
/*************************/
/*************************/
/* comparisons and tests */
/* comparisons and tests */
/*************************/
/*************************/
bool
operator
==
(
const
LENGTH
<
T
,
P
>
y
)
const
{
bool
operator
==
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
==
y
.
m_U
;
return
m_U
==
y
.
m_U
;
}
}
bool
operator
!=
(
const
LENGTH
<
T
,
P
>
y
)
const
{
bool
operator
!=
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
!=
y
.
m_U
;
return
m_U
!=
y
.
m_U
;
}
}
bool
operator
<
(
const
LENGTH
<
T
,
P
>
y
)
const
{
bool
operator
<
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
<
y
.
m_U
;
return
m_U
<
y
.
m_U
;
}
}
bool
operator
>=
(
const
LENGTH
<
T
,
P
>
y
)
const
{
bool
operator
>=
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
>=
y
.
m_U
;
return
m_U
>=
y
.
m_U
;
}
}
bool
operator
>
(
const
LENGTH
<
T
,
P
>
y
)
const
{
bool
operator
>
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
>
y
.
m_U
;
return
m_U
>
y
.
m_U
;
}
}
bool
operator
<=
(
const
LENGTH
<
T
,
P
>
y
)
const
{
bool
operator
<=
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
<=
y
.
m_U
;
return
m_U
<=
y
.
m_U
;
}
}
bool
operator
!
(
void
)
const
{
bool
operator
!
(
void
)
const
{
return
!
m_U
;
return
!
m_U
;
}
}
/*************************/
/*************************/
/* basic arithmetic */
/* basic arithmetic */
/*************************/
/*************************/
LENGTH
<
T
,
P
>
operator
-
(
void
)
const
{
LENGTH
<
T
,
P
>
operator
-
(
void
)
const
{
return
LENGTH
<
T
,
P
>
(
-
this
->
m_U
);
return
LENGTH
<
T
,
P
>
(
-
this
->
m_U
);
}
}
LENGTH
<
T
,
P
>
operator
-
(
const
LENGTH
<
T
,
P
>
y
)
const
{
LENGTH
<
T
,
P
>
operator
-
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
-
y
.
m_U
;
return
m_U
-
y
.
m_U
;
}
}
LENGTH
<
T
,
P
>
operator
+
(
const
LENGTH
<
T
,
P
>
y
)
const
{
LENGTH
<
T
,
P
>
operator
+
(
const
LENGTH
<
T
,
P
>
y
)
const
{
return
m_U
+
y
.
m_U
;
return
m_U
+
y
.
m_U
;
}
}
template
<
int
R
>
template
<
int
R
>
typename
LENGTH_TRAITS
<
T
,
P
+
R
>::
flat
operator
*
(
const
LENGTH
<
T
,
R
>
&
y
)
const
{
typename
LENGTH_TRAITS
<
T
,
P
+
R
>::
flat
operator
*
(
const
LENGTH
<
T
,
R
>
&
y
)
const
{
return
m_U
*
y
.
m_U
;
return
m_U
*
y
.
m_U
;
}
}
LENGTH
<
T
,
P
>
operator
*
(
const
T
&
y
)
const
{
LENGTH
<
T
,
P
>
operator
*
(
const
T
&
y
)
const
{
return
m_U
*
y
;
return
m_U
*
y
;
}
}
LENGTH
<
T
,
P
>
friend
operator
*
(
const
T
&
y
,
const
LENGTH
<
T
,
P
>
&
x
)
{
LENGTH
<
T
,
P
>
friend
operator
*
(
const
T
&
y
,
const
LENGTH
<
T
,
P
>
&
x
)
{
return
x
.
m_U
*
y
;
return
x
.
m_U
*
y
;
}
}
template
<
int
R
>
template
<
int
R
>
typename
LENGTH_TRAITS
<
T
,
P
-
R
>::
flat
operator
/
(
const
LENGTH
<
T
,
R
>
&
y
)
const
{
typename
LENGTH_TRAITS
<
T
,
P
-
R
>::
flat
operator
/
(
const
LENGTH
<
T
,
R
>
&
y
)
const
{
return
m_U
/
y
.
m_U
;
return
m_U
/
y
.
m_U
;
}
}
LENGTH
<
T
,
P
>
operator
/
(
const
T
&
y
)
const
{
LENGTH
<
T
,
P
>
operator
/
(
const
T
&
y
)
const
{
return
m_U
/
y
;
return
m_U
/
y
;
}
}
LENGTH
<
T
,
-
P
>
friend
operator
/
(
const
T
&
y
,
const
LENGTH
<
T
,
P
>
&
x
)
{
LENGTH
<
T
,
-
P
>
friend
operator
/
(
const
T
&
y
,
const
LENGTH
<
T
,
P
>
&
x
)
{
return
y
/
x
.
m_U
;
return
y
/
x
.
m_U
;
}
}
friend
LENGTH
<
T
,
P
>
sqrt
(
LENGTH
<
T
,
P
*
2
>
y
)
{
friend
LENGTH
<
T
,
P
>
sqrt
(
LENGTH
<
T
,
P
*
2
>
y
)
return
sqrt
(
y
.
m_U
);
{
return
sqrt
(
y
.
m_U
);
}
}
friend
LENGTH
<
T
,
P
>
cbrt
(
LENGTH
<
T
,
P
*
3
>
y
)
{
friend
LENGTH
<
T
,
P
>
cbrt
(
LENGTH
<
T
,
P
*
3
>
y
)
return
cbrt
(
y
.
m_U
);
{
return
cbrt
(
y
.
m_U
);
}
}
/*************************/
/*************************/
/* assignment arithmetic */
/* assignment arithmetic */
/*************************/
/*************************/
LENGTH
<
T
,
P
>&
operator
-=
(
const
LENGTH
<
T
,
P
>
y
)
{
LENGTH
<
T
,
P
>&
operator
-=
(
const
LENGTH
<
T
,
P
>
y
)
{
return
m_U
-=
y
.
m_U
;
return
m_U
-=
y
.
m_U
;
}
}
LENGTH
<
T
,
P
>&
operator
+=
(
const
LENGTH
<
T
,
P
>
y
)
{
LENGTH
<
T
,
P
>&
operator
+=
(
const
LENGTH
<
T
,
P
>
y
)
{
return
m_U
+=
y
.
m_U
;
return
m_U
+=
y
.
m_U
;
}
}
LENGTH
<
T
,
P
>&
operator
*=
(
const
T
y
)
{
LENGTH
<
T
,
P
>&
operator
*=
(
const
T
y
)
{
return
m_U
*=
y
;
return
m_U
*=
y
;
}
}
LENGTH
<
T
,
P
>&
operator
/=
(
const
T
y
)
{
LENGTH
<
T
,
P
>&
operator
/=
(
const
T
y
)
{
return
m_U
/=
y
;
return
m_U
/=
y
;
}
}
/*************************/
/*************************/
...
@@ -144,7 +219,21 @@ public:
...
@@ -144,7 +219,21 @@ public:
/*************************/
/*************************/
};
};
template
<
typename
T
=
DEF_LENGTH_VALUE
>
class
LENGTH_UNITS
{
/**
* Units of length
*
* How to use them:
* there are several functions, named LENGTH_UNITS< T >::METRE, which return
* named unit (1 meter in example) which have type LENGTH< T, P >.
* to get specific length you should use a multiplication:
* 3*LENGTH_UNITS::metre() gives 3 metres
* 0.01*LENGTH_UNITS::metre() gives 0.01 inch
* to get numeric value of length in specific units you should use a division
* length/LENGTH_UNITS::metre() gives number of metres in length
* legnth/LENGTH_UNITS::foot() gives number of feet in length
*/
template
<
typename
T
=
DEF_LENGTH_VALUE
>
class
LENGTH_UNITS
{
protected
:
protected
:
enum
enum
{
{
...
@@ -153,36 +242,37 @@ protected:
...
@@ -153,36 +242,37 @@ protected:
INCH
=
METRE
/
10000
*
254
INCH
=
METRE
/
10000
*
254
};
};
public
:
public
:
static
LENGTH
<
T
,
1
>
metre
(
void
)
{
static
LENGTH
<
T
,
1
>
metre
(
void
)
{
return
T
(
METRE
);
return
T
(
METRE
);
}
}
static
LENGTH
<
T
,
1
>
decimetre
(
void
)
{
static
LENGTH
<
T
,
1
>
decimetre
(
void
)
{
return
T
(
METRE
/
10
);
return
T
(
METRE
/
10
);
}
}
static
LENGTH
<
T
,
1
>
centimetre
(
void
)
{
static
LENGTH
<
T
,
1
>
centimetre
(
void
)
{
return
T
(
METRE
/
100
);
return
T
(
METRE
/
100
);
}
}
static
LENGTH
<
T
,
1
>
millimetre
(
void
)
{
static
LENGTH
<
T
,
1
>
millimetre
(
void
)
{
return
T
(
METRE
/
1000
);
return
T
(
METRE
/
1000
);
}
}
static
LENGTH
<
T
,
1
>
micrometre
(
void
)
{
static
LENGTH
<
T
,
1
>
micrometre
(
void
)
{
return
T
(
METRE
/
1000000
);
return
T
(
METRE
/
1000000
);
}
}
static
LENGTH
<
T
,
1
>
foot
(
void
)
{
/* do not think this will ever need */
static
LENGTH
<
T
,
1
>
foot
(
void
)
{
/* do not think this will ever need */
return
T
(
INCH
*
12
);
return
T
(
INCH
*
12
);
}
}
static
LENGTH
<
T
,
1
>
inch
(
void
)
{
static
LENGTH
<
T
,
1
>
inch
(
void
)
{
return
T
(
INCH
);
return
T
(
INCH
);
}
}
static
LENGTH
<
T
,
1
>
mil
(
void
)
{
static
LENGTH
<
T
,
1
>
mil
(
void
)
{
return
T
(
INCH
/
1000
);
return
T
(
INCH
/
1000
);
}
}
};
};
/* shortcut */
/**
template
<
typename
T
,
int
D
>
class
LENGTH_UNITS
<
LENGTH
<
T
,
D
>
>:
public
LENGTH_UNITS
<
T
>
{
* shortcut to get units of given length type
*/
template
<
typename
T
,
int
D
>
class
LENGTH_UNITS
<
LENGTH
<
T
,
D
>
>:
public
LENGTH_UNITS
<
T
>
{
};
};
/* TODO: argument promotion (but is this need? explicit casts would be enough) */
#endif
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment