You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
7.7 KiB

  1. /**
  2. * The physical length library. Made for nanometer scale.
  3. * @file length.h
  4. */
  5. /* sorry it is not styled correctly, i'll work on it further */
  6. #ifndef LENGTH_H_INCLUDED
  7. #define LENGTH_H_INCLUDED 1
  8. /* type to be used by length units by default */
  9. typedef int DEF_LENGTH_VALUE;
  10. /**
  11. * Length template class
  12. * @param T actual type holding a value (be aware of precision and range!)
  13. * @param P power of length unit: 1 - length, 2 - area, 3 - volume, -1 - lin. density etc...
  14. * This class check length dimension in compile time. In runtime it behaves
  15. * exactly like contained type t (which should be numeric type, like int or double)
  16. * This class can be replaced with its contained type or simple stub.
  17. * Check rules:
  18. * - comparisons (< = etc.), addition, subtraction require values of same dimension
  19. * e. g. length with length, area with area etc.
  20. * - multiplication and division result have appropriate dimension (powers
  21. * added and subtracted respectively)
  22. * - sqrt and cbrt have appropriate dimensions (P/2 and P/3).
  23. * Limitations:
  24. * - functions which should not be applied to dimensioned values are not implemeted:
  25. * they include algebraic (exp, log...), trigo (sin, cos...), hyperbolic (sinh, cosh..)
  26. * - pow function is not implemented as it is require dimension check in runtime
  27. * you should use multiplication, division, sqrt and cbrt functions instead.
  28. * - sqrt and cbrt result type should be instantiated before they used
  29. * Be aware when using them in complex formulae, e. g.
  30. * LENGTH< double, 1 > len = cbrt(vol) - is ok, but
  31. * LENGTH< double, 2 > vol = sqrt(area*area*area*area)/length - will fail
  32. * if LENGTH<..., 4> is not instantiated
  33. * - non-integer power values do not supported
  34. * they should be implemented carefully using natural fractions, not floats, to be exact
  35. * but they are very rare so you should not worry about.
  36. * e. g. linear electric noise density should be in mV/sqrt(m)
  37. * - automatic numeric type casts are not performed. You even have to manually
  38. * cast LENGTH< short > to LENGTH< int > or LENGTH< float >
  39. * to LENGTH< double >. Anyway it is not such trouble as progremmer should be
  40. * very careful when mixing numeric types and avoid automatic casts.
  41. *
  42. */
  43. template < typename T = DEF_LENGTH_VALUE, int P = 1 > class LENGTH;
  44. /**
  45. * Length units contained in this class
  46. */
  47. template <typename T> class LENGTH_UNITS;
  48. /**
  49. * For internal needs
  50. */
  51. template < typename T, int P > struct LENGTH_TRAITS
  52. {
  53. typedef LENGTH<T, P> flat;
  54. };
  55. template < typename T > struct LENGTH_TRAITS< T, 0 >
  56. {
  57. /* length dimension to power 0 is just a number, so LENGTH<T, 0> should be automatically converted to T */
  58. typedef T flat;
  59. };
  60. template < typename T, int P > class LENGTH
  61. {
  62. friend class LENGTH_UNITS< T >;
  63. friend class LENGTH_TRAITS< T, P >;
  64. template < typename Y, int R > friend class LENGTH;
  65. protected:
  66. T m_U;
  67. LENGTH( T units ) : m_U( units )
  68. {
  69. }
  70. static T RawValue( const LENGTH<T, P> &x )
  71. {
  72. return x.m_U;
  73. }
  74. static T RawValue( const T& x )
  75. {
  76. return x;
  77. }
  78. public:
  79. typedef T value_type;
  80. enum
  81. {
  82. dimension = P
  83. };
  84. LENGTH( const LENGTH <T, P> &orig ) : m_U( orig.m_U )
  85. {
  86. }
  87. LENGTH( void ) : m_U()
  88. {
  89. }
  90. static LENGTH<T, P> zero ( void )
  91. {
  92. return T(0);
  93. }
  94. LENGTH<T, P> & operator = ( const LENGTH<T, P> & y )
  95. {
  96. this->m_U = y.m_U;
  97. return *this;
  98. }
  99. template <typename Y> operator LENGTH< Y, P > ( void )
  100. {
  101. return this->m_U;
  102. }
  103. /*************************/
  104. /* comparisons and tests */
  105. /*************************/
  106. bool operator ==( const LENGTH < T, P > y ) const
  107. {
  108. return m_U == y.m_U;
  109. }
  110. bool operator !=( const LENGTH < T, P > y ) const
  111. {
  112. return m_U != y.m_U;
  113. }
  114. bool operator <( const LENGTH < T, P > y ) const
  115. {
  116. return m_U < y.m_U;
  117. }
  118. bool operator >=( const LENGTH < T, P > y ) const
  119. {
  120. return m_U >= y.m_U;
  121. }
  122. bool operator >( const LENGTH < T, P > y ) const
  123. {
  124. return m_U > y.m_U;
  125. }
  126. bool operator <=( const LENGTH < T, P > y ) const
  127. {
  128. return m_U <= y.m_U;
  129. }
  130. bool operator !( void ) const
  131. {
  132. return !m_U;
  133. }
  134. /*************************/
  135. /* basic arithmetic */
  136. /*************************/
  137. LENGTH< T, P > operator - ( void ) const
  138. {
  139. return LENGTH<T, P>(-this->m_U);
  140. }
  141. LENGTH< T, P > operator - ( const LENGTH< T, P > y ) const
  142. {
  143. return m_U - y.m_U;
  144. }
  145. LENGTH< T, P > operator + ( const LENGTH< T, P > y ) const
  146. {
  147. return m_U + y.m_U;
  148. }
  149. template < int R >
  150. typename LENGTH_TRAITS< T, P + R >::flat operator * ( const LENGTH<T, R> &y ) const
  151. {
  152. return m_U * y.m_U;
  153. }
  154. LENGTH< T, P > operator * ( const T & y) const
  155. {
  156. return m_U * y;
  157. }
  158. LENGTH< T, P > friend operator * ( const T &y, const LENGTH<T, P> &x )
  159. {
  160. return x.m_U * y;
  161. }
  162. template < int R >
  163. typename LENGTH_TRAITS< T, P - R >::flat operator / ( const LENGTH<T, R> &y ) const
  164. {
  165. return m_U / y.m_U;
  166. }
  167. LENGTH< T, P > operator / ( const T &y ) const
  168. {
  169. return m_U / y;
  170. }
  171. LENGTH< T, -P > friend operator / ( const T &y, const LENGTH< T, P > &x )
  172. {
  173. return y / x.m_U;
  174. }
  175. friend LENGTH< T, P > sqrt( LENGTH< T, P*2 > y )
  176. {
  177. return sqrt( y.m_U );
  178. }
  179. friend LENGTH< T, P > cbrt( LENGTH< T, P*3 > y )
  180. {
  181. return cbrt( y.m_U );
  182. }
  183. /*************************/
  184. /* assignment arithmetic */
  185. /*************************/
  186. LENGTH< T, P >& operator -= ( const LENGTH< T, P > y )
  187. {
  188. return m_U -= y.m_U;
  189. }
  190. LENGTH< T, P >& operator += ( const LENGTH< T, P > y )
  191. {
  192. return m_U += y.m_U;
  193. }
  194. LENGTH< T, P >& operator *= ( const T y )
  195. {
  196. return m_U *= y;
  197. }
  198. LENGTH< T, P >& operator /= ( const T y )
  199. {
  200. return m_U /= y;
  201. }
  202. /*************************/
  203. /* more arithmetic */
  204. /*************************/
  205. };
  206. /**
  207. * Units of length
  208. *
  209. * How to use them:
  210. * there are several functions, named LENGTH_UNITS< T >::METRE, which return
  211. * named unit (1 meter in example) which have type LENGTH< T, P >.
  212. * to get specific length you should use a multiplication:
  213. * 3*LENGTH_UNITS::metre() gives 3 metres
  214. * 0.01*LENGTH_UNITS::metre() gives 0.01 inch
  215. * to get numeric value of length in specific units you should use a division
  216. * length/LENGTH_UNITS::metre() gives number of metres in length
  217. * legnth/LENGTH_UNITS::foot() gives number of feet in length
  218. */
  219. template < typename T = DEF_LENGTH_VALUE > class LENGTH_UNITS {
  220. protected:
  221. enum
  222. {
  223. METRE = 1000000000, /* The ONLY constant connecting length to the real world */
  224. INCH = METRE / 10000 * 254
  225. };
  226. public:
  227. static LENGTH< T, 1 > metre( void ) {
  228. return T( METRE );
  229. }
  230. static LENGTH< T, 1 > decimetre( void ) {
  231. return T( METRE / 10 );
  232. }
  233. static LENGTH< T, 1 > centimetre( void ) {
  234. return T( METRE / 100 );
  235. }
  236. static LENGTH< T, 1 > millimetre( void ) {
  237. return T( METRE / 1000 );
  238. }
  239. static LENGTH< T, 1 > micrometre( void ) {
  240. return T( METRE / 1000000 );
  241. }
  242. static LENGTH< T, 1 > foot( void ) { /* do not think this will ever need */
  243. return T( INCH * 12 );
  244. }
  245. static LENGTH< T, 1 > inch( void ) {
  246. return T( INCH );
  247. }
  248. static LENGTH< T, 1 > mil( void ) {
  249. return T( INCH / 1000 );
  250. }
  251. };
  252. /**
  253. * shortcut to get units of given length type
  254. */
  255. template < typename T, int D > class LENGTH_UNITS< LENGTH< T, D > >: public LENGTH_UNITS< T >
  256. {
  257. };
  258. #endif