mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
7.7 KiB
272 lines
7.7 KiB
appdoc = """ |
|
This is generator of CLapack subset. |
|
The usage: |
|
|
|
1. Make sure you have the special version of f2c installed. |
|
Grab it from https://github.com/vpisarev/f2c/tree/for_lapack. |
|
2. Download fresh version of Lapack from |
|
https://github.com/Reference-LAPACK/lapack. |
|
You may choose some specific version or the latest snapshot. |
|
3. If necessary, edit "roots" and "banlist" variables in this script, specify the needed and unneeded functions |
|
4. From within a working directory run |
|
|
|
$ python3 <opencv_root>/3rdparty/clapack/make_clapack.py <lapack_root> |
|
or |
|
$ F2C=<path_to_custom_f2c> python3 <opencv_root>/3rdparty/clapack/make_clapack.py <lapack_root> |
|
|
|
it will generate "new_clapack" directory with "include" and "src" subdirectories. |
|
5. erase opencv/3rdparty/clapack/src and replace it with new_clapack/src. |
|
6. copy new_clapack/include/lapack.h to opencv/3rdparty/clapack/include. |
|
7. optionally, edit opencv/3rdparty/clapack/CMakeLists.txt and update CLAPACK_VERSION as needed. |
|
|
|
This is it. Now build it and enjoy. |
|
""" |
|
|
|
import glob, re, os, shutil, subprocess, sys |
|
|
|
roots = ["cgemm_", "dgemm_", "sgemm_", "zgemm_", |
|
"dgeev_", "dgesdd_", |
|
#"dsyevr_", |
|
#"dgesv_", "dgetrf_", "dposv_", "dpotrf_", "dgels_", "dgeqrf_", |
|
#"sgesv_", "sgetrf_", "sposv_", "spotrf_", "sgels_", "sgeqrf_" |
|
] |
|
banlist = ["slamch_", "slamc3_", "dlamch_", "dlamc3_", "lsame_", "xerbla_"] |
|
|
|
if len(sys.argv) < 2: |
|
print(appdoc) |
|
sys.exit(0) |
|
|
|
lapack_root = sys.argv[1] |
|
dst_path = "." |
|
|
|
def error(msg): |
|
print ("error: " + msg) |
|
sys.exit(0) |
|
|
|
def file2fun(fname): |
|
return (os.path.basename(fname)[:-2]).upper() |
|
|
|
def print_graph(m): |
|
for (k, neighbors) in sorted(m.items()): |
|
print (k + " : " + ", ".join(sorted(list(neighbors)))) |
|
|
|
blas_path = os.path.join(lapack_root, "BLAS/SRC") |
|
lapack_path = os.path.join(lapack_root, "SRC") |
|
|
|
roots = [f[:-1].upper() for f in roots] |
|
banlist = [f[:-1].upper() for f in banlist] |
|
|
|
def fun2file(func): |
|
filename = func.lower() + ".f" |
|
blas_loc = blas_path + "/" + filename |
|
lapack_loc = lapack_path + "/" + filename |
|
if os.path.exists(blas_loc): |
|
return blas_loc |
|
elif os.path.exists(lapack_loc): |
|
return lapack_loc |
|
else: |
|
error("neither %s nor %s exist" % (blas_loc, lapack_loc)) |
|
|
|
all_files = glob.glob(blas_path + "/*.f") + glob.glob(lapack_path + "/*.f") |
|
all_funcs = [file2fun(fname) for fname in all_files] |
|
all_funcs_set = set(all_funcs).difference(set(banlist)) |
|
all_funcs = sorted(list(all_funcs_set)) |
|
|
|
func_deps = {} |
|
|
|
#print all_funcs |
|
|
|
words_regexp = re.compile(r'\w+') |
|
|
|
def scan_deps(func): |
|
global func_deps |
|
if func in func_deps: |
|
return |
|
func_deps[func] = set([]) # to avoid possibly infinite recursion |
|
f = open(fun2file(func), 'rt') |
|
deps = [] |
|
external_mode = False |
|
for l in f.readlines(): |
|
if l.startswith('*'): |
|
continue |
|
l = l.strip().upper() |
|
if l.startswith('EXTERNAL '): |
|
external_mode = True |
|
elif l.startswith('$') and external_mode: |
|
pass |
|
else: |
|
external_mode = False |
|
if not external_mode: |
|
continue |
|
for w in words_regexp.findall(l): |
|
if w in all_funcs_set: |
|
deps.append(w) |
|
f.close() |
|
# remove func from its dependencies |
|
deps = set(deps).difference(set([func])) |
|
func_deps[func] = deps |
|
for d in deps: |
|
scan_deps(d) |
|
|
|
for r in roots: |
|
scan_deps(r) |
|
|
|
selected_funcs = sorted(func_deps.keys()) |
|
print ("total files before amalgamation: %d" % len(selected_funcs)) |
|
|
|
inv_deps = {} |
|
for func in selected_funcs: |
|
inv_deps[func] = set([]) |
|
|
|
for (func, deps) in func_deps.items(): |
|
for d in deps: |
|
inv_deps[d] = inv_deps[d].union(set([func])) |
|
|
|
#print_graph(inv_deps) |
|
|
|
func_home = {} |
|
for func in selected_funcs: |
|
func_home[func] = func |
|
|
|
def get_home0(func, func0): |
|
used_by = inv_deps[func] |
|
if len(used_by) == 1: |
|
p = list(used_by)[0] |
|
if p != func and p != func0: |
|
return get_home0(p, func0) |
|
return func |
|
return func |
|
|
|
# try to merge some files |
|
for func in selected_funcs: |
|
func_home[func] = get_home0(func, func) |
|
|
|
# try to merge some files even more |
|
for iters in range(100): |
|
homes_changed = False |
|
for (func, used_by) in inv_deps.items(): |
|
p0 = func_home[func] |
|
n = len(used_by) |
|
if n == 1: |
|
p = list(used_by)[0] |
|
p1 = func_home[p] |
|
if p1 != p0: |
|
func_home[func] = p1 |
|
homes_changed = True |
|
continue |
|
elif n > 1: |
|
phomes = set([]) |
|
for p in used_by: |
|
phomes.add(func_home[p]) |
|
if len(phomes) == 1: |
|
p1 = list(phomes)[0] |
|
if p1 != p0: |
|
func_home[func] = p1 |
|
homes_changed = True |
|
if not homes_changed: |
|
break |
|
|
|
res_files = {} |
|
for (func, h) in func_home.items(): |
|
elems = res_files.get(h, set([])) |
|
elems.add(func) |
|
res_files[h] = elems |
|
|
|
print ("total files after amalgamation: %d" % len(res_files)) |
|
#print_graph(res_files) |
|
|
|
outdir = os.path.join(dst_path, "new_clapack") |
|
outdir_src = os.path.join(outdir, "src") |
|
outdir_inc = os.path.join(outdir, "include") |
|
|
|
shutil.rmtree(outdir, ignore_errors=True) |
|
try: |
|
os.makedirs(outdir_src) |
|
except os.error: |
|
pass |
|
try: |
|
os.makedirs(outdir_inc) |
|
except os.error: |
|
pass |
|
|
|
f2c_appname = os.getenv("F2C", default="f2c") |
|
print ("f2c used: %s" % f2c_appname) |
|
|
|
f2c_getver_cmd = f2c_appname + " -v" |
|
|
|
verstr = subprocess.check_output(f2c_getver_cmd.split(' ')).decode("utf-8") |
|
if "for_lapack" not in verstr: |
|
error("invalid version of f2c\n" + appdoc) |
|
|
|
f2c_flags = "-ctypes -localconst -no-proto" |
|
f2c_cmd0 = f2c_appname + " " + f2c_flags |
|
f2c_cmd1 = f2c_appname + " -hdr none " + f2c_flags |
|
|
|
lapack_protos = {} |
|
extract_fn_regexp = re.compile(r'.+?(\w+)\s*\(') |
|
|
|
def extract_proto(func, csrc): |
|
global lapack_protos |
|
cname = func.lower() + "_" |
|
cfname = func.lower() + ".c" |
|
regexp_str = r'\n(?:/\* Subroutine \*/\s*)?\w+\s+\w+\s*\((?:.|\n)+?\)[\s\n]*\{' |
|
proto_regexp = re.compile(regexp_str) |
|
ps = proto_regexp.findall(csrc) |
|
for p in ps: |
|
n = p.find("*/") |
|
if n < 0: |
|
n = 0 |
|
else: |
|
n += 2 |
|
p = p[n:-1].strip() + ";" |
|
fns = extract_fn_regexp.findall(p) |
|
if len(fns) != 1: |
|
error("prototype of function (%s) when analyzing %s cannot be parsed" % (p, cfname)) |
|
fn = fns[0] |
|
if fn not in lapack_protos: |
|
p = re.sub(r'\bcomplex\b', 'lapack_complex', p) |
|
p = re.sub(r'\bdoublecomplex\b', 'lapack_doublecomplex', p) |
|
lapack_protos[fn] = p |
|
|
|
for (filename, funcs) in sorted(res_files.items()): |
|
out = "" |
|
f2c_cmd = f2c_cmd0 |
|
for func in sorted(list(funcs)): |
|
ffilename = fun2file(func) |
|
print ("running " + f2c_cmd + " on " + ffilename + " ...") |
|
ffile = open(ffilename, 'rt') |
|
delta_out = subprocess.check_output(f2c_cmd.split(' '), stdin=ffile).decode("utf-8") |
|
# remove trailing whitespaces |
|
delta_out = '\n'.join([l.rstrip() for l in delta_out.split('\n')]) |
|
extract_proto(func, delta_out) |
|
out += delta_out |
|
ffile.close() |
|
f2c_cmd = f2c_cmd1 |
|
outname = os.path.join(outdir_src, filename.lower() + ".c") |
|
outfile = open(outname, 'wt') |
|
outfile.write(out) |
|
outfile.close() |
|
|
|
proto_hdr = """// this is auto-generated header for Lapack subset |
|
#ifndef __CLAPACK_H__ |
|
#define __CLAPACK_H__ |
|
|
|
#include "cblas.h" |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
%s |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
#endif |
|
""" % "\n\n".join([p for (n, p) in sorted(lapack_protos.items())]) |
|
|
|
proto_hdr_fname = os.path.join(outdir_inc, "lapack.h") |
|
f = open(proto_hdr_fname, 'wt') |
|
f.write(proto_hdr) |
|
f.close()
|
|
|