61 public::
assignment(=),
operator(*),
operator(/),
operator(+)
62 private:: units_simplify
82 character(TOKEN),
pointer:: name(:)
83 character(TOKEN):: offset
84 real(
dp),
pointer:: power(:)
88 module procedure dcunitsclear
92 module procedure dcunitsdeallocate
95 interface assignment(=)
96 module procedure dcunitsbuild, dcunitstostring
100 module procedure dcunitsmul
103 interface operator(/)
104 module procedure dcunitsdiv
107 interface operator(+)
108 module procedure dcunitsadd
131 subroutine units_simplify(u, name, power)
132 type(UNITS),
intent(inout):: u
133 character(*),
intent(in):: name(u%nelems)
134 real(DP),
intent(in):: power(u%nelems)
135 integer:: i, n, j, onazi
136 integer:: table(u%nelems)
138 if (u%nelems < 1)
return
142 if (name(i) ==
'') cycle
145 if (name(j) == name(i))
then
150 table(i) = table(onazi)
156 allocate(u%name(n), u%power(n))
159 if (table(i) == 0) cycle
160 u%name(table(i)) = name(i)
161 u%power(table(i)) = u%power(table(i)) + power(i)
164 end subroutine units_simplify
179 type(
units) function dcunitsmul(u1, u2) result(result)
180 type(
units),
intent(in):: u1, u2
182 character(TOKEN),
allocatable:: name(:)
183 real(
dp),
allocatable:: power(:)
184 result%factor = u1%factor * u2%factor
185 result%nelems = u1%nelems + u2%nelems
189 nullify(result%name, result%power)
192 allocate(name(n), power(n))
193 name = (/u1%name, u2%name/)
194 power = (/u1%power, u2%power/)
195 call units_simplify(result, name, power)
196 deallocate(name, power)
197 end function dcunitsmul
212 type(
units) function dcunitsdiv(u1, u2) result(result)
213 type(
units),
intent(in):: u1, u2
215 character(TOKEN),
allocatable:: name(:)
216 real(dp),
allocatable:: power(:)
217 if (abs(u2%factor) < tiny(u2%factor))
then
218 result%factor = sign(u1%factor, 1.0_dp) * &
219 & sign(u2%factor, 1.0_dp) * &
222 result%factor = u1%factor / u2%factor
224 result%nelems = u1%nelems + u2%nelems
228 nullify(result%name, result%power)
231 allocate(name(n), power(n))
234 name(1:n1) = u1%name(1:n1)
235 power(1:n1) = u1%power(1:n1)
239 name(n1:n) = u2%name(1:u2%nelems)
240 power(n1:n) = -u2%power(1:u2%nelems)
242 call units_simplify(result, name, power)
243 deallocate(name, power)
244 end function dcunitsdiv
265 type(
units) function dcunitsadd(u1, u2) result(result)
266 type(
units),
intent(in):: u1, u2
268 result%offset = u1%offset
269 result%nelems = u1%nelems
270 result%factor = u1%factor + u2%factor
272 if (x%nelems == 0)
then
273 nullify(result%name, result%power)
276 if (all(abs(x%power(1:result%nelems)) < tiny(0.0_dp)))
then
277 allocate(result%name(result%nelems), result%power(result%nelems))
278 result%name = u1%name
279 result%power = u1%power
284 result%offset =
"MISMATCH"
285 nullify(result%name, result%power)
286 end function dcunitsadd
308 type(
units),
intent(in):: u1, u2
310 character(STRING):: debug
316 if (x%nelems == 0)
then
318 else if (all(abs(x%power(1:x%nelems)) < tiny(0.0_dp)))
then
339 subroutine dcunitsclear(u)
340 type(
units),
intent(inout):: u
346 end subroutine dcunitsclear
361 subroutine dcunitsdeallocate(u)
362 type(
units),
intent(inout):: u
363 if (
associated(u%name))
deallocate(u%name)
364 if (
associated(u%power))
deallocate(u%power)
368 end subroutine dcunitsdeallocate
389 subroutine dcunitstostring(string, u)
390 character(*),
intent(out):: string
391 type(
units),
intent(in):: u
392 integer:: i, ip, npower
393 character(TOKEN):: buffer
394 character:: mul =
'.'
395 real(DP),
parameter:: allowed = epsilon(1.0_dp) * 16.0
397 if (u%nelems < 0)
then
398 string =
'error from ' // u%offset
402 write(buffer,
"(1pg20.12)") u%factor
404 if (u%nelems < 1)
return
406 if (abs(u%factor - 1.0) < allowed)
then
408 else if (abs(u%factor + 1.0) < allowed)
then
412 ip = len_trim(string) + 1
414 npower = nint(u%power(i))
415 if (abs(1.0 - u%power(i)) < allowed)
then
417 else if (abs(npower - u%power(i)) < allowed)
then
418 write(buffer,
"(i10)") npower
419 buffer = adjustl(buffer)
421 write(buffer,
"(1pg10.3)") u%power(i)
422 buffer = adjustl(buffer)
424 if (buffer ==
'0') cycle
425 string = trim(string) // mul // trim(u%name(i)) // trim(buffer)
427 if (ip <= len(string)) string(ip:ip) =
' '
428 if (string(1:1) ==
" ") string = adjustl(string)
429 if (u%offset /=
"")
then
430 string = trim(string) //
'@' // trim(u%offset)
432 end subroutine dcunitstostring
465 subroutine dcunitsbuild(u, cunits)
467 type(
units),
intent(out):: u
468 character(*),
intent(in):: cunits
473 character(TOKEN):: name
474 real(DP):: power, factor
476 type(elem_units),
target:: ustack(100)
487 type(paren_t):: pstack(50)
491 integer,
parameter:: Y_INIT = 1, y_number = 2, y_name = 3, &
492 & y_nx = 4, y_ni = 5, y_mul = 6, y_shift = 7
493 integer:: yparse_status = y_init
499 character(TOKEN):: cvalue
505 if (
associated(u%name))
deallocate(u%name)
506 if (
associated(u%power))
deallocate(u%power)
510 if (cunits ==
"")
return
514 yparse_status = y_init
520 select case(yparse_status)
522 pstack(pi)%factor = pstack(pi)%factor * ivalue(1)
523 yparse_status = y_number
525 i = pstack(pi)%power_exp
526 ustack(i:ui)%power = ustack(i:ui)%power * ivalue(1)
535 select case(yparse_status)
537 pstack(pi)%factor = pstack(pi)%factor * dvalue
538 yparse_status = y_number
540 i = pstack(pi)%power_exp
541 ustack(i:ui)%power = ustack(i:ui)%power * dvalue
550 select case(yparse_status)
551 case (y_init, y_number, y_mul)
552 ustack(ui)%name = cvalue
553 yparse_status = y_name
557 ustack(ui)%name = cvalue
558 yparse_status = y_name
565 select case(yparse_status)
572 select case(yparse_status)
573 case (y_number, y_name)
575 yparse_status = y_mul
580 select case(yparse_status)
581 case (y_number, y_name)
583 pstack(pi)%factor_inv = .true.
584 yparse_status = y_mul
591 yparse_status = y_shift
608 u%factor = product(ustack(1:ui)%factor)
609 call units_simplify(u, ustack(1:ui)%name, ustack(1:ui)%power)
614 print *,
"DCUnitsBuild: syntax error, operator(**) ignored"
618 print *,
"DCUnitsBuild: unexpected token <", &
619 & trim(cvalue),
"> ignored"
622 subroutine power_next
625 pstack(pi)%power_exp = ui
626 end subroutine power_next
628 subroutine factor_next
631 i = pstack(pi)%factor_exp
632 factor = product(ustack(i:ui)%factor) * pstack(pi)%factor
633 if (pstack(pi)%factor_inv)
then
634 ustack(i:ui)%power = -ustack(i:ui)%power
635 factor = 1.0_dp / factor
637 ustack(i)%factor = factor
638 ustack(i+1:ui)%factor = 1.0_dp
640 pstack(pi)%factor = 1.0_dp
641 pstack(pi)%factor_exp = ui
642 end subroutine factor_next
644 subroutine units_finalize
646 end subroutine units_finalize
648 subroutine ustack_clear
651 end subroutine ustack_clear
653 subroutine ustack_grow
654 if (ui >=
size(ustack)) stop
'DCUnitsBuild: too many elements'
657 ustack(ui)%factor = 1.0_dp
658 ustack(ui)%power = 1.0_dp
659 end subroutine ustack_grow
661 subroutine pstack_clear
664 end subroutine pstack_clear
666 subroutine pstack_push
667 if (pi >=
size(pstack)) stop
'DCUnitsBuild: too many parens'
670 pstack(pi)%factor_exp = ui
671 pstack(pi)%factor = 1.0_dp
672 pstack(pi)%factor_inv = .false.
673 pstack(pi)%power_exp = ui
674 pstack(pi)%paren_exp = ui
675 end subroutine pstack_push
677 subroutine pstack_pop
681 end subroutine pstack_pop
683 end subroutine dcunitsbuild
integer, parameter, public token
単語やキーワードを保持する文字型変数の種別型パラメタ
integer, parameter, public dp
倍精度実数型変数
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
logical function, public add_okay(u1, u2)
integer, parameter, public s_real
実数シンボル
integer, parameter, public s_text
テキスト/名前トークンシンボル
integer, parameter, public s_multiply
乗算演算子シンボル
integer, parameter, public s_openpar
開き括弧シンボル
integer, parameter, public s_closepar
閉じ括弧シンボル
subroutine, public dcunitsgettoken(tokentype, ivalue, dvalue, cvalue)
subroutine, public dcunitssetline(line)
integer, parameter, public s_exponent
指数演算子シンボル
integer, parameter, public s_integer
整数シンボル
integer, parameter, public s_eof
ファイル/文字列終端シンボル
integer, parameter, public s_divide
除算演算子シンボル
integer, parameter, public s_shift
シフト演算子シンボル