units.scm 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;;; Manipulation of units
  21. (declare (usual-integrations))
  22. ;;; The units of a quantity are represented as a combination of a
  23. ;;; (labeled) vector of exponents, one for each base unit in a system,
  24. ;;; and a scale factor. The unit objects, such as meter or joule are
  25. ;;; such objects. Multiplication, division, and exponentiation are
  26. ;;; extended to combine units from the same system.
  27. #|
  28. ;;; in types.scm
  29. (define unit-type-tag '*unit*)
  30. (define (units? x)
  31. (or (eq? x '&unitless)
  32. (and (pair? x)
  33. (eq? (car x) unit-type-tag))))
  34. |#
  35. (define &unitless '&unitless)
  36. (define (unitless? x)
  37. (eq? x &unitless))
  38. (define the-empty-vector (vector))
  39. (define (make-unit system exponents scale-factor)
  40. (if (or (eq? exponents the-empty-vector)
  41. (vector-forall zero? exponents))
  42. (if (equal? scale-factor 1)
  43. &unitless
  44. (list unit-type-tag system the-empty-vector scale-factor))
  45. (list unit-type-tag system exponents scale-factor)))
  46. (define (unit-system u)
  47. (or (unitless? u) (cadr u)))
  48. (define (unit-exponents u)
  49. (if (unitless? u) the-empty-vector (caddr u)))
  50. (define (unit-scale u)
  51. (if (unitless? u) 1 (cadddr u)))
  52. (define (same-dimensions? u1 u2)
  53. (let ((v1 (unit-exponents u1)) (v2 (unit-exponents u2)))
  54. (let ((n (vector-length v1)))
  55. (let lp ((i 0))
  56. (or (fix:= i n)
  57. (and (n:= (vector-ref v1 i) (vector-ref v2 i))
  58. (lp (fix:+ i 1))))))))
  59. (define (same-units? u1 u2)
  60. (assert (and (units? u1) (units? u2)))
  61. (or (eq? u1 u2)
  62. (and (eq? (unit-system u1) (unit-system u2))
  63. (same-dimensions? u1 u2)
  64. (n:= (unit-scale u1) (unit-scale u2)))))
  65. (define (<-units? u1 u2)
  66. (assert (and (units? u1) (units? u2)))
  67. (or (eq? u1 u2)
  68. (and (eq? (unit-system u1) (unit-system u2))
  69. (same-dimensions? u1 u2)
  70. (n:< (unit-scale u1) (unit-scale u2)))))
  71. (define (<=-units? u1 u2)
  72. (assert (and (units? u1) (units? u2)))
  73. (or (eq? u1 u2)
  74. (and (eq? (unit-system u1) (unit-system u2))
  75. (same-dimensions? u1 u2)
  76. (or (n:< (unit-scale u1) (unit-scale u2))
  77. (n:= (unit-scale u1) (unit-scale u2))))))
  78. (define (>-units? u1 u2)
  79. (assert (and (units? u1) (units? u2)))
  80. (or (eq? u1 u2)
  81. (and (eq? (unit-system u1) (unit-system u2))
  82. (same-dimensions? u1 u2)
  83. (n:> (unit-scale u1) (unit-scale u2)))))
  84. (define (>=-units? u1 u2)
  85. (assert (and (units? u1) (units? u2)))
  86. (or (eq? u1 u2)
  87. (and (eq? (unit-system u1) (unit-system u2))
  88. (same-dimensions? u1 u2)
  89. (or (n:> (unit-scale u1) (unit-scale u2))
  90. (n:= (unit-scale u1) (unit-scale u2))))))
  91. (define (*units u1 u2)
  92. (cond ((unitless? u1) u2)
  93. ((unitless? u2) u1)
  94. (else (assert (and (units? u1) (units? u2)))
  95. (assert (and (eq? (unit-system u1) (unit-system u2))))
  96. (let ((v1 (unit-exponents u1)) (v2 (unit-exponents u2)))
  97. (cond ((eq? v1 the-empty-vector)
  98. (make-unit (unit-system u1)
  99. v2
  100. (n:* (unit-scale u1) (unit-scale u2))))
  101. ((eq? v2 the-empty-vector)
  102. (make-unit (unit-system u1)
  103. v1
  104. (n:* (unit-scale u1) (unit-scale u2))))
  105. (else
  106. (make-unit (unit-system u1)
  107. (make-initialized-vector (vector-length v1)
  108. (lambda (i)
  109. (n:+ (vector-ref v1 i)
  110. (vector-ref v2 i))))
  111. (n:* (unit-scale u1) (unit-scale u2)))))))))
  112. (define (invert-units u)
  113. (let ((v (unit-exponents u)))
  114. (if (eq? v the-empty-vector)
  115. (make-unit (unit-system u)
  116. the-empty-vector
  117. (n:/ 1 (unit-scale u)))
  118. (make-unit (unit-system u)
  119. (make-initialized-vector (vector-length v)
  120. (lambda (i)
  121. (n:* -1 (vector-ref v i))))
  122. (n:/ 1 (unit-scale u))))))
  123. (define (/units u1 u2)
  124. (cond ((unitless? u1)
  125. (if (unitless? u2)
  126. &unitless
  127. (let ((v2 (unit-exponents u2)))
  128. (make-unit (unit-system u2)
  129. (make-initialized-vector (vector-length v2)
  130. (lambda (i)
  131. (n:* -1 (vector-ref v2 i))))
  132. (n:/ 1 (unit-scale u2))))))
  133. ((unitless? u2) u1)
  134. (else (assert (and (eq? (unit-system u1) (unit-system u2))))
  135. (let ((v1 (unit-exponents u1)) (v2 (unit-exponents u2)))
  136. (cond ((eq? v1 the-empty-vector)
  137. (make-unit (unit-system u1)
  138. (make-initialized-vector (vector-length v2)
  139. (lambda (i)
  140. (n:- 0 (vector-ref v2 i))))
  141. (n:/ (unit-scale u1) (unit-scale u2))))
  142. ((eq? v2 the-empty-vector)
  143. (make-unit (unit-system u1)
  144. v1
  145. (n:/ (unit-scale u1) (unit-scale u2))))
  146. (else
  147. (make-unit (unit-system u1)
  148. (make-initialized-vector (vector-length v1)
  149. (lambda (i)
  150. (n:- (vector-ref v1 i)
  151. (vector-ref v2 i))))
  152. (n:/ (unit-scale u1) (unit-scale u2)))))))))
  153. (define (expt-units u p)
  154. (cond ((unitless? u) u)
  155. (else (assert (units? u) "Not a unit -- EXPT")
  156. (let ((v (unit-exponents u)))
  157. (make-unit (unit-system u)
  158. (make-initialized-vector (vector-length v)
  159. (lambda (i)
  160. (n:* p (vector-ref v i))))
  161. (n:expt (unit-scale u) p))))))
  162. (define %units-units-dummy-1
  163. (begin
  164. (assign-operation '= same-units? units? units?)
  165. (assign-operation '< <-units? units? units?)
  166. (assign-operation '<= <=-units? units? units?)
  167. (assign-operation '> >-units? units? units?)
  168. (assign-operation '>= >=-units? units? units?)
  169. (assign-operation '* *units units? units?)
  170. (assign-operation 'invert invert-units units?)
  171. (assign-operation '/ /units units? units?)
  172. (assign-operation 'expt expt-units units? number?)))