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
Provides kind type parameter values.
integer, parameter, public token
Character length for word, token
integer, parameter, public string
Character length for string
integer, parameter, public dp
Double Precision Real number
Unit system processing module.
logical function, public add_okay(u1, u2)
Internal module for dc_units.
integer, parameter, public s_real
Real number symbol
integer, parameter, public s_closepar
Close parenthesis symbol
integer, parameter, public s_text
Text/name token symbol
integer, parameter, public s_multiply
Multiply operator symbol
integer, parameter, public s_openpar
Open parenthesis symbol
integer, parameter, public s_shift
Shift operator symbol
integer, parameter, public s_integer
Integer number symbol
integer, parameter, public s_eof
End of file/string symbol
subroutine, public dcunitsgettoken(tokentype, ivalue, dvalue, cvalue)
subroutine, public dcunitssetline(line)
integer, parameter, public s_exponent
Exponent operator symbol
integer, parameter, public s_divide
Divide operator symbol