|
1 | | -#!/bin/env python |
| 1 | +#!/usr/bin/env python3 |
2 | 2 | # \author Hans J. Johnson |
3 | 3 | # |
4 | | -# Prepare for the future by recommending |
5 | | -# use of itk::Math:: functions over |
6 | | -# vnl_math:: functions. |
7 | | -# Rather than converting vnl_math_ to vnl_math:: |
8 | | -# this prefers to convert directly to itk::Math:: |
9 | | -# namespace. In cases where vnl_math:: is simply |
10 | | -# an alias to std:: functions, itk::Math directly |
11 | | -# uses the std:: version of the function. |
| 4 | +# Migrate a source file away from deprecated vnl_math usage, preferring |
| 5 | +# replacements that compile under C++17: |
| 6 | +# - vnl_math:: constants, functions, and predicates -> itk::Math:: equivalents |
| 7 | +# - vnl_math:: re-exports of std functions (max/min/cbrt/hypot) -> std:: |
| 8 | +# - vnl_math::abs / vnl_math_abs -> itk::Math::Absolute |
| 9 | +# - legacy vnl_math_* global-function spellings -> the same modern targets |
| 10 | +# - "vnl/vnl_math.h" include -> "itkMath.h" |
| 11 | +# vnl_huge_val cannot be rewritten textually (the replacement type depends on |
| 12 | +# context); occurrences are reported for manual migration to |
| 13 | +# std::numeric_limits<T>::infinity() or itk::NumericTraits<T>::max(). |
12 | 14 |
|
13 | | -import os |
14 | 15 | import sys |
15 | 16 | from collections import OrderedDict |
| 17 | +from pathlib import Path |
16 | 18 |
|
17 | | -## slight modification from grep command |
18 | | -info_for_conversion = """ |
19 | | -XXXX,vnl_math_isnan,itk::Math::isnan |
20 | | -XXXX,vnl_math_isinf,itk::Math::isinf |
21 | | -XXXX,vnl_math_isfinite,itk::Math::isfinite |
22 | | -XXXX,vnl_math_isnormal,itk::Math::isnormal |
23 | | -XXXX,vnl_math_max,std::max |
24 | | -XXXX,vnl_math_min,std::min |
25 | | -XXXX,vnl_math_cuberoot,itk::Math::cbrt |
26 | | -XXXX,vnl_math_hypot,itk::Math::hypot |
27 | | -XXXX,vnl_math_angle_0_to_2pi,itk::Math::angle_0_to_2pi |
28 | | -XXXX,vnl_math_angle_minuspi_to_pi,itk::Math::angle_minuspi_to_pi |
29 | | -XXXX,vnl_math_rnd_halfinttoeven,itk::Math::halfinttoeven |
30 | | -XXXX,vnl_math_rnd_halfintup,itk::Math::rnd_halfintup |
31 | | -XXXX,vnl_math_rnd,itk::Math::rnd |
32 | | -XXXX,vnl_math_floor,itk::Math::floor |
33 | | -XXXX,vnl_math_ceil,itk::Math::ceil |
34 | | -XXXX,vnl_math_abs,itk::Math::Absolute |
35 | | -XXXX,vnl_math_sqr,itk::Math::sqr |
36 | | -XXXX,vnl_math_cube,itk::Math::cube |
37 | | -XXXX,vnl_math_sgn,itk::Math::sgn |
38 | | -XXXX,vnl_math_sgn0,itk::Math::sgn0 |
39 | | -XXXX,vnl_math_squared_magnitude,itk::Math::squared_magnitude |
40 | | -XXXX,vnl_math_remainder_truncated,itk::Math::remainder_truncated |
41 | | -XXXX,vnl_math_remainder_floored,itk::Math::remainder_floored |
42 | | -""" |
| 19 | +replacements = OrderedDict() |
43 | 20 |
|
44 | | -ITK_replace_head_names = OrderedDict() |
45 | | -ITK_replace_functionnames = OrderedDict() |
46 | | -ITK_replace_manual = OrderedDict() |
| 21 | +# Includes. |
| 22 | +replacements['"vnl/vnl_math.h"'] = '"itkMath.h"' |
| 23 | +replacements["<vnl/vnl_math.h>"] = "<itkMath.h>" |
47 | 24 |
|
48 | | -ITK_replace_manual['"vnl/vnl_math.h"'] = '"itkMath.h"' |
49 | | -ITK_replace_manual["<vnl/vnl_math.h>"] = "<itkMath.h>" |
| 25 | +# Namespace spellings whose itk::Math name differs (must precede the catch-all). |
| 26 | +replacements["vnl_math::max"] = "std::max" |
| 27 | +replacements["vnl_math::min"] = "std::min" |
| 28 | +replacements["vnl_math::cbrt"] = "std::cbrt" |
| 29 | +replacements["vnl_math::hypot"] = "std::hypot" |
| 30 | +replacements["vnl_math::abs"] = "itk::Math::Absolute" |
50 | 31 |
|
51 | | -for line in info_for_conversion.splitlines(): |
52 | | - linevalues = line.split(",") |
53 | | - if len(linevalues) != 3: |
54 | | - # print("SKIPPING: " + str(linevalues)) |
55 | | - continue |
56 | | - fname = linevalues[0] |
57 | | - new_name = fname.replace("ITK_", "").replace(".h", "") |
58 | | - ITK_replace_head_names[ |
59 | | - f'#include "{fname}"' |
60 | | - ] = f"""#if !defined( ITK_LEGACY_FUTURE_REMOVE ) |
61 | | -# include "{fname}" |
62 | | -#endif |
63 | | -#include <{new_name}>""" |
64 | | - ITK_replace_head_names[ |
65 | | - f"#include <{fname}>" |
66 | | - ] = f"""#if !defined( ITK_LEGACY_FUTURE_REMOVE ) |
67 | | -# include <{fname}> |
68 | | -#endif |
69 | | -#include <{new_name}>""" |
70 | | - ITK_pat = linevalues[1] |
71 | | - new_pat = linevalues[2] |
72 | | - ITK_replace_functionnames[ITK_pat] = new_pat |
73 | | - # Need to fix the fact that both std::ios is a base and a prefix |
74 | | - if "std::ios::" in new_pat: |
75 | | - ITK_replace_manual[new_pat.replace("std::ios::", "std::ios_")] = new_pat |
| 32 | +# Catch-all: every other deprecated vnl_math:: member (constants, the 14 |
| 33 | +# functions, isnan/isinf/isfinite/isnormal) maps name-identically. |
| 34 | +replacements["vnl_math::"] = "itk::Math::" |
76 | 35 |
|
77 | | -# print(ITK_replace_head_names) |
78 | | -# print(ITK_replace_functionnames) |
| 36 | +# Legacy global-function spellings. Longer names precede their prefixes so |
| 37 | +# sequential str.replace cannot corrupt them. |
| 38 | +replacements["vnl_math_isnan"] = "itk::Math::isnan" |
| 39 | +replacements["vnl_math_isinf"] = "itk::Math::isinf" |
| 40 | +replacements["vnl_math_isfinite"] = "itk::Math::isfinite" |
| 41 | +replacements["vnl_math_isnormal"] = "itk::Math::isnormal" |
| 42 | +replacements["vnl_math_max"] = "std::max" |
| 43 | +replacements["vnl_math_min"] = "std::min" |
| 44 | +replacements["vnl_math_cuberoot"] = "std::cbrt" |
| 45 | +replacements["vnl_math_hypot"] = "std::hypot" |
| 46 | +replacements["vnl_math_abs"] = "itk::Math::Absolute" |
| 47 | +replacements["vnl_math_angle_0_to_2pi"] = "itk::Math::angle_0_to_2pi" |
| 48 | +replacements["vnl_math_angle_minuspi_to_pi"] = "itk::Math::angle_minuspi_to_pi" |
| 49 | +replacements["vnl_math_rnd_halfinttoeven"] = "itk::Math::rnd_halfinttoeven" |
| 50 | +replacements["vnl_math_rnd_halfintup"] = "itk::Math::rnd_halfintup" |
| 51 | +replacements["vnl_math_rnd"] = "itk::Math::rnd" |
| 52 | +replacements["vnl_math_floor"] = "itk::Math::floor" |
| 53 | +replacements["vnl_math_ceil"] = "itk::Math::ceil" |
| 54 | +replacements["vnl_math_sqr"] = "itk::Math::sqr" |
| 55 | +replacements["vnl_math_cube"] = "itk::Math::cube" |
| 56 | +replacements["vnl_math_sgn0"] = "itk::Math::sgn0" |
| 57 | +replacements["vnl_math_sgn"] = "itk::Math::sgn" |
| 58 | +replacements["vnl_math_squared_magnitude"] = "itk::Math::squared_magnitude" |
| 59 | +replacements["vnl_math_remainder_truncated"] = "itk::Math::remainder_truncated" |
| 60 | +replacements["vnl_math_remainder_floored"] = "itk::Math::remainder_floored" |
79 | 61 |
|
80 | | -cfile = sys.argv[1] |
81 | 62 |
|
82 | | -file_as_string = "" |
83 | | -with open(cfile) as rfp: |
84 | | - original_string = rfp.read() |
85 | | -file_as_string = original_string |
| 63 | +def main() -> int: |
| 64 | + cfile = Path(sys.argv[1]) |
| 65 | + original_string = cfile.read_text() |
| 66 | + file_as_string = original_string |
86 | 67 |
|
87 | | -required_header = "" ## For ITK, this is always empty |
| 68 | + for searchval, replaceval in replacements.items(): |
| 69 | + file_as_string = file_as_string.replace(searchval, replaceval) |
88 | 70 |
|
89 | | -for searchval, replaceval in ITK_replace_head_names.items(): |
90 | | - file_as_string_new = file_as_string.replace(searchval, required_header + replaceval) |
91 | | - if file_as_string_new != file_as_string: |
92 | | - required_header = "" |
93 | | - file_as_string = file_as_string_new |
| 71 | + if "vnl_huge_val" in file_as_string: |
| 72 | + print( |
| 73 | + f"MANUAL FIX NEEDED: {cfile}: vnl_huge_val -> " |
| 74 | + "std::numeric_limits<T>::infinity() or itk::NumericTraits<T>::max()" |
| 75 | + ) |
94 | 76 |
|
| 77 | + if file_as_string != original_string: |
| 78 | + print(f"Processing: {cfile}") |
| 79 | + cfile.write_text(file_as_string) |
| 80 | + else: |
| 81 | + print(f"SKIPPING: {cfile}") |
| 82 | + return 0 |
95 | 83 |
|
96 | | -for searchval, replaceval in ITK_replace_functionnames.items(): |
97 | | - file_as_string = file_as_string.replace(searchval, replaceval) |
98 | | -for searchval, replaceval in ITK_replace_manual.items(): |
99 | | - file_as_string = file_as_string.replace(searchval, replaceval) |
100 | | -if file_as_string != original_string: |
101 | | - print(f"Processing: {cfile}") |
102 | | - with open(cfile, "w") as wfp: |
103 | | - wfp.write(file_as_string) |
104 | | -else: |
105 | | - print(f"SKIPPING: {cfile}") |
| 84 | + |
| 85 | +if __name__ == "__main__": |
| 86 | + sys.exit(main()) |
0 commit comments