fbe-system.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. ;;;; Unit systems
  21. ;; (define* (define-unit-system system-name #:rest base-units)
  22. ;; (let ((n (length base-units)))
  23. ;; (let ((base-specs
  24. ;; (map (lambda (base-spec i)
  25. ;; (let* ((unit-name (car base-spec))
  26. ;; (exponents
  27. ;; (make-initialized-vector n
  28. ;; (lambda (j) (if (fix:= i j) 1 0))))
  29. ;; (unit (make-unit system-name exponents 1)))
  30. ;; (if (environment-bound? scmutils-base-environment
  31. ;; unit-name)
  32. ;; (write-line `(clobbering ,unit-name)))
  33. ;; (environment-define scmutils-base-environment
  34. ;; unit-name
  35. ;; unit)
  36. ;; (append base-spec (list unit))))
  37. ;; base-units
  38. ;; (iota n))))
  39. ;; (environment-define scmutils-base-environment
  40. ;; system-name
  41. ;; (list '*unit-system*
  42. ;; system-name
  43. ;; base-specs ;base units
  44. ;; '() ;derived units
  45. ;; '() ;additional units
  46. ;; ))))
  47. ;; system-name)
  48. (define-syntax define-unit-system
  49. (lambda (x)
  50. (syntax-case x ()
  51. ((_ (_ system-name) (_ (_ unit-name) unit-spec ...) ...)
  52. (with-syntax ((n (length #'(unit-name ...)))
  53. ((index ...) (let f ((i 0) (ids #'(unit-name ...)))
  54. (if (null? ids)
  55. '()
  56. (cons i (f (+ i 1) (cdr ids)))))))
  57. #`(begin
  58. (define system-name
  59. (list '*unit-system* 'system-name
  60. (list (append (list 'unit-name unit-spec ...)
  61. (list (make-unit 'system-name
  62. (make-initialized-vector
  63. n
  64. (lambda (j) (if (fix:= index j) 1 0)))
  65. 1))) ...) ;base units
  66. '() ;derived units
  67. '() ;additional units
  68. ))
  69. (define unit-name
  70. (make-unit 'system-name
  71. (make-initialized-vector
  72. n
  73. (lambda (j) (if (fix:= index j) 1 0)))
  74. 1))
  75. ...
  76. ))))))
  77. (define (unit-system? system)
  78. (and (pair? system)
  79. (eq? (car system) '*unit-system*)))
  80. (define (unit-system-name system)
  81. (cadr system))
  82. (define (base-units system)
  83. (caddr system))
  84. (define (derived-units system)
  85. (cadddr system))
  86. (define (alternate-units system)
  87. (car (cddddr system)))
  88. ;;; Data may be entered and results may be presented in derived units.
  89. ;; (define* (define-derived-unit system unit-name tex description content
  90. ;; #:optional scale-factor)
  91. ;; (assert (unit-system? system))
  92. ;; (if (environment-bound? scmutils-base-environment unit-name)
  93. ;; (write-line `(clobbering ,unit-name)))
  94. ;; (if (default-object? scale-factor)
  95. ;; (set! scale-factor 1))
  96. ;; (set! content
  97. ;; (make-unit (unit-system-name system)
  98. ;; (unit-exponents content)
  99. ;; (* (expression scale-factor) (unit-scale content))))
  100. ;; (let ((unit-spec (list unit-name tex description content)))
  101. ;; (define-derived-unit! system unit-spec)
  102. ;; (environment-define scmutils-base-environment unit-name content)
  103. ;; unit-name))
  104. (define-syntax define-derived-unit
  105. (syntax-rules ()
  106. ((_ system (_ unit-name) tex description content-u)
  107. (define unit-name
  108. (let* ((scale-factor 1)
  109. (content (make-unit (unit-system-name system)
  110. (unit-exponents content-u)
  111. (* (expression scale-factor) (unit-scale content-u)))))
  112. (let ((unit-spec (list 'unit-name tex description content)))
  113. (define-derived-unit! system unit-spec)
  114. content))))
  115. ((_ system (_ unit-name) tex description content-u scale-factor)
  116. (define unit-name
  117. (let* ((content (make-unit (unit-system-name system)
  118. (unit-exponents content-u)
  119. (* (expression scale-factor) (unit-scale content-u)))))
  120. (let ((unit-spec (list 'unit-name tex description content)))
  121. (define-derived-unit! system unit-spec)
  122. content))))))
  123. (define (define-derived-unit! system unit-spec)
  124. (set-car! (cdddr system)
  125. (append (cadddr system)
  126. (list unit-spec))))
  127. ;;; Data may be entered in additional units but results will not be
  128. ;;; presented in additional units.
  129. ;; (define* (define-additional-unit system unit-name tex description content
  130. ;; #:optional scale-factor)
  131. ;; (assert (unit-system? system))
  132. ;; (if (environment-bound? scmutils-base-environment unit-name)
  133. ;; (write-line `(clobbering ,unit-name)))
  134. ;; (if (default-object? scale-factor)
  135. ;; (set! scale-factor 1))
  136. ;; (set! content
  137. ;; (make-unit (unit-system-name system)
  138. ;; (unit-exponents content)
  139. ;; (* (expression scale-factor) (unit-scale content))))
  140. ;; (let ((unit-spec (list unit-name tex description content)))
  141. ;; (define-additional-unit! system unit-spec)
  142. ;; (environment-define scmutils-base-environment unit-name content)
  143. ;; unit-name))
  144. (define-syntax define-additional-unit
  145. (syntax-rules ()
  146. ((_ system (_ unit-name) tex description content-u)
  147. (define unit-name
  148. (let* ((scale-factor 1)
  149. (content (make-unit (unit-system-name system)
  150. (unit-exponents content-u)
  151. (* (expression scale-factor) (unit-scale content-u)))))
  152. (let ((unit-spec (list 'unit-name tex description content)))
  153. (define-additional-unit! system unit-spec)
  154. content))))
  155. ((_ system (_ unit-name) tex description content-u scale-factor)
  156. (define unit-name
  157. (let ((content (make-unit (unit-system-name system)
  158. (unit-exponents content-u)
  159. (* (expression scale-factor) (unit-scale content-u)))))
  160. (let ((unit-spec (list 'unit-name tex description content)))
  161. (define-additional-unit! system unit-spec)
  162. content))))))
  163. (define (define-additional-unit! system unit-spec)
  164. (set-car! (cddddr system)
  165. (append (car (cddddr system))
  166. (list unit-spec))))
  167. ;;; FBE: make it a parameter
  168. (define *multiplier-names* (make-parameter '()))
  169. ;; (define (define-multiplier name tex-string log-value)
  170. ;; (if (environment-bound? scmutils-base-environment name)
  171. ;; (write-line `(clobbering ,name)))
  172. ;; (set! *multiplier-names*
  173. ;; (cons (list name tex-string log-value)
  174. ;; *multiplier-names*))
  175. ;; (environment-define scmutils-base-environment
  176. ;; name
  177. ;; (expt 10 log-value)))
  178. (define-syntax define-multiplier
  179. (syntax-rules ()
  180. ((_ (_ name) tex-string log-value)
  181. (define name
  182. (let ()
  183. (*multiplier-names*
  184. (cons (list 'name tex-string log-value)
  185. (*multiplier-names*)))
  186. (expt 10 log-value))))))
  187. ;;; FBE: make it a parameter
  188. (define *numerical-constants* (make-parameter '()))
  189. ;; (define* (define-constant name tex-string description value units
  190. ;; #:optional uncertainty)
  191. ;; (if (environment-bound? scmutils-base-environment name)
  192. ;; (write-line `(clobbering ,name)))
  193. ;; (let ((constant (literal-number name)))
  194. ;; (cond ((with-units? value)
  195. ;; (assert (same-units? (u:units value) units))))
  196. ;; (set! value (g:simplify (u:value value)))
  197. ;; (add-property! constant 'name name)
  198. ;; (add-property! constant 'numerical-value value)
  199. ;; (add-property! constant 'units units)
  200. ;; (add-property! constant 'tex-string tex-string)
  201. ;; (add-property! constant 'description description)
  202. ;; (if (real? value) (declare-known-reals name))
  203. ;; (if (not (default-object? uncertainty))
  204. ;; (add-property! constant 'uncertainty uncertainty))
  205. ;; (set! *numerical-constants* (cons constant *numerical-constants*))
  206. ;; (environment-define scmutils-base-environment
  207. ;; name
  208. ;; (with-units value units))
  209. ;; name))
  210. (define-syntax define-constant
  211. (syntax-rules ()
  212. ((_ (_ name) tex-string description value-u units uncertainty)
  213. (define name
  214. (let ((constant (literal-number 'name))
  215. (value (g:simplify (u:value value-u))))
  216. (cond ((with-units? value)
  217. (assert (same-units? (u:units value) units))))
  218. (add-property! constant 'name 'name)
  219. (add-property! constant 'numerical-value value)
  220. (add-property! constant 'units units)
  221. (add-property! constant 'tex-string tex-string)
  222. (add-property! constant 'description description)
  223. (if (real? value) (declare-known-reals 'name))
  224. (add-property! constant 'uncertainty uncertainty)
  225. (*numerical-constants* (cons constant (*numerical-constants*)))
  226. (with-units value units))))
  227. ((_ (_ name) tex-string description value-u units)
  228. (define name
  229. (let ((constant (literal-number 'name))
  230. (value (g:simplify (u:value value-u))))
  231. (cond ((with-units? value)
  232. (assert (same-units? (u:units value) units))))
  233. (add-property! constant 'name 'name)
  234. (add-property! constant 'numerical-value value)
  235. (add-property! constant 'units units)
  236. (add-property! constant 'tex-string tex-string)
  237. (add-property! constant 'description description)
  238. (if (real? value) (declare-known-reals 'name))
  239. (*numerical-constants* (cons constant (*numerical-constants*)))
  240. (with-units value units))))))
  241. ;;; FBE start: comment out
  242. ;; (define* (numerical-constants #:optional units? constants)
  243. ;; (if (default-object? units?) (set! units? #t))
  244. ;; (if (default-object? constants) (set! constants (*numerical-constants*)))
  245. ;; (for-each (lambda (c)
  246. ;; (environment-assign!
  247. ;; scmutils-base-environment
  248. ;; (get-property c 'name)
  249. ;; (if units?
  250. ;; (with-units (get-property c 'numerical-value)
  251. ;; (get-property c 'units))
  252. ;; (g:* (get-property c 'numerical-value)
  253. ;; (unit-scale (get-property c 'units))))))
  254. ;; constants))
  255. ;; (define* (symbolic-constants #:optional units? constants)
  256. ;; (if (default-object? units?) (set! units? #t))
  257. ;; (if (default-object? constants) (set! constants (*numerical-constants*)))
  258. ;; (for-each (lambda (c)
  259. ;; (environment-assign!
  260. ;; scmutils-base-environment
  261. ;; (get-property c 'name)
  262. ;; (if units?
  263. ;; (with-units (get-property c 'name)
  264. ;; (get-property c 'units))
  265. ;; (g:* (get-property c 'name)
  266. ;; (unit-scale (get-property c 'units))))))
  267. ;; constants))
  268. ;;; FBE end
  269. (define (get-constant-data name)
  270. (find-matching-item (*numerical-constants*)
  271. (lambda (c) (eq? (get-property c 'name) name))))
  272. ;;; & is used to attach units to a number, or to check that a number
  273. ;;; has the given units.
  274. (define* (& value u1 #:optional u2)
  275. (let ((units (if (default-object? u2) u1 u2))
  276. (scale (if (default-object? u2) 1 u1)))
  277. (assert (and (not (units? value)) (number? scale) (units? units)))
  278. (if (with-units? value)
  279. (if (equal? (unit-exponents units)
  280. (unit-exponents (u:units value)))
  281. value
  282. (error "Units do not match: &" value units))
  283. (with-units (g:* scale (unit-scale units) value)
  284. (make-unit (unit-system units)
  285. (unit-exponents units)
  286. 1)))))
  287. (define *unit-constructor* '&)
  288. ;;; FBE: we comment the following definitions and move them after we
  289. ;;; create the 'generic-environment'.
  290. ;; (define unit-environment generic-environment)
  291. ;; (define (express-as num target-unit-expression)
  292. ;; (let ((target-unit-expression-value
  293. ;; (eval target-unit-expression unit-environment)))
  294. ;; (cond ((with-units? target-unit-expression-value)
  295. ;; (let ((target-val (u:value target-unit-expression-value))
  296. ;; (target-units (u:units target-unit-expression-value)))
  297. ;; (express-in-given-units (g:/ num target-val)
  298. ;; target-units
  299. ;; target-unit-expression)))
  300. ;; ((units? target-unit-expression-value)
  301. ;; (express-in-given-units num
  302. ;; target-unit-expression-value
  303. ;; target-unit-expression))
  304. ;; (else num))))
  305. (define (express-in-given-units num target-unit target-unit-expression)
  306. (cond ((with-units? num)
  307. (let ((value (g:* (unit-scale (u:units num)) (u:value num)))
  308. (vect (unit-exponents (u:units num))))
  309. (if (not (equal? vect (unit-exponents target-unit)))
  310. (error "Cannot express in given units"
  311. num target-unit target-unit-expression))
  312. (list *unit-constructor*
  313. (g:/ (expression value) (unit-scale target-unit))
  314. target-unit-expression)))
  315. ((units? num)
  316. (list *unit-constructor*
  317. (g:/ (unit-scale num) (unit-scale target-unit))
  318. target-unit-expression))
  319. (else num)))
  320. (define (with-units->expression system num)
  321. (assert (unit-system? system))
  322. (cond ((with-units? num)
  323. (let ((value (g:* (unit-scale (u:units num)) (u:value num)))
  324. (vect (unit-exponents (u:units num))))
  325. (make-unit-description value vect system)))
  326. ((units? num)
  327. (make-unit-description (unit-scale num)
  328. (unit-exponents num)
  329. system))
  330. (else num)))
  331. (define (make-unit-description value exponent-vector system)
  332. (let ((available
  333. (or (find-unit-description exponent-vector
  334. (base-units system))
  335. (find-unit-description exponent-vector
  336. (derived-units system)))))
  337. (if available
  338. (let ((unit-name (car available))
  339. (scale (unit-scale (list-ref available 3))))
  340. (list *unit-constructor*
  341. (g:simplify (g:/ value scale))
  342. unit-name))
  343. (list *unit-constructor*
  344. (g:simplify value)
  345. (unit-expresson (vector->list exponent-vector)
  346. (map car (base-units system)))))))
  347. (define (find-unit-description vect ulist)
  348. (find-matching-item ulist
  349. (lambda (entry)
  350. (equal? (unit-exponents (list-ref entry 3))
  351. vect))))
  352. (define (find-unit-name vect ulist)
  353. (let ((v (find-unit-description vect ulist)))
  354. (if v (car v) #f)))
  355. (define (unit-expresson exponents base-unit-names)
  356. (cons '*
  357. (apply append
  358. (map (lambda (exponent base-name)
  359. (cond ((g:zero? exponent) '())
  360. ((g:one? exponent) (list base-name))
  361. (else
  362. (list (list 'expt base-name exponent)))))
  363. exponents
  364. base-unit-names))))
  365. #|
  366. (with-units->expression SI &foot)
  367. ;Value: (& .3048 &meter)
  368. (with-units->expression SI (& 2 &foot))
  369. ;Value: (& .6096 &meter)
  370. (with-units->expression SI (/ (* :k (& 300 &kelvin)) :e))
  371. ;Value: (& .02585215707677003 &volt)
  372. (with-units->expression SI :c)
  373. ;Value: (& 299792458. (* &meter (expt &second -1)))
  374. (with-units->expression SI :h)
  375. ;Value: (& 6.6260755e-34 (* (expt &meter 2) &kilogram (expt &second -1)))
  376. |#
  377. #|
  378. ;;; Work in progress
  379. (define (foosh x)
  380. (let* ((logscale (round->exact (log10 x)))
  381. (scale (expt 10 logscale))
  382. )
  383. (list (/ x scale) scale)
  384. ))
  385. (foosh 3/1000)
  386. #|
  387. (3 1/1000)
  388. |#
  389. |#