dc_units Module Reference

Data Types

interface  assignment(=)
 
interface  clear
 
interface  deallocate
 
interface  operator(*)
 
interface  operator(+)
 
interface  operator(/)
 
type  units
 

Functions/Subroutines

subroutine, private units_simplify (u, name, power)
 
type(units) function dcunitsmul (u1, u2)
 
type(units) function dcunitsdiv (u1, u2)
 
type(units) function dcunitsadd (u1, u2)
 
logical function, public add_okay (u1, u2)
 
subroutine dcunitsclear (u)
 
subroutine dcunitsdeallocate (u)
 
subroutine dcunitstostring (string, u)
 
subroutine dcunitsbuild (u, cunits)
 

Function/Subroutine Documentation

◆ add_okay()

logical function, public dc_units::add_okay ( type(units), intent(in)  u1,
type(units), intent(in)  u2 
)

Definition at line 175 of file dc_units.f90.

Referenced by getmatch().

175  type(units), intent(in):: u1, u2
176  type(units):: x
177  character(STRING):: debug
178  call clear(x)
179  x = u1 / u2
180  debug = u1
181  debug = u2
182  debug = x
183  if (x%nelems == 0) then
184  result = .true.
185  else if (all(abs(x%power(1:x%nelems)) < tiny(0.0_dp))) then
186  result = .true.
187  else
188  result = .false.
189  endif
190  call deallocate(x)
Here is the caller graph for this function:

◆ dcunitsadd()

type(units) function dc_units::dcunitsadd ( type(units), intent(in)  u1,
type(units), intent(in)  u2 
)
private

Definition at line 152 of file dc_units.f90.

152  type(units), intent(in):: u1, u2
153  type(units):: x
154  result%offset = u1%offset
155  result%nelems = u1%nelems
156  result%factor = u1%factor + u2%factor
157  x = u1 / u2
158  if (x%nelems == 0) then
159  nullify(result%name, result%power)
160  return
161  endif
162  if (all(abs(x%power(1:result%nelems)) < tiny(0.0_dp))) then
163  allocate(result%name(result%nelems), result%power(result%nelems))
164  result%name = u1%name
165  result%power = u1%power
166  return
167  endif
168  result%factor = 0.0
169  result%nelems = -1
170  result%offset = "MISMATCH"
171  nullify(result%name, result%power)

◆ dcunitsbuild()

subroutine dc_units::dcunitsbuild ( type(units), intent(out)  u,
character(*), intent(in)  cunits 
)
private

Definition at line 260 of file dc_units.f90.

References cancel_exp(), dcunits_com::dcunitsgettoken(), dcunits_com::dcunitssetline(), error(), factor_next(), power_next(), pstack_clear(), pstack_pop(), pstack_push(), dcunits_com::s_closepar, dcunits_com::s_divide, dcunits_com::s_eof, dcunits_com::s_exponent, dcunits_com::s_integer, dcunits_com::s_multiply, dcunits_com::s_openpar, dcunits_com::s_real, dcunits_com::s_shift, dcunits_com::s_text, units_finalize(), units_simplify(), ustack_clear(), and ustack_grow().

260  !
261  ! 文字型変数から UNITS 型変数を生成します (constructor)。
262  !
263  use dcunits_com
264  type(units), intent(out):: u
265  character(*), intent(in):: cunits
266 
267  ! 構築中の情報、乗算対象の列として保持する。
268  ! これは shift オペレータ付き単位を乗算できないことを示す。
269  type elem_units
270  character(TOKEN):: name
271  real(DP):: power, factor
272  end type elem_units
273  type(elem_units), target:: ustack(100)
274  integer:: ui = 1
275 
276  ! 構文単位が占める乗算対象の stack における最初の添字
277  type paren_t
278  real(DP):: factor
279  integer:: factor_exp
280  logical:: factor_inv
281  integer:: power_exp
282  integer:: paren_exp
283  end type paren_t
284  type(paren_t):: pstack(50)
285  integer:: pi = 1
286 
287  ! パーサの状態遷移
288  integer, parameter:: y_init = 1, y_number = 2, y_name = 3, &
289  & y_nx = 4, y_ni = 5, y_mul = 6, y_shift = 7
290  integer:: yparse_status = y_init
291 
292  ! 字句
293  integer:: ltype
294  integer:: ivalue(5)
295  real(DP):: dvalue
296  character(TOKEN):: cvalue
297  ! その他
298  integer:: i
299 
300  ! --- 実行部 ---
301  ! 初期化
302  if (associated(u%name)) deallocate(u%name)
303  if (associated(u%power)) deallocate(u%power)
304  u%nelems = 0
305  u%offset = ""
306  u%factor = 1.0_dp
307  if (cunits == "") return
308  call dcunitssetline(cunits)
309  call ustack_clear
310  call pstack_clear
311  yparse_status = y_init
312 
313  do
314  call dcunitsgettoken(ltype, ivalue, dvalue, cvalue)
315  select case(ltype)
316  case (s_integer)
317  select case(yparse_status)
318  case (y_init, y_mul)
319  pstack(pi)%factor = pstack(pi)%factor * ivalue(1)
320  yparse_status = y_number
321  case (y_name, y_nx)
322  i = pstack(pi)%power_exp
323  ustack(i:ui)%power = ustack(i:ui)%power * ivalue(1)
324  call power_next
325  yparse_status = y_ni
326  case (y_shift)
327  u%offset = cvalue
328  case default
329  call error
330  end select
331  case (s_real)
332  select case(yparse_status)
333  case (y_init, y_mul)
334  pstack(pi)%factor = pstack(pi)%factor * dvalue
335  yparse_status = y_number
336  case (y_name, y_nx)
337  i = pstack(pi)%power_exp
338  ustack(i:ui)%power = ustack(i:ui)%power * dvalue
339  call power_next
340  yparse_status = y_ni
341  case (y_shift)
342  u%offset = cvalue
343  case default
344  call error
345  end select
346  case (s_text)
347  select case(yparse_status)
348  case (y_init, y_number, y_mul)
349  ustack(ui)%name = cvalue
350  yparse_status = y_name
351  case (y_name, y_ni)
352  call ustack_grow
353  call power_next
354  ustack(ui)%name = cvalue
355  yparse_status = y_name
356  case (y_shift)
357  u%offset = cvalue
358  case default
359  call error
360  end select
361  case (s_exponent)
362  select case(yparse_status)
363  case (y_name)
364  yparse_status = y_nx
365  case default
366  call error
367  end select
368  case (s_multiply)
369  select case(yparse_status)
370  case (y_number, y_name)
371  call factor_next
372  yparse_status = y_mul
373  case default
374  call error
375  end select
376  case (s_divide)
377  select case(yparse_status)
378  case (y_number, y_name)
379  call factor_next
380  pstack(pi)%factor_inv = .true.
381  yparse_status = y_mul
382  case default
383  call error
384  end select
385  case (s_shift)
386  if (yparse_status == y_nx) call cancel_exp
387  call units_finalize
388  yparse_status = y_shift
389  case (s_openpar)
390  if (yparse_status == y_nx) call cancel_exp
391  call pstack_push
392  case (s_closepar)
393  call units_finalize
394  call pstack_pop
395  case (s_eof)
396  exit
397  case default
398  call error
399  end select
400  enddo
401  if (yparse_status == y_nx) call cancel_exp
402  call units_finalize
403 
404  u%nelems = ui
405  u%factor = product(ustack(1:ui)%factor)
406  call units_simplify(u, ustack(1:ui)%name, ustack(1:ui)%power)
407 
408  contains
409 
410  subroutine cancel_exp
411  print *, operator"DCUnitsBuild: syntax error, (**) ignored"
412  end subroutine cancel_exp
413 
414  subroutine error
415  print *, "DCUnitsBuild: unexpected token <", &
416  & trim(cvalue), "> ignored"
417  end subroutine error
418 
419  subroutine power_next
420  ! power_exp の終了処理
421  call ustack_grow
422  pstack(pi)%power_exp = ui
423  end subroutine power_next
424 
425  subroutine factor_next
426  ! factor_exp の終了処理
427  real(DP):: factor
428  i = pstack(pi)%factor_exp
429  factor = product(ustack(i:ui)%factor) * pstack(pi)%factor
430  if (pstack(pi)%factor_inv) then
431  ustack(i:ui)%power = -ustack(i:ui)%power
432  factor = 1.0_dp / factor
433  endif
434  ustack(i)%factor = factor
435  ustack(i+1:ui)%factor = 1.0_dp
436  call power_next
437  pstack(pi)%factor = 1.0_dp
438  pstack(pi)%factor_exp = ui
439  end subroutine factor_next
440 
441  subroutine units_finalize
442  call factor_next
443  end subroutine units_finalize
444 
445  subroutine ustack_clear
446  ui = 0
447  call ustack_grow
448  end subroutine ustack_clear
449 
450  subroutine ustack_grow
451  if (ui >= size(ustack)) stop 'DCUnitsBuild: too many elements'
452  ui = ui + 1
453  ustack(ui)%name = ""
454  ustack(ui)%factor = 1.0_dp
455  ustack(ui)%power = 1.0_dp
456  end subroutine ustack_grow
457 
458  subroutine pstack_clear
459  pi = 0
460  call pstack_push
461  end subroutine pstack_clear
462 
463  subroutine pstack_push
464  if (pi >= size(pstack)) stop 'DCUnitsBuild: too many parens'
465  pi = pi + 1
466  call ustack_grow
467  pstack(pi)%factor_exp = ui
468  pstack(pi)%factor = 1.0_dp
469  pstack(pi)%factor_inv = .false.
470  pstack(pi)%power_exp = ui
471  pstack(pi)%paren_exp = ui
472  end subroutine pstack_push
473 
474  subroutine pstack_pop
475  ! factor_exp の終了処理
476  call power_next
477  pi = pi - 1
478  end subroutine pstack_pop
479 
integer, parameter, public s_exponent
Definition: dcunits_com.f90:34
subroutine ustack_clear
Definition: dc_units.f90:446
integer, parameter, public s_eof
Definition: dcunits_com.f90:29
integer, parameter, public s_openpar
Definition: dcunits_com.f90:35
subroutine error
Definition: dc_units.f90:415
integer, parameter, public s_shift
Definition: dcunits_com.f90:30
integer, parameter, public s_real
Definition: dcunits_com.f90:37
subroutine ustack_grow
Definition: dc_units.f90:451
subroutine cancel_exp
Definition: dc_units.f90:411
subroutine factor_next
Definition: dc_units.f90:426
integer, parameter, public s_divide
Definition: dcunits_com.f90:33
subroutine power_next
Definition: dc_units.f90:420
subroutine pstack_pop
Definition: dc_units.f90:475
integer, parameter, public s_multiply
Definition: dcunits_com.f90:32
integer, parameter, public s_closepar
Definition: dcunits_com.f90:36
integer, parameter, public s_text
Definition: dcunits_com.f90:31
subroutine, public dcunitsgettoken(tokentype, ivalue, dvalue, cvalue)
Definition: dcunits_com.f90:54
subroutine, public dcunitssetline(line)
Definition: dcunits_com.f90:47
integer, save, private i
Definition: dcunits_com.f90:42
integer, parameter, public s_integer
Definition: dcunits_com.f90:38
subroutine pstack_push
Definition: dc_units.f90:464
subroutine units_finalize
Definition: dc_units.f90:442
subroutine pstack_clear
Definition: dc_units.f90:459
Here is the call graph for this function:

◆ dcunitsclear()

subroutine dc_units::dcunitsclear ( type(units), intent(inout)  u)
private

Definition at line 194 of file dc_units.f90.

194  type(units), intent(inout):: u
195  nullify(u%name)
196  nullify(u%power)
197  u%factor = 1.0_dp
198  u%offset = ""
199  u%nelems = 0

◆ dcunitsdeallocate()

subroutine dc_units::dcunitsdeallocate ( type(units), intent(inout)  u)
private

Definition at line 203 of file dc_units.f90.

203  type(units), intent(inout):: u
204  if (associated(u%name)) deallocate(u%name)
205  if (associated(u%power)) deallocate(u%power)
206  u%factor = 1.0_dp
207  u%offset = ""
208  u%nelems = 0

◆ dcunitsdiv()

type(units) function dc_units::dcunitsdiv ( type(units), intent(in)  u1,
type(units), intent(in)  u2 
)
private

Definition at line 118 of file dc_units.f90.

References units_simplify().

118  type(units), intent(in):: u1, u2
119  integer:: n, n1
120  character(TOKEN), allocatable:: name(:)
121  real(DP), allocatable:: power(:)
122  if (abs(u2%factor) < tiny(u2%factor)) then
123  result%factor = sign(u1%factor, 1.0_dp) * &
124  & sign(u2%factor, 1.0_dp) * &
125  & huge(1.0_dp)
126  else
127  result%factor = u1%factor / u2%factor
128  endif
129  result%nelems = u1%nelems + u2%nelems
130  result%offset = ""
131  n = result%nelems
132  if (n == 0) then
133  nullify(result%name, result%power)
134  return
135  endif
136  allocate(name(n), power(n))
137  n1 = u1%nelems
138  if (n1 >= 1) then
139  name(1:n1) = u1%name(1:n1)
140  power(1:n1) = u1%power(1:n1)
141  endif
142  n1 = n1 + 1
143  if (n >= n1) then
144  name(n1:n) = u2%name(1:u2%nelems)
145  power(n1:n) = -u2%power(1:u2%nelems)
146  endif
147  call units_simplify(result, name, power)
148  deallocate(name, power)
Here is the call graph for this function:

◆ dcunitsmul()

type(units) function dc_units::dcunitsmul ( type(units), intent(in)  u1,
type(units), intent(in)  u2 
)
private

Definition at line 98 of file dc_units.f90.

References units_simplify().

98  type(units), intent(in):: u1, u2
99  integer:: n
100  character(TOKEN), allocatable:: name(:)
101  real(DP), allocatable:: power(:)
102  result%factor = u1%factor * u2%factor
103  result%nelems = u1%nelems + u2%nelems
104  result%offset = ""
105  n = result%nelems
106  if (n == 0) then
107  nullify(result%name, result%power)
108  return
109  endif
110  allocate(name(n), power(n))
111  name = (/u1%name, u2%name/)
112  power = (/u1%power, u2%power/)
113  call units_simplify(result, name, power)
114  deallocate(name, power)
Here is the call graph for this function:

◆ dcunitstostring()

subroutine dc_units::dcunitstostring ( character(*), intent(out)  string,
type(units), intent(in)  u 
)
private

Definition at line 212 of file dc_units.f90.

212  !
213  ! UNITS 型変数から文字型変数を生成します。
214  !
215  character(*), intent(out):: string
216  type(units), intent(in):: u
217  integer:: i, ip, npower
218  character(TOKEN):: buffer
219  character:: mul = '.'
220  real(DP), parameter:: allowed = epsilon(1.0_dp) * 16.0
221 
222  if (u%nelems < 0) then
223  string = 'error from ' // u%offset
224  return
225  endif
226 
227  write(buffer, "(1pg20.12)") u%factor
228  string = buffer
229  if (u%nelems < 1) return
230 
231  if (abs(u%factor - 1.0) < allowed) then
232  string = ""
233  else if (abs(u%factor + 1.0) < allowed) then
234  string = "-"
235  endif
236 
237  ip = len_trim(string) + 1
238  do, i = 1, u%nelems
239  npower = nint(u%power(i))
240  if (abs(1.0 - u%power(i)) < allowed) then
241  buffer = " "
242  else if (abs(npower - u%power(i)) < allowed) then
243  write(buffer, "(i10)") npower
244  buffer = adjustl(buffer)
245  else
246  write(buffer, "(1pg10.3)") u%power(i)
247  buffer = adjustl(buffer)
248  endif
249  if (buffer == '0') cycle
250  string = trim(string) // mul // trim(u%name(i)) // trim(buffer)
251  enddo
252  if (ip <= len(string)) string(ip:ip) = ' '
253  if (string(1:1) == " ") string = adjustl(string)
254  if (u%offset /= "") then
255  string = trim(string) // '@' // trim(u%offset)
256  endif
integer, save, private i
Definition: dcunits_com.f90:42
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition: dc_types.f90:118

◆ units_simplify()

subroutine, private dc_units::units_simplify ( type(units), intent(inout)  u,
character(*), dimension(u%nelems), intent(in)  name,
real(dp), dimension(u%nelems), intent(in)  power 
)
private

Definition at line 63 of file dc_units.f90.

Referenced by dcunitsbuild(), dcunitsdiv(), and dcunitsmul().

63  type(units), intent(inout):: u
64  character(*), intent(in):: name(u%nelems)
65  real(DP), intent(in):: power(u%nelems)
66  integer:: i, n, j, onazi
67  integer:: table(u%nelems)
68 
69  if (u%nelems < 1) return
70  table(:) = 0
71  n = 0
72  do, i = 1, u%nelems
73  if (name(i) == '') cycle
74  onazi = 0
75  do, j = 1, i - 1
76  if (name(j) == name(i)) then
77  onazi = j
78  endif
79  enddo
80  if (onazi > 0) then
81  table(i) = table(onazi)
82  else
83  n = n + 1
84  table(i) = n
85  endif
86  enddo
87  allocate(u%name(n), u%power(n))
88  u%power = 0.0_dp
89  do, i = 1, u%nelems
90  if (table(i) == 0) cycle
91  u%name(table(i)) = name(i)
92  u%power(table(i)) = u%power(table(i)) + power(i)
93  enddo
94  u%nelems = n
integer, save, private i
Definition: dcunits_com.f90:42
Here is the caller graph for this function: