m4ri-20140914/0000755000175000017500000000000012405124577007643 500000000000000m4ri-20140914/m4/0000755000175000017500000000000012405124576010162 500000000000000m4ri-20140914/m4/ax_cache_size.m40000644000175000017500000001072012354166226013132 00000000000000# =========================================================================== # http://autoconf-archive.cryp.to/ax_cache_size.html # =========================================================================== # # SYNOPSIS # # AX_CACHE_SIZE # # DESCRIPTION # # Find L1 and L2 caches size by reading the corresponding file on UNIX or # by requesting cpuid. The results are available in the substituted variables # M4RI_CPU_L1_CACHE and M4RI_CPU_L2_CACHE. # # This macro depends on AX_GCC_X86_CPUID, AC_PROG_SED, and AX_CPU_VENDOR. # # LAST MODIFICATION # # 2011-04-11 # # COPYLEFT # # Copyright (c) 2008 Christophe Tournayre # # Patched by: # # Copyright (c) 2008 Martin Albrecht # Copyright (c) 2008 Arnaud Bergeron # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_CACHE_SIZE], [ AC_REQUIRE([AC_PROG_SED]) AC_REQUIRE([AX_GCC_X86_CPUID]) AC_REQUIRE([AX_CPU_VENDOR]) AX_CPU_VENDOR ax_l1_size= ax_l2_size= #Check if the variable is present if test -e /sys/devices/system/cpu/cpu0/cache/index0/size; then for idx in `seq 0 3`; do if test -e /sys/devices/system/cpu/cpu0/cache/index$idx/size ; then level=`cat /sys/devices/system/cpu/cpu0/cache/index$idx/level` size=`cat /sys/devices/system/cpu/cpu0/cache/index$idx/size` eval CPU0\_L$level\_CACHE="$size" fi done ax_l1_size=$CPU0_L1_CACHE ax_l2_size=$CPU0_L2_CACHE ax_l3_size=$CPU0_L3_CACHE else if test "x$ax_cv_cpu_vendor" != "xUnknown"; then #Or use CPUID AX_GCC_X86_CPUID(0x80000000) cpu_exthigh=`echo $ax_cv_gcc_x86_cpuid_0x80000000 | cut -d ":" -f 1` if test "x$cpu_exthi" > "x80000004"; then AX_GCC_X86_CPUID(0x80000005) # For L1 cache l1_hexval=`echo $ax_cv_gcc_x86_cpuid_0x80000005 | cut -d ":" -f 4` ax_l1_size=$((0x$l1_hexval >> 24)) fi if test "x$cpu_exthi" > "x80000005"; then AX_GCC_X86_CPUID(0x80000006) # For L2 cache l2_hexval=`echo $ax_cv_gcc_x86_cpuid_0x80000006 | cut -d ":" -f 3` ax_l2_size=$((0x$l2_hexval >> 16)) fi if test "x$cpu_exthi" > "x80000005"; then AX_GCC_X86_CPUID(0x80000006) # For L3 cache l2_hexval=`echo $ax_cv_gcc_x86_cpuid_0x80000006 | cut -d ":" -f 4` ax_l2_size=$((0x$l2_hexval >> 18))*512 fi fi #Or use sysctl sysctl_exe= if test -x /usr/sbin/sysctl ; then sysctl_exe=/usr/sbin/sysctl elif test -x /sbin/sysctl ; then sysctl_exe=/sbin/sysctl fi if test -n "$sysctl_exe"; then if test -z "$ax_l2_size" -o "$ax_l2_size" = "0"; then sysctl_out=`$sysctl_exe -n hw.l2cachesize 2>/dev/null`; if test ! -z "$sysctl_out"; then ax_l2_size=$(($sysctl_out / 1024)) fi; fi if test -z "$ax_l1_size" -o "$ax_l1_size" = "0" ; then sysctl_out=`$sysctl_exe -n hw.l1dcachesize 2>/dev/null`; if test ! -z "$sysctl_out"; then ax_l1_size=$(($sysctl_out / 1024)) fi; fi if test -z "$ax_l1_size" -o "ax_l1_size" = "0" ; then sysctl_out=`$sysctl_exe -n hw.l1cachesize 2>/dev/null`; if test ! -z "$sysctl_out"; then ax_l1_size=$(($sysctl_out / 1024)) fi; fi fi fi test -z "$ax_l1_size" && ax_l1_size=0 test -z "$ax_l2_size" && ax_l2_size=0 test -z "$ax_l3_size" && ax_l3_size=$ax_l2_size # Keep only digits if there is a unit (ie 1024K -> 1024) and convert in Bytes AC_MSG_CHECKING(the L1 cache size) ax_l1_size=`echo $ax_l1_size | $SED 's/\([[0-9]]\)[[A-Za-z]]$/\1/g'` ax_l1_size=$(($ax_l1_size*1024)) AC_MSG_RESULT( $ax_l1_size Bytes) AC_MSG_CHECKING(the L2 cache size) ax_l2_size=`echo $ax_l2_size | $SED 's/\([[0-9]]\)[[A-Za-z]]$/\1/g'` ax_l2_size=$(($ax_l2_size*1024)) AC_MSG_RESULT( $ax_l2_size Bytes) AC_MSG_CHECKING(the L3 cache size) ax_l3_size=`echo $ax_l3_size | $SED 's/\([[0-9]]\)[[A-Za-z]]$/\1/g'` ax_l3_size=$(($ax_l3_size*1024)) AC_MSG_RESULT( $ax_l3_size Bytes) M4RI_CPU_L1_CACHE=${ax_l1_size} M4RI_CPU_L2_CACHE=${ax_l2_size} M4RI_CPU_L3_CACHE=${ax_l3_size} AC_SUBST(M4RI_CPU_L1_CACHE) AC_SUBST(M4RI_CPU_L2_CACHE) AC_SUBST(M4RI_CPU_L3_CACHE) ]) m4ri-20140914/m4/ax_cache_size_tune.m40000644000175000017500000001211412354166226014164 00000000000000# SYNOPSIS # # AX_CACHE_SIZE_TUNE # # DESCRIPTION # # Find L1, L2, L3 caches size by running some timing experiments. # The results are available in the defines __M4RI_CPU_L1_CACHE, # __M4RI_CPU_L2_CACHE and __M4RI_CPU_L3_CACHE. # # This macro depends on AC_PROG_SED, AC_PROG_CC. # # LAST MODIFICATION # # 2011-04-11 # # COPYLEFT # # Copyright (c) 2009,2010 Martin Albrecht # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_CACHE_SIZE_TUNE], [ AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for cache sizes, ax_cv_cache_sizes, [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include double walltime(double t0) { double mic, time; double mega = 0.000001; struct timeval tp; static long base_sec = 0; static long base_usec = 0; (void) gettimeofday(&tp,NULL); if (base_sec == 0) { base_sec = tp.tv_sec; base_usec = tp.tv_usec; } time = (double) (tp.tv_sec - base_sec); mic = (double) (tp.tv_usec - base_usec); time = (time + mic * mega) - t0; return(time); } double run_experiment(size_t size, size_t trials) { size_t i,j; unsigned long *a = (unsigned long*)malloc(size/4); unsigned long *b = (unsigned long*)malloc(size/4); unsigned long *c = (unsigned long*)malloc(size/4); unsigned long *d = (unsigned long*)malloc(size/4); size_t n = size/4/(sizeof(unsigned long)); /* we setup a lookup table with a random-ish pattern */ a[0] = 1337; b[0] = 5345345; for(j=1; j 0.25) { _trials = _trials/2; mult = 2*mult; wt /= 2.0; result /= 2.0; } } printf("\n"); } for(i=0;i dtimes[0][max] ) { max = i; } } return candidates[max-1]; } ]], [[ const size_t c1[] = { 4, 8, 16, 32, 64, 128}; const size_t c2[] = { 128, 256, 512}; const size_t c3[] = {1024,1536,2048,3072,4096,6144,8192,16384,32768}; FILE *f; printf("\n"); size_t _l1 = cache_size(c1, 6, 1ULL<<15); size_t _l2 = cache_size(c2, 3, 1ULL<<12); size_t _l3 = cache_size(c3, 9, 1ULL<< 9); f = fopen("conftest_cache_sizes", "w"); if (!f) return 1; fprintf(f,"%lu:%lu:%lu\n",(unsigned long)(_l1*1024),(unsigned long)(_l2*1024),(unsigned long)(_l3*1024)); fclose(f); return 0; ]])], [ax_cv_cache_sizes=`cat conftest_cache_sizes`; rm -f conftest_cache_sizes], [ax_cv_cache_sizes=unknown; rm -f conftest_cache_sizes], [ax_cv_cache_sizes=unknown])]) AC_LANG_POP([C]) AC_MSG_CHECKING(the L1 cache size) ax_l1_size=`echo $ax_cv_cache_sizes | cut -d ':' -f 1` AC_MSG_RESULT( $ax_l1_size Bytes) AC_MSG_CHECKING(the L2 cache size) ax_l2_size=`echo $ax_cv_cache_sizes | cut -d ':' -f 2` AC_MSG_RESULT( $ax_l2_size Bytes) AC_MSG_CHECKING(the L3 cache size) ax_l3_size=`echo $ax_cv_cache_sizes | cut -d ':' -f 3` AC_MSG_RESULT( $ax_l3_size Bytes) M4RI_CPU_L1_CACHE=${ax_l1_size} M4RI_CPU_L2_CACHE=${ax_l2_size} M4RI_CPU_L3_CACHE=${ax_l3_size} AC_SUBST(M4RI_CPU_L1_CACHE) AC_SUBST(M4RI_CPU_L2_CACHE) AC_SUBST(M4RI_CPU_L3_CACHE) ]) m4ri-20140914/m4/ax_check_compiler_flags.m40000644000175000017500000000637712354166226015175 00000000000000# =========================================================================== # http://autoconf-archive.cryp.to/ax_check_compiler_flags.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILER_FLAGS(FLAGS, [ACTION-SUCCESS], [ACTION-FAILURE]) # # DESCRIPTION # # Check whether the given compiler FLAGS work with the current language's # compiler, or whether they give an error. (Warnings, however, are # ignored.) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # LAST MODIFICATION # # 2008-04-12 # # COPYLEFT # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Macro Archive. When you make and # distribute a modified version of the Autoconf Macro, you may extend this # special exception to the GPL to apply to your modified version as well. AC_DEFUN([AX_CHECK_COMPILER_FLAGS], [AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1]) dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname: AS_LITERAL_IF([$1], [AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1), [ ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$1" AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes, AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no) _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])], [ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$1" AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes, eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no) _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS]) eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1) AC_MSG_RESULT($ax_check_compiler_flags) if test "x$ax_check_compiler_flags" = xyes; then m4_default([$2], :) else m4_default([$3], :) fi ])dnl AX_CHECK_COMPILER_FLAGS m4ri-20140914/m4/ax_cpu_vendor.m40000644000175000017500000000271212354166226013203 00000000000000# =========================================================================== # http://autoconf-archive.cryp.to/ax_cpu_vendor.html # =========================================================================== # # SYNOPSIS # # AX_CPU_VENDOR # # DESCRIPTION # # Find your CPU's vendor by requesting cpuid and define "ax_cv_cpu_vendor" # accordingly. This macro depends on AX_GCC_X86_CPUID. # # LAST MODIFICATION # # 2008-04-12 # # COPYLEFT # # Copyright (c) 2008 Christophe Tournayre # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_CPU_VENDOR], [ AC_REQUIRE([AX_GCC_X86_CPUID]) AX_GCC_X86_CPUID(0x0) AC_CACHE_CHECK(for the processor vendor, ax_cv_cpu_vendor, [ vendor=`echo $ax_cv_gcc_x86_cpuid_0x0 | cut -d ":" -f 2` case $vendor in 756e6547*) ax_cv_cpu_vendor="Intel" ;; 68747541*) ax_cv_cpu_vendor="AMD" ;; 69727943*) ax_cv_cpu_vendor="Cyrix" ;; 746e6543*) ax_cv_cpu_vendor="IDT" ;; 646f6547*) ax_cv_cpu_vendor="Natsemi Geode" ;; 52697365*) ax_cv_cpu_vendor="Rise" ;; 65736952*) ax_cv_cpu_vendor="Rise" ;; 20536953*) ax_cv_cpu_vendor="SiS" ;; *) ax_cv_cpu_vendor="Unknown" ;; esac ]) ]) m4ri-20140914/m4/ax_ext.m40000644000175000017500000000601112354166226011633 00000000000000# =========================================================================== # http://autoconf-archive.cryp.to/ax_ext.html # =========================================================================== # # SYNOPSIS # # AX_EXT # # DESCRIPTION # /# Find supported SIMD extensions by requesting cpuid. When an SIMD # extension is found, the -m"simdextensionname" is added to SIMD_CFLAGS # (only if compilator support it) (ie : if "sse2" is available "-msse2" is # added to SIMD_CFLAGS) # # This macro calls: # # AC_SUBST(SIMD_CFLAGS) # # And defines: # # HAVE_MMX / HAVE_SSE / HAVE_SSE2 / HAVE_SSE3 / HAVE_SSSE3 # # LAST MODIFICATION # # 2008-04-12 # # COPYLEFT # # Copyright (c) 2008 Christophe Tournayre # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_EXT], [ #AC_REQUIRE([AX_GCC_X86_CPUID]) AX_GCC_X86_CPUID(0x00000001) ecx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3` edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4` AC_CACHE_CHECK([whether mmx is supported], [ax_cv_have_mmx_ext], [ ax_cv_have_mmx_ext=no if test "$((0x$edx>>23&0x01))" = 1; then ax_cv_have_mmx_ext=yes fi ]) AC_CACHE_CHECK([whether sse is supported], [ax_cv_have_sse_ext], [ ax_cv_have_sse_ext=no if test "$((0x$edx>>25&0x01))" = 1; then ax_cv_have_sse_ext=yes fi ]) AC_CACHE_CHECK([whether sse2 is supported], [ax_cv_have_sse2_ext], [ ax_cv_have_sse2_ext=no if test "$((0x$edx>>26&0x01))" = 1; then ax_cv_have_sse2_ext=yes fi ]) AC_CACHE_CHECK([whether sse3 is supported], [ax_cv_have_sse3_ext], [ ax_cv_have_sse3_ext=no if test "$((0x$ecx&0x01))" = 1; then ax_cv_have_sse3_ext=yes fi ]) AC_CACHE_CHECK([whether ssse3 is supported], [ax_cv_have_ssse3_ext], [ ax_cv_have_ssse3_ext=no if test "$((0x$ecx>>9&0x01))" = 1; then ax_cv_have_ssse3_ext=yes fi ]) if test "$ax_cv_have_mmx_ext" = yes; then AC_DEFINE(HAVE_MMX,,[Support mmx instructions]) AX_CHECK_COMPILER_FLAGS(-mmmx, SIMD_CFLAGS="$SIMD_CFLAGS -mmmx", []) fi if test "$ax_cv_have_sse_ext" = yes; then AC_DEFINE(HAVE_SSE,,[Support SSE (Streaming SIMD Extensions) instructions]) AX_CHECK_COMPILER_FLAGS(-msse, SIMD_CFLAGS="$SIMD_CFLAGS -msse", []) fi if test "$ax_cv_have_sse2_ext" = yes; then AC_DEFINE(HAVE_SSE2,,[Support SSE2 (Streaming SIMD Extensions 2) instructions]) AX_CHECK_COMPILER_FLAGS(-msse2, SIMD_CFLAGS="$SIMD_CFLAGS -msse2", []) fi if test "$ax_cv_have_sse3_ext" = yes; then AC_DEFINE(HAVE_SSE3,,[Support SSE3 (Streaming SIMD Extensions 3) instructions]) AX_CHECK_COMPILER_FLAGS(-msse3, SIMD_CFLAGS="$SIMD_CFLAGS -msse3", []) fi if test "$ax_cv_have_ssse3_ext" = yes; then AC_DEFINE(HAVE_SSSE3,,[Support SSSE3 (Supplemental Streaming SIMD Extensions 3) instructions]) fi AC_SUBST(SIMD_CFLAGS) ]) m4ri-20140914/m4/ax_func_posix_memalign.m40000644000175000017500000000277212354166226015073 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_func_posix_memalign.html # =========================================================================== # # SYNOPSIS # # AX_FUNC_POSIX_MEMALIGN # # DESCRIPTION # # Some versions of posix_memalign (notably glibc 2.2.5) incorrectly apply # their power-of-two check to the size argument, not the alignment # argument. AX_FUNC_POSIX_MEMALIGN defines HAVE_POSIX_MEMALIGN if the # power-of-two check is correctly applied to the alignment argument. # # LICENSE # # Copyright (c) 2008 Scott Pakin # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 7 AC_DEFUN([AX_FUNC_POSIX_MEMALIGN], [AC_CACHE_CHECK([for working posix_memalign], [ax_cv_func_posix_memalign_works], [AC_TRY_RUN([ #include int main () { void *buffer; /* Some versions of glibc incorrectly perform the alignment check on * the size word. */ exit (posix_memalign (&buffer, sizeof(void *), 123) != 0); } ], [ax_cv_func_posix_memalign_works=yes], [ax_cv_func_posix_memalign_works=no], [ax_cv_func_posix_memalign_works=no])]) if test "$ax_cv_func_posix_memalign_works" = "yes" ; then AC_DEFINE([HAVE_POSIX_MEMALIGN], [1], [Define to 1 if `posix_memalign' works.]) fi ]) m4ri-20140914/m4/ax_gcc_x86_cpuid.m40000644000175000017500000000712512354166226013467 00000000000000# =========================================================================== # http://autoconf-archive.cryp.to/ax_gcc_x86_cpuid.html # =========================================================================== # # SYNOPSIS # # AX_GCC_X86_CPUID(OP) # # DESCRIPTION # # On Pentium and later x86 processors, with gcc or a compiler that has a # compatible syntax for inline assembly instructions, run a small program # that executes the cpuid instruction with input OP. This can be used to # detect the CPU type. # # On output, the values of the eax, ebx, ecx, and edx registers are stored # as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable # ax_cv_gcc_x86_cpuid_OP. # # If the cpuid instruction fails (because you are running a # cross-compiler, or because you are not using gcc, or because you are on # a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP # is set to the string "unknown". # # This macro mainly exists to be used in AX_GCC_ARCHFLAG. # # LAST MODIFICATION # # 2008-04-12 # # COPYLEFT # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Macro Archive. When you make and # distribute a modified version of the Autoconf Macro, you may extend this # special exception to the GPL to apply to your modified version as well. AC_DEFUN([AX_GCC_X86_CPUID], [AC_REQUIRE([AC_PROG_CC]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ int op = $1+0, eax, ebx, ecx, edx; FILE *f; /* 64-bit code is easy */ if (sizeof(long) == 8) { __asm__("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (op)); } else { __asm__("pushl %%ebx \n\t" "cpuid \n\t" "movl %%ebx, %1 \n\t" "popl %%ebx \n\t" : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) : "a" (op)); } f = fopen("conftest_cpuid", "w"); if (!f) return 1; fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); fclose(f); return 0; ])], [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown])]) AC_LANG_POP([C]) ]) m4ri-20140914/m4/ax_guess_path_header.m40000644000175000017500000000354412354166226014515 00000000000000# # SYNOPSIS # # AX_GUESS_PATH_HEADER([foo.h]) # # DESCRIPTION # # Search for header foo.h in -Ipath's found in CPPFLAGS and CFLAGS and set FOO_H_PATH to # the full directory path where foo.h was found. # If no header is found in the paths given in CPPFLAGS and CFLAGS, then lastly it looks in /usr/local/include. # # LAST MODIFICATION # # 2011-04-11 # # COPYLEFT # # Copyright (c) 2011 Carlo Wood # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_GUESS_PATH_HEADER], [ function cw_search_header_path { n=2 while test $n -le [$]#; do eval arg=\$"$n" case "$arg" in -I*) path="`echo "$arg" | sed -e 's/-I//'`" if test -e "$path/$1"; then echo "$path" return fi ;; esac n=$((n+1)) done if test -e "/usr/local/include/$1"; then echo "/usr/local/include" fi } have_realpath=`which realpath` cw_headername_uppercase=`echo "m4_toupper([$1])" | sed -e 's/[[^A-Z]]/_/g'` AC_CACHE_CHECK([if we can find [$1]], [cw_cv_"$[]cw_headername_uppercase"_path], [ cw_header_path=`eval cw_search_header_path [$1] $CPPFLAGS $CFLAGS` if test -n "$cw_header_path"; then if test "x$have_realpath" != "x"; then eval cw_cv_"$cw_headername_uppercase"_path=`realpath -s "$cw_header_path"` else eval cw_cv_"$cw_headername_uppercase"_path="$cw_header_path" fi else eval cw_cv_"$cw_headername_uppercase"_path="no" fi ]) if eval test \"\$cw_cv_"$cw_headername_uppercase"_path\" = "no"; then eval "$cw_headername_uppercase"_PATH="" else eval "$cw_headername_uppercase"_PATH=\"\$cw_cv_"$cw_headername_uppercase"_path\" fi ]) m4ri-20140914/m4/ax_guess_path_lib.m40000644000175000017500000000344312354166226014031 00000000000000# # SYNOPSIS # # AX_GUESS_PATH_LIB([foo]) # # DESCRIPTION # # Search for library foo in -Lpath's found in LDFLAGS and set LIBFOO_PATH to # the full directory path where libfoo.so was found. # If no library is found in paths given in LDFLAGS, then lastly it looks in /usr/local/lib. # # LAST MODIFICATION # # 2011-04-11 # # COPYLEFT # # Copyright (c) 2011 Carlo Wood # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_GUESS_PATH_LIB], [ function cw_search_library_path { n=2 while test $n -le [$]#; do eval arg=\$"$n" case "$arg" in -L*) path="`echo "$arg" | sed -e 's/-L//'`" if test -e "$path/lib$1.so"; then echo "$path" return fi ;; esac n=$((n+1)) done if test -e "/usr/local/lib/lib$1.so"; then echo "/usr/local/lib" fi } have_realpath=`which realpath` cw_libname_uppercase="m4_toupper([$1])" AC_CACHE_CHECK([if we can find lib[$1].so], [cw_cv_lib"$[]cw_libname_uppercase"_path], [ cw_library_path=`eval cw_search_library_path [$1] $LDFLAGS` if test -n "$cw_library_path"; then if test "x$have_realpath" != "x"; then eval cw_cv_lib"$cw_libname_uppercase"_path=`realpath -s "$cw_library_path"` else eval cw_cv_lib"$cw_libname_uppercase"_path="$cw_library_path" fi else eval cw_cv_lib"$cw_libname_uppercase"_path="no" fi ]) if eval test \"\$cw_cv_lib"$cw_libname_uppercase"_path\" = "no"; then eval LIB"$cw_libname_uppercase"_PATH="" else eval LIB"$cw_libname_uppercase"_PATH=\"\$cw_cv_lib"$cw_libname_uppercase"_path\" fi ]) m4ri-20140914/m4/ax_openmp.m40000644000175000017500000001033612354166226012336 00000000000000# =========================================================================== # http://autoconf-archive.cryp.to/ax_openmp.html # =========================================================================== # # SYNOPSIS # # AX_OPENMP([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro tries to find out how to compile programs that use OpenMP a # standard API and set of compiler directives for parallel programming # (see http://www-unix.mcs/) # # On success, it sets the OPENMP_CFLAGS/OPENMP_CXXFLAGS/OPENMP_F77FLAGS # output variable to the flag (e.g. -omp) used both to compile *and* link # OpenMP programs in the current language. # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. # # If you want to compile everything with OpenMP, you should set: # # CFLAGS="$CFLAGS $OPENMP_CFLAGS" # #OR# CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS" # #OR# FFLAGS="$FFLAGS $OPENMP_FFLAGS" # # (depending on the selected language). # # The user can override the default choice by setting the corresponding # environment variable (e.g. OPENMP_CFLAGS). # # ACTION-IF-FOUND is a list of shell commands to run if an OpenMP flag is # found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it is # not found. If ACTION-IF-FOUND is not specified, the default action will # define HAVE_OPENMP. # # LAST MODIFICATION # # 2008-04-12 # # COPYLEFT # # Copyright (c) 2008 Steven G. Johnson # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Macro Archive. When you make and # distribute a modified version of the Autoconf Macro, you may extend this # special exception to the GPL to apply to your modified version as well. AC_DEFUN([AX_OPENMP], [ AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX AC_CACHE_CHECK([for OpenMP flag of _AC_LANG compiler], ax_cv_[]_AC_LANG_ABBREV[]_openmp, [save[]_AC_LANG_PREFIX[]FLAGS=$[]_AC_LANG_PREFIX[]FLAGS ax_cv_[]_AC_LANG_ABBREV[]_openmp=unknown # Flags to try: -fopenmp (gcc), -openmp (icc), -mp (SGI & PGI), # -xopenmp (Sun), -omp (Tru64), -qsmp=omp (AIX), none ax_openmp_flags="-fopenmp -openmp -mp -xopenmp -omp -qsmp=omp none" if test "x$OPENMP_[]_AC_LANG_PREFIX[]FLAGS" != x; then ax_openmp_flags="$OPENMP_[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flags" fi for ax_openmp_flag in $ax_openmp_flags; do case $ax_openmp_flag in none) []_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[] ;; *) []_AC_LANG_PREFIX[]FLAGS="$save[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flag" ;; esac AC_TRY_LINK_FUNC(omp_set_num_threads, [ax_cv_[]_AC_LANG_ABBREV[]_openmp=$ax_openmp_flag; break]) done []_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[]FLAGS ]) if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" = "xunknown"; then m4_default([$2],:) else if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" != "xnone"; then OPENMP_[]_AC_LANG_PREFIX[]FLAGS=$ax_cv_[]_AC_LANG_ABBREV[]_openmp fi m4_default([$1], [AC_DEFINE(HAVE_OPENMP,1,[Define if OpenMP is enabled])]) fi ])dnl AX_OPENMP m4ri-20140914/m4/libtool.m40000644000175000017500000106011112404411375012003 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS m4ri-20140914/m4/ltoptions.m40000644000175000017500000003007312404411375012375 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) m4ri-20140914/m4/ltsugar.m40000644000175000017500000001042412404411375012021 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) m4ri-20140914/m4/ltversion.m40000644000175000017500000000126212404411375012365 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) m4ri-20140914/m4/lt~obsolete.m40000644000175000017500000001375612404411375012725 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) m4ri-20140914/m4/pkg.m40000644000175000017500000001302312354166226011125 00000000000000# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES m4ri-20140914/m4ri/0000755000175000017500000000000012405124577010516 500000000000000m4ri-20140914/m4ri/config.h.in0000644000175000017500000000437712404411377012470 00000000000000/* m4ri/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define when libpapi is available. */ #undef HAVE_LIBPAPI /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Support mmx instructions */ #undef HAVE_MMX /* Support aligned allocations */ #undef HAVE_MM_MALLOC /* Define if OpenMP is enabled */ #undef HAVE_OPENMP /* Define to 1 if `posix_memalign' works. */ #undef HAVE_POSIX_MEMALIGN /* Support SSE (Streaming SIMD Extensions) instructions */ #undef HAVE_SSE /* Support SSE2 (Streaming SIMD Extensions 2) instructions */ #undef HAVE_SSE2 /* Support SSE3 (Streaming SIMD Extensions 3) instructions */ #undef HAVE_SSE3 /* Support SSSE3 (Supplemental Streaming SIMD Extensions 3) instructions */ #undef HAVE_SSSE3 /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define whether debugging is enabled */ #undef NDEBUG /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION m4ri-20140914/m4ri/m4ri_config.h.in0000644000175000017500000000217012354166226013414 00000000000000#ifndef M4RI_M4RI_CONFIG_H #define M4RI_M4RI_CONFIG_H // Defines determined during configuration of m4ri. #define __M4RI_HAVE_MM_MALLOC @M4RI_HAVE_MM_MALLOC@ #define __M4RI_HAVE_POSIX_MEMALIGN @M4RI_HAVE_POSIX_MEMALIGN@ #define __M4RI_HAVE_SSE2 @M4RI_HAVE_SSE2@ #define __M4RI_HAVE_OPENMP @M4RI_HAVE_OPENMP@ #define __M4RI_CPU_L1_CACHE @M4RI_CPU_L1_CACHE@ #define __M4RI_CPU_L2_CACHE @M4RI_CPU_L2_CACHE@ #define __M4RI_CPU_L3_CACHE @M4RI_CPU_L3_CACHE@ #define __M4RI_DEBUG_DUMP (@M4RI_DEBUG_DUMP@ || @M4RI_DEBUG_MZD@) #define __M4RI_DEBUG_MZD @M4RI_DEBUG_MZD@ #define __M4RI_HAVE_LIBPNG @M4RI_HAVE_LIBPNG@ #define __M4RI_CC "@CC@" #define __M4RI_CFLAGS "@SIMD_CFLAGS@ @OPENMP_CFLAGS@ @CFLAGS@" #define __M4RI_SIMD_CFLAGS "@SIMD_CFLAGS@" #define __M4RI_OPENMP_CFLAGS "@OPENMP_CFLAGS@" // Helper macros. #define __M4RI_USE_MM_MALLOC (__M4RI_HAVE_MM_MALLOC && __M4RI_HAVE_SSE2) #define __M4RI_USE_POSIX_MEMALIGN (__M4RI_HAVE_POSIX_MEMALIGN && __M4RI_HAVE_SSE2) #define __M4RI_DD_QUIET (@M4RI_DEBUG_MZD@ && !@M4RI_DEBUG_DUMP@) #endif // M4RI_M4RI_CONFIG_H m4ri-20140914/m4ri/m4ri.h0000644000175000017500000000422612354166226011466 00000000000000/** * \file m4ri.h * \brief Main include file for the M4RI library. * * \author Gregory Bard * \author Martin Albrecht */ /****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007 Gregory Bard * Copyright (C) 2007,2008 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifndef M4RI_M4RI_H #define M4RI_M4RI_H /** * \mainpage * * M4RI is a library to do fast arithmetic with dense matrices over * \f$F_2\f$. M4RI is available under the GPLv2+ and used by the Sage * mathematics software and the PolyBoRi library. See * http://m4ri.sagemath.org for details. * * \example testsuite/test_multiplication.c */ #include #include #include #if defined(__M4RI_HAVE_SSE2) && __M4RI_HAVE_SSE2 # if !defined(__SSE2__) || !__SSE2__ # error "Your current compiler and / or CFLAGS setting doesn't allow SSE2 code. Please change that or these to the setting(s) you used when compiling M4RI." # endif #endif #if defined(__cplusplus) && !defined (_MSC_VER) extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__cplusplus) && !defined (_MSC_VER) } #endif #endif // M4RI_M4RI_H m4ri-20140914/m4ri/brilliantrussian.h0000644000175000017500000002507512405042237014175 00000000000000/** * \file brilliantrussian.h * \brief M4RI and M4RM. * * \author Gregory Bard * \author Martin Albrecht * * \note For reference see Gregory Bard; Accelerating Cryptanalysis with * the Method of Four Russians; 2006; * http://eprint.iacr.org/2006/251.pdf */ #ifndef M4RI_BRILLIANTRUSSIAN_H #define M4RI_BRILLIANTRUSSIAN_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007, 2008 Gregory Bard * Copyright (C) 2008-2010 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #include #include #include #include /** * \brief Constructs all possible \f$2^k\f$ row combinations using the gray * code table. * * \param M matrix to generate the tables from * \param r the starting row * \param c the starting column (only exact up to block) * \param k * \param T prealloced matrix of dimension \f$2^k\f$ x m->ncols * \param L prealloced table of length \f$2^k\f$ */ void mzd_make_table(mzd_t const *M, rci_t r, rci_t c, int k, mzd_t *T, rci_t *L); /** * \brief The function looks up k bits from position i,startcol in * each row and adds the appropriate row from T to the row i. * * This process is iterated for i from startrow to stoprow * (exclusive). * * \param M Matrix to operate on * \param startrow top row which is operated on * \param endrow bottom row which is operated on * \param startcol Starting column for addition * \param k M4RI parameter * \param T contains the correct row to be added * \param L Contains row number to be added */ void mzd_process_rows(mzd_t *M, rci_t startrow, rci_t endrow, rci_t startcol, int k, mzd_t const *T, rci_t const *L); /** * \brief Same as mzd_process_rows but works with two Gray code tables * in parallel. * * \param M Matrix to operate on * \param startrow top row which is operated on * \param endrow bottom row which is operated on * \param startcol Starting column for addition * \param k M4RI parameter * \param T0 contains the correct row to be added * \param L0 Contains row number to be added * \param T1 contains the correct row to be added * \param L1 Contains row number to be added */ void mzd_process_rows2(mzd_t *M, rci_t startrow, rci_t endrow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1); /** * \brief Same as mzd_process_rows but works with three Gray code tables * in parallel. * * \param M Matrix to operate on * \param startrow top row which is operated on * \param endrow bottom row which is operated on * \param startcol Starting column for addition * \param k M4RI parameter * \param T0 contains the correct row to be added * \param L0 Contains row number to be added * \param T1 contains the correct row to be added * \param L1 Contains row number to be added * \param T2 contains the correct row to be added * \param L2 Contains row number to be added */ void mzd_process_rows3(mzd_t *M, rci_t startrow, rci_t endrow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2); /** * \brief Same as mzd_process_rows but works with four Gray code tables * in parallel. * * \param M Matrix to operate on * \param startrow top row which is operated on * \param endrow bottom row which is operated on * \param startcol Starting column for addition * \param k M4RI parameter * \param T0 contains the correct row to be added * \param L0 Contains row number to be added * \param T1 contains the correct row to be added * \param L1 Contains row number to be added * \param T2 contains the correct row to be added * \param L2 Contains row number to be added * \param T3 contains the correct row to be added * \param L3 Contains row number to be added */ void mzd_process_rows4(mzd_t *M, rci_t startrow, rci_t endrow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2, mzd_t const *T3, rci_t const *L3); /** * \brief Same as mzd_process_rows but works with five Gray code tables * in parallel. * * \param M Matrix to operate on * \param startrow top row which is operated on * \param endrow bottom row which is operated on * \param startcol Starting column for addition * \param k M4RI parameter * \param T0 contains the correct row to be added * \param L0 Contains row number to be added * \param T1 contains the correct row to be added * \param L1 Contains row number to be added * \param T2 contains the correct row to be added * \param L2 Contains row number to be added * \param T3 contains the correct row to be added * \param L3 Contains row number to be added * \param T4 contains the correct row to be added * \param L4 Contains row number to be added */ void mzd_process_rows5(mzd_t *M, rci_t startrow, rci_t endrow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2, mzd_t const *T3, rci_t const *L3, mzd_t const *T4, rci_t const *L4); /** * \brief Same as mzd_process_rows but works with six Gray code tables * in parallel. * * \param M Matrix to operate on * \param startrow top row which is operated on * \param endrow bottom row which is operated on * \param startcol Starting column for addition * \param k M4RI parameter * \param T0 contains the correct row to be added * \param L0 Contains row number to be added * \param T1 contains the correct row to be added * \param L1 Contains row number to be added * \param T2 contains the correct row to be added * \param L2 Contains row number to be added * \param T3 contains the correct row to be added * \param L3 Contains row number to be added * \param T4 contains the correct row to be added * \param L4 Contains row number to be added * \param T5 contains the correct row to be added * \param L5 Contains row number to be added */ void mzd_process_rows6(mzd_t *M, rci_t startrow, rci_t endrow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2, mzd_t const *T3, rci_t const *L3, mzd_t const *T4, rci_t const *L4, mzd_t const *T5, rci_t const *L5); /** * \brief Matrix elimination using the 'Method of the Four Russians' * (M4RI). * * The M4RI algorithm was proposed in Gregory Bard; Accelerating * Cryptanalysis with the Method of Four Russians; 2006; * http://eprint.iacr.org/2006/251 * * Our implementatation is discussed in in Martin Albrecht and Clément * Pernet; Efficient Decomposition of Dense Matrices over GF(2); * http://arxiv.org/abs/1006.1744 * * \param M Matrix to be reduced. * \param full Return the reduced row echelon form, not only upper triangular form. * \param k M4RI parameter, may be 0 for auto-choose. * * \example testsuite/test_elimination.c * \example testsuite/bench_elimination.c * * \return Rank of A. */ rci_t _mzd_echelonize_m4ri(mzd_t *A, const int full, int k, int heuristic, const double threshold); /** * \brief Given a matrix in upper triangular form compute the reduced row * echelon form of that matrix. * * \param M Matrix to be reduced. * \param k M4RI parameter, may be 0 for auto-choose. * * */ void mzd_top_echelonize_m4ri(mzd_t *M, int k); /** * \brief Given a matrix in upper triangular form compute the reduced * row echelon form of that matrix but only start to do anything for * the pivot at (r,c). * * \param A Matrix to be reduced. * \param k M4RI parameter, may be 0 for auto-choose. * \param r Row index. * \param c Column index. * \param max_r Only clear top max_r rows. * * */ rci_t _mzd_top_echelonize_m4ri(mzd_t *A, int k, rci_t r, rci_t c, rci_t max_r); /** * \brief Invert the matrix src using Konrod's method. * * \param dst Matrix to hold the inverse (may be NULL) * \param src Matrix to be inverted. * \param k Table size parameter, may be 0 for automatic choice. * * * \return Inverse of src if src has full rank */ mzd_t *mzd_inv_m4ri(mzd_t *dst, const mzd_t* src, int k); /** * \brief Matrix multiplication using Konrod's method, i.e. compute C * such that C == AB. * * This is the convenient wrapper function, please see _mzd_mul_m4rm * for authors and implementation details. * * \param C Preallocated product matrix, may be NULL for automatic creation. * \param A Input matrix A * \param B Input matrix B * \param k M4RI parameter, may be 0 for auto-choose. * * * \return Pointer to C. */ mzd_t *mzd_mul_m4rm(mzd_t *C, mzd_t const *A, mzd_t const *B, int k); /** * Set C to C + AB using Konrod's method. * * This is the convenient wrapper function, please see _mzd_mul_m4rm * for authors and implementation details. * * \param C Preallocated product matrix, may be NULL for zero matrix. * \param A Input matrix A * \param B Input matrix B * \param k M4RI parameter, may be 0 for auto-choose. * * * \return Pointer to C. */ mzd_t *mzd_addmul_m4rm(mzd_t *C, mzd_t const *A, mzd_t const *B, int k); /** * \brief Matrix multiplication using Konrod's method, i.e. compute C such * that C == AB. * * This is the actual implementation. * * This function is described in Martin Albrecht, Gregory Bard and * William Hart; Efficient Multiplication of Dense Matrices over * GF(2); pre-print available at http://arxiv.org/abs/0811.1714 * * \param C Preallocated product matrix. * \param A Input matrix A * \param B Input matrix B * \param k M4RI parameter, may be 0 for auto-choose. * \param clear clear the matrix C first * * \author Martin Albrecht -- initial implementation * \author William Hart -- block matrix implementation, use of several * Gray code tables, general speed-ups * * * \return Pointer to C. */ mzd_t *_mzd_mul_m4rm(mzd_t *C, mzd_t const *A, mzd_t const *B, int k, int clear); #endif // M4RI_BRILLIANTRUSSIAN_H m4ri-20140914/m4ri/misc.h0000644000175000017500000004656612405041303011544 00000000000000 /** * \file misc.h * \brief Helper functions. * * \author Gregory Bard * \author Martin Albrecht * \author Carlo Wood */ #ifndef M4RI_MISC_H #define M4RI_MISC_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007, 2008 Gregory Bard * Copyright (C) 2008 Martin Albrecht * Copyright (C) 2011 Carlo Wood * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #if __M4RI_USE_MM_MALLOC #include #endif #include #include #include /// @cond INTERNAL #define __STDC_LIMIT_MACROS /// @endcond #include /* * These define entirely the word width used in the library. */ /** * \brief Pretty for a boolean int. * * The value of a BIT is either 0 or 1. */ typedef int BIT; /** * \brief Type of row and column indexes. * * This type is used for integer values that hold row/colum sized values. */ typedef int rci_t; /** * \brief Type of word indexes. * * This type is used for the array of words that make up a row. */ typedef int wi_t; /** * \brief A word is the typical packed data structure to represent packed bits. */ typedef uint64_t word; /** * \brief Explicit conversion macro. * * Explicit conversion of a word, representing 64 columns, to an integer * to be used as index into an array. This is used for Gray codes. * No error checking is done that the most significant bits in w are zero. * * \note This is a no-op. It's purpose it to track intention. */ #define __M4RI_CONVERT_TO_INT(w) ((int)(w)) /** * \brief Explicit conversion macro. * * Explicit conversion of a word, representing 64 columns, to a BIT * to be used as boolean: this is an int with value 0 (false) or 1 (true). * No error checking is done that only the least significant bit is set (if any). * * \note This is a no-op. It's purpose it to track intention. */ #define __M4RI_CONVERT_TO_BIT(w) ((BIT)(w)) /** * \brief Explicit conversion macro. * * Explicit conversion of a word, representing 64 columns, to an uint64_t. * * The returned value is the underlaying integer representation of these 64 columns, * meaning in particular that if val is an uint64_t then * __M4RI_CONVERT_TO_UINT64_T(__M4RI_CONVERT_TO_WORD(val)) == val. * * \note This is a no-op. It's purpose it to track intention. */ #define __M4RI_CONVERT_TO_UINT64_T(w) (w) /** * \brief Explicit conversion macro. * * Explicit conversion of an integer to a word. * * \note This is a no-op. It's purpose it to track intention. */ #define __M4RI_CONVERT_TO_WORD(i) ((word)(i)) /** * \brief The number of bits in a word. */ static int const m4ri_radix = 64; /** * \brief The number one as a word. */ static word const m4ri_one = __M4RI_CONVERT_TO_WORD(1); /** * \brief A word with all bits set. */ static word const m4ri_ffff = __M4RI_CONVERT_TO_WORD(-1); /** * \brief Return the maximal element of x and y * * \param x Word * \param y Word */ #ifndef MAX #define MAX(x,y) (((x) > (y))?(x):(y)) #endif /** * \brief Return the minimal element of x and y * * \param x Word * \param y Word */ #ifndef MIN #define MIN(x,y) (((x) < (y))?(x):(y)) #endif /** *\brief Pretty for 1. */ #ifndef TRUE #define TRUE 1 #endif /** *\brief Pretty for 0. */ #ifndef FALSE #define FALSE 0 #endif /** * \brief $2^i$ * * \param i Integer. */ #define __M4RI_TWOPOW(i) ((uint64_t)1 << (i)) /** * \brief Clear the bit spot (counting from the left) in the word w * * \param w Word * \param spot Integer with 0 <= spot < m4ri_radix */ #define __M4RI_CLR_BIT(w, spot) ((w) &= ~(m4ri_one << (spot)) /** * \brief Set the bit spot (counting from the left) in the word w * * \param w Word * \param spot Integer with 0 <= spot < m4ri_radix */ #define __M4RI_SET_BIT(w, spot) ((w) |= (m4ri_one << (spot))) /** * \brief Get the bit spot (counting from the left) in the word w * * \param w Word * \param spot Integer with 0 <= spot < m4ri_radix */ #define __M4RI_GET_BIT(w, spot) __M4RI_CONVERT_TO_BIT(((w) >> (spot)) & m4ri_one) /** * \brief Write the value to the bit spot in the word w * * \param w Word. * \param spot Integer with 0 <= spot < m4ri_radix. * \param value Either 0 or 1. */ #define __M4RI_WRITE_BIT(w, spot, value) ((w) = (((w) & ~(m4ri_one << (spot))) | (-__M4RI_CONVERT_TO_WORD(value) & (m4ri_one << (spot))))) /** * \brief Flip the spot in the word w * * \param w Word. * \param spot Integer with 0 <= spot < m4ri_radix. */ #define __M4RI_FLIP_BIT(w, spot) ((w) ^= (m4ri_one << (spot))) /** * \brief create a bit mask to zero out all but the (n - 1) % m4ri_radix + 1 leftmost bits. * * This function returns 1..64 bits, never zero bits. * This mask is mainly used to mask the valid bits in the most significant word, * by using __M4RI_LEFT_BITMASK((M->ncols + M->offset) % m4ri_radix). * In other words, the set bits represent the columns with the lowest index in the word. * * Thus, * * n Output * 0=64 1111111111111111111111111111111111111111111111111111111111111111 * 1 0000000000000000000000000000000000000000000000000000000000000001 * 2 0000000000000000000000000000000000000000000000000000000000000011 * . ... * 62 0011111111111111111111111111111111111111111111111111111111111111 * 63 0111111111111111111111111111111111111111111111111111111111111111 * * Note that n == 64 is only passed from __M4RI_MIDDLE_BITMASK, and still works * (behaves the same as n == 0): the input is modulo 64. * * \param n Integer with 0 <= n <= m4ri_radix */ #define __M4RI_LEFT_BITMASK(n) (m4ri_ffff >> (m4ri_radix - (n)) % m4ri_radix) /** * \brief create a bit mask to zero out all but the n rightmost bits. * * This function returns 1..64 bits, never zero bits. * This mask is mainly used to mask the n valid bits in the least significant word * with valid bits by using __M4RI_RIGHT_BITMASK(m4ri_radix - M->offset). * In other words, the set bits represent the columns with the highest index in the word. * * Thus, * * n Output * 1 1000000000000000000000000000000000000000000000000000000000000000 * 2 1100000000000000000000000000000000000000000000000000000000000000 * 3 1110000000000000000000000000000000000000000000000000000000000000 * . ... * 63 1111111111111111111111111111111111111111111111111111111111111110 * 64 1111111111111111111111111111111111111111111111111111111111111111 * * Note that n == 0 is never passed and would fail. * * \param n Integer with 0 < n <= m4ri_radix */ #define __M4RI_RIGHT_BITMASK(n) (m4ri_ffff << (m4ri_radix - (n))) /** * \brief create a bit mask that is the combination of __M4RI_LEFT_BITMASK and __M4RI_RIGHT_BITMASK. * * This function returns 1..64 bits, never zero bits. * This mask is mainly used to mask the n valid bits in the only word with valid bits, * when M->ncols + M->offset <= m4ri_radix), by using __M4RI_MIDDLE_BITMASK(M->ncols, M->offset). * It is equivalent to __M4RI_LEFT_BITMASK(n + offset) & __M4RI_RIGHT_BITMASK(m4ri_radix - offset). * In other words, the set bits represent the valid columns in the word. * * Note that when n == m4ri_radix (and thus offset == 0) then __M4RI_LEFT_BITMASK is called with n == 64. * * \param n Integer with 0 < n <= m4ri_radix - offset * \param offset Column offset, with 0 <= offset < m4ri_radix */ #define __M4RI_MIDDLE_BITMASK(n, offset) (__M4RI_LEFT_BITMASK(n) << (offset)) /** * \brief swap bits in the word v * * \param v The word whose bits need to be reversed. */ static inline word m4ri_swap_bits(word v) { v = ((v >> 1) & 0x5555555555555555ULL) | ((v & 0x5555555555555555ULL) << 1); v = ((v >> 2) & 0x3333333333333333ULL) | ((v & 0x3333333333333333ULL) << 2); v = ((v >> 4) & 0x0F0F0F0F0F0F0F0FULL) | ((v & 0x0F0F0F0F0F0F0F0FULL) << 4); v = ((v >> 8) & 0x00FF00FF00FF00FFULL) | ((v & 0x00FF00FF00FF00FFULL) << 8); v = ((v >> 16) & 0x0000FFFF0000FFFFULL) | ((v & 0x0000FFFF0000FFFFULL) << 16); v = (v >> 32) | (v << 32); return v; } /** * \brief pack bits (inverse of m4ri_spread_bits) * * \param from bitstring * \param Q array with bit positions * \param length bitsize of the output * \param base subtracted from every value in Q * * \returns inverse of m4ri_spread_bits) * * \see m4ri_spread_bits */ static inline word m4ri_shrink_bits(word const from, rci_t* const Q, int const length, int const base) { word to = 0; switch(length-1) { case 15: to |= (from & (m4ri_one << (Q[15] - base))) >> (Q[15] - 15 - base); case 14: to |= (from & (m4ri_one << (Q[14] - base))) >> (Q[14] - 14 - base); case 13: to |= (from & (m4ri_one << (Q[13] - base))) >> (Q[13] - 13 - base); case 12: to |= (from & (m4ri_one << (Q[12] - base))) >> (Q[12] - 12 - base); case 11: to |= (from & (m4ri_one << (Q[11] - base))) >> (Q[11] - 11 - base); case 10: to |= (from & (m4ri_one << (Q[10] - base))) >> (Q[10] - 10 - base); case 9: to |= (from & (m4ri_one << (Q[ 9] - base))) >> (Q[ 9] - 9 - base); case 8: to |= (from & (m4ri_one << (Q[ 8] - base))) >> (Q[ 8] - 8 - base); case 7: to |= (from & (m4ri_one << (Q[ 7] - base))) >> (Q[ 7] - 7 - base); case 6: to |= (from & (m4ri_one << (Q[ 6] - base))) >> (Q[ 6] - 6 - base); case 5: to |= (from & (m4ri_one << (Q[ 5] - base))) >> (Q[ 5] - 5 - base); case 4: to |= (from & (m4ri_one << (Q[ 4] - base))) >> (Q[ 4] - 4 - base); case 3: to |= (from & (m4ri_one << (Q[ 3] - base))) >> (Q[ 3] - 3 - base); case 2: to |= (from & (m4ri_one << (Q[ 2] - base))) >> (Q[ 2] - 2 - base); case 1: to |= (from & (m4ri_one << (Q[ 1] - base))) >> (Q[ 1] - 1 - base); case 0: to |= (from & (m4ri_one << (Q[ 0] - base))) >> (Q[ 0] - 0 - base); break; default: abort(); } return to; } /** * \brief spread bits * * Given a bitstring 'from' and a spreading table Q, return a * bitstring where the bits of 'from' are in the positions indicated * by Q. * * \param from bitstring of length 'length' stored in a word * \param Q table with new bit positions * \param length bitsize of input * \param base subtracted from every value in Q * * \returns bitstring having the same bits as from but spread using Q * * \see m4ri_shrink_bits */ static inline word m4ri_spread_bits(word const from, rci_t* const Q, int const length, int const base) { word to = 0; switch(length-1) { case 15: to |= (from & (m4ri_one << (15))) << (Q[15]-15-base); case 14: to |= (from & (m4ri_one << (14))) << (Q[14]-14-base); case 13: to |= (from & (m4ri_one << (13))) << (Q[13]-13-base); case 12: to |= (from & (m4ri_one << (12))) << (Q[12]-12-base); case 11: to |= (from & (m4ri_one << (11))) << (Q[11]-11-base); case 10: to |= (from & (m4ri_one << (10))) << (Q[10]-10-base); case 9: to |= (from & (m4ri_one << ( 9))) << (Q[ 9]- 9-base); case 8: to |= (from & (m4ri_one << ( 8))) << (Q[ 8]- 8-base); case 7: to |= (from & (m4ri_one << ( 7))) << (Q[ 7]- 7-base); case 6: to |= (from & (m4ri_one << ( 6))) << (Q[ 6]- 6-base); case 5: to |= (from & (m4ri_one << ( 5))) << (Q[ 5]- 5-base); case 4: to |= (from & (m4ri_one << ( 4))) << (Q[ 4]- 4-base); case 3: to |= (from & (m4ri_one << ( 3))) << (Q[ 3]- 3-base); case 2: to |= (from & (m4ri_one << ( 2))) << (Q[ 2]- 2-base); case 1: to |= (from & (m4ri_one << ( 1))) << (Q[ 1]- 1-base); case 0: to |= (from & (m4ri_one << ( 0))) << (Q[ 0]- 0-base); break; default: abort(); } return to; } /** * \brief Return alignment of addr w.r.t. n. For example the address * 17 would be 1 aligned w.r.t. 16. * * \param addr * \param n */ #define __M4RI_ALIGNMENT(addr, n) (((unsigned long)(addr))%(n)) /** * \brief Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc * * \param maj The major version. * \param min The minor version. * \return TRUE iff we are using a GNU compile of at least version maj.min. */ #if defined(__GNUC__) && defined(__GNUC_MINOR__) #define __M4RI_GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) #else #define __M4RI_GNUC_PREREQ(maj, min) FALSE #endif /* __builtin_expect is in gcc 3.0, and not in 2.95. */ #if __M4RI_GNUC_PREREQ(3,0) || defined(M4RI_DOXYGEN) /** * \brief Macro to help with branch prediction. */ #define __M4RI_LIKELY(cond) __builtin_expect ((cond) != 0, 1) /** * \brief Macro to help with branch prediction. */ #define __M4RI_UNLIKELY(cond) __builtin_expect ((cond) != 0, 0) #else #define __M4RI_LIKELY(cond) (cond) #define __M4RI_UNLIKELY(cond) (cond) #endif /** * Return true if a's least significant bit is smaller than b's least significant bit. * * return true if LSBI(a) < LSBI(b), * where LSBI(w) is the index of the least significant bit that is set in w, or 64 if w is zero. * * \param a Word * \param b Word */ static inline int m4ri_lesser_LSB(word a, word b) { uint64_t const ia = __M4RI_CONVERT_TO_UINT64_T(a); uint64_t const ib = __M4RI_CONVERT_TO_UINT64_T(b); /* * If a is zero then we should always return false, otherwise * if b is zero we should return true iff a has at least one bit set. */ return !(ib ? ((ia - 1) ^ ia) & ib : !ia); } /**** Error Handling *****/ /** * \brief Print error message and abort(). * * The function accepts additional * parameters like printf, so e.g. m4ri_die("foo %d bar %f\n",1 ,2.0) * is valid and will print the string "foo 1 bar 2.0" before dying. * * \param errormessage a string to be printed. * * \todo Allow user to register callback which is called on * m4ri_die(). * * \warning The provided string is not free'd. */ void m4ri_die(const char *errormessage, ...); /**** IO *****/ /** * \brief Write a sting representing the word data to destination. * * \param destination Address of buffer of length at least m4ri_radix*1.3 * \param data Source word * \param colon Insert a Colon after every 4-th bit. * \warning Assumes destination has m4ri_radix*1.3 bytes available */ void m4ri_word_to_str( char *destination, word data, int colon); /** * \brief Return 1 or 0 uniformly randomly distributed. * * \todo Allow user to provide her own random() function. */ static inline BIT m4ri_coin_flip() { if (rand() < RAND_MAX/2) { return 0; } else { return 1; } } /** * \brief Return uniformly randomly distributed random word. * * \todo Allow user to provide her own random() function. */ word m4ri_random_word(); /***** Initialization *****/ /** * \brief Initialize global data structures for the M4RI library. * * On Linux/Solaris this is called automatically when the shared * library is loaded, but it doesn't harm if it is called twice. */ #if defined(__GNUC__) void __attribute__ ((constructor)) m4ri_init(void); #else void m4ri_init(void); #endif #ifdef __SUNPRO_C #pragma init(m4ri_init) #endif /** * \brief De-initialize global data structures from the M4RI library. * * On Linux/Solaris this is called automatically when the shared * library is unloaded, but it doesn't harm if it is called twice. */ #if defined(__GNUC__) void __attribute__ ((destructor)) m4ri_fini(void); #else void m4ri_fini(void); #endif #ifdef __SUNPRO_C #pragma fini(m4ri_fini) #endif /***** Memory Management *****/ /// @cond INTERNAL #if __M4RI_CPU_L3_CACHE == 0 /* * Fix some standard value for L3 cache size if it couldn't be * determined by configure. */ #undef __M4RI_CPU_L3_CACHE #if __M4RI_CPU_L2_CACHE #define __M4RI_CPU_L3_CACHE __M4RI_CPU_L2_CACHE #else #define __M4RI_CPU_L3_CACHE 4194304 #endif // __M4RI_CPU_L2_CACHE #endif // __M4RI_CPU_L3_CACHE #if __M4RI_CPU_L2_CACHE == 0 /* * Fix some standard value for L2 cache size if it couldn't be * determined by configure. */ #undef __M4RI_CPU_L2_CACHE #define __M4RI_CPU_L2_CACHE 262144 #endif // __M4RI_CPU_L2_CACHE #if __M4RI_CPU_L1_CACHE == 0 /* * Fix some standard value for L1 cache size if it couldn't be * determined by configure. */ #undef __M4RI_CPU_L1_CACHE #define __M4RI_CPU_L1_CACHE 16384 #endif // __M4RI_CPU_L1_CACHE /// @endcond /** * \brief Calloc wrapper. * * \param count Number of elements. * \param size Size of each element. * * \return pointer to allocated memory block. * * \todo Allow user to register calloc function. */ static inline void *m4ri_mm_calloc(size_t count, size_t size) { void *newthing; #if __M4RI_USE_MM_MALLOC newthing = _mm_malloc(count * size, 64); #elif __M4RI_USE_POSIX_MEMALIGN int error = posix_memalign(&newthing, 64, count * size); if (error) newthing = NULL; #else newthing = calloc(count, size); #endif if (newthing == NULL) { m4ri_die("m4ri_mm_calloc: calloc returned NULL\n"); return NULL; /* unreachable. */ } #if __M4RI_USE_MM_MALLOC || __M4RI_USE_POSIX_MEMALIGN char *b = (char*)newthing; memset(b, 0, count * size); #endif return newthing; } /** * \brief Aligned malloc wrapper. * * This function will attempt to align memory, but does not guarantee * success in case neither _mm_malloc nor posix_memalign are available. * * \param size Size in bytes. * \param alignment Alignment (16,64,...). * * \return pointer to allocated memory block. * * \todo Allow user to register malloc function. */ static inline void *m4ri_mm_malloc_aligned(size_t size, size_t alignment) { void *newthing; #if __M4RI_USE_MM_MALLOC newthing = _mm_malloc(size, alignment); #elif __M4RI_USE_POSIX_MEMALIGN int error = posix_memalign(&newthing, alignment, size); if (error) newthing = NULL; #else newthing = malloc(size); #endif if (newthing==NULL && (size>0)) { m4ri_die("m4ri_mm_malloc: malloc returned NULL\n"); return NULL; /* unreachable */ } else return newthing; } /** * \brief Malloc wrapper. * * \param size Size in bytes. * * \return pointer to allocated memory block. * * \todo Allow user to register malloc function. */ static inline void *m4ri_mm_malloc(size_t size) { void *newthing; #if __M4RI_USE_MM_MALLOC newthing = _mm_malloc(size, 64); #elif __M4RI_USE_POSIX_MEMALIGN int error = posix_memalign(&newthing, 64, size); if (error) newthing = NULL; #else newthing = malloc(size); #endif //__M4RI_USE_MM_MALLOC if (newthing==NULL && (size>0)) { m4ri_die("m4ri_mm_malloc: malloc returned NULL\n"); return NULL; /* unreachable */ } else return newthing; } /** * \brief Free wrapper. * * \param condemned Pointer. * * \todo Allow user to register free function. */ /* void m4ri_mm_free(void *condemned, ...); */ static inline void m4ri_mm_free(void *condemned, ...) { #if __M4RI_USE_MM_MALLOC _mm_free(condemned); #else free(condemned); #endif } /// @cond INTERNAL /* * MSVC does not understand the restrict keyword */ #if defined (__GNUC__) #define RESTRICT __restrict__ #else #define RESTRICT #endif /* * Macros for template expansion. */ #define __M4RI_TEMPLATE_EXPAND0(x,y) x ## _ ## y #define __M4RI_TEMPLATE_EXPAND1(x,y) __M4RI_TEMPLATE_EXPAND0(x,y) #define __M4RI_TEMPLATE_NAME(fun) __M4RI_TEMPLATE_EXPAND1(fun, N) //// @endcond #endif // M4RI_MISC_H m4ri-20140914/m4ri/mzd.h0000644000175000017500000010453112405042406011373 00000000000000/** * \file mzd.h * \brief Dense matrices over GF(2) represented as a bit field. * * \author Gregory Bard * \author Martin Albrecht * \author Carlo Wood */ #ifndef M4RI_MZD #define M4RI_MZD /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007, 2008 Gregory Bard * Copyright (C) 2008-2013 Martin Albrecht * Copyright (C) 2011 Carlo Wood * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #if __M4RI_HAVE_SSE2 #include #endif #include #include /** * Maximum number of words allocated for one mzd_t block. * * \note This value must fit in an int, even though it's type is size_t. */ #define __M4RI_MAX_MZD_BLOCKSIZE (((size_t)1) << 27) /** * \brief Matrix multiplication block-ing dimension. * * Defines the number of rows of the matrix A that are * processed as one block during the execution of a multiplication * algorithm. */ #define __M4RI_MUL_BLOCKSIZE MIN(((int)sqrt((double)(4 * __M4RI_CPU_L3_CACHE))) / 2, 2048) /** * \brief Data containers containing the values packed into words */ typedef struct { size_t size; /*!< number of words */ word* begin; /*!< first word */ word* end; /*!< last word */ } mzd_block_t; /** * \brief Dense matrices over GF(2). * * The most fundamental data type in this library. */ typedef struct mzd_t { rci_t nrows; /*!< Number of rows. */ rci_t ncols; /*!< Number of columns. */ wi_t width; /*!< Number of words with valid bits: width = ceil(ncols / m4ri_radix) */ /** * Offset in words between rows. * * rowstride = (width < mzd_paddingwidth || (width & 1) == 0) ? width : width + 1; * where width is the width of the underlying non-windowed matrix. */ wi_t rowstride; /** * Offset in words from start of block to first word. * * rows[0] = blocks[0].begin + offset_vector; * This, together with rowstride, makes the rows array obsolete. */ wi_t offset_vector; wi_t row_offset; /*!< Number of rows to the first row counting from the start of the first block. */ /** * Booleans to speed up things. * * The bits have the following meaning: * * 1: Has non-zero excess. * 2: Is windowed, but has zero offset. * 3: Is windowed, but has zero excess. * 4: Is windowed, but owns the blocks allocations. * 5: Spans more than 1 block. */ uint8_t flags; /** * blockrows_log = log2(blockrows); * where blockrows is the number of rows in one block, which is a power of 2. */ uint8_t blockrows_log; word high_bitmask; /*!< Mask for valid bits in the word with the highest index (width - 1). */ mzd_block_t *blocks; /*!< Pointers to the actual blocks of memory containing the values packed into words. */ word **rows; /*!< Address of first word in each row, so the first word of row i is is m->rows[i] */ uint64_t dummy; /*!< ensures sizeof(mzd_t) == 64 */ } mzd_t; /** * \brief The minimum width where padding occurs. */ static wi_t const mzd_paddingwidth = 1; /** * \brief flag when ncols%64 == 0 */ static uint8_t const mzd_flag_nonzero_excess = 0x2; /** * \brief flag for windowed matrix */ static uint8_t const mzd_flag_windowed_zerooffset = 0x4; /** * \brief flag for windowed matrix where ncols%64 == 0 */ static uint8_t const mzd_flag_windowed_zeroexcess = 0x8; /** * \brief flag for windowed matrix wich owns its memory */ static uint8_t const mzd_flag_windowed_ownsblocks = 0x10; /** * \brief flag for multiply blocks */ static uint8_t const mzd_flag_multiple_blocks = 0x20; /** * \brief Test if a matrix is windowed. * * \param M Matrix * * \return a non-zero value if the matrix is windowed, otherwise return zero. */ static inline int mzd_is_windowed(mzd_t const *M) { return M->flags & (mzd_flag_windowed_zerooffset); } /** * \brief Test if this mzd_t should free blocks. * * \param M Matrix * * \return TRUE iff blocks is non-zero and should be freed upon a call to mzd_free. */ static inline int mzd_owns_blocks(mzd_t const *M) { return M->blocks && (!mzd_is_windowed(M) || ((M->flags & mzd_flag_windowed_ownsblocks))); } /** * \brief Get a pointer the first word. * * \param M Matrix * * \return a pointer to the first word of the first row. */ static inline word* mzd_first_row(mzd_t const *M) { word* result = M->blocks[0].begin + M->offset_vector; assert(M->nrows == 0 || result == M->rows[0]); return result; } /** * \brief Get a pointer to the first word in block n. * * Use mzd_first_row for block number 0. * * \param M Matrix * \param n The block number. Must be larger than 0. * * \return a pointer to the first word of the first row in block n. */ static inline word* mzd_first_row_next_block(mzd_t const* M, int n) { assert(n > 0); return M->blocks[n].begin + M->offset_vector - M->row_offset * M->rowstride; } /** * \brief Convert row to blocks index. * * \param M Matrix. * \param row The row to convert. * * \return the block number that contains this row. */ static inline int mzd_row_to_block(mzd_t const* M, rci_t row) { return (M->row_offset + row) >> M->blockrows_log; } /** * \brief Total number of rows in this block. * * Should be called with a constant n=0, or with * n > 0 when n is a variable, for optimization * reasons. * * \param M Matrix * \param n The block number. * * \return the total number of rows in this block. */ static inline wi_t mzd_rows_in_block(mzd_t const* M, int n) { if (__M4RI_UNLIKELY(M->flags & mzd_flag_multiple_blocks)) { if (__M4RI_UNLIKELY(n == 0)) { return (1 << M->blockrows_log) - M->row_offset; } else { int const last_block = mzd_row_to_block(M, M->nrows - 1); if (n < last_block) return (1 << M->blockrows_log); return M->nrows + M->row_offset - (n << M->blockrows_log); } } return n ? 0 : M->nrows; } /** * \brief Number of rows in this block including r * * \param M Matrix * \param r row * * \return the number of rows with index >= r in this block */ static inline wi_t mzd_remaining_rows_in_block(mzd_t const* M, rci_t r) { const int n = mzd_row_to_block(M, r); r = (r - (n << M->blockrows_log)); if (__M4RI_UNLIKELY(M->flags & mzd_flag_multiple_blocks)) { if (__M4RI_UNLIKELY(n == 0)) { return (1 << M->blockrows_log) - M->row_offset - r; } else { int const last_block = mzd_row_to_block(M, M->nrows - 1); if (n < last_block) return (1 << M->blockrows_log) - r; return M->nrows + M->row_offset - (n << M->blockrows_log) - r; } } return n ? 0 : M->nrows - r; } /** * \brief Get pointer to first word of row. * * \param M Matrix * \param row The row index. * * \return pointer to first word of the row. */ static inline word* mzd_row(mzd_t const* M, rci_t row) { wi_t big_vector = M->offset_vector + row * M->rowstride; word* result = M->blocks[0].begin + big_vector; if (__M4RI_UNLIKELY(M->flags & mzd_flag_multiple_blocks)) { int const n = (M->row_offset + row) >> M->blockrows_log; result = M->blocks[n].begin + big_vector - n * (M->blocks[0].size / sizeof(word)); } assert(result == M->rows[row]); return result; } /** * \brief Create a new matrix of dimension r x c. * * Use mzd_free to kill it. * * \param r Number of rows * \param c Number of columns * */ mzd_t *mzd_init(rci_t const r, rci_t const c); /** * \brief Free a matrix created with mzd_init. * * \param A Matrix */ void mzd_free(mzd_t *A); /** * \brief Create a window/view into the matrix M. * * A matrix window for M is a meta structure on the matrix M. It is * setup to point into the matrix so M \em must \em not be freed while the * matrix window is used. * * This function puts the restriction on the provided parameters that * all parameters must be within range for M which is not enforced * currently . * * Use mzd_free_window to free the window. * * \param M Matrix * \param lowr Starting row (inclusive) * \param lowc Starting column (inclusive, must be multiple of m4ri_radix) * \param highr End row (exclusive) * \param highc End column (exclusive) * */ mzd_t *mzd_init_window(mzd_t *M, rci_t const lowr, rci_t const lowc, rci_t const highr, rci_t const highc); /** * \brief Create a const window/view into a const matrix M. * * See mzd_init_window, but for constant M. */ static inline mzd_t const *mzd_init_window_const(mzd_t const *M, rci_t const lowr, rci_t const lowc, rci_t const highr, rci_t const highc) { return mzd_init_window((mzd_t*)M, lowr, lowc, highr, highc); } /** * \brief Free a matrix window created with mzd_init_window. * * \param A Matrix */ #define mzd_free_window mzd_free /** * \brief Swap the two rows rowa and rowb starting at startblock. * * \param M Matrix with a zero offset. * \param rowa Row index. * \param rowb Row index. * \param startblock Start swapping only in this block. */ static inline void _mzd_row_swap(mzd_t *M, rci_t const rowa, rci_t const rowb, wi_t const startblock) { if ((rowa == rowb) || (startblock >= M->width)) return; wi_t width = M->width - startblock - 1; word *a = M->rows[rowa] + startblock; word *b = M->rows[rowb] + startblock; word tmp; word const mask_end = M->high_bitmask; for(wi_t i = 0; i < width; ++i) { tmp = a[i]; a[i] = b[i]; b[i] = tmp; } tmp = (a[width] ^ b[width]) & mask_end; a[width] ^= tmp; b[width] ^= tmp; __M4RI_DD_ROW(M, rowa); __M4RI_DD_ROW(M, rowb); } /** * \brief Swap the two rows rowa and rowb. * * \param M Matrix * \param rowa Row index. * \param rowb Row index. */ static inline void mzd_row_swap(mzd_t *M, rci_t const rowa, rci_t const rowb) { _mzd_row_swap(M, rowa, rowb, 0); } /** * \brief copy row j from A to row i from B. * * The offsets of A and B must match and the number of columns of A * must be less than or equal to the number of columns of B. * * \param B Target matrix. * \param i Target row index. * \param A Source matrix. * \param j Source row index. */ void mzd_copy_row(mzd_t *B, rci_t i, mzd_t const *A, rci_t j); /** * \brief Swap the two columns cola and colb. * * \param M Matrix. * \param cola Column index. * \param colb Column index. */ void mzd_col_swap(mzd_t *M, rci_t const cola, rci_t const colb); /** * \brief Swap the two columns cola and colb but only between start_row and stop_row. * * \param M Matrix. * \param cola Column index. * \param colb Column index. * \param start_row Row index. * \param stop_row Row index (exclusive). */ static inline void mzd_col_swap_in_rows(mzd_t *M, rci_t const cola, rci_t const colb, rci_t const start_row, rci_t const stop_row) { if (cola == colb) return; rci_t const _cola = cola; rci_t const _colb = colb; wi_t const a_word = _cola / m4ri_radix; wi_t const b_word = _colb / m4ri_radix; int const a_bit = _cola % m4ri_radix; int const b_bit = _colb % m4ri_radix; word* RESTRICT ptr = mzd_row(M, start_row); int max_bit = MAX(a_bit, b_bit); int count_remaining = stop_row - start_row; int min_bit = a_bit + b_bit - max_bit; int block = mzd_row_to_block(M, start_row); int offset = max_bit - min_bit; word mask = m4ri_one << min_bit; int count = MIN(mzd_remaining_rows_in_block(M, start_row), count_remaining); // Apparently we're calling with start_row == stop_row sometimes (seems a bug to me). if (count <= 0) return; if (a_word == b_word) { while(1) { count_remaining -= count; ptr += a_word; int fast_count = count / 4; int rest_count = count - 4 * fast_count; word xor_v[4]; wi_t const rowstride = M->rowstride; while (fast_count--) { xor_v[0] = ptr[0]; xor_v[1] = ptr[rowstride]; xor_v[2] = ptr[2 * rowstride]; xor_v[3] = ptr[3 * rowstride]; xor_v[0] ^= xor_v[0] >> offset; xor_v[1] ^= xor_v[1] >> offset; xor_v[2] ^= xor_v[2] >> offset; xor_v[3] ^= xor_v[3] >> offset; xor_v[0] &= mask; xor_v[1] &= mask; xor_v[2] &= mask; xor_v[3] &= mask; xor_v[0] |= xor_v[0] << offset; xor_v[1] |= xor_v[1] << offset; xor_v[2] |= xor_v[2] << offset; xor_v[3] |= xor_v[3] << offset; ptr[0] ^= xor_v[0]; ptr[rowstride] ^= xor_v[1]; ptr[2 * rowstride] ^= xor_v[2]; ptr[3 * rowstride] ^= xor_v[3]; ptr += 4 * rowstride; } while (rest_count--) { word xor_v = *ptr; xor_v ^= xor_v >> offset; xor_v &= mask; *ptr ^= xor_v | (xor_v << offset); ptr += rowstride; } block++; if ((count = MIN(mzd_rows_in_block(M, block), count_remaining)) <= 0) break; ptr = mzd_first_row_next_block(M, block); } } else { word* RESTRICT min_ptr; wi_t max_offset; if (min_bit == a_bit) { min_ptr = ptr + a_word; max_offset = b_word - a_word; } else { min_ptr = ptr + b_word; max_offset = a_word - b_word; } while(1) { count_remaining -= count; wi_t const rowstride = M->rowstride; while(count--) { word xor_v = (min_ptr[0] ^ (min_ptr[max_offset] >> offset)) & mask; min_ptr[0] ^= xor_v; min_ptr[max_offset] ^= xor_v << offset; min_ptr += rowstride; } block++; if ((count = MIN(mzd_rows_in_block(M,+block), count_remaining)) <= 0) break; ptr = mzd_first_row_next_block(M, block); if (min_bit == a_bit) min_ptr = ptr + a_word; else min_ptr = ptr + b_word; } } __M4RI_DD_MZD(M); } /** * \brief Read the bit at position M[row,col]. * * \param M Matrix * \param row Row index * \param col Column index * * \note No bounds checks whatsoever are performed. * */ static inline BIT mzd_read_bit(mzd_t const *M, rci_t const row, rci_t const col ) { return __M4RI_GET_BIT(M->rows[row][col/m4ri_radix], col%m4ri_radix); } /** * \brief Write the bit value to position M[row,col] * * \param M Matrix * \param row Row index * \param col Column index * \param value Either 0 or 1 * * \note No bounds checks whatsoever are performed. * */ static inline void mzd_write_bit(mzd_t *M, rci_t const row, rci_t const col, BIT const value) { __M4RI_WRITE_BIT(M->rows[row][col/m4ri_radix], col%m4ri_radix, value); } /** * \brief XOR n bits from values to M starting a position (x,y). * * \param M Source matrix. * \param x Starting row. * \param y Starting column. * \param n Number of bits (<= m4ri_radix); * \param values Word with values; */ static inline void mzd_xor_bits(mzd_t const *M, rci_t const x, rci_t const y, int const n, word values) { int const spot = y % m4ri_radix; wi_t const block = y / m4ri_radix; M->rows[x][block] ^= values << spot; int const space = m4ri_radix - spot; if (n > space) M->rows[x][block + 1] ^= values >> space; } /** * \brief AND n bits from values to M starting a position (x,y). * * \param M Source matrix. * \param x Starting row. * \param y Starting column. * \param n Number of bits (<= m4ri_radix); * \param values Word with values; */ static inline void mzd_and_bits(mzd_t const *M, rci_t const x, rci_t const y, int const n, word values) { /* This is the best way, since this will drop out once we inverse the bits in values: */ values >>= (m4ri_radix - n); /* Move the bits to the lowest columns */ int const spot = y % m4ri_radix; wi_t const block = y / m4ri_radix; M->rows[x][block] &= values << spot; int const space = m4ri_radix - spot; if (n > space) M->rows[x][block + 1] &= values >> space; } /** * \brief Clear n bits in M starting a position (x,y). * * \param M Source matrix. * \param x Starting row. * \param y Starting column. * \param n Number of bits (0 < n <= m4ri_radix); */ static inline void mzd_clear_bits(mzd_t const *M, rci_t const x, rci_t const y, int const n) { assert(n>0 && n <= m4ri_radix); word values = m4ri_ffff >> (m4ri_radix - n); int const spot = y % m4ri_radix; wi_t const block = y / m4ri_radix; M->rows[x][block] &= ~(values << spot); int const space = m4ri_radix - spot; if (n > space) M->rows[x][block + 1] &= ~(values >> space); } /** * \brief Add the rows sourcerow and destrow and stores the total in the row * destrow, but only begins at the column coloffset. * * \param M Matrix * \param dstrow Index of target row * \param srcrow Index of source row * \param coloffset Start column (0 <= coloffset < M->ncols) * * \warning This function expects that there is at least one word worth of work. */ static inline void mzd_row_add_offset(mzd_t *M, rci_t dstrow, rci_t srcrow, rci_t coloffset) { assert(dstrow < M->nrows && srcrow < M->nrows && coloffset < M->ncols); wi_t const startblock= coloffset/m4ri_radix; wi_t wide = M->width - startblock; word *src = M->rows[srcrow] + startblock; word *dst = M->rows[dstrow] + startblock; word const mask_begin = __M4RI_RIGHT_BITMASK(m4ri_radix - coloffset % m4ri_radix); word const mask_end = M->high_bitmask; *dst++ ^= *src++ & mask_begin; --wide; #if __M4RI_HAVE_SSE2 int not_aligned = __M4RI_ALIGNMENT(src,16) != 0; /* 0: Aligned, 1: Not aligned */ if (wide > not_aligned + 1) /* Speed up for small matrices */ { if (not_aligned) { *dst++ ^= *src++; --wide; } /* Now wide > 1 */ __m128i* __src = (__m128i*)src; __m128i* __dst = (__m128i*)dst; __m128i* const eof = (__m128i*)((unsigned long)(src + wide) & ~0xFUL); do { __m128i xmm1 = _mm_xor_si128(*__dst, *__src); *__dst++ = xmm1; } while(++__src < eof); src = (word*)__src; dst = (word*)__dst; wide = ((sizeof(word)*wide)%16)/sizeof(word); } #endif wi_t i = -1; while(++i < wide) dst[i] ^= src[i]; /* * Revert possibly non-zero excess bits. * Note that i == wide here, and wide can be 0. * But really, src[wide - 1] is M->rows[srcrow][M->width - 1] ;) * We use i - 1 here to let the compiler know these are the same addresses * that we last accessed, in the previous loop. */ dst[i - 1] ^= src[i - 1] & ~mask_end; __M4RI_DD_ROW(M, dstrow); } /** * \brief Add the rows sourcerow and destrow and stores the total in * the row destrow. * * \param M Matrix * \param sourcerow Index of source row * \param destrow Index of target row * * \note this can be done much faster with mzd_combine. */ void mzd_row_add(mzd_t *M, rci_t const sourcerow, rci_t const destrow); /** * \brief Transpose a matrix. * * This function uses the fact that: \verbatim [ A B ]T [AT CT] [ C D ] = [BT DT] \endverbatim * and thus rearranges the blocks recursively. * * \param DST Preallocated return matrix, may be NULL for automatic creation. * \param A Matrix */ mzd_t *mzd_transpose(mzd_t *DST, mzd_t const *A); /** * \brief Naive cubic matrix multiplication. * * That is, compute C such that C == AB. * * \param C Preallocated product matrix, may be NULL for automatic creation. * \param A Input matrix A. * \param B Input matrix B. * * \note Normally, if you will multiply several times by b, it is * smarter to calculate bT yourself, and keep it, and then use the * function called _mzd_mul_naive * */ mzd_t *mzd_mul_naive(mzd_t *C, mzd_t const *A, mzd_t const *B); /** * \brief Naive cubic matrix multiplication and addition * * That is, compute C such that C == C + AB. * * \param C Preallocated product matrix. * \param A Input matrix A. * \param B Input matrix B. * * \note Normally, if you will multiply several times by b, it is * smarter to calculate bT yourself, and keep it, and then use the * function called _mzd_mul_naive */ mzd_t *mzd_addmul_naive(mzd_t *C, mzd_t const *A, mzd_t const *B); /** * \brief Naive cubic matrix multiplication with the pre-transposed B. * * That is, compute C such that C == AB^t. * * \param C Preallocated product matrix. * \param A Input matrix A. * \param B Pre-transposed input matrix B. * \param clear Whether to clear C before accumulating AB */ mzd_t *_mzd_mul_naive(mzd_t *C, mzd_t const *A, mzd_t const *B, int const clear); /** * \brief Matrix multiplication optimized for v*A where v is a vector. * * \param C Preallocated product matrix. * \param v Input matrix v. * \param A Input matrix A. * \param clear If set clear C first, otherwise add result to C. * */ mzd_t *_mzd_mul_va(mzd_t *C, mzd_t const *v, mzd_t const *A, int const clear); /** * \brief Fill matrix M with uniformly distributed bits. * * \param M Matrix * * \todo Allow the user to provide a RNG callback. */ void mzd_randomize(mzd_t *M); /** * \brief Set the matrix M to the value equivalent to the integer * value provided. * * Specifically, this function does nothing if value%2 == 0 and * returns the identity matrix if value%2 == 1. * * If the matrix is not square then the largest possible square * submatrix is set to the identity matrix. * * \param M Matrix * \param value Either 0 or 1 */ void mzd_set_ui(mzd_t *M, unsigned int const value); /** * \brief Gaussian elimination. * * This will do Gaussian elimination on the matrix m but will start * not at column 0 necc but at column startcol. If full=FALSE, then it * will do triangular style elimination, and if full=TRUE, it will do * Gauss-Jordan style, or full elimination. * * \param M Matrix * \param startcol First column to consider for reduction. * \param full Gauss-Jordan style or upper triangular form only. */ rci_t mzd_gauss_delayed(mzd_t *M, rci_t const startcol, int const full); /** * \brief Gaussian elimination. * * This will do Gaussian elimination on the matrix m. If full=FALSE, * then it will do triangular style elimination, and if full=TRUE, * it will do Gauss-Jordan style, or full elimination. * * \param M Matrix * \param full Gauss-Jordan style or upper triangular form only. * * \sa mzd_echelonize_m4ri(), mzd_echelonize_pluq() */ rci_t mzd_echelonize_naive(mzd_t *M, int const full); /** * \brief Return TRUE if A == B. * * \param A Matrix * \param B Matrix */ int mzd_equal(mzd_t const *A, mzd_t const *B); /** * \brief Return -1,0,1 if if A < B, A == B or A > B respectively. * * \param A Matrix. * \param B Matrix. * * \note This comparison is not well defined mathematically and * relatively arbitrary since elements of GF(2) don't have an * ordering. */ int mzd_cmp(mzd_t const *A, mzd_t const *B); /** * \brief Copy matrix A to DST. * * \param DST May be NULL for automatic creation. * \param A Source matrix. */ mzd_t *mzd_copy(mzd_t *DST, mzd_t const *A); /** * \brief Concatenate B to A and write the result to C. * * That is, * \verbatim [ A ], [ B ] -> [ A B ] = C \endverbatim * * The inputs are not modified but a new matrix is created. * * \param C Matrix, may be NULL for automatic creation * \param A Matrix * \param B Matrix * * \note This is sometimes called augment. */ mzd_t *mzd_concat(mzd_t *C, mzd_t const *A, mzd_t const *B); /** * \brief Stack A on top of B and write the result to C. * * That is, * \verbatim [ A ], [ B ] -> [ A ] = C [ B ] \endverbatim * * The inputs are not modified but a new matrix is created. * * \param C Matrix, may be NULL for automatic creation * \param A Matrix * \param B Matrix */ mzd_t *mzd_stack(mzd_t *C, mzd_t const *A, mzd_t const *B); /** * \brief Copy a submatrix. * * Note that the upper bounds are not included. * * \param S Preallocated space for submatrix, may be NULL for automatic creation. * \param M Matrix * \param lowr start rows * \param lowc start column * \param highr stop row (this row is \em not included) * \param highc stop column (this column is \em not included) */ mzd_t *mzd_submatrix(mzd_t *S, mzd_t const *M, rci_t const lowr, rci_t const lowc, rci_t const highr, rci_t const highc); /** * \brief Invert the matrix target using Gaussian elimination. * * To avoid recomputing the identity matrix over and over again, I may * be passed in as identity parameter. * * \param INV Preallocated space for inversion matrix, may be NULL for automatic creation. * \param A Matrix to be reduced. * \param I Identity matrix. */ mzd_t *mzd_invert_naive(mzd_t *INV, mzd_t const *A, mzd_t const *I); /** * \brief Set C = A+B. * * C is also returned. If C is NULL then a new matrix is created which * must be freed by mzd_free. * * \param C Preallocated sum matrix, may be NULL for automatic creation. * \param A Matrix * \param B Matrix */ mzd_t *mzd_add(mzd_t *C, mzd_t const *A, mzd_t const *B); /** * \brief Same as mzd_add but without any checks on the input. * * \param C Preallocated sum matrix, may be NULL for automatic creation. * \param A Matrix * \param B Matrix */ mzd_t *_mzd_add(mzd_t *C, mzd_t const *A, mzd_t const *B); /** * \brief Same as mzd_add. * * \param C Preallocated difference matrix, may be NULL for automatic creation. * \param A Matrix * \param B Matrix */ #define mzd_sub mzd_add /** * \brief Same as mzd_sub but without any checks on the input. * * \param C Preallocated difference matrix, may be NULL for automatic creation. * \param A Matrix * \param B Matrix */ #define _mzd_sub _mzd_add /** * Get n bits starting a position (x,y) from the matrix M. * * \param M Source matrix. * \param x Starting row. * \param y Starting column. * \param n Number of bits (<= m4ri_radix); */ static inline word mzd_read_bits(mzd_t const *M, rci_t const x, rci_t const y, int const n) { int const spot = y % m4ri_radix; wi_t const block = y / m4ri_radix; int const spill = spot + n - m4ri_radix; word temp = (spill <= 0) ? M->rows[x][block] << -spill : (M->rows[x][block + 1] << (m4ri_radix - spill)) | (M->rows[x][block] >> spill); return temp >> (m4ri_radix - n); } /** * \brief a_row[a_startblock:] += b_row[b_startblock:] for offset 0 * * Adds a_row of A, starting with a_startblock to the end, to * b_row of B, starting with b_startblock to the end. This gets stored * in A, in a_row, starting with a_startblock. * * \param A destination matrix * \param a_row destination row for matrix C * \param a_startblock starting block to work on in matrix C * \param B source matrix * \param b_row source row for matrix B * \param b_startblock starting block to work on in matrix B * */ static inline void mzd_combine_even_in_place(mzd_t *A, rci_t const a_row, wi_t const a_startblock, mzd_t const *B, rci_t const b_row, wi_t const b_startblock) { wi_t wide = A->width - a_startblock - 1; word *a = A->rows[a_row] + a_startblock; word *b = B->rows[b_row] + b_startblock; #if __M4RI_HAVE_SSE2 if(wide > 2) { /** check alignments **/ if (__M4RI_ALIGNMENT(a,16)) { *a++ ^= *b++; wide--; } if (__M4RI_ALIGNMENT(a, 16) == 0 && __M4RI_ALIGNMENT(b, 16) == 0) { __m128i *a128 = (__m128i*)a; __m128i *b128 = (__m128i*)b; const __m128i *eof = (__m128i*)((unsigned long)(a + wide) & ~0xFUL); do { *a128 = _mm_xor_si128(*a128, *b128); ++b128; ++a128; } while(a128 < eof); a = (word*)a128; b = (word*)b128; wide = ((sizeof(word) * wide) % 16) / sizeof(word); } } #endif // __M4RI_HAVE_SSE2 if (wide > 0) { wi_t n = (wide + 7) / 8; switch (wide % 8) { case 0: do { *(a++) ^= *(b++); case 7: *(a++) ^= *(b++); case 6: *(a++) ^= *(b++); case 5: *(a++) ^= *(b++); case 4: *(a++) ^= *(b++); case 3: *(a++) ^= *(b++); case 2: *(a++) ^= *(b++); case 1: *(a++) ^= *(b++); } while (--n > 0); } } *a ^= *b & A->high_bitmask; __M4RI_DD_MZD(A); } /** * \brief c_row[c_startblock:] = a_row[a_startblock:] + b_row[b_startblock:] for offset 0 * * Adds a_row of A, starting with a_startblock to the end, to * b_row of B, starting with b_startblock to the end. This gets stored * in C, in c_row, starting with c_startblock. * * \param C destination matrix * \param c_row destination row for matrix C * \param c_startblock starting block to work on in matrix C * \param A source matrix * \param a_row source row for matrix A * \param a_startblock starting block to work on in matrix A * \param B source matrix * \param b_row source row for matrix B * \param b_startblock starting block to work on in matrix B * */ static inline void mzd_combine_even(mzd_t *C, rci_t const c_row, wi_t const c_startblock, mzd_t const *A, rci_t const a_row, wi_t const a_startblock, mzd_t const *B, rci_t const b_row, wi_t const b_startblock) { wi_t wide = A->width - a_startblock - 1; word *a = A->rows[a_row] + a_startblock; word *b = B->rows[b_row] + b_startblock; word *c = C->rows[c_row] + c_startblock; #if __M4RI_HAVE_SSE2 if(wide > 2) { /** check alignments **/ if (__M4RI_ALIGNMENT(a,16)) { *c++ = *b++ ^ *a++; wide--; } if ( (__M4RI_ALIGNMENT(b, 16) | __M4RI_ALIGNMENT(c, 16)) == 0) { __m128i *a128 = (__m128i*)a; __m128i *b128 = (__m128i*)b; __m128i *c128 = (__m128i*)c; const __m128i *eof = (__m128i*)((unsigned long)(a + wide) & ~0xFUL); do { *c128 = _mm_xor_si128(*a128, *b128); ++c128; ++b128; ++a128; } while(a128 < eof); a = (word*)a128; b = (word*)b128; c = (word*)c128; wide = ((sizeof(word) * wide) % 16) / sizeof(word); } } #endif // __M4RI_HAVE_SSE2 if (wide > 0) { wi_t n = (wide + 7) / 8; switch (wide % 8) { case 0: do { *(c++) = *(a++) ^ *(b++); case 7: *(c++) = *(a++) ^ *(b++); case 6: *(c++) = *(a++) ^ *(b++); case 5: *(c++) = *(a++) ^ *(b++); case 4: *(c++) = *(a++) ^ *(b++); case 3: *(c++) = *(a++) ^ *(b++); case 2: *(c++) = *(a++) ^ *(b++); case 1: *(c++) = *(a++) ^ *(b++); } while (--n > 0); } } *c ^= ((*a ^ *b ^ *c) & C->high_bitmask); __M4RI_DD_MZD(C); } /** * \brief row3[col3:] = row1[col1:] + row2[col2:] * * Adds row1 of SC1, starting with startblock1 to the end, to * row2 of SC2, starting with startblock2 to the end. This gets stored * in DST, in row3, starting with startblock3. * * \param C destination matrix * \param c_row destination row for matrix dst * \param c_startblock starting block to work on in matrix dst * \param A source matrix * \param a_row source row for matrix sc1 * \param a_startblock starting block to work on in matrix sc1 * \param B source matrix * \param b_row source row for matrix sc2 * \param b_startblock starting block to work on in matrix sc2 * */ static inline void mzd_combine(mzd_t *C, rci_t const c_row, wi_t const c_startblock, mzd_t const *A, rci_t const a_row, wi_t const a_startblock, mzd_t const *B, rci_t const b_row, wi_t const b_startblock) { if( (C == A) & (a_row == c_row) & (a_startblock == c_startblock) ) mzd_combine_even_in_place(C, c_row, c_startblock, B, b_row, b_startblock); else mzd_combine_even(C, c_row, c_startblock, A, a_row, a_startblock, B, b_row, b_startblock); return; } /** * \brief Get n bits starting a position (x,y) from the matrix M. * * This function is in principle the same as mzd_read_bits, * but it explicitely returns an 'int' and is used as * index into an array (Gray code). */ static inline int mzd_read_bits_int(mzd_t const *M, rci_t const x, rci_t const y, int const n) { return __M4RI_CONVERT_TO_INT(mzd_read_bits(M, x, y, n)); } /** * \brief Zero test for matrix. * * \param A Input matrix. * */ int mzd_is_zero(mzd_t const *A); /** * \brief Clear the given row, but only begins at the column coloffset. * * \param M Matrix * \param row Index of row * \param coloffset Column offset */ void mzd_row_clear_offset(mzd_t *M, rci_t const row, rci_t const coloffset); /** * \brief Find the next nonzero entry in M starting at start_row and start_col. * * This function walks down rows in the inner loop and columns in the * outer loop. If a nonzero entry is found this function returns 1 and * zero otherwise. * * If and only if a nonzero entry is found r and c are updated. * * \param M Matrix * \param start_row Index of row where to start search * \param start_col Index of column where to start search * \param r Row index updated if pivot is found * \param c Column index updated if pivot is found */ int mzd_find_pivot(mzd_t const *M, rci_t start_row, rci_t start_col, rci_t *r, rci_t *c); /** * \brief Return the number of nonzero entries divided by nrows * * ncols * * If res = 0 then 100 samples per row are made, if res > 0 the * function takes res sized steps within each row (res = 1 uses every * word). * * \param A Matrix * \param res Resolution of sampling (in words) */ double mzd_density(mzd_t const *A, wi_t res); /** * \brief Return the number of nonzero entries divided by nrows * * ncols considering only the submatrix starting at (r,c). * * If res = 0 then 100 samples per row are made, if res > 0 the * function takes res sized steps within each row (res = 1 uses every * word). * * \param A Matrix * \param res Resolution of sampling (in words) * \param r Row to start counting * \param c Column to start counting */ double _mzd_density(mzd_t const *A, wi_t res, rci_t r, rci_t c); /** * \brief Return the first row with all zero entries. * * If no such row can be found returns nrows. * * \param A Matrix */ rci_t mzd_first_zero_row(mzd_t const *A); /** * \brief Return hash value for matrix. * * \param A Matrix */ static inline word mzd_hash(mzd_t const *A) { word hash = 0; for (rci_t r = 0; r < A->nrows; ++r) hash ^= rotate_word(calculate_hash(A->rows[r], A->width), r % m4ri_radix); return hash; } /** * Return upper triangular submatrix of A * * \param U Output matrix, if NULL a new matrix will be returned * \param A Source matrix * * \return U */ mzd_t *mzd_extract_u(mzd_t *U, mzd_t const *A); /** * Return lower triangular submatrix of A * * \param L Output matrix, if NULL a new matrix will be returned * \param A Source matrix * * \return L */ mzd_t *mzd_extract_l(mzd_t *L, mzd_t const *A); #endif // M4RI_MZD m4ri-20140914/m4ri/graycode.h0000644000175000017500000000736112405042467012410 00000000000000/** * \file graycode.h * \brief Gray code implementation. * * The Gray code is a binary numeral system where two successive * values differ in only one digit. * * \author Gregory Bard * \author Martin Albrecht */ #ifndef M4RI_GRAYFLEX_H #define M4RI_GRAYFLEX_H /****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007 Gregory Bard * Copyright (C) 2007 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ /** * Maximum allowed value for k. */ #define __M4RI_MAXKAY 16 /** * \brief Gray codes. * * A codestruct represents one entry in the code book, i.e. it * represents a Gray code of a given length. * * For example the Gray code table of length \f$2^3\f$ is: * * \verbatim ------------------- | i | ord | inc | ------------------- | 0 | 0 | 0 | | 1 | 4 | 1 | | 2 | 6 | 0 | | 3 | 2 | 2 | | 4 | 3 | 0 | | 5 | 7 | 1 | | 6 | 5 | 0 | | 7 | 1 | 2 | ------------------- * \endverbatim */ typedef struct { /** * array of of Gray code entries */ int *ord; /** * increment */ int *inc; } code; /** * Global m4ri_codebook. * * \warning Not thread safe! */ extern code **m4ri_codebook; /** * Returns the i-th gray code entry for a gray code of length \f$2^l\f$. * * \param i The index in the Gray code table. * \param l Length of the Gray code. * * \return i-th Gray code entry. */ int m4ri_gray_code(int i, int l); /** * Fills var ord and var inc with Gray code data for a Gray code of * length \f$2^l\f$. * * \param ord Will hold gray code data, must be preallocated with correct size * \param inc Will hold some increment data, must be preallocated with correct size * \param l Logarithm of length of Gray code. * * \note Robert Miller had the idea for a non-recursive * implementation. */ void m4ri_build_code(int *ord, int *inc, int l); /** * \brief Generates global code book. * * This function is called automatically when the shared library is * loaded. * * \warning Not thread safe! */ void m4ri_build_all_codes(void); /** * Frees memory from the global code book. * * This function is called automatically when the shared library is * unloaded. * * \warning Not thread safe! */ void m4ri_destroy_all_codes(void); /** * floor(log_2(v)) */ static inline int log2_floor(int v) { static unsigned const int b[] = { 0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000 }; static unsigned const int S[] = { 1, 2, 4, 8, 16 }; unsigned int r = 0; for (int i = 4; i >= 0; --i) { if ((v & b[i])) { v >>= S[i]; r |= S[i]; } } return r; } /** * \brief Return the optimal var k for the given parameters. * * If var c != 0 then var k for multiplication is returned, else * var k for inversion. The optimal var k here means \f$0.75 log_2(n)\f$ * where \f$n\f$ is \f$min(a,b)\f$ for inversion and * \f$b\f$ for multiplication. * * \param a Number of rows of (first) matrix * \param b Number of columns of (first) matrix * \param c Number of columns of second matrix (may be 0) * * \return k */ int m4ri_opt_k(int a,int b,int c); #endif // M4RI_GRAYFLEX_H m4ri-20140914/m4ri/strassen.h0000644000175000017500000001051312354166226012451 00000000000000/** * \file strassen.h * * \brief Matrix operations using Strassen's formulas including * Winograd's improvements. * * \author Gregory Bard * \author Martin Albrecht */ #ifndef M4RI_STRASSEN_H #define M4RI_STRASSEN_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Martin Albrecht * Copyright (C) 2008 Clement Pernet * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #include #include /** * \brief Matrix multiplication via the Strassen-Winograd matrix * multiplication algorithm, i.e. compute C = AB. * * This is the wrapper function including bounds checks. See * _mzd_mul_even for implementation details. * * \param C Preallocated product matrix, may be NULL for automatic creation. * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for Strassen recursion. */ mzd_t *mzd_mul(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * \brief Matrix multiplication and in-place addition via the * Strassen-Winograd matrix multiplication algorithm, i.e. compute * C = C+ AB. * * This is the wrapper function including bounds checks. See * _mzd_addmul_even for implementation details. * * \param C product matrix * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for Strassen recursion. */ mzd_t *mzd_addmul(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * \brief Matrix multiplication via the Strassen-Winograd matrix * multiplication algorithm, i.e. compute C = AB. * * This is the actual implementation. Any matrix where either the * number of rows or the number of columns is smaller than cutoff is * processed using the M4RM algorithm. * * \param C Preallocated product matrix, may be NULL for automatic creation. * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for Strassen recursion. * * \note This implementation is heavily inspired by the function * strassen_window_multiply_c in Sage 3.0; For reference see * http://www.sagemath.org */ mzd_t *_mzd_mul_even(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * \brief Matrix multiplication and in-place addition via the * Strassen-Winograd matrix multiplication algorithm, i.e. compute * C = C+ AB. * * This is the actual implementation. Any matrix where either the * number of rows or the number of columns is smaller than cutoff is * processed using the M4RM algorithm. * * \param C Preallocated product matrix, may be NULL for automatic creation. * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for Strassen recursion. * * \note This implementation is heavily inspired by the function * strassen_window_multiply_c in Sage 3.0; For reference see * http://www.sagemath.org */ mzd_t *_mzd_addmul_even(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * \brief Matrix multiplication and in-place addition via the * Strassen-Winograd matrix multiplication algorithm, i.e. compute * C = C + AB. * * The matrices A and B are respectively m x k and k x n, and can be not * aligned on the m4ri_radix grid. * * \param C Preallocated product matrix, may be NULL for automatic creation. * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for Strassen recursion. * */ mzd_t *_mzd_addmul(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * The default cutoff for Strassen-Winograd multiplication. It should * hold hold that 2 * (n^2)/8 fits into the L2 cache. */ #ifndef __M4RI_STRASSEN_MUL_CUTOFF #define __M4RI_STRASSEN_MUL_CUTOFF MIN(((int)sqrt((double)(4 * __M4RI_CPU_L3_CACHE))), 4096) #endif #endif // M4RI_STRASSEN_H m4ri-20140914/m4ri/parity.h0000644000175000017500000000715312354166226012125 00000000000000#ifndef M4RI_PARITY_H #define M4RI_PARITY_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 David Harvey * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ /** * \file parity.h * * \brief Compute the parity of 64 words in parallel. * * \author David Harvey */ #include /** * \brief Step for mixing two 64-bit words to compute their parity. */ #define __M4RI_MIX32(a, b) (((((a) >> 32) ^ (a)) << 32) | \ ((((b) << 32) ^ (b)) >> 32)) /** * \brief Step for mixing two 64-bit words to compute their parity. */ #define __M4RI_MIX16(a, b) (((((a) << 16) ^ (a)) & __M4RI_CONVERT_TO_WORD(0xFFFF0000FFFF0000ull)) | \ ((((b) >> 16) ^ (b)) & __M4RI_CONVERT_TO_WORD(0x0000FFFF0000FFFFull))); /** * \brief Step for mixing two 64-bit words to compute their parity. */ #define __M4RI_MIX8(a, b) (((((a) << 8) ^ (a)) & __M4RI_CONVERT_TO_WORD(0xFF00FF00FF00FF00ull)) | \ ((((b) >> 8) ^ (b)) & __M4RI_CONVERT_TO_WORD(0x00FF00FF00FF00FFull))); /** * \brief Step for mixing two 64-bit words to compute their parity. */ #define __M4RI_MIX4(a, b) (((((a) << 4) ^ (a)) & __M4RI_CONVERT_TO_WORD(0xF0F0F0F0F0F0F0F0ull)) | \ ((((b) >> 4) ^ (b)) & __M4RI_CONVERT_TO_WORD(0x0F0F0F0F0F0F0F0Full))); /** * \brief Step for mixing two 64-bit words to compute their parity. */ #define __M4RI_MIX2(a, b) (((((a) << 2) ^ (a)) & __M4RI_CONVERT_TO_WORD(0xCCCCCCCCCCCCCCCCull)) | \ ((((b) >> 2) ^ (b)) & __M4RI_CONVERT_TO_WORD(0x3333333333333333ull))); /** * \brief Step for mixing two 64-bit words to compute their parity. */ #define __M4RI_MIX1(a, b) (((((a) << 1) ^ (a)) & __M4RI_CONVERT_TO_WORD(0xAAAAAAAAAAAAAAAAull)) | \ ((((b) >> 1) ^ (b)) & __M4RI_CONVERT_TO_WORD(0x5555555555555555ull))); /** * \brief See parity64. */ static inline word m4ri_parity64_helper(word *buf) { word a0, a1, b0, b1, c0, c1; a0 = __M4RI_MIX32(buf[0x20], buf[0x00]); a1 = __M4RI_MIX32(buf[0x30], buf[0x10]); b0 = __M4RI_MIX16(a1, a0); a0 = __M4RI_MIX32(buf[0x28], buf[0x08]); a1 = __M4RI_MIX32(buf[0x38], buf[0x18]); b1 = __M4RI_MIX16(a1, a0); c0 = __M4RI_MIX8(b1, b0); a0 = __M4RI_MIX32(buf[0x24], buf[0x04]); a1 = __M4RI_MIX32(buf[0x34], buf[0x14]); b0 = __M4RI_MIX16(a1, a0); a0 = __M4RI_MIX32(buf[0x2C], buf[0x0C]); a1 = __M4RI_MIX32(buf[0x3C], buf[0x1C]); b1 = __M4RI_MIX16(a1, a0); c1 = __M4RI_MIX8(b1, b0); return __M4RI_MIX4(c1, c0); } /** * \brief Computes parity of each of buf[0], buf[1], ..., buf[63]. * Returns single word whose bits are the parities of buf[0], ..., * buf[63]. * * \param buf buffer of words of length 64 */ static inline word m4ri_parity64(word *buf) { word d0, d1, e0, e1; d0 = m4ri_parity64_helper(buf); d1 = m4ri_parity64_helper(buf + 2); e0 = __M4RI_MIX2(d1, d0); d0 = m4ri_parity64_helper(buf + 1); d1 = m4ri_parity64_helper(buf + 3); e1 = __M4RI_MIX2(d1, d0); return __M4RI_MIX1(e1, e0); } #endif // M4RI_PARITY_H m4ri-20140914/m4ri/mzp.h0000644000175000017500000001161412405042272011407 00000000000000/** * \file mzp.h * * \brief Permutation matrices. * * \author Martin Albrecht * */ /****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifndef M4RI_MZP #define M4RI_MZP #include /** * \brief Permutations. */ typedef struct mzp_t { /** * The swap operations in LAPACK format. */ rci_t *values; /** * The length of the swap array. */ rci_t length; } mzp_t; // note that this is NOT mpz_t /** * Construct an identity permutation. * * \param length Length of the permutation. */ mzp_t *mzp_init(rci_t length); /** * Free a mzp_t. * * \param P Permutation to free. */ void mzp_free(mzp_t *P); /** * \brief Create a window/view into the permutation P. * * Use mzp_free_mzp_t_window() to free the window. * * \param P Permutation matrix * \param begin Starting index (inclusive) * \param end Ending index (exclusive) * */ mzp_t *mzp_init_window(mzp_t *P, rci_t begin, rci_t end); /** * \brief Free a permutation window created with * mzp_init_mzp_t_window(). * * \param condemned Permutation Matrix */ void mzp_free_window(mzp_t *condemned); /** * \brief copy permutation Q to P * * \param P Target permutation matrix (may be NULL) * \param Q Source permutation matrix (must not be NULL) */ mzp_t *mzp_copy(mzp_t *P, const mzp_t *Q); /** * \brief Set the permutation P to the identity permutation. The only * allowed value is 1. * * * \param P Permutation * \param value 1 * * \note This interface was chosen to be similar to mzd_set_ui(). */ void mzp_set_ui(mzp_t *P, unsigned int value); /** * Apply the permutation P to A from the left. * * This is equivalent to row swaps walking from 0 to length-1. * * \param A Matrix. * \param P Permutation. */ void mzd_apply_p_left(mzd_t *A, mzp_t const *P); /** * Apply the permutation P to A from the left but transpose P before. * * This is equivalent to row swaps walking from length-1 to 0. * * \param A Matrix. * \param P Permutation. */ void mzd_apply_p_left_trans(mzd_t *A, mzp_t const *P); /** * Apply the permutation P to A from the right. * * This is equivalent to column swaps walking from length-1 to 0. * * \param A Matrix. * \param P Permutation. */ void mzd_apply_p_right(mzd_t *A, mzp_t const *P); /** * Apply the permutation P to A from the right but transpose P before. * * This is equivalent to column swaps walking from 0 to length-1. * * \param A Matrix. * \param P Permutation. */ void mzd_apply_p_right_trans(mzd_t *A, mzp_t const *P); /** * Apply the permutation P to A from the right starting at start_row. * * This is equivalent to column swaps walking from length-1 to 0. * * \param A Matrix. * \param P Permutation. * \param start_row Start swapping at this row. * \param start_col Start swapping at this column. */ void mzd_apply_p_right_even_capped(mzd_t *A, mzp_t const *P, rci_t start_row, rci_t start_col); /** * Apply the permutation P^T to A from the right starting at start_row. * * This is equivalent to column swaps walking from 0 to length-1. * * \param A Matrix. * \param P Permutation. * \param start_row Start swapping at this row. * \param start_col Start swapping at this column. */ void mzd_apply_p_right_trans_even_capped(mzd_t *A, mzp_t const *P, rci_t start_row, rci_t start_col); /** * Apply the mzp_t P to A from the right but transpose P before. * * This is equivalent to column swaps walking from 0 to length-1. * * \param A Matrix. * \param P Permutation. */ void mzd_apply_p_right_trans(mzd_t *A, mzp_t const *P); /** * Apply the permutation P to A from the right, but only on the upper * the matrix A above the main diagonal. * * This is equivalent to column swaps walking from length-1 to 0. * * \param A Matrix. * \param Q Permutation. */ void mzd_apply_p_right_trans_tri(mzd_t *A, mzp_t const *Q); /** * Print the mzp_t P * * \param P Permutation. */ void mzp_print(mzp_t const *P); /** * Compresses the matrix L in a step in blockwise-recursive PLE * decomposition. * * \param A Matrix. * \param r1 Rank of left matrix. * \param n1 Column cut which separates left and right matrix. * \param r2 Rank of right matrix. */ void _mzd_compress_l(mzd_t *A, rci_t r1, rci_t n1, rci_t r2); #endif // M4RI_MZP m4ri-20140914/m4ri/triangular.h0000644000175000017500000001170712405042030012744 00000000000000/** * \file triangular.h * * \brief Triangular system solving with Matrix routines. * * \author Clement Pernet */ #ifndef M4RI_TRSM_H #define M4RI_TRSM_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Clement Pernet * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include /** * \brief Solves X U = B with X and B matrices and U upper triangular. * * X is stored inplace on B. * * \attention Note, that the 'right' variants of TRSM are slower than * the 'left' variants. * * This is the wrapper function including bounds checks. See * _mzd_trsm_upper_right() for implementation details. * * \param U Input upper triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. */ void mzd_trsm_upper_right(mzd_t const *U, mzd_t *B, const int cutoff); /** * \brief Solves X U = B with X and B matrices and U upper triangular. * * X is stored inplace on B. * * \attention Note, that the 'right' variants of TRSM are slower than * the 'left' variants. * * \param U Input upper triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. */ void _mzd_trsm_upper_right(mzd_t const *U, mzd_t *B, const int cutoff); /** * \brief Solves X L = B with X and B matrices and L lower triangular. * * X is stored inplace on B. * * This is the wrapper function including bounds checks. See * _mzd_trsm_upper_right() for implementation details. * * \attention Note, that the 'right' variants of TRSM are slower than the 'left' * variants. * * \param L Input upper triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. */ void mzd_trsm_lower_right(mzd_t const *L, mzd_t *B, const int cutoff); /** * \brief Solves X L = B with X and B with matrices and L lower * triangular. * * This version assumes that the matrices are at an even position on * the m4ri_radix grid and that their dimension is a multiple of m4ri_radix. * X is stored inplace on B. * * \attention Note, that the 'right' variants of TRSM are slower than * the 'left' variants. * * \param L Input lower triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. * */ void _mzd_trsm_lower_right(mzd_t const *L, mzd_t *B, const int cutoff); /** * \brief Solves L X = B with X and B matrices and L lower triangular. * * X is stored inplace on B. * * This is the wrapper function including bounds checks. See * _mzd_trsm_lower_left() for implementation details. * * \param L Input lower triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. */ void mzd_trsm_lower_left(mzd_t const *L, mzd_t *B, const int cutoff); /** * \brief Solves L X = B with X and B matrices and L lower triangular. * * X is stored inplace on B. * * \param L Input lower triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. */ void _mzd_trsm_lower_left(mzd_t const *L, mzd_t *B, const int cutoff); /** * \brief Solves U X = B with X and B matrices and U upper triangular. * * X is stored inplace on B. * * This is the wrapper function including bounds checks. See * _mzd_trsm_upper_left() for implementation details. * * \param U Input upper triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. */ void mzd_trsm_upper_left(mzd_t const *U, mzd_t *B, const int cutoff); /** * \brief Solves U X = B with X and B matrices and U upper triangular. * * X is stored inplace on B. * * \param U Input upper triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion. */ void _mzd_trsm_upper_left (mzd_t const *U, mzd_t *B, const int cutoff); /** * \brief Invert the upper triangular matrix A by reduction to matrix multiplication. * * \param A Matrix to be inverted (overwritten). * * \return Inverse of A or throws an error */ mzd_t *mzd_trtri_upper(mzd_t *A); #endif // M4RI_TRSM_H m4ri-20140914/m4ri/triangular_russian.h0000644000175000017500000000407312405042333014514 00000000000000/** * \file triangular_russian.h * \brief TRSM and TRTRI via Gray code tables. * * \author Martin Albrecht */ #ifndef M4RI_TRIANGULAR_RUSSIAN #define M4RI_TRIANGULAR_RUSSIAN /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008-2011 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include /** * \brief Solves L X = B with X and B matrices and L lower triangular using Gray code tables. * * X is stored inplace on B. * * \param L Input lower triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param k Size of Gray code tables or zero for automatic choice (recommended). */ void _mzd_trsm_lower_left_russian(mzd_t const *L, mzd_t *B, int k); /** * \brief Solves U X = B with X and B matrices and U upper triangular using Gray code tables. * * X is stored inplace on B. * * \param U Input upper triangular matrix. * \param B Input matrix, being overwritten by the solution matrix X * \param k Size of Gray code tables or zero for automatic choice (recommended). */ void _mzd_trsm_upper_left_russian(mzd_t const *U, mzd_t *B, int k); /** * \brief Invert the upper triangular matrix A using Kronrod's method. * * \param A Matrix to be inverted (overwritten). * \param k Table size parameter, may be 0 for automatic choice. * * \return Inverse of A or throws an error */ mzd_t *mzd_trtri_upper_russian(mzd_t *A, int k); #endif //M4RI_TRIANGULAR_RUSSIAN m4ri-20140914/m4ri/ple.h0000644000175000017500000001075712405042311011362 00000000000000/** * \file ple.h * * \brief PLE and PLUQ matrix decomposition routines. * * \author Clement Pernet * */ #ifndef M4RI_PLUQ_H #define M4RI_PLUQ_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008, 2009 Clement Pernet * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #include /** * Crossover point for PLUQ factorization. */ #define __M4RI_PLE_CUTOFF MIN(524288, __M4RI_CPU_L3_CACHE >> 3) /** * \brief PLUQ matrix decomposition. * * Returns (P,L,U,Q) satisfying PLUQ = A where P and Q are two * permutation matrices, of dimension respectively m x m and n x n, L * is m x r unit lower triangular and U is r x n upper triangular. * * P and Q must be preallocated but they don't have to be * identity permutations. If cutoff is zero a value is chosen * automatically. It is recommended to set cutoff to zero for most * applications. * * The row echelon form (not reduced) can be read from the upper * triangular matrix U. See mzd_echelonize_pluq() for details. * * This is the wrapper function including bounds checks. See * _mzd_pluq() for implementation details. * * \param A Input m x n matrix * \param P Output row permutation of length m * \param Q Output column permutation matrix of length n * \param cutoff Minimal dimension for Strassen recursion. * * \sa _mzd_pluq() _mzd_pluq_mmpf() mzd_echelonize_pluq() * * \return Rank of A. */ rci_t mzd_pluq(mzd_t *A, mzp_t *P, mzp_t *Q, const int cutoff); /** * \brief PLE matrix decomposition. * * Computes the PLE matrix decomposition using a block recursive * algorithm. * * Returns (P,L,S,Q) satisfying PLE = A where P is a permutation matrix * of dimension m x m, L is m x r unit lower triangular and S is an r * x n matrix which is upper triangular except that its columns are * permuted, that is S = UQ for U r x n upper triangular and Q is a n * x n permutation matrix. The matrix L and S are stored in place over * A. * * P and Q must be preallocated but they don't have to be * identity permutations. If cutoff is zero a value is chosen * automatically. It is recommended to set cutoff to zero for most * applications. * * This is the wrapper function including bounds checks. See * _mzd_ple() for implementation details. * * \param A Input m x n matrix * \param P Output row permutation of length m * \param Q Output column permutation matrix of length n * \param cutoff Minimal dimension for Strassen recursion. * * \sa _mzd_ple() _mzd_pluq() _mzd_pluq_mmpf() mzd_echelonize_pluq() * * \return Rank of A. */ rci_t mzd_ple(mzd_t *A, mzp_t *P, mzp_t *Q, const int cutoff); /** * \brief PLUQ matrix decomposition. * * See mzd_pluq() for details. * * \param A Input matrix * \param P Output row mzp_t matrix * \param Q Output column mzp_t matrix * \param cutoff Minimal dimension for Strassen recursion. * * \sa mzd_pluq() * * \return Rank of A. */ rci_t _mzd_pluq(mzd_t *A, mzp_t *P, mzp_t *Q, const int cutoff); /** * \brief PLE matrix decomposition. * * See mzd_ple() for details. * * \param A Input matrix * \param P Output row mzp_t matrix * \param Qt Output column mzp_t matrix * \param cutoff Minimal dimension for Strassen recursion. * * \sa mzd_ple() * * \return Rank of A. */ rci_t _mzd_ple(mzd_t *A, mzp_t *P, mzp_t *Qt, const int cutoff); /** * \brief PLUQ matrix decomposition (naive base case). * * See mzd_pluq() for details. * * \param A Input matrix * \param P Output row mzp_t matrix * \param Q Output column mzp_t matrix * * \sa mzd_pluq() * * \return Rank of A. */ rci_t _mzd_pluq_naive(mzd_t *A, mzp_t *P, mzp_t *Q); /** * \brief PLE matrix decomposition (naive base case). * * See mzd_ple() for details. * * \param A Input matrix * \param P Output row mzp_t matrix * \param Qt Output column mzp_t matrix * * \sa mzd_ple() * * \return Rank of A. */ rci_t _mzd_ple_naive(mzd_t *A, mzp_t *P, mzp_t *Qt); #endif // M4RI_PLUQ_H m4ri-20140914/m4ri/ple_russian.h0000644000175000017500000001537412405042324013132 00000000000000/** * \file ple_russian.h * \brief PLE and PLUQ factorization using Gray codes. * * \author Martin Albrecht * * \example testsuite/test_ple.c */ #ifndef M4RI_PLE_RUSSIAN #define M4RI_PLE_RUSSIAN /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008-2011 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #include /** * \brief PLE Elimination Tables */ typedef struct { mzd_t *T; /*!< the actual table with 2^k entries */ rci_t *M; /*!< lookup for multiplication */ rci_t *E; /*!< lookup for elimination */ word *B; /*!< cache of first 64 entries in each row */ } ple_table_t; /** * Create new table with 2^k rows and ncols. * * \param k log2 of the number of rows (0 < k <= 8). * \param ncols Number of columns. */ ple_table_t *ple_table_init(int k, rci_t ncols); /** * \brief Delete table T * * \param T PLE table. */ void ple_table_free(ple_table_t *T); /** * \brief PLE matrix decomposition of A using Gray codes. * * Returns (P,L,E,Q) satisfying PLE = A where P is a permutation * matrix of dimension m x m, L is m x r unit lower triangular and S * is an r x n matrix which is upper triangular except that its * columns are permuted, that is E = UQ for U r x n upper triangular * and Q is a n x n permutation matrix. The matrix L and E are stored * in place over A. * * \param A Matrix. * \param P Preallocated row permutation. * \param Q Preallocated column permutation. * \param k Size of Gray code tables. * * \return Rank of A. */ rci_t _mzd_ple_russian(mzd_t *A, mzp_t *P, mzp_t *Q, int k); /** * \brief PLUQ matrix decomposition of A using Gray codes. * * Returns (P,L,U,Q) satisfying PLUQ = A where P and Q are two * permutation matrices, of dimension respectively m x m and n x n, L * is m x r unit lower triangular and U is r x n upper triangular. * * \param A Matrix. * \param P Preallocated row permutation. * \param Q Preallocated column permutation. * \param k Size of Gray code tables. * * \return Rank of A. */ rci_t _mzd_pluq_russian(mzd_t *A, mzp_t *P, mzp_t *Q, int k); /** * \brief PLE matrix decomposition of a submatrix for up to k columns * starting at (r,c). * * Updates P and Q and modifies A in place. The buffer done afterwards * holds how far a particular row was already eliminated. * * \param A Matrix. * \param start_row Row Offset. * \param stop_row Up to which row the matrix should be processed (exclusive). * \param start_col Column Offset. * \param k Size of Gray code tables. * \param P Preallocated row permutation. * \param Q Preallocated column permutation. * \param pivots which column holds the i-th pivot * \param done Preallocated temporary buffer. * \param done_row Stores the last row which is already reduced processed after function execution. * \param splitblock First block which is not considered by this function. * * \retval knar rank of the considered submatrix */ int _mzd_ple_submatrix(mzd_t *A, rci_t const start_row, rci_t const stop_row, rci_t const start_col, int const k, mzp_t *P, mzp_t *Q, rci_t *pivots, rci_t *done, rci_t *done_row, wi_t const splitblock); /** * \brief Extract the k x A::ncols echelon form submatrix of A starting at row r and column c. * * \param E Storage for k x A::ncols matrix. * \param A Source matrix. * \param r Row index. * \param c Column index. * \param k Rank of E. * \param k Map from i to column of i-th pivot. * \param offsets Encodes which columns contain pivots */ mzd_t *_mzd_ple_to_e(mzd_t *E, mzd_t const *A, rci_t r, rci_t c, int k, rci_t *offsets); /** * \brief add rows T[0],T[1] to M between startrow and stoprow, starting at startcol. * * \param M Matrix * \param startrow Start processing in this row * \param stoprow Stop processing in this row * \param startcol Start processing in this column * \param k Number of bits to read in each table * \param T PLE Table with 2^k[i] rows */ void _mzd_process_rows_ple_2(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int const *k, const ple_table_t **T); /** * \brief add rows T[0],T[1],T[2] to M between startrow and stoprow, starting at startcol. * * \param M Matrix * \param startrow Start processing in this row * \param stoprow Stop processing in this row * \param startcol Start processing in this column * \param k Number of bits to read in each table * \param T PLE Table with 2^k[i] rows */ void _mzd_process_rows_ple_3(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int const *k, const ple_table_t **T); /** * \brief add rows T[0],T[1],T[2],T[3] to M between startrow and stoprow, starting at startcol. * * \param M Matrix * \param startrow Start processing in this row * \param stoprow Stop processing in this row * \param startcol Start processing in this column * \param k Number of bits to read in each table * \param T PLE Table with 2^k[i] rows */ void _mzd_process_rows_ple_4(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int const *k, const ple_table_t **T); /** * \brief add rows T[0],T[1],T[2],T[3],T[4] to M between startrow and stoprow, starting at startcol. * * \param M Matrix * \param startrow Start processing in this row * \param stoprow Stop processing in this row * \param startcol Start processing in this column * \param k Number of bits to read in each table * \param T PLE Table with 2^k[i] rows */ void _mzd_process_rows_ple_5(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int const *k, const ple_table_t **T); /** * \brief add rows T[0],T[1],T[2],T[3],T[4],T[5] to M between startrow and stoprow, starting at startcol. * * \param M Matrix * \param startrow Start processing in this row * \param stoprow Stop processing in this row * \param startcol Start processing in this column * \param k Number of bits to read in each table * \param T PLE Table with 2^k[i] rows */ void _mzd_process_rows_ple_6(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int const *k, const ple_table_t **T); #endif // M4RI_PLE_RUSSIAN m4ri-20140914/m4ri/ple_russian_template.h0000644000175000017500000001347112354166226015034 00000000000000#include void __M4RI_TEMPLATE_NAME(_mzd_process_rows_ple)(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int const k[N], const ple_table_t const *table[N]) { assert(1 <= N && N <= 8); const mzd_t *T[N]; const rci_t *E[N]; const word *B[N]; word bm[N]; int sh[N]; int x[N]; const word * t[N]; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: T[7] = table[7]->T; E[7] = table[7]->E; B[7] = table[7]->B; bm[7] = __M4RI_LEFT_BITMASK(k[7]); sh[7] = k[0] + k[1] + k[2] + k[3] + k[4] + k[5] + k[6]; case 7: T[6] = table[6]->T; E[6] = table[6]->E; B[6] = table[6]->B; bm[6] = __M4RI_LEFT_BITMASK(k[6]); sh[6] = k[0] + k[1] + k[2] + k[3] + k[4] + k[5]; case 6: T[5] = table[5]->T; E[5] = table[5]->E; B[5] = table[5]->B; bm[5] = __M4RI_LEFT_BITMASK(k[5]); sh[5] = k[0] + k[1] + k[2] + k[3] + k[4]; case 5: T[4] = table[4]->T; E[4] = table[4]->E; B[4] = table[4]->B; bm[4] = __M4RI_LEFT_BITMASK(k[4]); sh[4] = k[0] + k[1] + k[2] + k[3]; case 4: T[3] = table[3]->T; E[3] = table[3]->E; B[3] = table[3]->B; bm[3] = __M4RI_LEFT_BITMASK(k[3]); sh[3] = k[0] + k[1] + k[2]; case 3: T[2] = table[2]->T; E[2] = table[2]->E; B[2] = table[2]->B; bm[2] = __M4RI_LEFT_BITMASK(k[2]); sh[2] = k[0] + k[1]; case 2: T[1] = table[1]->T; E[1] = table[1]->E; B[1] = table[1]->B; bm[1] = __M4RI_LEFT_BITMASK(k[1]); sh[1] = k[0]; case 1: T[0] = table[0]->T; E[0] = table[0]->E; B[0] = table[0]->B; bm[0] = __M4RI_LEFT_BITMASK(k[0]); sh[0] = 0; } wi_t const block = startcol / m4ri_radix; wi_t const wide = M->width - block; for(rci_t r = startrow; r < stoprow; ++r) { word bits = mzd_read_bits(M, r, startcol, sh[N-1] + k[N-1]); word *m = M->rows[r] + block; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: x[ N-8 ] = E[ N-8 ][ (bits>> sh[ N-8 ]) & bm[ N-8 ] ]; bits ^= B[ N-8 ][x[ N-8 ]]; t[ N-8 ] = T[ N-8 ]->rows[x[ N-8 ]] + block; case 7: x[ N-7 ] = E[ N-7 ][ (bits>> sh[ N-7 ]) & bm[ N-7 ] ]; bits ^= B[ N-7 ][x[ N-7 ]]; t[ N-7 ] = T[ N-7 ]->rows[x[ N-7 ]] + block; case 6: x[ N-6 ] = E[ N-6 ][ (bits>> sh[ N-6 ]) & bm[ N-6 ] ]; bits ^= B[ N-6 ][x[ N-6 ]]; t[ N-6 ] = T[ N-6 ]->rows[x[ N-6 ]] + block; case 5: x[ N-5 ] = E[ N-5 ][ (bits>> sh[ N-5 ]) & bm[ N-5 ] ]; bits ^= B[ N-5 ][x[ N-5 ]]; t[ N-5 ] = T[ N-5 ]->rows[x[ N-5 ]] + block; case 4: x[ N-4 ] = E[ N-4 ][ (bits>> sh[ N-4 ]) & bm[ N-4 ] ]; bits ^= B[ N-4 ][x[ N-4 ]]; t[ N-4 ] = T[ N-4 ]->rows[x[ N-4 ]] + block; case 3: x[ N-3 ] = E[ N-3 ][ (bits>> sh[ N-3 ]) & bm[ N-3 ] ]; bits ^= B[ N-3 ][x[ N-3 ]]; t[ N-3 ] = T[ N-3 ]->rows[x[ N-3 ]] + block; case 2: x[ N-2 ] = E[ N-2 ][ (bits>> sh[ N-2 ]) & bm[ N-2 ] ]; bits ^= B[ N-2 ][x[ N-2 ]]; t[ N-2 ] = T[ N-2 ]->rows[x[ N-2 ]] + block; case 1: x[ N-1 ] = E[ N-1 ][ (bits>> sh[ N-1 ]) & bm[ N-1 ] ]; bits ^= B[ N-1 ][x[ N-1 ]]; t[ N-1 ] = T[ N-1 ]->rows[x[ N-1 ]] + block; } __M4RI_TEMPLATE_NAME(_mzd_combine)(m, t, wide); } __M4RI_DD_MZD(M); } void __M4RI_TEMPLATE_NAME(_mzd_ple_a11)(mzd_t *A, rci_t const start_row, rci_t const stop_row, rci_t const start_col, wi_t const block, int const k[N], ple_table_t const *table[N]) { wi_t const wide = A->width - block; if(wide <= 0) return; const mzd_t *T[N]; const rci_t *M[N]; word bm[N]; int sh[N]; int x[N]; const word * t[N]; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: T[7] = table[7]->T; M[7] = table[7]->M; bm[7] = __M4RI_LEFT_BITMASK(k[7]); sh[7] = k[0] + k[1] + k[2] + k[3] + k[4] + k[5] + k[6]; case 7: T[6] = table[6]->T; M[6] = table[6]->M; bm[6] = __M4RI_LEFT_BITMASK(k[6]); sh[6] = k[0] + k[1] + k[2] + k[3] + k[4] + k[5]; case 6: T[5] = table[5]->T; M[5] = table[5]->M; bm[5] = __M4RI_LEFT_BITMASK(k[5]); sh[5] = k[0] + k[1] + k[2] + k[3] + k[4]; case 5: T[4] = table[4]->T; M[4] = table[4]->M; bm[4] = __M4RI_LEFT_BITMASK(k[4]); sh[4] = k[0] + k[1] + k[2] + k[3]; case 4: T[3] = table[3]->T; M[3] = table[3]->M; bm[3] = __M4RI_LEFT_BITMASK(k[3]); sh[3] = k[0] + k[1] + k[2]; case 3: T[2] = table[2]->T; M[2] = table[2]->M; bm[2] = __M4RI_LEFT_BITMASK(k[2]); sh[2] = k[0] + k[1]; case 2: T[1] = table[1]->T; M[1] = table[1]->M; bm[1] = __M4RI_LEFT_BITMASK(k[1]); sh[1] = k[0]; case 1: T[0] = table[0]->T; M[0] = table[0]->M; bm[0] = __M4RI_LEFT_BITMASK(k[0]); sh[0] = 0; }; const rci_t bits_to_read = sh[N-1] + k[N-1]; for(rci_t i = start_row; i < stop_row; ++i) { const word bits = mzd_read_bits(A, i, start_col, bits_to_read); word *m = A->rows[i] + block; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: x[ N-8 ] = M[ N-8 ][ (bits>> sh[ N-8 ]) & bm[ N-8 ] ]; t[ N-8 ] = T[ N-8 ]->rows[ x[ N-8 ] ] + block; case 7: x[ N-7 ] = M[ N-7 ][ (bits>> sh[ N-7 ]) & bm[ N-7 ] ]; t[ N-7 ] = T[ N-7 ]->rows[ x[ N-7 ] ] + block; case 6: x[ N-6 ] = M[ N-6 ][ (bits>> sh[ N-6 ]) & bm[ N-6 ] ]; t[ N-6 ] = T[ N-6 ]->rows[ x[ N-6 ] ] + block; case 5: x[ N-5 ] = M[ N-5 ][ (bits>> sh[ N-5 ]) & bm[ N-5 ] ]; t[ N-5 ] = T[ N-5 ]->rows[ x[ N-5 ] ] + block; case 4: x[ N-4 ] = M[ N-4 ][ (bits>> sh[ N-4 ]) & bm[ N-4 ] ]; t[ N-4 ] = T[ N-4 ]->rows[ x[ N-4 ] ] + block; case 3: x[ N-3 ] = M[ N-3 ][ (bits>> sh[ N-3 ]) & bm[ N-3 ] ]; t[ N-3 ] = T[ N-3 ]->rows[ x[ N-3 ] ] + block; case 2: x[ N-2 ] = M[ N-2 ][ (bits>> sh[ N-2 ]) & bm[ N-2 ] ]; t[ N-2 ] = T[ N-2 ]->rows[ x[ N-2 ] ] + block; case 1: x[ N-1 ] = M[ N-1 ][ (bits>> sh[ N-1 ]) & bm[ N-1 ] ]; t[ N-1 ] = T[ N-1 ]->rows[ x[ N-1 ] ] + block; } __M4RI_TEMPLATE_NAME(_mzd_combine)(m, t, wide); } __M4RI_DD_MZD(A); } m4ri-20140914/m4ri/solve.h0000644000175000017500000001202512405042331011722 00000000000000/** * \file solve.h * * \brief System solving with matrix routines. * * \author Jean-Guillaume Dumas * */ #ifndef M4RI_SOLVE_H #define M4RI_SOLVE_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Jean-Guillaume.Dumas@imag.fr * * Distributed under the terms of the GNU General Public License (GPL) * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #include /** * \brief Solves A X = B with A and B matrices. * * The solution X is stored inplace on B. * * \param A Input matrix (overwritten). * \param B Input matrix, being overwritten by the solution matrix X * \param cutoff Minimal dimension for Strassen recursion (default: 0). * \param inconsistency_check decide wether or not to perform a check * for incosistency (faster without but output not defined if * system is not consistent). * \return 0 if a solution was found, -1 otherwise */ int mzd_solve_left(mzd_t *A, mzd_t *B, int const cutoff, int const inconsistency_check); /** * \brief Solves (P L U Q) X = B * * A is an input matrix supposed to store both: * \li an upper right triangular matrix U * \li a lower left unitary triangular matrix L. * * The solution X is stored inplace on B * * This version assumes that the matrices are at an even position on * the m4ri_radix grid and that their dimension is a multiple of m4ri_radix. * * \param A Input upper/lower triangular matrices. * \param rank is rank of A. * \param P Input row permutation matrix. * \param Q Input column permutation matrix. * \param B Input matrix, being overwritten by the solution matrix X. * \param cutoff Minimal dimension for Strassen recursion (default: 0). * \param inconsistency_check decide whether or not to perform a check * for incosistency (faster without but output not defined if * system is not consistent). \return 0 if a solution was * found, -1 otherwise * \return 0 if a solution was found, -1 otherwise */ int mzd_pluq_solve_left (mzd_t const *A, rci_t rank, mzp_t const *P, mzp_t const *Q, mzd_t *B, int const cutoff, int const inconsistency_check); /** * \brief Solves (P L U Q) X = B * * A is an input matrix supposed to store both: * \li an upper right triangular matrix U * \li a lower left unitary triangular matrix L. * The solution X is stored inplace on B. * * This version assumes that the matrices are at an even position on * the m4ri_radix grid and that their dimension is a multiple of m4ri_radix. * * \param A Input upper/lower triangular matrices. * \param rank is rank of A. * \param P Input row permutation matrix. * \param Q Input column permutation matrix. * \param B Input matrix, being overwritten by the solution matrix X. * \param cutoff Minimal dimension for Strassen recursion (default: 0). * \param inconsistency_check decide whether or not to perform a check * for incosistency (faster without but output not defined if * system is not consistent). \return 0 if a solution was * found, -1 otherwise * \return 0 if a solution was found, -1 otherwise */ int _mzd_pluq_solve_left(mzd_t const *A, rci_t rank, mzp_t const *P, mzp_t const *Q, mzd_t *B, int const cutoff, int const inconsistency_check); /** * \brief Solves A X = B with A and B matrices. * * The solution X is stored inplace on B. * * This version assumes that the matrices are at an even position on * the m4ri_radix grid and that their dimension is a multiple of m4ri_radix. * * \param A Input matrix (overwritten). * \param B Input matrix, being overwritten by the solution matrix X. * \param cutoff Minimal dimension for Strassen recursion (default: 0). * \param inconsistency_check decide whether or not to perform a check * for incosistency (faster without but output not defined if * system is not consistent). \return 0 if a solution was * found, -1 otherwise * \return 0 if a solution was found, -1 otherwise */ int _mzd_solve_left(mzd_t *A, mzd_t *B, int const cutoff, int const inconsistency_check); /** * \brief Solve X for A X = 0. * * If r is the rank of the nr x nc matrix A, return the nc x (nc-r) * matrix X such that A*X == 0 and that the columns of X are linearly * independent. * * \param A Input matrix (overwritten). * \param cutoff Minimal dimension for Strassen recursion (default: 0). * * \sa mzd_pluq() * * \return X, NULL if kernel is empty */ mzd_t *mzd_kernel_left_pluq(mzd_t *A, int const cutoff); #endif // M4RI_SOLVE_H m4ri-20140914/m4ri/echelonform.h0000644000175000017500000000372012405042255013102 00000000000000/** * \file echelonform.h * \brief Row echelon forms * * \author Martin Albrecht */ #ifndef M4RI_ECHELONFORM_H #define M4RI_ECHELONFORM_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2010 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include /** * Density at which we switch to PLE decomposition. */ #define __M4RI_ECHELONFORM_CROSSOVER_DENSITY 0.15 /** * \brief (Reduced) row echelon form. * * This function will * * \param A Matrix. * \param full Return the reduced row echelon form, not only upper triangular form. * * \return Rank of A. */ rci_t mzd_echelonize(mzd_t *A, int full); /** * \brief (Reduced) row echelon form using PLUQ factorisation. * * \param A Matrix. * \param full Return the reduced row echelon form, not only upper triangular form. * * \sa mzd_pluq() * * \return Rank of A. */ rci_t mzd_echelonize_pluq(mzd_t *A, int full); /** * \brief Matrix elimination using the 'Method of the Four Russians' (M4RI). * * This is a wrapper function for _mzd_echelonize_m4ri() * * \param A Matrix to be reduced. * \param full Return the reduced row echelon form, not only upper triangular form. * \param k M4RI parameter, may be 0 for auto-choose. * * \sa _mzd_echelonize_m4ri() * * \return Rank of A. */ rci_t mzd_echelonize_m4ri(mzd_t *A, int full, int k); #endif // M4RI_ECHELONFORM_H m4ri-20140914/m4ri/xor.h0000644000175000017500000000503212405037407011412 00000000000000/* * Functions for adding vectors. * * \author Martin Albrecht * */ #ifndef M4RI_XOR_H #define M4RI_XOR_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008-2013 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #if __M4RI_HAVE_SSE2 #include #endif #include /** * Compute c[i] += t1[i] for 0 <= i < wide * */ static inline void _mzd_combine(word *c, word const *t1, wi_t wide_in) { wi_t wide = wide_in; #if __M4RI_HAVE_SSE2 /* assuming c, t1 are alligned the same way */ if (__M4RI_ALIGNMENT(c,16)==8 && wide) { *c++ ^= *t1++; wide--; } __m128i *__c = (__m128i*)c; __m128i *__t1 = (__m128i*)t1; const __m128i *eof = (__m128i*)((unsigned long)(c + wide) & ~0xFUL); __m128i xmm1; while(__c < eof-1) { xmm1 = _mm_xor_si128(*__c, *__t1++); *__c++ = xmm1; xmm1 = _mm_xor_si128(*__c, *__t1++); *__c++ = xmm1; } if(__c < eof) { xmm1 = _mm_xor_si128(*__c, *__t1++); *__c++ = xmm1; } c = (word*)__c; t1 = (word*)__t1; wide = ((sizeof(word) * wide) % 16) / sizeof(word); if(!wide) { __M4RI_DD_RAWROW(c, wide_in); return; } #endif // __M4RI_HAVE_SSE2 wi_t n = (wide + 7) / 8; switch (wide % 8) { case 0: do { *c++ ^= *t1++; case 7: *c++ ^= *t1++; case 6: *c++ ^= *t1++; case 5: *c++ ^= *t1++; case 4: *c++ ^= *t1++; case 3: *c++ ^= *t1++; case 2: *c++ ^= *t1++; case 1: *c++ ^= *t1++; } while (--n > 0); } __M4RI_DD_RAWROW(c, wide_in); } #define N 2 #include "xor_template.h" #undef N #define N 3 #include "xor_template.h" #undef N #define N 4 #include "xor_template.h" #undef N #define N 5 #include "xor_template.h" #undef N #define N 6 #include "xor_template.h" #undef N #define N 7 #include "xor_template.h" #undef N #define N 8 #include "xor_template.h" #undef N #endif // M4RI_XOR_H m4ri-20140914/m4ri/xor_template.h0000644000175000017500000003552412354166226013323 00000000000000#include #include /** * Compute c[i] += sum(t[j][i], 0 <= j < N) for 0 <= i < wide * * \todo the non SSE2 version of this code is slow, replace by code from mzd_process_rows8 * * \warn Assumes __M4RI_ALIGNMENT(c, 16) == __M4RI_ALIGNMENT(t[i], 16) */ static inline void __M4RI_TEMPLATE_NAME(_mzd_combine)(word *m, word const *t[N], wi_t wide) { assert(1 <= N && N <= 8); #if __M4RI_HAVE_SSE2 assert( (__M4RI_ALIGNMENT(m,16) == 8) | (__M4RI_ALIGNMENT(m,16) == 0) ); switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[7],16)); case 7: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[6],16)); case 6: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[5],16)); case 5: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[4],16)); case 4: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[3],16)); case 3: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[2],16)); case 2: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[1],16)); case 1: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[0],16)); }; if (__M4RI_UNLIKELY(__M4RI_ALIGNMENT(m,16) == 8)) { switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; }; wide--; } __m128i *m__ = (__m128i*)m; __m128i *t__[N]; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: t__[N-8] = (__m128i*)t[N-8]; case 7: t__[N-7] = (__m128i*)t[N-7]; case 6: t__[N-6] = (__m128i*)t[N-6]; case 5: t__[N-5] = (__m128i*)t[N-5]; case 4: t__[N-4] = (__m128i*)t[N-4]; case 3: t__[N-3] = (__m128i*)t[N-3]; case 2: t__[N-2] = (__m128i*)t[N-2]; case 1: t__[N-1] = (__m128i*)t[N-1]; }; __m128i xmm0, xmm1, xmm2, xmm3; for(wi_t i=0; i< (wide>>1); i++) { switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: xmm0 = _mm_xor_si128(*t__[0]++, *t__[1]++); xmm1 = _mm_xor_si128(*t__[2]++, *t__[3]++); xmm2 = _mm_xor_si128(*t__[4]++, *t__[5]++); xmm3 = _mm_xor_si128(*t__[6]++, *t__[7]++); xmm0 = _mm_xor_si128(xmm0, xmm1); xmm2 = _mm_xor_si128(xmm2, xmm3); xmm0 = _mm_xor_si128(xmm0, xmm2); xmm0 = _mm_xor_si128(*m__, xmm0); break; case 7: xmm0 = _mm_xor_si128(*t__[0]++, *t__[1]++); xmm1 = _mm_xor_si128(*t__[2]++, *t__[3]++); xmm0 = _mm_xor_si128(xmm0, *t__[4]++); xmm1 = _mm_xor_si128(xmm1, *t__[5]++); xmm0 = _mm_xor_si128(xmm0, *t__[6]++); xmm0 = _mm_xor_si128(xmm0, xmm1); xmm0 = _mm_xor_si128(*m__, xmm0); break; case 6: xmm0 = _mm_xor_si128(*t__[0]++, *t__[1]++); xmm1 = _mm_xor_si128(*t__[2]++, *t__[3]++); xmm0 = _mm_xor_si128(xmm0, *t__[4]++); xmm1 = _mm_xor_si128(xmm1, *t__[5]++); xmm0 = _mm_xor_si128(xmm0, xmm1); xmm0 = _mm_xor_si128(*m__, xmm0); break; case 5: xmm0 = _mm_xor_si128(*t__[0]++, *t__[1]++); xmm1 = _mm_xor_si128(*t__[2]++, *t__[3]++); xmm0 = _mm_xor_si128(xmm0, *t__[4]++); xmm0 = _mm_xor_si128(xmm0, xmm1); xmm0 = _mm_xor_si128(*m__, xmm0); break; case 4: xmm0 = _mm_xor_si128(*t__[0]++, *t__[1]++); xmm1 = _mm_xor_si128(*t__[2]++, *t__[3]++); xmm0 = _mm_xor_si128(xmm0, xmm1); xmm0 = _mm_xor_si128(*m__, xmm0); break; case 3: xmm0 = _mm_xor_si128(*t__[0]++, *t__[1]++); xmm1 = _mm_xor_si128(*m__, *t__[2]++); xmm0 = _mm_xor_si128(xmm0, xmm1); break; case 2: xmm0 = _mm_xor_si128(*t__[0]++, *t__[1]++); xmm0 = _mm_xor_si128(*m__, xmm0); break; case 1: xmm0 = _mm_xor_si128(*m__, *t__[0]++); break; }; *m__++ = xmm0; } if(wide & 0x1) { m = (word*)m__; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: t[N-8] = (word*)t__[N-8]; case 7: t[N-7] = (word*)t__[N-7]; case 6: t[N-6] = (word*)t__[N-6]; case 5: t[N-5] = (word*)t__[N-5]; case 4: t[N-4] = (word*)t__[N-4]; case 3: t[N-3] = (word*)t__[N-3]; case 2: t[N-2] = (word*)t__[N-2]; case 1: t[N-1] = (word*)t__[N-1]; } switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; } } return; #else for(wi_t i=0; i< wide; i++) { switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; } } return; #endif // __M4RI_HAVE_SSE2 } /** * Compute c[i] += sum(t[j][i], 0 <= j < N) for 0 <= i < wide * * \todo the non SSE2 version of this code is slow, replace by code from mzd_process_rows8 * * \warn Assumes __M4RI_ALIGNMENT(c, 16) == 8 and __M4RI_ALIGNMENT(c, 16) == __M4RI_ALIGNMENT(t[i], 16) */ static inline void __M4RI_TEMPLATE_NAME(_mzd_combine_u)(word *m, word const *t[N], wi_t wide) { assert(1 <= N && N <= 8); #if __M4RI_HAVE_SSE2 assert( (__M4RI_ALIGNMENT(m,16) == 8) ); switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[7],16)); case 7: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[6],16)); case 6: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[5],16)); case 5: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[4],16)); case 4: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[3],16)); case 3: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[2],16)); case 2: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[1],16)); case 1: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[0],16)); }; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; }; wide--; __m128i *m__ = (__m128i*)m; __m128i *t__[N]; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: t__[N-8] = (__m128i*)t[N-8]; case 7: t__[N-7] = (__m128i*)t[N-7]; case 6: t__[N-6] = (__m128i*)t[N-6]; case 5: t__[N-5] = (__m128i*)t[N-5]; case 4: t__[N-4] = (__m128i*)t[N-4]; case 3: t__[N-3] = (__m128i*)t[N-3]; case 2: t__[N-2] = (__m128i*)t[N-2]; case 1: t__[N-1] = (__m128i*)t[N-1]; }; __m128i xmm1; for(wi_t i=0; i< (wide>>1); i++) { xmm1 = _mm_xor_si128(*m__, *t__[0]++); switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: xmm1 = _mm_xor_si128(xmm1, *t__[N-7]++); case 7: xmm1 = _mm_xor_si128(xmm1, *t__[N-6]++); case 6: xmm1 = _mm_xor_si128(xmm1, *t__[N-5]++); case 5: xmm1 = _mm_xor_si128(xmm1, *t__[N-4]++); case 4: xmm1 = _mm_xor_si128(xmm1, *t__[N-3]++); case 3: xmm1 = _mm_xor_si128(xmm1, *t__[N-2]++); case 2: xmm1 = _mm_xor_si128(xmm1, *t__[N-1]++); case 1: break; }; *m__++ = xmm1; } if(wide & 0x1) { m = (word*)m__; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: t[N-8] = (word*)t__[N-8]; case 7: t[N-7] = (word*)t__[N-7]; case 6: t[N-6] = (word*)t__[N-6]; case 5: t[N-5] = (word*)t__[N-5]; case 4: t[N-4] = (word*)t__[N-4]; case 3: t[N-3] = (word*)t__[N-3]; case 2: t[N-2] = (word*)t__[N-2]; case 1: t[N-1] = (word*)t__[N-1]; } switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; } } return; #else for(wi_t i=0; i< wide; i++) { switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; } } return; #endif // __M4RI_HAVE_SSE2 } /** * Compute c[i] += sum(t[j][i], 0 <= j < N) for 0 <= i < wide * * \todo the non SSE2 version of this code is slow, replace by code from mzd_process_rows8 * * \warn Assumes __M4RI_ALIGNMENT(c, 16) == 0 and __M4RI_ALIGNMENT(c, 16) == __M4RI_ALIGNMENT(t[i], 16) */ static inline void __M4RI_TEMPLATE_NAME(_mzd_combine_a)(word *m, word const *t[N], wi_t wide) { assert(1 <= N && N <= 8); #if __M4RI_HAVE_SSE2 assert( __M4RI_ALIGNMENT(m,16) == 0 ); switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[7],16)); case 7: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[6],16)); case 6: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[5],16)); case 5: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[4],16)); case 4: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[3],16)); case 3: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[2],16)); case 2: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[1],16)); case 1: assert(__M4RI_ALIGNMENT(m,16) == __M4RI_ALIGNMENT(t[0],16)); }; __m128i *m__ = (__m128i*)m; __m128i *t__[N]; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: t__[N-8] = (__m128i*)t[N-8]; case 7: t__[N-7] = (__m128i*)t[N-7]; case 6: t__[N-6] = (__m128i*)t[N-6]; case 5: t__[N-5] = (__m128i*)t[N-5]; case 4: t__[N-4] = (__m128i*)t[N-4]; case 3: t__[N-3] = (__m128i*)t[N-3]; case 2: t__[N-2] = (__m128i*)t[N-2]; case 1: t__[N-1] = (__m128i*)t[N-1]; }; __m128i xmm1; for(wi_t i=0; i< (wide>>1); i++) { xmm1 = _mm_xor_si128(*m__, *t__[0]++); switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: xmm1 = _mm_xor_si128(xmm1, *t__[N-7]++); case 7: xmm1 = _mm_xor_si128(xmm1, *t__[N-6]++); case 6: xmm1 = _mm_xor_si128(xmm1, *t__[N-5]++); case 5: xmm1 = _mm_xor_si128(xmm1, *t__[N-4]++); case 4: xmm1 = _mm_xor_si128(xmm1, *t__[N-3]++); case 3: xmm1 = _mm_xor_si128(xmm1, *t__[N-2]++); case 2: xmm1 = _mm_xor_si128(xmm1, *t__[N-1]++); case 1: break; }; *m__++ = xmm1; } if(wide & 0x1) { m = (word*)m__; switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: t[N-8] = (word*)t__[N-8]; case 7: t[N-7] = (word*)t__[N-7]; case 6: t[N-6] = (word*)t__[N-6]; case 5: t[N-5] = (word*)t__[N-5]; case 4: t[N-4] = (word*)t__[N-4]; case 3: t[N-3] = (word*)t__[N-3]; case 2: t[N-2] = (word*)t__[N-2]; case 1: t[N-1] = (word*)t__[N-1]; } switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; } } return; #else for(wi_t i=0; i< wide; i++) { switch(N) { /* we rely on the compiler to optimise this switch away, it reads nicer than #if */ case 8: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++ ^ *t[7]++; break; case 7: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++ ^ *t[6]++; break; case 6: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++ ^ *t[5]++; break; case 5: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++ ^ *t[4]++; break; case 4: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++ ^ *t[3]++; break; case 3: *m++ ^= *t[0]++ ^ *t[1]++ ^ *t[2]++; break; case 2: *m++ ^= *t[0]++ ^ *t[1]++; break; case 1: *m++ ^= *t[0]++; break; } } return; #endif // __M4RI_HAVE_SSE2 } m4ri-20140914/m4ri/mmc.h0000644000175000017500000000412112354166226011361 00000000000000/** * \file mmc.h * \brief The mmc memory management functions check a cache for re-usable unused memory before asking the system for it. * * \author Gregory Bard * \author Martin Albrecht */ #ifndef M4RI_MMC_H #define M4RI_MMC_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007, 2008 Gregory Bard * Copyright (C) 2008 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include void *m4ri_mmc_malloc(size_t size); void m4ri_mmc_free(void *condemned, size_t size); void m4ri_mmc_cleanup(void); /** * \brief Enable memory block cache (default: enabled). */ #define __M4RI_ENABLE_MMC /** * \brief Number of blocks that are cached. */ #define __M4RI_MMC_NBLOCKS 16 /** * \brief Maximal size of blocks stored in cache. */ #define __M4RI_MMC_THRESHOLD __M4RI_CPU_L3_CACHE /** * \brief Tuple of pointer to allocated memory block and it's size. */ typedef struct _mm_block { /** * Size in bytes of the data. */ size_t size; /** * Pointer to buffer of data. */ void *data; } mmb_t; /** * \brief Allocate an array of count times size zeroed bytes. * * \param count Number of elements. * \param size Number of bytes per element. * * \return Pointer to allocated memory block. */ static inline void *m4ri_mmc_calloc(size_t count, size_t size) { size_t total_size = count * size; void *ret = m4ri_mmc_malloc(total_size); memset((char*)ret, 0, total_size); return ret; } #endif // M4RI_MMC_H m4ri-20140914/m4ri/debug_dump.h0000644000175000017500000000533412405036013012712 00000000000000/* * To enable dumping of output per function, configure the library with --enable-debug-dump. */ /****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2011 Carlo Wood * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifndef M4RI_DEBUG_DUMP #define M4RI_DEBUG_DUMP static inline word calculate_hash(word const* rowptr, wi_t wide) { word hash = 0; for (word const* ptr = rowptr; ptr < rowptr + wide; ++ptr) hash ^= *ptr; return hash; } static inline word rotate_word(word w, int shift) { return (w << shift) | (w >> (m4ri_radix - w)); } #if __M4RI_DEBUG_DUMP struct mzd_t; struct mzp_t; extern void m4ri_dd_int(char const* function, char const* file, int line, int i); extern void m4ri_dd_rci(char const* function, char const* file, int line, rci_t rci); extern void m4ri_dd_rci_array(char const* function, char const* file, int line, rci_t *rciptr, int len); extern void m4ri_dd_rawrow(char const* function, char const* file, int line, word const* rowptr, wi_t wide); extern void m4ri_dd_row(char const* function, char const* file, int line, struct mzd_t const* M, rci_t row); extern void m4ri_dd_mzd(char const* function, char const* file, int line, struct mzd_t const* M); extern void m4ri_dd_mzp(char const* function, char const* file, int line, struct mzp_t const* P); #define __M4RI_DD_INT(i) m4ri_dd_int(__FUNCTION__, __FILE__, __LINE__, i) #define __M4RI_DD_RCI(rci) m4ri_dd_rci(__FUNCTION__, __FILE__, __LINE__, rci) #define __M4RI_DD_RCI_ARRAY(rciptr, len) m4ri_dd_rci_array(__FUNCTION__, __FILE__, __LINE__, rciptr, len) #define __M4RI_DD_RAWROW(rowptr, wide) m4ri_dd_rawrow(__FUNCTION__, __FILE__, __LINE__, rowptr, wide) #define __M4RI_DD_ROW(M, row) m4ri_dd_row(__FUNCTION__, __FILE__, __LINE__, M, row) #define __M4RI_DD_MZD(M) m4ri_dd_mzd(__FUNCTION__, __FILE__, __LINE__, M) #define __M4RI_DD_MZP(P) m4ri_dd_mzp(__FUNCTION__, __FILE__, __LINE__, P) #else // __M4RI_DEBUG_DUMP #define __M4RI_DD_INT(i) #define __M4RI_DD_RCI(rci) #define __M4RI_DD_RCI_ARRAY(rciptr, len) #define __M4RI_DD_RAWROW(rowptr, wide) #define __M4RI_DD_ROW(M, row) #define __M4RI_DD_MZD(M) #define __M4RI_DD_MZP(P) #endif // __M4RI_DEBUG_DUMP #endif // M4RI_DEBUG_DUMP m4ri-20140914/m4ri/io.h0000644000175000017500000000766012405036455011224 00000000000000/** * \file io.h * \brief Input/output routines for matrices * * \author Martin Albrecht */ #ifndef M4RI_IO_H #define M4RI_IO_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2011 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include #include /** * \brief Print a matrix to stdout. * * The output will contain colons between every 4-th column. * * \param M Matrix */ void mzd_print(mzd_t const *M); /** * \brief Print row i of M to stdout. * * The output will contain colons between every 4-th column. * * \param M Matrix * \param i Row to print */ void mzd_print_row(mzd_t const *M, const rci_t i); /** * \brief Print compact information about the matrix to stdout. * * Prints number of rows, number of columns, density (and rank). * * \param A Matrix * \param do_rank Also display the rank (expensive) */ void mzd_info(const mzd_t *A, int do_rank); #if __M4RI_HAVE_LIBPNG /** * \brief Read matrix from 1-bit PNG image. * * This function returns a matrix on success and NULL otherwise. 1-bit * Grayscale and 1-bit Palette images are supported. * * \param fn Filename * \param verbose Print error message to stdout if != 0 */ mzd_t * mzd_from_png(const char *fn, int verbose); /** * \brief Write matrix to 1-bit PNG image. * * This function returns zero on success and some value != 0 * otherwise. The parameter compression_level takes a zlib compression * level, i.e., an integer betweeen -1 and 9 (inclusive) such that * \verbatim #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) \endverbatim * * The optional comment string is written as a PNG comment. * * * \param A Matrix * \param fn Filename (must have write permission) * \param compression_level Zlib compression level (see above) * \param comment Optional comment (may be NULL) * \param verbose Print error message to stdout if != 0 */ int mzd_to_png(const mzd_t *A, const char *fn, int compression_level, const char *comment, int verbose); #endif //__M4RI_HAVE_LIBPNG /** * \brief Read matrix from ASCII file in JCF format. * * The format is as follows: \verbatim nrows ncols modulus nonzero_entries_upper_bound column_index \endverbatim * * where a negative column_index indicates a row_index increase by one and a non-zero entry at index * -column_index. * * \note the JCF format is one-based in contrast to everything else in this library which is * zero-based. * * For example, a valid input is: \verbatim 3 2 2 3 -2 -1 -2 \endverbatim * * which produces the matrix \verbatim [0 1] [1 0] [0 1] \endverbatim * * * \param fn Filename * \param verbose Print error message to stdout if != 0 */ mzd_t *mzd_from_jcf(const char *fn, int verbose); /** * \brief Create matrix from dense ASCII string * * The provided string is parsed in row major ordering, i.e. the first entry is * writen to A[0,0], the second entry to A[0,1] etc. * * For example, calling \verbatim mzd_t *A = mzd_from_str(4, 4, "1000010000100001"); \endverbatim * * would create a 4 x 4 identity matrix. * * \param m Number of rows * \param n Nimber of columns * \param str String containing ASCII zeros and ones of length m*n */ mzd_t *mzd_from_str(rci_t m, rci_t n, const char *str); #endif //M4RI_IO_H m4ri-20140914/m4ri/djb.h0000644000175000017500000000710612405041562011342 00000000000000/** * \file djb.h * * \brief Dan Bernstein's "Optimizing linear maps mod 2" * * This code is a port of sort1.cpp available at http://binary.cr.yp.to/linearmod2.html * * Given a matrix A djb_compile(A) will compute a djb_t data structure which realises A with * (heuristically) (m * n)/(log m - loglog m) XORs. * * It makes use of a binary heap written by Martin Kunev which is available at * https://gist.github.com/martinkunev/1365481 * * \author Martin Albrecht */ #ifndef M4RI_DJB_H #define M4RI_DJB_H #include /** * \brief Specify source type of addition */ typedef enum { source_target, //< add from target matrix source_source //< add from source matrix } srctyp_t; /** * \brief DJB's optimized linear maps mod 2 */ typedef struct { rci_t nrows; /*!< Number of rows of map */ rci_t ncols; /*!< Number of columns of map */ rci_t *target; /*!< target row at index i */ rci_t *source; /*!< source row at index i */ srctyp_t *srctyp; /*!< source type at index i */ rci_t length; /*!< length of target, source and srctype */ wi_t allocated; /*!< how much did we allocate already */ } djb_t; /** * Standard allocation chunk */ #define M4RI_DJB_BASE_SIZE 64 /** * Allocate a new DJB linear map * * \param nrows Number of rows * \param ncols Number of columns */ static inline djb_t *djb_init(rci_t nrows, rci_t ncols) { /* we want to use realloc, so we call unaligned malloc */ djb_t *m = (djb_t*)malloc(sizeof(djb_t)); if (m == NULL) m4ri_die("malloc failed.\n"); m->nrows = nrows; m->ncols = ncols; m->target = (rci_t*)malloc(sizeof(rci_t) * M4RI_DJB_BASE_SIZE); m->source = (rci_t*)malloc(sizeof(rci_t) * M4RI_DJB_BASE_SIZE); m->srctyp = (srctyp_t*)malloc(sizeof(srctyp_t) * M4RI_DJB_BASE_SIZE); m->length = 0; m->allocated = M4RI_DJB_BASE_SIZE; if (m->target == NULL || m->source == NULL || m->srctyp == NULL) m4ri_die("malloc failed.\n"); return m; } /** * Free a DJB linear maps * * \param m Map */ static inline void djb_free(djb_t *m) { free(m->target); free(m->source); free(m->srctyp); free(m); } /** * Add a new operation out[target] ^= srctype[source] to queue. * * \param z DJB linear map. * \param target Output index * \param source Input index * \param srctyp Type of input (source_source or source_target) */ static inline void djb_push_back(djb_t *z, rci_t target, rci_t source, srctyp_t srctyp) { assert((target < z->nrows) && ((source < z->ncols) | (srctyp != source_source)) && ((source < z->nrows) | (srctyp != source_target))); if (z->length >= z->allocated) { z->allocated += M4RI_DJB_BASE_SIZE; z->target = (rci_t*)realloc(z->target, z->allocated*sizeof(rci_t)); z->source = (rci_t*)realloc(z->source, z->allocated*sizeof(rci_t)); z->srctyp = (srctyp_t*)realloc(z->srctyp, z->allocated*sizeof(srctyp_t)); } z->target[z->length] = target; z->source[z->length] = source; z->srctyp[z->length] = srctyp; z->length++; } /** * Compile a new DJB linear map from A. * * \param A */ djb_t *djb_compile(mzd_t *A); /** * \brief W = m*V * * Apply the linear map m to V and write the result in W. * * \param z DJB linear map. * \param W Output matrix * \param V Input matrix */ void djb_apply_mzd(djb_t *z, mzd_t *W, const mzd_t *V); /** * Print infomrmation on linear map mA */ static inline void djb_info(djb_t *z) { double save = (double)z->length / (double)(z->nrows * z->ncols); printf("%d x %d linear map in %d xors (cost: %.5f)\n", z->nrows, z->ncols, z->length, save); } #endif //M4RI_DJB_H m4ri-20140914/m4ri/mp.h0000644000175000017500000000506412354166226011230 00000000000000/** * \file mp.h * * \brief multicore matrix operations * * \author Martin Albrecht */ #ifndef M4RI_MP_H #define M4RI_MP_H /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2014 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include /** * \brief Matrix multiplication via the cubic multiplication algorithm on * multiple cores, i.e. compute C = AB. * * This is the wrapper function including bounds checks. See _mzd_mul_mp4 for * implementation details. * * \param C Preallocated product matrix, may be NULL for automatic creation. * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for recursion. */ mzd_t *mzd_mul_mp(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * \brief Matrix multiplication and in-place addition via the cubic matrix * multiplication algorithm on multiple cores, i.e. compute C = C+ AB. * * This is the wrapper function including bounds checks. See _mzd_addmul_mp4 for * implementation details. * * \param C product matrix * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for recursion. */ mzd_t *mzd_addmul_mp(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * \brief Matrix multiplication and in-place addition via cubic matrix * multiplication algorithm on up to four cores, i.e. compute C = C+ AB. * * \param C Product matrix * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for recursion. */ mzd_t *_mzd_addmul_mp4(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); /** * \brief Matrix multiplication via cubic matrix multiplication algorithm on up * to four cores, i.e. compute C = C+ AB. * * \param C Product matrix * \param A Input matrix A * \param B Input matrix B * \param cutoff Minimal dimension for recursion. */ mzd_t *_mzd_mul_mp4(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff); #endif //__M4RI_HAVE_OPENMP m4ri-20140914/m4ri/brilliantrussian.c0000644000175000017500000011221212354166226014166 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007, 2008 Gregory Bard * Copyright (C) 2008-2010 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "brilliantrussian.h" #include "xor.h" #include "graycode.h" #include "echelonform.h" #include "ple_russian.h" /** * \brief Perform Gaussian reduction to reduced row echelon form on a * submatrix. * * The submatrix has dimension at most k starting at r x c of A. Checks * for pivot rows up to row endrow (exclusive). Terminates as soon as * finding a pivot column fails. * * \param A Matrix. * \param r First row. * \param c First column. * \param k Maximal dimension of identity matrix to produce. * \param end_row Maximal row index (exclusive) for rows to consider * for inclusion. */ static inline int _mzd_gauss_submatrix_full(mzd_t *A, rci_t r, rci_t c, rci_t end_row, int k) { assert(k <= m4ri_radix); rci_t start_row = r; rci_t j; for (j = c; j < c + k; ++j) { int found = 0; for (rci_t i = start_row; i < end_row; ++i) { /* first we need to clear the first columns */ word const tmp = mzd_read_bits(A, i, c, j - c + 1); if(tmp) { for (int l = 0; l < j - c; ++l) if (__M4RI_GET_BIT(tmp, l)) mzd_row_add_offset(A, i, r+l, c+l); /* pivot? */ if (mzd_read_bit(A, i, j)) { mzd_row_swap(A, i, start_row); /* clear above */ for (rci_t l = r; l < start_row; ++l) { if (mzd_read_bit(A, l, j)) { mzd_row_add_offset(A, l, start_row, j); } } ++start_row; found = 1; break; } } } if (found == 0) { break; } } __M4RI_DD_MZD(A); __M4RI_DD_INT(j - c); return j - c; } /** * \brief Perform Gaussian reduction to upper triangular matrix on a * submatrix. * * The submatrix has dimension at most k starting at r x c of A. Checks * for pivot rows up to row end_row (exclusive). Terminates as soon as * finding a pivot column fails. * * \param A Matrix. * \param r First row. * \param c First column. * \param k Maximal dimension of identity matrix to produce. * \param end_row Maximal row index (exclusive) for rows to consider * for inclusion. */ static inline int _mzd_gauss_submatrix(mzd_t *A, rci_t r, rci_t c, rci_t end_row, int k) { rci_t start_row = r; int found; rci_t j; for (j = c; j < c+k; ++j) { found = 0; for (rci_t i = start_row; i < end_row; ++i) { /* first we need to clear the first columns */ for (int l = 0; l < j - c; ++l) if (mzd_read_bit(A, i, c+l)) mzd_row_add_offset(A, i, r+l, c+l); /* pivot? */ if (mzd_read_bit(A, i, j)) { mzd_row_swap(A, i, start_row); start_row++; found = 1; break; } } if (found == 0) { break; } } __M4RI_DD_MZD(A); __M4RI_DD_INT(j - c); return j - c; } /** * \brief Given a submatrix in upper triangular form compute the * reduced row echelon form. * * The submatrix has dimension at most k starting at r x c of A. Checks * for pivot rows up to row end_row (exclusive). Terminates as soon as * finding a pivot column fails. * * \param A Matrix. * \param r First row. * \param c First column. * \param k Maximal dimension of identity matrix to produce. * \param end_row Maximal row index (exclusive) for rows to consider * for inclusion. */ static inline int _mzd_gauss_submatrix_top(mzd_t *A, rci_t r, rci_t c, int k) { rci_t start_row = r; for (rci_t j = c; j < c + k; ++j) { for (rci_t l = r; l < start_row; ++l) { if (mzd_read_bit(A, l, j)) { mzd_row_add_offset(A, l, start_row, j); } } ++start_row; } __M4RI_DD_MZD(A); __M4RI_DD_INT(k); return k; } static inline void _mzd_copy_back_rows(mzd_t *A, mzd_t const *U, rci_t r, rci_t c, int k) { wi_t const startblock = c / m4ri_radix; wi_t const width = A->width - startblock; for (int i = 0; i < k; ++i) { word const *const src = U->rows[i] + startblock; word *const dst = A->rows[r+i] + startblock; for (wi_t j = 0; j < width; ++j) { dst[j] = src[j]; } } __M4RI_DD_MZD(A); } void mzd_make_table(mzd_t const *M, rci_t r, rci_t c, int k, mzd_t *T, rci_t *L) { wi_t const homeblock = c / m4ri_radix; word const mask_end = __M4RI_LEFT_BITMASK(M->ncols % m4ri_radix); word const pure_mask_begin = __M4RI_RIGHT_BITMASK(m4ri_radix - (c % m4ri_radix)); word const mask_begin = (M->width - homeblock != 1) ? pure_mask_begin : pure_mask_begin & mask_end; wi_t const wide = M->width - homeblock; int const twokay = __M4RI_TWOPOW(k); L[0] = 0; for (rci_t i = 1; i < twokay; ++i) { word *ti = T->rows[i] + homeblock; word *ti1 = T->rows[i-1] + homeblock; rci_t const rowneeded = r + m4ri_codebook[k]->inc[i - 1]; int const id = m4ri_codebook[k]->ord[i]; L[id] = i; if (rowneeded >= M->nrows) continue; word *m = M->rows[rowneeded] + homeblock; *ti++ = (*m++ ^ *ti1++) & mask_begin; wi_t j; for(j = 1; j + 8 <= wide - 1; j += 8) { *ti++ = *m++ ^ *ti1++; *ti++ = *m++ ^ *ti1++; *ti++ = *m++ ^ *ti1++; *ti++ = *m++ ^ *ti1++; *ti++ = *m++ ^ *ti1++; *ti++ = *m++ ^ *ti1++; *ti++ = *m++ ^ *ti1++; *ti++ = *m++ ^ *ti1++; } switch(wide - j) { case 8: *ti++ = *m++ ^ *ti1++; case 7: *ti++ = *m++ ^ *ti1++; case 6: *ti++ = *m++ ^ *ti1++; case 5: *ti++ = *m++ ^ *ti1++; case 4: *ti++ = *m++ ^ *ti1++; case 3: *ti++ = *m++ ^ *ti1++; case 2: *ti++ = *m++ ^ *ti1++; case 1: *ti++ = (*m++ ^ *ti1++) & mask_end; } } __M4RI_DD_MZD(T); __M4RI_DD_RCI_ARRAY(L, twokay); } void mzd_process_rows(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int k, mzd_t const *T, rci_t const *L) { wi_t const block = startcol / m4ri_radix; wi_t const wide = M->width - block; wi_t const count = (wide + 7) / 8; /* Unrolled loop count */ int const entry_point = wide % 8; /* Unrolled loop entry point */ if(k == 1) { word const bm = m4ri_one << (startcol % m4ri_radix); rci_t r; for (r = startrow; r + 2 <= stoprow; r += 2) { word const b0 = M->rows[r+0][block] & bm; word const b1 = M->rows[r+1][block] & bm; word *m0 = M->rows[r+0] + block; word *m1 = M->rows[r+1] + block; word *t = T->rows[1] + block; wi_t n = count; if((b0 & b1)) { switch (entry_point) { case 0: do { *m0++ ^= *t; *m1++ ^= *t++; case 7: *m0++ ^= *t; *m1++ ^= *t++; case 6: *m0++ ^= *t; *m1++ ^= *t++; case 5: *m0++ ^= *t; *m1++ ^= *t++; case 4: *m0++ ^= *t; *m1++ ^= *t++; case 3: *m0++ ^= *t; *m1++ ^= *t++; case 2: *m0++ ^= *t; *m1++ ^= *t++; case 1: *m0++ ^= *t; *m1++ ^= *t++; } while (--n > 0); } } else if(b0) { switch (entry_point) { case 0: do { *m0++ ^= *t++; case 7: *m0++ ^= *t++; case 6: *m0++ ^= *t++; case 5: *m0++ ^= *t++; case 4: *m0++ ^= *t++; case 3: *m0++ ^= *t++; case 2: *m0++ ^= *t++; case 1: *m0++ ^= *t++; } while (--n > 0); } } else if(b1) { switch (entry_point) { case 0: do { *m1++ ^= *t++; case 7: *m1++ ^= *t++; case 6: *m1++ ^= *t++; case 5: *m1++ ^= *t++; case 4: *m1++ ^= *t++; case 3: *m1++ ^= *t++; case 2: *m1++ ^= *t++; case 1: *m1++ ^= *t++; } while (--n > 0); } } } /* TODO: this code is a bit silly/overkill, it just takes care of the last row */ for( ; r < stoprow; ++r) { rci_t const x0 = L[ mzd_read_bits_int(M, r, startcol, k) ]; word *m0 = M->rows[r] + block; word *t0 = T->rows[x0] + block; wi_t n = count; switch (entry_point) { case 0: do { *m0++ ^= *t0++; case 7: *m0++ ^= *t0++; case 6: *m0++ ^= *t0++; case 5: *m0++ ^= *t0++; case 4: *m0++ ^= *t0++; case 3: *m0++ ^= *t0++; case 2: *m0++ ^= *t0++; case 1: *m0++ ^= *t0++; } while (--n > 0); } } __M4RI_DD_MZD(M); return; } rci_t r; for (r = startrow; r + 2 <= stoprow; r += 2) { rci_t const x0 = L[ mzd_read_bits_int(M, r+0, startcol, k) ]; rci_t const x1 = L[ mzd_read_bits_int(M, r+1, startcol, k) ]; word *m0 = M->rows[r+0] + block; word *t0 = T->rows[x0] + block; word *m1 = M->rows[r+1] + block; word *t1 = T->rows[x1] + block; wi_t n = count; switch (entry_point) { case 0: do { *m0++ ^= *t0++; *m1++ ^= *t1++; case 7: *m0++ ^= *t0++; *m1++ ^= *t1++; case 6: *m0++ ^= *t0++; *m1++ ^= *t1++; case 5: *m0++ ^= *t0++; *m1++ ^= *t1++; case 4: *m0++ ^= *t0++; *m1++ ^= *t1++; case 3: *m0++ ^= *t0++; *m1++ ^= *t1++; case 2: *m0++ ^= *t0++; *m1++ ^= *t1++; case 1: *m0++ ^= *t0++; *m1++ ^= *t1++; } while (--n > 0); } } for( ; r < stoprow; ++r) { rci_t const x0 = L[ mzd_read_bits_int(M, r, startcol, k) ]; word *m0 = M->rows[r] + block; word *t0 = T->rows[x0] + block; wi_t n = count; switch (entry_point) { case 0: do { *m0++ ^= *t0++; case 7: *m0++ ^= *t0++; case 6: *m0++ ^= *t0++; case 5: *m0++ ^= *t0++; case 4: *m0++ ^= *t0++; case 3: *m0++ ^= *t0++; case 2: *m0++ ^= *t0++; case 1: *m0++ ^= *t0++; } while (--n > 0); } } __M4RI_DD_MZD(M); } void mzd_process_rows2(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1) { assert(k <= m4ri_radix); wi_t const blocknum = startcol / m4ri_radix; wi_t const wide = M->width - blocknum; int const ka = k / 2; int const kb = k - k / 2; rci_t r; word const ka_bm = __M4RI_LEFT_BITMASK(ka); word const kb_bm = __M4RI_LEFT_BITMASK(kb); #if __M4RI_HAVE_OPENMP #pragma omp parallel for private(r) shared(startrow, stoprow) schedule(static,512) // MAX((__M4RI_CPU_L1_CACHE >> 3) / wide, #endif for(r = startrow; r < stoprow; ++r) { word bits = mzd_read_bits(M, r, startcol, k); rci_t const x0 = L0[ bits & ka_bm ]; bits>>=ka; rci_t const x1 = L1[ bits & kb_bm ]; if((x0 | x1) == 0) // x0 == 0 && x1 == 0 continue; word *m0 = M->rows[r] + blocknum; word const *t[2]; t[0] = T0->rows[x0] + blocknum; t[1] = T1->rows[x1] + blocknum; _mzd_combine_2( m0, t, wide); } __M4RI_DD_MZD(M); } void mzd_process_rows3(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2) { assert(k <= m4ri_radix); wi_t const blocknum = startcol / m4ri_radix; wi_t const wide = M->width - blocknum; int rem = k % 3; int const ka = k / 3 + ((rem >= 2) ? 1 : 0); int const kb = k / 3 + ((rem >= 1) ? 1 : 0); int const kc = k / 3; rci_t r; word const ka_bm = __M4RI_LEFT_BITMASK(ka); word const kb_bm = __M4RI_LEFT_BITMASK(kb); word const kc_bm = __M4RI_LEFT_BITMASK(kc); #if __M4RI_HAVE_OPENMP #pragma omp parallel for private(r) shared(startrow, stoprow) schedule(static,512) //if(stoprow-startrow > 128) #endif for(r= startrow; r < stoprow; ++r) { word bits = mzd_read_bits(M, r, startcol, k); rci_t const x0 = L0[ bits & ka_bm ]; bits>>=ka; rci_t const x1 = L1[ bits & kb_bm ]; bits>>=kb; rci_t const x2 = L2[ bits & kc_bm ]; if((x0 | x1 | x2) == 0) // x0 == 0 && x1 == 0 && x2 == 0 continue; word *m0 = M->rows[r] + blocknum; word const *t[3]; t[0] = T0->rows[x0] + blocknum; t[1] = T1->rows[x1] + blocknum; t[2] = T2->rows[x2] + blocknum; _mzd_combine_3( m0, t, wide); } __M4RI_DD_MZD(M); } void mzd_process_rows4(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2, mzd_t const *T3, rci_t const *L3) { assert(k <= m4ri_radix); wi_t const blocknum = startcol / m4ri_radix; wi_t const wide = M->width - blocknum; int const rem = k % 4; int const ka = k / 4 + ((rem >= 3) ? 1 : 0); int const kb = k / 4 + ((rem >= 2) ? 1 : 0); int const kc = k / 4 + ((rem >= 1) ? 1 : 0); int const kd = k / 4; rci_t r; word const ka_bm = __M4RI_LEFT_BITMASK(ka); word const kb_bm = __M4RI_LEFT_BITMASK(kb); word const kc_bm = __M4RI_LEFT_BITMASK(kc); word const kd_bm = __M4RI_LEFT_BITMASK(kd); #if __M4RI_HAVE_OPENMP #pragma omp parallel for private(r) shared(startrow, stoprow) schedule(static,512) //if(stoprow-startrow > 128) #endif for(r = startrow; r < stoprow; ++r) { word bits = mzd_read_bits(M, r, startcol, k); rci_t const x0 = L0[ bits & ka_bm ]; bits>>=ka; rci_t const x1 = L1[ bits & kb_bm ]; bits>>=kb; rci_t const x2 = L2[ bits & kc_bm ]; bits>>=kc; rci_t const x3 = L3[ bits & kd_bm ]; if(((x0 | x1) | (x2 | x3)) == 0) // x0 == 0 && x1 == 0 && x2 == 0 && x3 == 0 continue; word *m0 = M->rows[r] + blocknum; word const *t[4]; t[0] = T0->rows[x0] + blocknum; t[1] = T1->rows[x1] + blocknum; t[2] = T2->rows[x2] + blocknum; t[3] = T3->rows[x3] + blocknum; _mzd_combine_4( m0, t, wide); } __M4RI_DD_MZD(M); } void mzd_process_rows5(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2, mzd_t const *T3, rci_t const *L3, mzd_t const *T4, rci_t const *L4) { assert(k <= m4ri_radix); wi_t const blocknum = startcol / m4ri_radix; wi_t const wide = M->width - blocknum; int rem = k % 5; int const ka = k / 5 + ((rem >= 4) ? 1 : 0); int const kb = k / 5 + ((rem >= 3) ? 1 : 0); int const kc = k / 5 + ((rem >= 2) ? 1 : 0); int const kd = k / 5 + ((rem >= 1) ? 1 : 0); int const ke = k / 5; rci_t r; word const ka_bm = __M4RI_LEFT_BITMASK(ka); word const kb_bm = __M4RI_LEFT_BITMASK(kb); word const kc_bm = __M4RI_LEFT_BITMASK(kc); word const kd_bm = __M4RI_LEFT_BITMASK(kd); word const ke_bm = __M4RI_LEFT_BITMASK(ke); #if __M4RI_HAVE_OPENMP #pragma omp parallel for private(r) shared(startrow, stoprow) schedule(static,512) //if(stoprow-startrow > 128) #endif for(r = startrow; r < stoprow; ++r) { word bits = mzd_read_bits(M, r, startcol, k); rci_t const x0 = L0[ bits & ka_bm ]; bits>>=ka; rci_t const x1 = L1[ bits & kb_bm ]; bits>>=kb; rci_t const x2 = L2[ bits & kc_bm ]; bits>>=kc; rci_t const x3 = L3[ bits & kd_bm ]; bits>>=kd; rci_t const x4 = L4[ bits & ke_bm ]; if(((x0 | x1 | x2) | (x3 | x4)) == 0) // x0 == 0 && x1 == 0 && x2 == 0 && x3 == 0 && x4 == 0 continue; word *m0 = M->rows[r] + blocknum; word const *t[5]; t[0] = T0->rows[x0] + blocknum; t[1] = T1->rows[x1] + blocknum; t[2] = T2->rows[x2] + blocknum; t[3] = T3->rows[x3] + blocknum; t[4] = T4->rows[x4] + blocknum; _mzd_combine_5( m0, t, wide); } __M4RI_DD_MZD(M); } void mzd_process_rows6(mzd_t *M, rci_t startrow, rci_t stoprow, rci_t startcol, int k, mzd_t const *T0, rci_t const *L0, mzd_t const *T1, rci_t const *L1, mzd_t const *T2, rci_t const *L2, mzd_t const *T3, rci_t const *L3, mzd_t const *T4, rci_t const *L4, mzd_t const *T5, rci_t const *L5) { assert(k <= m4ri_radix); wi_t const blocknum = startcol / m4ri_radix; wi_t const wide = M->width - blocknum; int const rem = k % 6; int const ka = k / 6 + ((rem >= 5) ? 1 : 0); int const kb = k / 6 + ((rem >= 4) ? 1 : 0); int const kc = k / 6 + ((rem >= 3) ? 1 : 0); int const kd = k / 6 + ((rem >= 2) ? 1 : 0); int const ke = k / 6 + ((rem >= 1) ? 1 : 0);; int const kf = k / 6; rci_t r; word const ka_bm = __M4RI_LEFT_BITMASK(ka); word const kb_bm = __M4RI_LEFT_BITMASK(kb); word const kc_bm = __M4RI_LEFT_BITMASK(kc); word const kd_bm = __M4RI_LEFT_BITMASK(kd); word const ke_bm = __M4RI_LEFT_BITMASK(ke); word const kf_bm = __M4RI_LEFT_BITMASK(kf); #if __M4RI_HAVE_OPENMP #pragma omp parallel for private(r) shared(startrow, stoprow) schedule(static,512) //if(stoprow-startrow > 128) #endif for(r = startrow; r < stoprow; ++r) { word bits = mzd_read_bits(M, r, startcol, k); rci_t const x0 = L0[ bits & ka_bm ]; bits>>=ka; rci_t const x1 = L1[ bits & kb_bm ]; bits>>=kb; rci_t const x2 = L2[ bits & kc_bm ]; bits>>=kc; rci_t const x3 = L3[ bits & kd_bm ]; bits>>=kd; rci_t const x4 = L4[ bits & ke_bm ]; bits>>=ke; rci_t const x5 = L5[ bits & kf_bm ]; /* Waste three clocks on OR-ing (modern CPU can do three in * parallel) to avoid possible multiple conditional jumps. */ if(((x0 | x1) | (x2 | x3) | (x4 | x5)) == 0) // x0 == 0 && x1 == 0 && x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 continue; word *m0 = M->rows[r] + blocknum; word const *t[6]; t[0] = T0->rows[x0] + blocknum; t[1] = T1->rows[x1] + blocknum; t[2] = T2->rows[x2] + blocknum; t[3] = T3->rows[x3] + blocknum; t[4] = T4->rows[x4] + blocknum; t[5] = T5->rows[x5] + blocknum; _mzd_combine_6( m0, t, wide); } __M4RI_DD_MZD(M); } rci_t _mzd_echelonize_m4ri(mzd_t *A, int const full, int k, int heuristic, double const threshold) { /** * \par General algorithm * \li Step 1.Denote the first column to be processed in a given * iteration as \f$a_i\f$. Then, perform Gaussian elimination on the * first \f$3k\f$ rows after and including the \f$i\f$-th row to * produce an identity matrix in \f$a_{i,i} ... a_{i+k-1,i+k-1},\f$ * and zeroes in \f$a_{i+k,i} ... a_{i+3k-1,i+k-1}\f$. * * \li Step 2. Construct a table consisting of the \f$2^k\f$ binary strings of * length k in a Gray code. Thus with only \f$2^k\f$ vector * additions, all possible linear combinations of these k rows * have been precomputed. * * \li Step 3. One can rapidly process the remaining rows from \f$i + * 3k\f$ until row \f$m\f$ (the last row) by using the table. For * example, suppose the \f$j\f$-th row has entries \f$a_{j,i} * ... a_{j,i+k-1}\f$ in the columns being processed. Selecting the * row of the table associated with this k-bit string, and adding it * to row j will force the k columns to zero, and adjust the * remaining columns from \f$ i + k\f$ to n in the appropriate way, * as if Gaussian elimination had been performed. * * \li Step 4. While the above form of the algorithm will reduce a * system of boolean linear equations to unit upper triangular form, * and thus permit a system to be solved with back substitution, the * M4RI algorithm can also be used to invert a matrix, or put the * system into reduced row echelon form (RREF). Simply run Step 3 * on rows \f$0 ... i-1\f$ as well as on rows \f$i + 3k * ... m\f$. This only affects the complexity slightly, changing the * 2.5 coeffcient to 3. * * \attention This function implements a variant of the algorithm * described above. If heuristic is true, then this algorithm, will * switch to PLUQ based echelon form computation once the density * reaches the threshold. */ rci_t const ncols = A->ncols; if (k == 0) { k = m4ri_opt_k(A->nrows, ncols, 0); if (k >= 7) k = 7; if (0.75 * __M4RI_TWOPOW(k) * ncols > __M4RI_CPU_L3_CACHE / 2.0) k -= 1; } int kk = 6 * k; mzd_t *U = mzd_init(kk, ncols); mzd_t *T0 = mzd_init(__M4RI_TWOPOW(k), ncols); mzd_t *T1 = mzd_init(__M4RI_TWOPOW(k), ncols); mzd_t *T2 = mzd_init(__M4RI_TWOPOW(k), ncols); mzd_t *T3 = mzd_init(__M4RI_TWOPOW(k), ncols); mzd_t *T4 = mzd_init(__M4RI_TWOPOW(k), ncols); mzd_t *T5 = mzd_init(__M4RI_TWOPOW(k), ncols); rci_t *L0 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L1 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L2 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L3 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L4 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L5 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t last_check = 0; rci_t r = 0; rci_t c = 0; if (heuristic) { if (c < ncols && r < A->nrows && _mzd_density(A, 32, 0, 0) >= threshold) { wi_t const tmp = c / m4ri_radix; rci_t const tmp2 = tmp * m4ri_radix; mzd_t *Abar = mzd_init_window(A, r, tmp2, A->nrows, ncols); r += mzd_echelonize_pluq(Abar, full); mzd_free(Abar); c = ncols; } } while(c < ncols) { if (heuristic && c > (last_check + 256)) { last_check = c; if (c < ncols && r < A->nrows && _mzd_density(A, 32, r, c) >= threshold) { mzd_t *Abar = mzd_init_window(A, r, (c / m4ri_radix) * m4ri_radix, A->nrows, ncols); if (!full) { r += mzd_echelonize_pluq(Abar, full); } else { rci_t r2 = mzd_echelonize_pluq(Abar, full); if (r > 0) _mzd_top_echelonize_m4ri(A, 0, r, c, r); r += r2; } mzd_free(Abar); break; } } if(c + kk > ncols) { kk = ncols - c; } int kbar; if (full) { kbar = _mzd_gauss_submatrix_full(A, r, c, A->nrows, kk); } else { kbar = _mzd_gauss_submatrix(A, r, c, A->nrows, kk); /* this isn't necessary, adapt make_table */ U = mzd_submatrix(U, A, r, 0, r + kbar, ncols); _mzd_gauss_submatrix_top(A, r, c, kbar); } if (kbar > 5 * k) { int const rem = kbar % 6; int const ka = kbar / 6 + ((rem >= 5) ? 1 : 0); int const kb = kbar / 6 + ((rem >= 4) ? 1 : 0); int const kc = kbar / 6 + ((rem >= 3) ? 1 : 0); int const kd = kbar / 6 + ((rem >= 2) ? 1 : 0); int const ke = kbar / 6 + ((rem >= 1) ? 1 : 0);; int const kf = kbar / 6; if(full || kbar == kk) { mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); mzd_make_table(A, r+ka+kb+kc, c, kd, T3, L3); mzd_make_table(A, r+ka+kb+kc+kd, c, ke, T4, L4); mzd_make_table(A, r+ka+kb+kc+kd+ke, c, kf, T5, L5); } if(kbar == kk) mzd_process_rows6(A, r+kbar, A->nrows, c, kbar, T0, L0, T1, L1, T2, L2, T3, L3, T4, L4, T5, L5); if(full) mzd_process_rows6(A, 0, r, c, kbar, T0, L0, T1, L1, T2, L2, T3, L3, T4, L4, T5, L5); } else if (kbar > 4 * k) { int const rem = kbar % 5; int const ka = kbar / 5 + ((rem >= 4) ? 1 : 0); int const kb = kbar / 5 + ((rem >= 3) ? 1 : 0); int const kc = kbar / 5 + ((rem >= 2) ? 1 : 0); int const kd = kbar / 5 + ((rem >= 1) ? 1 : 0); int const ke = kbar / 5; if(full || kbar == kk) { mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); mzd_make_table(A, r+ka+kb+kc, c, kd, T3, L3); mzd_make_table(A, r+ka+kb+kc+kd, c, ke, T4, L4); } if(kbar == kk) mzd_process_rows5(A, r+kbar, A->nrows, c, kbar, T0, L0, T1, L1, T2, L2, T3, L3, T4, L4); if(full) mzd_process_rows5(A, 0, r, c, kbar, T0, L0, T1, L1, T2, L2, T3, L3, T4, L4); } else if (kbar > 3 * k) { int const rem = kbar % 4; int const ka = kbar / 4 + ((rem >= 3) ? 1 : 0); int const kb = kbar / 4 + ((rem >= 2) ? 1 : 0); int const kc = kbar / 4 + ((rem >= 1) ? 1 : 0); int const kd = kbar / 4; if(full || kbar == kk) { mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); mzd_make_table(A, r+ka+kb+kc, c, kd, T3, L3); } if(kbar == kk) mzd_process_rows4(A, r+kbar, A->nrows, c, kbar, T0, L0, T1, L1, T2, L2, T3, L3); if(full) mzd_process_rows4(A, 0, r, c, kbar, T0, L0, T1, L1, T2, L2, T3, L3); } else if (kbar > 2 * k) { int const rem = kbar % 3; int const ka = kbar / 3 + ((rem >= 2) ? 1 : 0); int const kb = kbar / 3 + ((rem >= 1) ? 1 : 0); int const kc = kbar / 3; if(full || kbar == kk) { mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); } if(kbar == kk) mzd_process_rows3(A, r+kbar, A->nrows, c, kbar, T0, L0, T1, L1, T2, L2); if(full) mzd_process_rows3(A, 0, r, c, kbar, T0, L0, T1, L1, T2, L2); } else if (kbar > k) { int const ka = kbar / 2; int const kb = kbar - ka; if(full || kbar == kk) { mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); } if(kbar == kk) mzd_process_rows2(A, r+kbar, A->nrows, c, kbar, T0, L0, T1, L1); if(full) mzd_process_rows2(A, 0, r, c, kbar, T0, L0, T1, L1); } else if(kbar > 0) { if(full || kbar == kk) { mzd_make_table(A, r, c, kbar, T0, L0); } if(kbar == kk) mzd_process_rows(A, r+kbar, A->nrows, c, kbar, T0, L0); if(full) mzd_process_rows(A, 0, r, c, kbar, T0, L0); } if (!full) { _mzd_copy_back_rows(A, U, r, c, kbar); } r += kbar; c += kbar; if(kk != kbar) { rci_t cbar; rci_t rbar; if (mzd_find_pivot(A, r, c, &rbar, &cbar)) { c = cbar; mzd_row_swap(A, r, rbar); } else { break; } //c++; } } mzd_free(T0); m4ri_mm_free(L0); mzd_free(T1); m4ri_mm_free(L1); mzd_free(T2); m4ri_mm_free(L2); mzd_free(T3); m4ri_mm_free(L3); mzd_free(T4); m4ri_mm_free(L4); mzd_free(T5); m4ri_mm_free(L5); mzd_free(U); __M4RI_DD_MZD(A); __M4RI_DD_RCI(r); return r; } rci_t _mzd_top_echelonize_m4ri(mzd_t *A, int k, rci_t r, rci_t c, rci_t max_r) { rci_t const ncols = A->ncols; int kbar = 0; if (k == 0) { k = m4ri_opt_k(max_r, A->ncols, 0); if (k >= 7) k = 7; if (0.75 * __M4RI_TWOPOW(k) *A->ncols > __M4RI_CPU_L3_CACHE / 2.0) k -= 1; } int kk = 6 * k; mzd_t *U = mzd_init(kk, A->ncols); mzd_t *T0 = mzd_init(__M4RI_TWOPOW(k), A->ncols); mzd_t *T1 = mzd_init(__M4RI_TWOPOW(k), A->ncols); mzd_t *T2 = mzd_init(__M4RI_TWOPOW(k), A->ncols); mzd_t *T3 = mzd_init(__M4RI_TWOPOW(k), A->ncols); mzd_t *T4 = mzd_init(__M4RI_TWOPOW(k), A->ncols); mzd_t *T5 = mzd_init(__M4RI_TWOPOW(k), A->ncols); rci_t *L0 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L1 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L2 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L3 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L4 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); rci_t *L5 = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); while(c < ncols) { if(c+kk > A->ncols) { kk = ncols - c; } kbar = _mzd_gauss_submatrix_full(A, r, c, MIN(A->nrows,r+kk), kk); if (kbar > 5 * k) { int const rem = kbar % 6; int const ka = kbar / 6 + ((rem >= 5) ? 1 : 0); int const kb = kbar / 6 + ((rem >= 4) ? 1 : 0); int const kc = kbar / 6 + ((rem >= 3) ? 1 : 0); int const kd = kbar / 6 + ((rem >= 2) ? 1 : 0); int const ke = kbar / 6 + ((rem >= 1) ? 1 : 0);; int const kf = kbar / 6; mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); mzd_make_table(A, r+ka+kb+kc, c, kd, T3, L3); mzd_make_table(A, r+ka+kb+kc+kd, c, ke, T4, L4); mzd_make_table(A, r+ka+kb+kc+kd+ke, c, kf, T5, L5); mzd_process_rows6(A, 0, MIN(r, max_r), c, kbar, T0, L0, T1, L1, T2, L2, T3, L3, T4, L4, T5, L5); } else if (kbar > 4 * k) { int const rem = kbar % 5; int const ka = kbar / 5 + ((rem >= 4) ? 1 : 0); int const kb = kbar / 5 + ((rem >= 3) ? 1 : 0); int const kc = kbar / 5 + ((rem >= 2) ? 1 : 0); int const kd = kbar / 5 + ((rem >= 1) ? 1 : 0); int const ke = kbar / 5; mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); mzd_make_table(A, r+ka+kb+kc, c, kd, T3, L3); mzd_make_table(A, r+ka+kb+kc+kd, c, ke, T4, L4); mzd_process_rows5(A, 0, MIN(r, max_r), c, kbar, T0, L0, T1, L1, T2, L2, T3, L3, T4, L4); } else if (kbar > 3 * k) { const int rem = kbar%4; const int ka = kbar/4 + ((rem >= 3) ? 1 : 0); const int kb = kbar/4 + ((rem >= 2) ? 1 : 0); const int kc = kbar/4 + ((rem >= 1) ? 1 : 0); const int kd = kbar/4; mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); mzd_make_table(A, r+ka+kb+kc, c, kd, T3, L3); mzd_process_rows4(A, 0, MIN(r, max_r), c, kbar, T0, L0, T1, L1, T2, L2, T3, L3); } else if (kbar > 2 * k) { const int rem = kbar%3; const int ka = kbar/3 + ((rem >= 2) ? 1 : 0); const int kb = kbar/3 + ((rem >= 1) ? 1 : 0); const int kc = kbar/3; mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_make_table(A, r+ka+kb, c, kc, T2, L2); mzd_process_rows3(A, 0, MIN(r, max_r), c, kbar, T0, L0, T1, L1, T2, L2); } else if (kbar > k) { const int ka = kbar/2; const int kb = kbar - ka; mzd_make_table(A, r, c, ka, T0, L0); mzd_make_table(A, r+ka, c, kb, T1, L1); mzd_process_rows2(A, 0, MIN(r, max_r), c, kbar, T0, L0, T1, L1); } else if(kbar > 0) { mzd_make_table(A, r, c, kbar, T0, L0); mzd_process_rows(A, 0, MIN(r, max_r), c, kbar, T0, L0); } r += kbar; c += kbar; if(kk != kbar) { c++; } } mzd_free(T0); m4ri_mm_free(L0); mzd_free(T1); m4ri_mm_free(L1); mzd_free(T2); m4ri_mm_free(L2); mzd_free(T3); m4ri_mm_free(L3); mzd_free(T4); m4ri_mm_free(L4); mzd_free(T5); m4ri_mm_free(L5); mzd_free(U); __M4RI_DD_MZD(A); __M4RI_DD_RCI(r); return r; } void mzd_top_echelonize_m4ri(mzd_t *M, int k) { _mzd_top_echelonize_m4ri(M,k,0,0,M->nrows); } mzd_t *mzd_inv_m4ri(mzd_t *B, mzd_t const* A, int k) { assert(A->nrows == A->ncols); if(B == NULL) { B = mzd_init(A->nrows, A->ncols); } else { assert(B->ncols == A->ncols && B->nrows && A->ncols); } const rci_t n = A->nrows; const rci_t nr = m4ri_radix * A->width; mzd_t *C = mzd_init(n, 2*nr); mzd_t *AW = mzd_init_window(C, 0, 0, n, n); mzd_t *BW = mzd_init_window(C, 0, nr, n, nr+n); mzd_copy(AW, A); mzd_set_ui(BW, 1); mzd_echelonize_m4ri(C, TRUE, 0); mzd_copy(B, BW); mzd_free_window(AW); mzd_free_window(BW); mzd_free(C); __M4RI_DD_MZD(B); return B; } mzd_t *mzd_mul_m4rm(mzd_t *C, mzd_t const *A, mzd_t const *B, int k) { rci_t a = A->nrows; rci_t c = B->ncols; if(A->ncols != B->nrows) m4ri_die("mzd_mul_m4rm: A ncols (%d) need to match B nrows (%d).\n", A->ncols, B->nrows); if (C == NULL) { C = mzd_init(a, c); } else { if (C->nrows != a || C->ncols != c) m4ri_die("mzd_mul_m4rm: C (%d x %d) has wrong dimensions.\n", C->nrows, C->ncols); } return _mzd_mul_m4rm(C, A, B, k, TRUE); } mzd_t *mzd_addmul_m4rm(mzd_t *C, mzd_t const *A, mzd_t const *B, int k) { rci_t a = A->nrows; rci_t c = B->ncols; if(C->ncols == 0 || C->nrows == 0) return C; if(A->ncols != B->nrows) m4ri_die("mzd_mul_m4rm A ncols (%d) need to match B nrows (%d) .\n", A->ncols, B->nrows); if (C == NULL) { C = mzd_init(a, c); } else { if (C->nrows != a || C->ncols != c) m4ri_die("mzd_mul_m4rm: C has wrong dimensions.\n"); } return _mzd_mul_m4rm(C, A, B, k, FALSE); } #define __M4RI_M4RM_NTABLES 8 mzd_t *_mzd_mul_m4rm(mzd_t *C, mzd_t const *A, mzd_t const *B, int k, int clear) { /** * The algorithm proceeds as follows: * * Step 1. Make a Gray code table of all the \f$2^k\f$ linear combinations * of the \f$k\f$ rows of \f$B_i\f$. Call the \f$x\f$-th row * \f$T_x\f$. * * Step 2. Read the entries * \f$a_{j,(i-1)k+1}, a_{j,(i-1)k+2} , ... , a_{j,(i-1)k+k}.\f$ * * Let \f$x\f$ be the \f$k\f$ bit binary number formed by the * concatenation of \f$a_{j,(i-1)k+1}, ... , a_{j,ik}\f$. * * Step 3. for \f$h = 1,2, ... , c\f$ do * calculate \f$C_{jh} = C_{jh} + T_{xh}\f$. */ rci_t x[__M4RI_M4RM_NTABLES]; rci_t *L[__M4RI_M4RM_NTABLES]; word const *t[__M4RI_M4RM_NTABLES]; mzd_t *T[__M4RI_M4RM_NTABLES]; #ifdef __M4RI_HAVE_SSE2 mzd_t *Talign[__M4RI_M4RM_NTABLES]; int c_align = (__M4RI_ALIGNMENT(C->rows[0], 16) == 8); #endif word *c; rci_t const a_nr = A->nrows; rci_t const a_nc = A->ncols; rci_t const b_nc = B->ncols; if (b_nc < m4ri_radix-10 || a_nr < 16) { if(clear) return mzd_mul_naive(C, A, B); else return mzd_addmul_naive(C, A, B); } /* clear first */ if (clear) { mzd_set_ui(C, 0); } const int blocksize = __M4RI_MUL_BLOCKSIZE; if(k==0) { /* __M4RI_CPU_L2_CACHE == 2^k * B->width * 8 * 8 */ k = (int)log2((__M4RI_CPU_L2_CACHE/64)/(double)B->width); if ((__M4RI_CPU_L2_CACHE - 64*__M4RI_TWOPOW(k)*B->width) > (64*__M4RI_TWOPOW(k+1)*B->width - __M4RI_CPU_L2_CACHE)) k++; rci_t const klog = round(0.75 * log2_floor(MIN(MIN(a_nr,a_nc),b_nc))); if(klog < k) k = klog; if (k<2) k=2; else if(k>6) k=6; } const wi_t wide = C->width; const word bm = __M4RI_TWOPOW(k)-1; rci_t *buffer = (rci_t*)m4ri_mm_malloc(__M4RI_M4RM_NTABLES * __M4RI_TWOPOW(k) * sizeof(rci_t)); for(int z=0; z<__M4RI_M4RM_NTABLES; z++) { L[z] = buffer + z*__M4RI_TWOPOW(k); #ifdef __M4RI_HAVE_SSE2 /* we make sure that T are aligned as C */ Talign[z] = mzd_init(__M4RI_TWOPOW(k), b_nc+m4ri_radix); T[z] = mzd_init_window(Talign[z], 0, c_align*m4ri_radix, Talign[z]->nrows, b_nc + c_align*m4ri_radix); #else T[z] = mzd_init(__M4RI_TWOPOW(k), b_nc); #endif } /* process stuff that fits into multiple of k first, but blockwise (babystep-giantstep)*/ int const kk = __M4RI_M4RM_NTABLES * k; assert(kk <= m4ri_radix); rci_t const end = a_nc / kk; for (rci_t giantstep = 0; giantstep < a_nr; giantstep += blocksize) { for(rci_t i = 0; i < end; ++i) { #if __M4RI_HAVE_OPENMP #pragma omp parallel for schedule(static,1) #endif for(int z=0; z<__M4RI_M4RM_NTABLES; z++) { mzd_make_table( B, kk*i + k*z, 0, k, T[z], L[z]); } const rci_t blockend = MIN(giantstep+blocksize, a_nr); #if __M4RI_HAVE_OPENMP #pragma omp parallel for schedule(static,512) private(x,t) #endif for(rci_t j = giantstep; j < blockend; j++) { const word a = mzd_read_bits(A, j, kk*i, kk); switch(__M4RI_M4RM_NTABLES) { case 8: t[7] = T[ 7]->rows[ L[7][ (a >> 7*k) & bm ] ]; case 7: t[6] = T[ 6]->rows[ L[6][ (a >> 6*k) & bm ] ]; case 6: t[5] = T[ 5]->rows[ L[5][ (a >> 5*k) & bm ] ]; case 5: t[4] = T[ 4]->rows[ L[4][ (a >> 4*k) & bm ] ]; case 4: t[3] = T[ 3]->rows[ L[3][ (a >> 3*k) & bm ] ]; case 3: t[2] = T[ 2]->rows[ L[2][ (a >> 2*k) & bm ] ]; case 2: t[1] = T[ 1]->rows[ L[1][ (a >> 1*k) & bm ] ]; case 1: t[0] = T[ 0]->rows[ L[0][ (a >> 0*k) & bm ] ]; break; default: m4ri_die("__M4RI_M4RM_NTABLES must be <= 8 but got %d", __M4RI_M4RM_NTABLES); } c = C->rows[j]; switch(__M4RI_M4RM_NTABLES) { case 8: _mzd_combine_8(c, t, wide); break; case 7: _mzd_combine_7(c, t, wide); break; case 6: _mzd_combine_6(c, t, wide); break; case 5: _mzd_combine_5(c, t, wide); break; case 4: _mzd_combine_4(c, t, wide); break; case 3: _mzd_combine_3(c, t, wide); break; case 2: _mzd_combine_2(c, t, wide); break; case 1: _mzd_combine(c, t[0], wide); break; default: m4ri_die("__M4RI_M4RM_NTABLES must be <= 8 but got %d", __M4RI_M4RM_NTABLES); } } } } /* handle stuff that doesn't fit into multiple of kk */ if (a_nc%kk) { rci_t i; for (i = kk / k * end; i < a_nc / k; ++i) { mzd_make_table( B, k*i, 0, k, T[0], L[0]); for(rci_t j = 0; j < a_nr; ++j) { x[0] = L[0][ mzd_read_bits_int(A, j, k*i, k) ]; c = C->rows[j]; t[0] = T[0]->rows[x[0]]; for(wi_t ii = 0; ii < wide; ++ii) { c[ii] ^= t[0][ii]; } } } /* handle stuff that doesn't fit into multiple of k */ if (a_nc%k) { mzd_make_table( B, k*(a_nc/k), 0, a_nc%k, T[0], L[0]); for(rci_t j = 0; j < a_nr; ++j) { x[0] = L[0][ mzd_read_bits_int(A, j, k*i, a_nc%k) ]; c = C->rows[j]; t[0] = T[0]->rows[x[0]]; for(wi_t ii = 0; ii < wide; ++ii) { c[ii] ^= t[0][ii]; } } } } for(int j=0; j<__M4RI_M4RM_NTABLES; j++) { mzd_free(T[j]); #ifdef __M4RI_HAVE_SSE2 mzd_free(Talign[j]); #endif } m4ri_mm_free(buffer); __M4RI_DD_MZD(C); return C; } m4ri-20140914/m4ri/misc.c0000644000175000017500000000553412354166226011544 00000000000000/****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007 Gregory Bard * Copyright (C) 2011 Carlo Wood * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef _MSC_VER #include #endif #include #include #include #include "graycode.h" #include "misc.h" #include "mmc.h" void m4ri_die(const char *errormessage, ...) { va_list lst; va_start(lst, errormessage); vfprintf(stderr, errormessage, lst); va_end(lst); abort(); } /* Warning: If colon, destination must have m4ri_radix + (m4ri_radix - 1) / 4 + 1 bytes available. */ void m4ri_word_to_str(char *destination, word data, int colon) { int j = 0; for (int i = 0; i < m4ri_radix; ++i) { if (colon && (i % 4) == 0 && i != 0) destination[j++] = ':'; if (__M4RI_GET_BIT(data, i)) destination[j++] = '1'; else destination[j++] = ' '; } destination[j] = '\0'; } word m4ri_random_word() { #ifdef _MSC_VER word a = 0; int i; for(i=0; i< m4ri_radix; i+=8) { a ^= (((word)rand())< * Copyright (C) 2009-2013 Martin Albrecht * Copyright (C) 2011 Carlo Wood * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef __M4RI_HAVE_LIBPNG #include #endif #include #include #include "mzd.h" #include "parity.h" #include "mmc.h" /** * \brief Cache of mzd_t containers */ typedef struct mzd_t_cache { mzd_t mzd[64]; /*!< cached matrices */ struct mzd_t_cache *prev; /*!< previous block */ struct mzd_t_cache *next; /*!< next block */ uint64_t used; /*!< bitmasks which matrices in this block are used */ unsigned char padding[sizeof(mzd_t) - 2 * sizeof(struct mzd_t_cache*) - sizeof(uint64_t)]; /*!< alignment */ #ifdef __GNUC__ } mzd_t_cache_t __attribute__ ((__aligned__ (64))); #else } mzd_t_cache_t; #endif #define __M4RI_MZD_T_CACHE_MAX 16 static mzd_t_cache_t mzd_cache; static mzd_t_cache_t* current_cache = &mzd_cache; static int log2_floor(uint64_t v) { static uint64_t const b[] = { 0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000 }; static unsigned int const S[] = { 1, 2, 4, 8, 16, 32 }; unsigned int r = 0; for (int i = 5; i >= 0; --i) { if ((v & b[i])) { v >>= S[i]; r |= S[i]; } } return r; } /* * Return a pointer to a new mzd_t structure. * The structure will be 64 byte aligned. * Call mzd_t_free to free the structure for next use. */ static mzd_t* mzd_t_malloc() { #if __M4RI_HAVE_OPENMP return (mzd_t*)m4ri_mm_malloc(sizeof(mzd_t)); #else mzd_t *ret = NULL; int i=0; if (current_cache->used == (uint64_t)-1) { mzd_t_cache_t *cache = &mzd_cache; while (cache && cache->used == (uint64_t)-1) { current_cache = cache; cache = cache->next; i++; } if (!cache && i< __M4RI_MZD_T_CACHE_MAX) { cache = (mzd_t_cache_t*)m4ri_mm_malloc_aligned(sizeof(mzd_t_cache_t), 64); memset((char*)cache, 0, sizeof(mzd_t_cache_t)); cache->prev = current_cache; current_cache->next = cache; current_cache = cache; } else if (!cache && i>= __M4RI_MZD_T_CACHE_MAX) { /* We have reached the upper limit on the number of caches */ ret = (mzd_t*)m4ri_mm_malloc(sizeof(mzd_t)); } else { current_cache = cache; } } if (ret == NULL) { int free_entry =log2_floor(~current_cache->used); current_cache->used |= ((uint64_t)1 << free_entry); ret = ¤t_cache->mzd[free_entry]; } return ret; #endif //__M4RI_HAVE_OPENMP } static void mzd_t_free(mzd_t *M) { #if __M4RI_HAVE_OPENMP m4ri_mm_free(M); #else int foundit = 0; mzd_t_cache_t *cache = &mzd_cache; while(cache) { size_t entry = M - cache->mzd; if (entry < 64) { cache->used &= ~((uint64_t)1 << entry); if (cache->used == 0) { if (cache == &mzd_cache) { current_cache = cache; } else { if (cache == current_cache) { current_cache = cache->prev; } cache->prev->next = cache->next; if (cache->next) cache->next->prev = cache->prev; m4ri_mm_free(cache); } } foundit = 1; break; } cache = cache->next; } if(!foundit) { m4ri_mm_free(M); } #endif } mzd_t *mzd_init(rci_t r, rci_t c) { assert(sizeof(mzd_t) == 64); mzd_t *A = mzd_t_malloc(); A->nrows = r; A->ncols = c; A->width = (c + m4ri_radix - 1) / m4ri_radix; A->rowstride = (A->width < mzd_paddingwidth || (A->width & 1) == 0) ? A->width : A->width + 1; A->high_bitmask = __M4RI_LEFT_BITMASK(c % m4ri_radix); A->flags = (A->high_bitmask != m4ri_ffff) ? mzd_flag_nonzero_excess : 0; A->offset_vector = 0; A->row_offset = 0; A->rows = (word**)m4ri_mmc_calloc(r + 1, sizeof(word*)); // We're overcomitting here. if (r && c) { int blockrows = __M4RI_MAX_MZD_BLOCKSIZE / A->rowstride; A->blockrows_log = 0; while(blockrows >>= 1) A->blockrows_log++; blockrows = 1 << A->blockrows_log; int const blockrows_mask = blockrows - 1; int const nblocks = (r + blockrows - 1) / blockrows; A->flags |= (nblocks > 1) ? mzd_flag_multiple_blocks : 0; A->blocks = (mzd_block_t*)m4ri_mmc_calloc(nblocks + 1, sizeof(mzd_block_t)); size_t block_words = (r - (nblocks - 1) * blockrows) * A->rowstride; for(int i = nblocks - 1; i >= 0; --i) { A->blocks[i].size = block_words * sizeof(word); A->blocks[i].begin = (word*)m4ri_mmc_calloc(1, A->blocks[i].size); A->blocks[i].end = A->blocks[i].begin + block_words; block_words = blockrows * A->rowstride; } for(rci_t i = 0; i < A->nrows; ++i) { A->rows[i] = A->blocks[i >> A->blockrows_log].begin + (i & blockrows_mask) * A->rowstride; } } else { A->blocks = NULL; } return A; } /* Explanation of offset_vector (in words), and row_offset. <------------------------------- row_stride (in words)---------------------> .---------------------------------------------------------------------------. <-- m->blocks[0].begin ^ | ^ /| | | m->row_offset| m->offset_vector_/ | | | v / | | | .--------------------------------------------------------------------v<--|---- m->rows[0] |_ skipped_blocks (in blocks) | |m (also a window) ^ | | | | | | | | | `---------------------------------|-----------------------------------------' v .---------------------------------|----------------------------------------_. <-- m->blocks[1].begin <-- windows.blocks[0].begin | | ^ lowr| |_^ | | | window->row_offset| | window->offset_vector _-^| | | | v v _-^ | | | | .----------------------------------------------------------v<--. |<--|---- m->rows[lowr] | | |window | `-|---|---- window->rows[0] | | | | | | `---------------------------------------------------------------------------' .---------------------------------------------------------------------------. <-- m->blocks[2].begin <-- windows.blocks[1].begin | | | | | | | | | | lowc | | | | | |<---->| | | | | | \__|___|__ also wrd_offset (in words) | | `----------------------------------------------------------' | | | `--------------------------------------------------------------------' | `---------------------------------------------------------------------------' .---------------------------------------------------------------------------. | | */ mzd_t *mzd_init_window(mzd_t *M, rci_t lowr, rci_t lowc, rci_t highr, rci_t highc) { assert(lowc % m4ri_radix == 0); mzd_t *W = mzd_t_malloc(); rci_t nrows = MIN(highr - lowr, M->nrows - lowr); rci_t ncols = highc - lowc; W->nrows = nrows; W->ncols = ncols; W->rowstride = M->rowstride; W->width = (ncols + m4ri_radix - 1) / m4ri_radix; W->high_bitmask = __M4RI_LEFT_BITMASK(ncols % m4ri_radix); W->flags = mzd_flag_windowed_zerooffset; W->flags |= (ncols % m4ri_radix == 0) ? mzd_flag_windowed_zeroexcess : mzd_flag_nonzero_excess; W->blockrows_log = M->blockrows_log; wi_t const blockrows_mask = (1 << W->blockrows_log) - 1; int const skipped_blocks = (M->row_offset + lowr) >> W->blockrows_log; assert(skipped_blocks == 0 || ((M->flags & mzd_flag_multiple_blocks))); W->row_offset = (M->row_offset + lowr) & blockrows_mask; W->blocks = &M->blocks[skipped_blocks]; wi_t const wrd_offset = lowc / m4ri_radix; W->offset_vector = (M->offset_vector + wrd_offset) + (W->row_offset - M->row_offset) * W->rowstride; if(nrows) W->rows = (word**)m4ri_mmc_calloc(nrows + 1, sizeof(word*)); else W->rows = NULL; for(rci_t i = 0; i < nrows; ++i) { W->rows[i] = M->rows[lowr + i] + wrd_offset; } if (mzd_row_to_block(W, nrows - 1) > 0) W->flags |= M->flags & mzd_flag_multiple_blocks; /* offset_vector is the distance from the start of the first block to the first word of the first row. */ assert(nrows == 0 || W->blocks[0].begin + W->offset_vector == W->rows[0]); __M4RI_DD_MZD(W); return W; } void mzd_free(mzd_t *A) { if(A->rows) m4ri_mmc_free(A->rows, (A->nrows + 1) * sizeof(word*)); if(mzd_owns_blocks(A)) { int i; for(i = 0; A->blocks[i].size; ++i) { m4ri_mmc_free(A->blocks[i].begin, A->blocks[i].size); } m4ri_mmc_free(A->blocks, (i + 1) * sizeof(mzd_block_t)); } mzd_t_free(A); } void mzd_row_add(mzd_t *M, rci_t sourcerow, rci_t destrow) { mzd_row_add_offset(M, destrow, sourcerow, 0); } void mzd_row_clear_offset(mzd_t *M, rci_t row, rci_t coloffset) { wi_t const startblock = coloffset / m4ri_radix; word temp; /* make sure to start clearing at coloffset */ if (coloffset%m4ri_radix) { temp = M->rows[row][startblock]; temp &= __M4RI_RIGHT_BITMASK(m4ri_radix - coloffset); } else { temp = 0; } M->rows[row][startblock] = temp; for (wi_t i = startblock + 1; i < M->width; ++i) { M->rows[row][i] = 0; } __M4RI_DD_ROW(M, row); } rci_t mzd_gauss_delayed(mzd_t *M, rci_t startcol, int full) { rci_t startrow = startcol; rci_t pivots = 0; for (rci_t i = startcol; i < M->ncols ; ++i) { for(rci_t j = startrow ; j < M->nrows; ++j) { if (mzd_read_bit(M, j, i)) { mzd_row_swap(M, startrow, j); ++pivots; for(rci_t ii = full ? 0 : startrow + 1; ii < M->nrows; ++ii) { if (ii != startrow) { if (mzd_read_bit(M, ii, i)) { mzd_row_add_offset(M, ii, startrow, i); } } } startrow = startrow + 1; break; } } } __M4RI_DD_MZD(M); __M4RI_DD_RCI(pivots); return pivots; } rci_t mzd_echelonize_naive(mzd_t *M, int full) { return mzd_gauss_delayed(M, 0, full); } /** * Transpose a 64 x 64 matrix with width 1. * * \param dst First word of destination matrix. * \param src First word of source matrix. * \param rowstride_dst Rowstride of matrix dst. * \param rowstride_src Rowstride of matrix src. * * Rows of both matrices are expected to fit exactly in a word (offset == 0) * and lay entirely inside a single block. * * \note This function also works when dst == src. */ static inline void _mzd_copy_transpose_64x64(word* RESTRICT dst, word const* RESTRICT src, wi_t rowstride_dst, wi_t rowstride_src) { /* * m runs over the values: * 0x00000000FFFFFFFF * 0x0000FFFF0000FFFF * 0x00FF00FF00FF00FF * 0x0F0F0F0F0F0F0F0F * 0x3333333333333333 * 0x5555555555555555, * alternating j zeroes with j ones. * * Assume we have a matrix existing of four jxj matrices ((0,0) is in the top-right corner, * this is the memory-model view, see the layout on http://m4ri.sagemath.org/doxygen/structmzd__t.html): * ...[A1][B1][A0][B0] * ...[C1][D1][C0][D0] * . [A2][B2] * . [C2][B2] * . . * . * The following calulates the XOR between A and D, * and subsequently applies that to A and D respectively, * swapping A and D as a result. * Therefore wk starts at the first row and then has rowstride * added j times, running over the rows of A, then skips C * by adding j * rowstride to continue with the next A below C. */ word m = __M4RI_CONVERT_TO_WORD(0xFFFFFFFF); wi_t j_rowstride_dst = rowstride_dst * 64; wi_t j_rowstride_src = rowstride_src * 32; word* const end = dst + j_rowstride_dst; // We start with j = 32, and a one-time unrolled loop, where // we copy from src and write the result to dst, swapping // the two 32x32 corner matrices. int j = 32; j_rowstride_dst >>= 1; word* RESTRICT wk = dst; for (word const* RESTRICT wks = src; wk < end; wk += j_rowstride_dst, wks += j_rowstride_src) { for (int k = 0; k < j; ++k, wk += rowstride_dst, wks += rowstride_src) { word xor = ((*wks >> j) ^ *(wks + j_rowstride_src)) & m; *wk = *wks ^ (xor << j); *(wk + j_rowstride_dst) = *(wks + j_rowstride_src) ^ xor; } } // Next we work in-place in dst and swap the corners of // each of the last matrices, all in parallel, for all // remaining values of j. m ^= m << 16; for (j = 16; j != 0; j = j >> 1, m ^= m << j) { j_rowstride_dst >>= 1; for (wk = dst; wk < end; wk += j_rowstride_dst) { for (int k = 0; k < j; ++k, wk += rowstride_dst) { word xor = ((*wk >> j) ^ *(wk + j_rowstride_dst)) & m; *wk ^= xor << j; *(wk + j_rowstride_dst) ^= xor; } } } } /** * Transpose two 64 x 64 matrix with width 1. * * \param dst1 First word of destination matrix 1. * \param dst2 First word of destination matrix 2. * \param src1 First word of source matrix 1. * \param src2 First word of source matrix 2. * \param rowstride_dst Rowstride of destination matrices. * \param rowstride_src Rowstride of source matrices. * * Rows of all matrices are expected to fit exactly in a word (offset == 0) * and lay entirely inside a single block. * * \note This function also works to transpose in-place. */ static inline void _mzd_copy_transpose_64x64_2(word* RESTRICT dst1, word* RESTRICT dst2, word const* RESTRICT src1, word const* RESTRICT src2, wi_t rowstride_dst, wi_t rowstride_src) { word m = __M4RI_CONVERT_TO_WORD(0xFFFFFFFF); wi_t j_rowstride_dst = rowstride_dst * 64; wi_t j_rowstride_src = rowstride_src * 32; word* const end = dst1 + j_rowstride_dst; int j = 32; word* RESTRICT wk[2]; word const* RESTRICT wks[2]; word xor[2]; j_rowstride_dst >>= 1; wk[0] = dst1; wk[1] = dst2; wks[0] = src1; wks[1] = src2; do { for (int k = 0; k < j; ++k) { xor[0] = ((*wks[0] >> j) ^ *(wks[0] + j_rowstride_src)) & m; xor[1] = ((*wks[1] >> j) ^ *(wks[1] + j_rowstride_src)) & m; *wk[0] = *wks[0] ^ (xor[0] << j); *wk[1] = *wks[1] ^ (xor[1] << j); *(wk[0] + j_rowstride_dst) = *(wks[0] + j_rowstride_src) ^ xor[0]; *(wk[1] + j_rowstride_dst) = *(wks[1] + j_rowstride_src) ^ xor[1]; wk[0] += rowstride_dst; wk[1] += rowstride_dst; wks[0] += rowstride_src; wks[1] += rowstride_src; } wk[0] += j_rowstride_dst; wk[1] += j_rowstride_dst; wks[0] += j_rowstride_src; wks[1] += j_rowstride_src; } while(wk[0] < end); m ^= m << 16; for (j = 16; j != 0; j = j >> 1, m ^= m << j) { j_rowstride_dst >>= 1; wk[0] = dst1; wk[1] = dst2; do { for (int k = 0; k < j; ++k) { xor[0] = ((*wk[0] >> j) ^ *(wk[0] + j_rowstride_dst)) & m; xor[1] = ((*wk[1] >> j) ^ *(wk[1] + j_rowstride_dst)) & m; *wk[0] ^= xor[0] << j; *wk[1] ^= xor[1] << j; *(wk[0] + j_rowstride_dst) ^= xor[0]; *(wk[1] + j_rowstride_dst) ^= xor[1]; wk[0] += rowstride_dst; wk[1] += rowstride_dst; } wk[0] += j_rowstride_dst; wk[1] += j_rowstride_dst; } while(wk[0] < end); } } static unsigned char log2_ceil_table[64] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }; static inline int log2_ceil(int n) { return log2_ceil_table[n - 1]; } static word const transpose_mask[6] = { 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL, }; /** * Transpose 64/j matrices of size jxj in parallel. * * Where j equals n rounded up to the nearest power of 2. * The input array t must be of size j (containing the rows i of all matrices in t[i]). * * t[0..{j-1}] = [Al]...[A1][A0] * * \param t An array of j words. * \param n The number of rows in each matrix. * * \return log2(j) */ static inline int _mzd_transpose_Nxjx64(word* RESTRICT t, int n) { int j = 1; int mi = 0; // Index into the transpose_mask array. while (j < n) // Don't swap with entirely undefined data (where [D] exists entirely of non-existant rows). { // Swap 64/j matrices of size jxj in 2j rows. Thus, // <---- one word ---> // [Al][Bl]...[A0][B0] // [Cl][Dl]...[C0][D0], where l = 64/j - 1 and each matrix [A], [B] etc is jxj. // Then swap [A] and [D] in-place. // m runs over the values in transpose_mask, so that at all // times m exists of j zeroes followed by j ones, repeated. word const m = transpose_mask[mi]; int k = 0; // Index into t[]. do { // Run over all rows of [A] and [D]. for (int i = 0; i < j; ++i, ++k) { // t[k] contains row i of all [A], and t[k + j] contains row i of all [D]. Swap them. word xor = ((t[k] >> j) ^ t[k + j]) & m; t[k] ^= xor << j; t[k + j] ^= xor; } k += j; // Skip [C]. } while (k < n); // Stop if we passed all valid input. // Double the size of j and repeat this for the next 2j rows until all // n rows have been swapped (possibly with non-existant rows). j <<= 1; ++mi; } return mi; } /** * Transpose a n x 64 matrix with width 1. * * \param dst First word of destination matrix. * \param src First word of source matrix. * \param rowstride_dst Rowstride of destination matrix. * \param rowstride_src Rowstride of source matrix. * \param n Number of rows in source matrix, must be less than 64. * * Rows of all matrices are expected have offset zero * and lay entirely inside a single block. * * \note This function also works to transpose in-place. */ static inline void _mzd_copy_transpose_lt64x64(word* RESTRICT dst, word const* RESTRICT src, wi_t rowstride_dst, wi_t rowstride_src, int n) { // Preload the n input rows into level 1, using a minimum of cache lines (compact storage). word t[64]; word const* RESTRICT wks = src; int k; for (k = 0; k < n; ++k) { t[k] = *wks; wks += rowstride_src; } if (n > 32) { while (k < 64) t[k++] = 0; _mzd_copy_transpose_64x64(dst, t, rowstride_dst, 1); return; } int log2j = _mzd_transpose_Nxjx64(t, n); // All output bits are now transposed, but still might need to be shifted in place. // What we have now is 64/j matrices of size jxj. Thus, // [Al]...[A1][A0], where l = 64/j - 1. // while the actual output is: // [A0] // [A1] // ... // [Al] word const m = __M4RI_LEFT_BITMASK(n); word* RESTRICT wk = dst; switch (log2j) { case 5: { wi_t const j_rowstride_dst = 32 * rowstride_dst; for (int k = 0; k < 32; ++k) { wk[0] = t[k] & m; wk[j_rowstride_dst] = (t[k] >> 32) & m; wk += rowstride_dst; } break; } case 4: { wi_t const j_rowstride_dst = 16 * rowstride_dst; for (int k = 0; k < 16; ++k) { wk[0] = t[k] & m; wk[j_rowstride_dst] = (t[k] >> 16) & m; wk[2 * j_rowstride_dst] = (t[k] >> 32) & m; wk[3 * j_rowstride_dst] = (t[k] >> 48) & m; wk += rowstride_dst; } break; } case 3: { wi_t const j_rowstride_dst = 8 * rowstride_dst; for (int k = 0; k < 8; ++k) { wk[0] = t[k] & m; wk[j_rowstride_dst] = (t[k] >> 8) & m; wk[2 * j_rowstride_dst] = (t[k] >> 16) & m; wk[3 * j_rowstride_dst] = (t[k] >> 24) & m; wk[4 * j_rowstride_dst] = (t[k] >> 32) & m; wk[5 * j_rowstride_dst] = (t[k] >> 40) & m; wk[6 * j_rowstride_dst] = (t[k] >> 48) & m; wk[7 * j_rowstride_dst] = (t[k] >> 56) & m; wk += rowstride_dst; } break; } case 2: { wi_t const j_rowstride_dst = 4 * rowstride_dst; for (int k = 0; k < 4; ++k) { word* RESTRICT wk2 = wk; word tk = t[k]; for (int i = 0; i < 2; ++i) { wk2[0] = tk & m; wk2[j_rowstride_dst] = (tk >> 4) & m; wk2[2 * j_rowstride_dst] = (tk >> 8) & m; wk2[3 * j_rowstride_dst] = (tk >> 12) & m; wk2[4 * j_rowstride_dst] = (tk >> 16) & m; wk2[5 * j_rowstride_dst] = (tk >> 20) & m; wk2[6 * j_rowstride_dst] = (tk >> 24) & m; wk2[7 * j_rowstride_dst] = (tk >> 28) & m; wk2 += 8 * j_rowstride_dst; tk >>= 32; } wk += rowstride_dst; } break; } case 1: { wi_t const j_rowstride_dst = 2 * rowstride_dst; for (int k = 0; k < 2; ++k) { word* RESTRICT wk2 = wk; word tk = t[k]; for (int i = 0; i < 8; ++i) { wk2[0] = tk & m; wk2[j_rowstride_dst] = (tk >> 2) & m; wk2[2 * j_rowstride_dst] = (tk >> 4) & m; wk2[3 * j_rowstride_dst] = (tk >> 6) & m; wk2 += 4 * j_rowstride_dst; tk >>= 8; } wk += rowstride_dst; } break; } case 0: { word* RESTRICT wk2 = wk; word tk = t[0]; for (int i = 0; i < 16; ++i) { wk2[0] = tk & m; wk2[rowstride_dst] = (tk >> 1) & m; wk2[2 * rowstride_dst] = (tk >> 2) & m; wk2[3 * rowstride_dst] = (tk >> 3) & m; wk2 += 4 * rowstride_dst; tk >>= 4; } break; } } } /** * Transpose a 64 x n matrix with width 1. * * \param dst First word of destination matrix. * \param src First word of source matrix. * \param rowstride_dst Rowstride of destination matrix. * \param rowstride_src Rowstride of source matrix. * \param n Number of columns in source matrix, must be less than 64. * * Rows of all matrices are expected have offset zero * and lay entirely inside a single block. * * \note This function also works to transpose in-place. */ static inline void _mzd_copy_transpose_64xlt64(word* RESTRICT dst, word const* RESTRICT src, wi_t rowstride_dst, wi_t rowstride_src, int n) { word t[64]; int log2j = log2_ceil(n); word const* RESTRICT wks = src; switch (log2j) { case 6: { _mzd_copy_transpose_64x64(t, src, 1, rowstride_src); word* RESTRICT wk = dst; for (int k = 0; k < n; ++k) { *wk = t[k]; wk += rowstride_dst; } return; } case 5: { wi_t const j_rowstride_src = 32 * rowstride_src; for (int k = 0; k < 32; ++k) { t[k] = wks[0] | (wks[j_rowstride_src] << 32); wks += rowstride_src; } break; } case 4: { wi_t const j_rowstride_src = 16 * rowstride_src; for (int k = 0; k < 16; ++k) { t[k] = wks[0] | (wks[j_rowstride_src] << 16); t[k] |= (wks[2 * j_rowstride_src] << 32) | (wks[3 * j_rowstride_src] << 48); wks += rowstride_src; } break; } case 3: { wi_t const j_rowstride_src = 8 * rowstride_src; word tt; for (int k = 0; k < 8; ++k) { tt = wks[0] | (wks[j_rowstride_src] << 8); t[k] = (wks[2 * j_rowstride_src] << 16) | (wks[3 * j_rowstride_src] << 24); tt |= (wks[4 * j_rowstride_src] << 32) | (wks[5 * j_rowstride_src] << 40); t[k] |= (wks[6 * j_rowstride_src] << 48) | (wks[7 * j_rowstride_src] << 56); wks += rowstride_src; t[k] |= tt; } break; } case 2: { word const* RESTRICT wks2 = wks + 60 * rowstride_src; t[0] = wks2[0]; t[1] = wks2[rowstride_src]; t[2] = wks2[2 * rowstride_src]; t[3] = wks2[3 * rowstride_src]; for (int i = 0; i < 15; ++i) { wks2 -= 4 * rowstride_src; t[0] <<= 4; t[1] <<= 4; t[2] <<= 4; t[3] <<= 4; t[0] |= wks2[0]; t[1] |= wks2[rowstride_src]; t[2] |= wks2[2 * rowstride_src]; t[3] |= wks2[3 * rowstride_src]; } break; } case 1: { wks += 62 * rowstride_src; t[0] = wks[0]; t[1] = wks[rowstride_src]; for (int i = 0; i < 31; ++i) { wks -= 2 * rowstride_src; t[0] <<= 2; t[1] <<= 2; t[0] |= wks[0]; t[1] |= wks[rowstride_src]; } break; } case 0: { word tt[2]; tt[0] = wks[0]; tt[1] = wks[rowstride_src]; for (int i = 2; i < 64; i += 2) { wks += 2 * rowstride_src; tt[0] |= wks[0] << i; tt[1] |= wks[rowstride_src] << i; } *dst = tt[0] | (tt[1] << 1); return; } } int j = 1 << log2j; _mzd_transpose_Nxjx64(t, j); word* RESTRICT wk = dst; for (int k = 0; k < n; ++k) { *wk = t[k]; wk += rowstride_dst; } } /** * Transpose a n x m matrix with width 1, offset 0 and m and n less than or equal 8. * * \param dst First word of destination matrix. * \param src First word of source matrix. * \param rowstride_dst Rowstride of destination matrix. * \param rowstride_src Rowstride of source matrix. * \param n Number of rows in source matrix, must be less than or equal 8. * \param m Number of columns in source matrix, must be less than or equal 8. * * Rows of all matrices are expected to have offset zero * and lay entirely inside a single block. * * \note This function also works to transpose in-place. */ static inline void _mzd_copy_transpose_le8xle8(word* RESTRICT dst, word const* RESTRICT src, wi_t rowstride_dst, wi_t rowstride_src, int n, int m, int maxsize) { int end = maxsize * 7; word const* RESTRICT wks = src; word w = *wks; int shift = 0; for (int i = 1; i < n; ++i) { wks += rowstride_src; shift += 8; w |= (*wks << shift); } word mask = 0x80402010080402ULL; word w7 = w >> 7; shift = 7; --m; do { word xor = (w ^ w7) & mask; mask >>= 8; w ^= (xor << shift); shift += 7; w7 >>= 7; w ^= xor; } while(shift < end); word* RESTRICT wk = dst + m * rowstride_dst; for (int shift = 8 * m; shift > 0; shift -= 8) { *wk = (unsigned char)(w >> shift); wk -= rowstride_dst; } *wk = (unsigned char)w; } /** * Transpose a n x m matrix with width 1, offset 0 and m and n less than or equal 16. * * \param dst First word of destination matrix. * \param src First word of source matrix. * \param rowstride_dst Rowstride of destination matrix. * \param rowstride_src Rowstride of source matrix. * \param n Number of rows in source matrix, must be less than or equal 16. * \param m Number of columns in source matrix, must be less than or equal 16. * * Rows of all matrices are expected to have offset zero * and lay entirely inside a single block. * * \note This function also works to transpose in-place. */ static inline void _mzd_copy_transpose_le16xle16(word* RESTRICT dst, word const* RESTRICT src, wi_t rowstride_dst, wi_t rowstride_src, int n, int m, int maxsize) { int end = maxsize * 3; word const* RESTRICT wks = src; word t[4]; int i = n; do { t[0] = wks[0]; if (--i == 0) { t[1] = 0; t[2] = 0; t[3] = 0; break; } t[1] = wks[rowstride_src]; if (--i == 0) { t[2] = 0; t[3] = 0; break; } t[2] = wks[2 * rowstride_src]; if (--i == 0) { t[3] = 0; break; } t[3] = wks[3 * rowstride_src]; if (--i == 0) break; wks += 4 * rowstride_src; for(int shift = 16;; shift += 16) { t[0] |= (*wks << shift); if (--i == 0) break; t[1] |= (wks[rowstride_src] << shift); if (--i == 0) break; t[2] |= (wks[2 * rowstride_src] << shift); if (--i == 0) break; t[3] |= (wks[3 * rowstride_src] << shift); if (--i == 0) break; wks += 4 * rowstride_src; } } while(0); word mask = 0xF0000F0000F0ULL; int shift = 12; word xor[4]; do { xor[0] = (t[0] ^ (t[0] >> shift)) & mask; xor[1] = (t[1] ^ (t[1] >> shift)) & mask; xor[2] = (t[2] ^ (t[2] >> shift)) & mask; xor[3] = (t[3] ^ (t[3] >> shift)) & mask; mask >>= 16; t[0] ^= (xor[0] << shift); t[1] ^= (xor[1] << shift); t[2] ^= (xor[2] << shift); t[3] ^= (xor[3] << shift); shift += 12; t[0] ^= xor[0]; t[1] ^= xor[1]; t[2] ^= xor[2]; t[3] ^= xor[3]; } while(shift < end); _mzd_transpose_Nxjx64(t, 4); i = m; word* RESTRICT wk = dst; do { wk[0] = (uint16_t)t[0]; if (--i == 0) break; wk[rowstride_dst] = (uint16_t)t[1]; if (--i == 0) break; wk[2 * rowstride_dst] = (uint16_t)t[2]; if (--i == 0) break; wk[3 * rowstride_dst] = (uint16_t)t[3]; if (--i == 0) break; wk += 4 * rowstride_dst; for(int shift = 16;; shift += 16) { wk[0] = (uint16_t)(t[0] >> shift); if (--i == 0) break; wk[rowstride_dst] = (uint16_t)(t[1] >> shift); if (--i == 0) break; wk[2 * rowstride_dst] = (uint16_t)(t[2] >> shift); if (--i == 0) break; wk[3 * rowstride_dst] = (uint16_t)(t[3] >> shift); if (--i == 0) break; wk += 4 * rowstride_dst; } } while(0); } /** * Transpose a n x m matrix with width 1, offset 0 and m and n less than or equal 32. * * \param dst First word of destination matrix. * \param src First word of source matrix. * \param rowstride_dst Rowstride of destination matrix. * \param rowstride_src Rowstride of source matrix. * \param n Number of rows in source matrix, must be less than or equal 32. * \param m Number of columns in source matrix, must be less than or equal 32. * * Rows of all matrices are expected to have offset zero * and lay entirely inside a single block. * * \note This function also works to transpose in-place. */ static inline void _mzd_copy_transpose_le32xle32(word* RESTRICT dst, word const* RESTRICT src, wi_t rowstride_dst, wi_t rowstride_src, int n, int m) { word const* RESTRICT wks = src; word t[16]; int i = n; if (n > 16) { i -= 16; for (int j = 0; j < 16; ++j) { t[j] = *wks; wks += rowstride_src; } int j = 0; do { t[j++] |= (*wks << 32); wks += rowstride_src; } while(--i); } else { int j; for (j = 0; j < n; ++j) { t[j] = *wks; wks += rowstride_src; } for (; j < 16; ++j) t[j] = 0; } _mzd_transpose_Nxjx64(t, 16); int one_more = (m & 1); word* RESTRICT wk = dst; if (m > 16) { m -= 16; for (int j = 0; j < 16; j += 2) { *wk = (t[j] & 0xFFFF) | ((t[j] >> 16) & 0xFFFF0000); wk[rowstride_dst] = (t[j + 1] & 0xFFFF) | ((t[j + 1] >> 16) & 0xFFFF0000); wk += 2 * rowstride_dst; } for (int j = 1; j < m; j += 2) { *wk = ((t[j - 1] >> 16) & 0xFFFF) | ((t[j - 1] >> 32) & 0xFFFF0000); wk[rowstride_dst] = ((t[j] >> 16) & 0xFFFF) | ((t[j] >> 32) & 0xFFFF0000); wk += 2 * rowstride_dst; } if (one_more) { *wk = ((t[m - 1] >> 16) & 0xFFFF) | ((t[m - 1] >> 32) & 0xFFFF0000); } } else { for (int j = 1; j < m; j += 2) { *wk = (t[j - 1] & 0xFFFF) | ((t[j - 1] >> 16) & 0xFFFF0000); wk[rowstride_dst] = (t[j] & 0xFFFF) | ((t[j] >> 16) & 0xFFFF0000); wk += 2 * rowstride_dst; } if (one_more) { *wk = (t[m - 1] & 0xFFFF) | ((t[m - 1] >> 16) & 0xFFFF0000); } } } static inline void _mzd_copy_transpose_le64xle64(word* RESTRICT dst, word const* RESTRICT src, wi_t rowstride_dst, wi_t rowstride_src, int n, int m) { word const* RESTRICT wks = src; word t[64]; int k; for (k = 0; k < n; ++k) { t[k] = *wks; wks += rowstride_src; } while(k < 64) t[k++] = 0; _mzd_copy_transpose_64x64(t, t, 1, 1); word* RESTRICT wk = dst; for (int k = 0; k < m; ++k) { *wk = t[k]; wk += rowstride_dst; } return; } void _mzd_transpose_multiblock(mzd_t *DST, mzd_t const *A, word* RESTRICT* fwdp, word const* RESTRICT* fwsp, rci_t* nrowsp, rci_t* ncolsp); mzd_t *_mzd_transpose(mzd_t *DST, mzd_t const *A) { assert(!mzd_is_windowed(DST) && !mzd_is_windowed(A)); // We assume that there fit at least 64 rows in a block, if // that is the case then each block will contain a multiple // of 64 rows, since blockrows is a power of 2. assert(A->blockrows_log >= 6 && DST->blockrows_log >= 6); rci_t nrows = A->nrows; rci_t ncols = A->ncols; rci_t maxsize = MAX(nrows, ncols); word* RESTRICT fwd = mzd_first_row(DST); word const* RESTRICT fws = mzd_first_row(A); if (maxsize >= 64) { // This is the most non-intrusive way to deal with the case of multiple blocks. // Note that this code is VERY sensitive. ANY change to _mzd_transpose can easily // reduce the speed for small matrices (up to 64x64) by 5 to 10%. int const multiple_blocks = (A->flags | DST->flags) & mzd_flag_multiple_blocks; if (__M4RI_UNLIKELY(multiple_blocks)) { word* RESTRICT non_register_fwd; word const* RESTRICT non_register_fws; rci_t non_register_nrows; rci_t non_register_ncols; _mzd_transpose_multiblock(DST, A, &non_register_fwd, &non_register_fws, &non_register_nrows, &non_register_ncols); fwd = non_register_fwd; fws = non_register_fws; nrows = non_register_nrows; ncols = non_register_ncols; } if (nrows >= 64) { /* * This is an interesting #if ... * I recommend to investigate the number of instructions, and the clocks per instruction, * as function of various sizes of the matrix (most likely especially the number of columns * (the size of a row) will have influence; also always use multiples of 64 or even 128), * for both cases below. * * To measure this run for example: * * ./bench_mzd -m 10 -x 10 -p PAPI_TOT_INS,PAPI_L1_TCM,PAPI_L2_TCM mzd_transpose 32000 32000 * ./bench_mzd -m 10 -x 100 -p PAPI_TOT_INS,PAPI_L1_TCM,PAPI_L2_TCM mzd_transpose 128 10240 * etc (increase -x for smaller sizes to get better accuracy). * * --Carlo Wood */ #if 1 int js = ncols & nrows & 64; // True if the total number of whole 64x64 matrices is odd. wi_t const rowstride_64_dst = 64 * DST->rowstride; word* RESTRICT fwd_current = fwd; word const* RESTRICT fws_current = fws; if (js) { js = 1; _mzd_copy_transpose_64x64(fwd, fws, DST->rowstride, A->rowstride); if ((nrows | ncols) == 64) { __M4RI_DD_MZD(DST); return DST; } fwd_current += rowstride_64_dst; ++fws_current; } rci_t const whole_64cols = ncols / 64; // The use of delayed and even, is to avoid calling _mzd_copy_transpose_64x64_2 twice. // This way it can be inlined without duplicating the amount of code that has to be loaded. word* RESTRICT fwd_delayed = NULL; word const* RESTRICT fws_delayed = NULL; int even = 0; while (1) { for (int j = js; j < whole_64cols; ++j) { if (!even) { fwd_delayed = fwd_current; fws_delayed = fws_current; } else { _mzd_copy_transpose_64x64_2(fwd_delayed, fwd_current, fws_delayed, fws_current, DST->rowstride, A->rowstride); } fwd_current += rowstride_64_dst; ++fws_current; even = !even; } nrows -= 64; if (ncols % 64) { _mzd_copy_transpose_64xlt64(fwd + whole_64cols * rowstride_64_dst, fws + whole_64cols, DST->rowstride, A->rowstride, ncols % 64); } fwd += 1; fws += 64 * A->rowstride; if (nrows < 64) break; js = 0; fws_current = fws; fwd_current = fwd; } #else // The same as the above, but without using _mzd_copy_transpose_64x64_2. wi_t const rowstride_64_dst = 64 * DST->rowstride; rci_t const whole_64cols = ncols / 64; assert(nrows >= 64); do { for (int j = 0; j < whole_64cols; ++j) { _mzd_copy_transpose_64x64(fwd + j * rowstride_64_dst, fws + j, DST->rowstride, A->rowstride); } nrows -= 64; if (ncols % 64) { _mzd_copy_transpose_64xlt64(fwd + whole_64cols * rowstride_64_dst, fws + whole_64cols, DST->rowstride, A->rowstride, ncols % 64); } fwd += 1; fws += 64 * A->rowstride; } while(nrows >= 64); #endif } if (nrows == 0) { __M4RI_DD_MZD(DST); return DST; } // Transpose the remaining top rows. Now 0 < nrows < 64. while (ncols >= 64) { _mzd_copy_transpose_lt64x64(fwd, fws, DST->rowstride, A->rowstride, nrows); ncols -= 64; fwd += 64 * DST->rowstride; fws += 1; } if (ncols == 0) { __M4RI_DD_MZD(DST); return DST; } maxsize = MAX(nrows, ncols); } // Transpose the remaining corner. Now both 0 < nrows < 64 and 0 < ncols < 64. if (maxsize <= 8) { _mzd_copy_transpose_le8xle8(fwd, fws, DST->rowstride, A->rowstride, nrows, ncols, maxsize); } else if (maxsize <= 16) { _mzd_copy_transpose_le16xle16(fwd, fws, DST->rowstride, A->rowstride, nrows, ncols, maxsize); } else if (maxsize <= 32) { _mzd_copy_transpose_le32xle32(fwd, fws, DST->rowstride, A->rowstride, nrows, ncols); } else { _mzd_copy_transpose_le64xle64(fwd, fws, DST->rowstride, A->rowstride, nrows, ncols); } __M4RI_DD_MZD(DST); return DST; } void _mzd_transpose_multiblock(mzd_t *DST, mzd_t const *A, word* RESTRICT* fwdp, word const* RESTRICT* fwsp, rci_t* nrowsp, rci_t* ncolsp) { rci_t nrows = A->nrows; rci_t ncols = A->ncols; rci_t blockrows_dst = 1 << DST->blockrows_log; // The maximum number of rows in a block of DST. rci_t blockrows_src = 1 << A->blockrows_log; // The maximum number of rows in a block of A. /* We're deviding the source matrix into blocks of multiples of 64x64, such that each * block fits entirely inside a single memory allocation block, both in the source * as well as the corresponding destination. * * <-------------------ncols-----------------> * <---------blockrows_dst-------> * .---------------------------------------------------------------. * |P ^ Matrix A:| . |Q . . . |<-^---- A->blocks[0].begin * | | | . | . . . | | * | | | . | . . . | | * | | |- - - - - -|- - - - - - - - - - - - - - - -| | * | | | . | . ^ . . | | * | | | . | .<64x64>. . | | * | | | . | . v . . | | * | | |- - - - - -|- - - - - - - - - - - - - - - -| |- blockrows_src * | | | . | . . . | | * | | | . | . . . | | * | | | . | . . . | | * | |nrows |- - - - - -|- - - - - - - - - - - - - - - -| | * | | | . | . . . | | * | | | . | . . . | | * | | | . | . . . | v * |===================+===========================================| * |R | | . |S . . . |<------ A->blocks[1].begin * | | | . | . . . | * | | | . | . . . | * | | |- - - - - -|- - - - - - - - - - - - - - - -| * | | | . | . . . | * | | | . | . . . | * | | | . | . . . | * | | |- - - - - -|- - - - - - - - - - - - - - - -| * | v | . | . . . | * | `-------------------------------------------| * | | | * | | | * | | | * | | | * | | | * `---------------------------------------------------------------' * * Imagine this also to be the memory map of DST, which then would be * mirrored in the diagonal line from the top/right to the bottom/left. * Then each of the squares P, Q, R and S lay entirely inside one * memory block in both the source as well as the destination matrix. * P and Q are really the same block for matrix A (as are R and S), * while P and R (and Q and S) are really the same block for DST. * * We're going to run over the top/right corners of each of these * memory "blocks" and then transpose it, one by one, running * from right to left and top to bottom. The last one (R) will be * done by the calling function, so we just return when we get there. */ rci_t R_top = (nrows >> A->blockrows_log) << A->blockrows_log; rci_t R_right = (ncols >> DST->blockrows_log) << DST->blockrows_log; for (rci_t col = 0; col < ncols; col += blockrows_dst) { rci_t end = (col == R_right) ? R_top : nrows; for (rci_t row = 0; row < end; row += blockrows_src) { rci_t nrowsb = (row < R_top) ? blockrows_src : (nrows - R_top); rci_t ncolsb = (col < R_right) ? blockrows_dst : (ncols - R_right); word const* RESTRICT fws = mzd_row(A, row) + col / m4ri_radix; word* RESTRICT fwd = mzd_row(DST, col) + row / m4ri_radix; // The following code is (almost) duplicated from _mzd_transpose. if (nrowsb >= 64) { int js = ncolsb & nrowsb & 64; // True if the total number of whole 64x64 matrices is odd. wi_t const rowstride_64_dst = 64 * DST->rowstride; word* RESTRICT fwd_current = fwd; word const* RESTRICT fws_current = fws; if (js) { js = 1; _mzd_copy_transpose_64x64(fwd, fws, DST->rowstride, A->rowstride); fwd_current += rowstride_64_dst; ++fws_current; } rci_t const whole_64cols = ncolsb / 64; // The use of delayed and even, is to avoid calling _mzd_copy_transpose_64x64_2 twice. // This way it can be inlined without duplicating the amount of code that has to be loaded. word* RESTRICT fwd_delayed = NULL; word const* RESTRICT fws_delayed = NULL; int even = 0; while (1) { for (int j = js; j < whole_64cols; ++j) { if (!even) { fwd_delayed = fwd_current; fws_delayed = fws_current; } else { _mzd_copy_transpose_64x64_2(fwd_delayed, fwd_current, fws_delayed, fws_current, DST->rowstride, A->rowstride); } fwd_current += rowstride_64_dst; ++fws_current; even = !even; } nrowsb -= 64; if (ncolsb % 64) { _mzd_copy_transpose_64xlt64(fwd + whole_64cols * rowstride_64_dst, fws + whole_64cols, DST->rowstride, A->rowstride, ncolsb % 64); } fwd += 1; fws += 64 * A->rowstride; if (nrowsb < 64) break; js = 0; fws_current = fws; fwd_current = fwd; } } if (nrowsb == 0) continue; // Transpose the remaining top rows. Now 0 < nrowsb < 64. while (ncolsb >= 64) { _mzd_copy_transpose_lt64x64(fwd, fws, DST->rowstride, A->rowstride, nrowsb); ncolsb -= 64; fwd += 64 * DST->rowstride; fws += 1; } // This is true because if it wasn't then nrowsb has to be 0 and we continued before already. assert(ncolsb == 0); } } *nrowsp = nrows - R_top; *ncolsp = ncols - R_right; if (R_top < nrows) *fwsp = mzd_row(A, R_top) + R_right / m4ri_radix; if (R_right < ncols) *fwdp = mzd_row(DST, R_right) + R_top / m4ri_radix; } mzd_t *mzd_transpose(mzd_t *DST, mzd_t const *A) { if (DST == NULL) { DST = mzd_init( A->ncols, A->nrows ); } else if (__M4RI_UNLIKELY(DST->nrows != A->ncols || DST->ncols != A->nrows)) { m4ri_die("mzd_transpose: Wrong size for return matrix.\n"); } else { /** it seems this is taken care of in the subroutines, re-enable if running into problems **/ //mzd_set_ui(DST,0); } if(A->nrows == 0 || A->ncols == 0) return mzd_copy(DST, A); if (__M4RI_LIKELY(!mzd_is_windowed(DST) && !mzd_is_windowed(A))) return _mzd_transpose(DST, A); int A_windowed = mzd_is_windowed(A); if (A_windowed) A = mzd_copy(NULL, A); if (__M4RI_LIKELY(!mzd_is_windowed(DST))) _mzd_transpose(DST, A); else { mzd_t *D = mzd_init(DST->nrows, DST->ncols); _mzd_transpose(D, A); mzd_copy(DST, D); mzd_free(D); } if (A_windowed) mzd_free((mzd_t*)A); return DST; } mzd_t *mzd_mul_naive(mzd_t *C, mzd_t const *A, mzd_t const *B) { if (C == NULL) { C = mzd_init(A->nrows, B->ncols); } else { if (C->nrows != A->nrows || C->ncols != B->ncols) { m4ri_die("mzd_mul_naive: Provided return matrix has wrong dimensions.\n"); } } if(B->ncols < m4ri_radix-10) { /* this cutoff is rather arbitrary */ mzd_t *BT = mzd_transpose(NULL, B); _mzd_mul_naive(C, A, BT, 1); mzd_free (BT); } else { _mzd_mul_va(C, A, B, 1); } return C; } mzd_t *mzd_addmul_naive(mzd_t *C, mzd_t const *A, mzd_t const *B) { if (C->nrows != A->nrows || C->ncols != B->ncols) { m4ri_die("mzd_mul_naive: Provided return matrix has wrong dimensions.\n"); } if(B->ncols < m4ri_radix-10) { /* this cutoff is rather arbitrary */ mzd_t *BT = mzd_transpose(NULL, B); _mzd_mul_naive(C, A, BT, 0); mzd_free (BT); } else { _mzd_mul_va(C, A, B, 0); } return C; } mzd_t *_mzd_mul_naive(mzd_t *C, mzd_t const *A, mzd_t const *B, const int clear) { wi_t eol; word *a, *b, *c; if (clear) { word const mask_end = C->high_bitmask; /* improves performance on x86_64 but is not cross plattform */ /* asm __volatile__ (".p2align 4\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop"); */ for (rci_t i = 0; i < C->nrows; ++i) { wi_t j = 0; for (; j < C->width - 1; ++j) { C->rows[i][j] = 0; } C->rows[i][j] &= ~mask_end; } } if(C->ncols % m4ri_radix) { eol = (C->width - 1); } else { eol = (C->width); } word parity[64]; for (int i = 0; i < 64; ++i) { parity[i] = 0; } wi_t const wide = A->width; int const blocksize = __M4RI_MUL_BLOCKSIZE; for (rci_t start = 0; start + blocksize <= C->nrows; start += blocksize) { for (rci_t i = start; i < start + blocksize; ++i) { a = A->rows[i]; c = C->rows[i]; for (rci_t j = 0; j < m4ri_radix * eol; j += m4ri_radix) { for (int k = 0; k < m4ri_radix; ++k) { b = B->rows[j + k]; parity[k] = a[0] & b[0]; for (wi_t ii = wide - 1; ii >= 1; --ii) parity[k] ^= a[ii] & b[ii]; } c[j / m4ri_radix] ^= m4ri_parity64(parity); } if (eol != C->width) { word const mask_end = C->high_bitmask; /* improves performance on x86_64 but is not cross plattform */ /* asm __volatile__ (".p2align 4\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop"); */ for (int k = 0; k < (C->ncols % m4ri_radix); ++k) { b = B->rows[m4ri_radix * eol + k]; parity[k] = a[0] & b[0]; for (wi_t ii = 1; ii < A->width; ++ii) parity[k] ^= a[ii] & b[ii]; } c[eol] ^= m4ri_parity64(parity) & mask_end; } } } for (rci_t i = C->nrows - (C->nrows % blocksize); i < C->nrows; ++i) { a = A->rows[i]; c = C->rows[i]; for (rci_t j = 0; j < m4ri_radix * eol; j += m4ri_radix) { for (int k = 0; k < m4ri_radix; ++k) { b = B->rows[j+k]; parity[k] = a[0] & b[0]; for (wi_t ii = wide - 1; ii >= 1; --ii) parity[k] ^= a[ii] & b[ii]; } c[j/m4ri_radix] ^= m4ri_parity64(parity); } if (eol != C->width) { word const mask_end = C->high_bitmask; /* improves performance on x86_64 but is not cross plattform */ /* asm __volatile__ (".p2align 4\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop"); */ for (int k = 0; k < (C->ncols % m4ri_radix); ++k) { b = B->rows[m4ri_radix * eol + k]; parity[k] = a[0] & b[0]; for (wi_t ii = 1; ii < A->width; ++ii) parity[k] ^= a[ii] & b[ii]; } c[eol] ^= m4ri_parity64(parity) & mask_end; } } __M4RI_DD_MZD(C); return C; } mzd_t *_mzd_mul_va(mzd_t *C, mzd_t const *v, mzd_t const *A, int const clear) { if(clear) mzd_set_ui(C, 0); rci_t const m = v->nrows; rci_t const n = v->ncols; for(rci_t i = 0; i < m; ++i) for(rci_t j = 0; j < n; ++j) if (mzd_read_bit(v,i,j)) mzd_combine(C,i,0, C,i,0, A,j,0); __M4RI_DD_MZD(C); return C; } void mzd_randomize(mzd_t *A) { wi_t const width = A->width - 1; word const mask_end = A->high_bitmask; for(rci_t i = 0; i < A->nrows; ++i) { for(wi_t j = 0; j < width; ++j) A->rows[i][j] = m4ri_random_word(); A->rows[i][width] ^= (A->rows[i][width] ^ m4ri_random_word()) & mask_end; } __M4RI_DD_MZD(A); } void mzd_set_ui( mzd_t *A, unsigned int value) { word const mask_end = A->high_bitmask; for (rci_t i = 0; i < A->nrows; ++i) { word *row = A->rows[i]; for(wi_t j = 0; j < A->width - 1; ++j) row[j] = 0; row[A->width - 1] &= ~mask_end; } if(value % 2 == 0) { __M4RI_DD_MZD(A); return; } rci_t const stop = MIN(A->nrows, A->ncols); for (rci_t i = 0; i < stop; ++i) { mzd_write_bit(A, i, i, 1); } __M4RI_DD_MZD(A); } int mzd_equal(mzd_t const *A, mzd_t const *B) { if (A->nrows != B->nrows) return FALSE; if (A->ncols != B->ncols) return FALSE; if (A == B) return TRUE; wi_t Awidth = A->width - 1; for (rci_t i = 0; i < A->nrows; ++i) { for (wi_t j = 0; j < Awidth; ++j) { if (A->rows[i][j] != B->rows[i][j]) return FALSE; } } word const mask_end = A->high_bitmask; for (rci_t i = 0; i < A->nrows; ++i) { if (((A->rows[i][Awidth] ^ B->rows[i][Awidth]) & mask_end)) return FALSE; } return TRUE; } int mzd_cmp(mzd_t const *A, mzd_t const *B) { if(A->nrows < B->nrows) return -1; if(B->nrows < A->nrows) return 1; if(A->ncols < B->ncols) return -1; if(B->ncols < A->ncols) return 1; const word mask_end = A->high_bitmask; const wi_t n = A->width-1; /* Columns with large index are "larger", but rows with small index are more important than with large index. */ for(rci_t i=0; inrows; i++) { if ((A->rows[i][n]&mask_end) < (B->rows[i][n]&mask_end)) return -1; else if ((A->rows[i][n]&mask_end) > (B->rows[i][n]&mask_end)) return 1; for(wi_t j=n-1; j>=0; j--) { if (A->rows[i][j] < B->rows[i][j]) return -1; else if (A->rows[i][j] > B->rows[i][j]) return 1; } } return 0; } mzd_t *mzd_copy(mzd_t *N, mzd_t const *P) { if (N == P) return N; if (N == NULL) { N = mzd_init(P->nrows, P->ncols); } else { if (N->nrows < P->nrows || N->ncols < P->ncols) m4ri_die("mzd_copy: Target matrix is too small."); } word *p_truerow, *n_truerow; wi_t const wide = P->width - 1; word mask_end = P->high_bitmask; for (rci_t i = 0; i < P->nrows; ++i) { p_truerow = P->rows[i]; n_truerow = N->rows[i]; for (wi_t j = 0; j < wide; ++j) n_truerow[j] = p_truerow[j]; n_truerow[wide] = (n_truerow[wide] & ~mask_end) | (p_truerow[wide] & mask_end); } __M4RI_DD_MZD(N); return N; } /* This is sometimes called augment */ mzd_t *mzd_concat(mzd_t *C, mzd_t const *A, mzd_t const *B) { if (A->nrows != B->nrows) { m4ri_die("mzd_concat: Bad arguments to concat!\n"); } if (C == NULL) { C = mzd_init(A->nrows, A->ncols + B->ncols); } else if (C->nrows != A->nrows || C->ncols != (A->ncols + B->ncols)) { m4ri_die("mzd_concat: C has wrong dimension!\n"); } for (rci_t i = 0; i < A->nrows; ++i) { word *dst_truerow = C->rows[i]; word *src_truerow = A->rows[i]; for (wi_t j = 0; j < A->width; ++j) { dst_truerow[j] = src_truerow[j]; } } for (rci_t i = 0; i < B->nrows; ++i) { for (rci_t j = 0; j < B->ncols; ++j) { mzd_write_bit(C, i, j + A->ncols, mzd_read_bit(B, i, j)); } } __M4RI_DD_MZD(C); return C; } mzd_t *mzd_stack(mzd_t *C, mzd_t const *A, mzd_t const *B) { if (A->ncols != B->ncols) { m4ri_die("mzd_stack: A->ncols (%d) != B->ncols (%d)!\n", A->ncols, B->ncols); } if (C == NULL) { C = mzd_init(A->nrows + B->nrows, A->ncols); } else if (C->nrows != (A->nrows + B->nrows) || C->ncols != A->ncols) { m4ri_die("mzd_stack: C has wrong dimension!\n"); } for(rci_t i = 0; i < A->nrows; ++i) { word *src_truerow = A->rows[i]; word *dst_truerow = C->rows[i]; for (wi_t j = 0; j < A->width; ++j) { dst_truerow[j] = src_truerow[j]; } } for(rci_t i = 0; i < B->nrows; ++i) { word *dst_truerow = C->rows[A->nrows + i]; word *src_truerow = B->rows[i]; for (wi_t j = 0; j < B->width; ++j) { dst_truerow[j] = src_truerow[j]; } } __M4RI_DD_MZD(C); return C; } mzd_t *mzd_invert_naive(mzd_t *INV, mzd_t const *A, mzd_t const *I) { mzd_t *H; H = mzd_concat(NULL, A, I); rci_t x = mzd_echelonize_naive(H, TRUE); if (x == 0) { mzd_free(H); return NULL; } INV = mzd_submatrix(INV, H, 0, A->ncols, A->nrows, 2 * A->ncols); mzd_free(H); __M4RI_DD_MZD(INV); return INV; } mzd_t *mzd_add(mzd_t *ret, mzd_t const *left, mzd_t const *right) { if (left->nrows != right->nrows || left->ncols != right->ncols) { m4ri_die("mzd_add: rows and columns must match.\n"); } if (ret == NULL) { ret = mzd_init(left->nrows, left->ncols); } else if (ret != left) { if (ret->nrows != left->nrows || ret->ncols != left->ncols) { m4ri_die("mzd_add: rows and columns of returned matrix must match.\n"); } } return _mzd_add(ret, left, right); } mzd_t *_mzd_add(mzd_t *C, mzd_t const *A, mzd_t const *B) { rci_t const nrows = MIN(MIN(A->nrows, B->nrows), C->nrows); if (C == B) { //swap mzd_t const *tmp = A; A = B; B = tmp; } word const mask_end = C->high_bitmask; switch(A->width) { case 0: return C; case 1: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] ^= ((A->rows[i][0] ^ B->rows[i][0] ^ C->rows[i][0]) & mask_end); } break; case 2: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] = A->rows[i][0] ^ B->rows[i][0]; C->rows[i][1] ^= ((A->rows[i][1] ^ B->rows[i][1] ^ C->rows[i][1]) & mask_end); } break; case 3: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] = A->rows[i][0] ^ B->rows[i][0]; C->rows[i][1] = A->rows[i][1] ^ B->rows[i][1]; C->rows[i][2] ^= ((A->rows[i][2] ^ B->rows[i][2] ^ C->rows[i][2]) & mask_end); } break; case 4: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] = A->rows[i][0] ^ B->rows[i][0]; C->rows[i][1] = A->rows[i][1] ^ B->rows[i][1]; C->rows[i][2] = A->rows[i][2] ^ B->rows[i][2]; C->rows[i][3] ^= ((A->rows[i][3] ^ B->rows[i][3] ^ C->rows[i][3]) & mask_end); } break; case 5: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] = A->rows[i][0] ^ B->rows[i][0]; C->rows[i][1] = A->rows[i][1] ^ B->rows[i][1]; C->rows[i][2] = A->rows[i][2] ^ B->rows[i][2]; C->rows[i][3] = A->rows[i][3] ^ B->rows[i][3]; C->rows[i][4] ^= ((A->rows[i][4] ^ B->rows[i][4] ^ C->rows[i][4]) & mask_end); } break; case 6: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] = A->rows[i][0] ^ B->rows[i][0]; C->rows[i][1] = A->rows[i][1] ^ B->rows[i][1]; C->rows[i][2] = A->rows[i][2] ^ B->rows[i][2]; C->rows[i][3] = A->rows[i][3] ^ B->rows[i][3]; C->rows[i][4] = A->rows[i][4] ^ B->rows[i][4]; C->rows[i][5] ^= ((A->rows[i][5] ^ B->rows[i][5] ^ C->rows[i][5]) & mask_end); } break; case 7: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] = A->rows[i][0] ^ B->rows[i][0]; C->rows[i][1] = A->rows[i][1] ^ B->rows[i][1]; C->rows[i][2] = A->rows[i][2] ^ B->rows[i][2]; C->rows[i][3] = A->rows[i][3] ^ B->rows[i][3]; C->rows[i][4] = A->rows[i][4] ^ B->rows[i][4]; C->rows[i][5] = A->rows[i][5] ^ B->rows[i][5]; C->rows[i][6] ^= ((A->rows[i][6] ^ B->rows[i][6] ^ C->rows[i][6]) & mask_end); } break; case 8: for(rci_t i = 0; i < nrows; ++i) { C->rows[i][0] = A->rows[i][0] ^ B->rows[i][0]; C->rows[i][1] = A->rows[i][1] ^ B->rows[i][1]; C->rows[i][2] = A->rows[i][2] ^ B->rows[i][2]; C->rows[i][3] = A->rows[i][3] ^ B->rows[i][3]; C->rows[i][4] = A->rows[i][4] ^ B->rows[i][4]; C->rows[i][5] = A->rows[i][5] ^ B->rows[i][5]; C->rows[i][6] = A->rows[i][6] ^ B->rows[i][6]; C->rows[i][7] ^= ((A->rows[i][7] ^ B->rows[i][7] ^ C->rows[i][7]) & mask_end); } break; default: for(rci_t i = 0; i < nrows; ++i) { mzd_combine_even(C,i,0, A,i,0, B,i,0); } } __M4RI_DD_MZD(C); return C; } mzd_t *mzd_submatrix(mzd_t *S, mzd_t const *M, rci_t const startrow, rci_t const startcol, rci_t const endrow, rci_t const endcol) { rci_t const nrows = endrow - startrow; rci_t const ncols = endcol - startcol; if (S == NULL) { S = mzd_init(nrows, ncols); } else if( (S->nrows < nrows) | (S->ncols < ncols) ) { m4ri_die("mzd_submatrix: got S with dimension %d x %d but expected %d x %d\n", S->nrows, S->ncols, nrows, ncols); } if (startcol % m4ri_radix == 0) { wi_t const startword = startcol / m4ri_radix; /* we start at the beginning of a word */ if(ncols / m4ri_radix != 0) { for(rci_t x = startrow, i = 0; i < nrows; ++i, ++x) { memcpy(S->rows[i], M->rows[x] + startword, sizeof(word) * (ncols / m4ri_radix)); } } if (ncols % m4ri_radix) { word const mask_end = __M4RI_LEFT_BITMASK(ncols % m4ri_radix); for(rci_t x = startrow, i = 0; i < nrows; ++i, ++x) { /* process remaining bits */ word temp = M->rows[x][startword + ncols / m4ri_radix] & mask_end; S->rows[i][ncols / m4ri_radix] = temp; } } } else { wi_t j; for(rci_t i=0; irows[i][j/m4ri_radix] = mzd_read_bits(M, startrow+i, startcol+j, m4ri_radix); S->rows[i][j/m4ri_radix] &= ~S->high_bitmask; S->rows[i][j/m4ri_radix] |= mzd_read_bits(M, startrow+i, startcol+j, ncols - j) & S->high_bitmask; } } __M4RI_DD_MZD(S); return S; } void mzd_col_swap(mzd_t *M, rci_t const cola, rci_t const colb) { if (cola == colb) return; rci_t const _cola = cola; rci_t const _colb = colb; wi_t const a_word = _cola / m4ri_radix; wi_t const b_word = _colb / m4ri_radix; int const a_bit = _cola % m4ri_radix; int const b_bit = _colb % m4ri_radix; word* RESTRICT ptr = mzd_first_row(M); int max_bit = MAX(a_bit, b_bit); int count = mzd_rows_in_block(M, 0); assert(count > 0); int min_bit = a_bit + b_bit - max_bit; int block = 0; int offset = max_bit - min_bit; word mask = m4ri_one << min_bit; if (a_word == b_word) { while(1) { ptr += a_word; int fast_count = count / 4; int rest_count = count - 4 * fast_count; word xor[4]; wi_t const rowstride = M->rowstride; while (fast_count--) { xor[0] = ptr[0]; xor[1] = ptr[rowstride]; xor[2] = ptr[2 * rowstride]; xor[3] = ptr[3 * rowstride]; xor[0] ^= xor[0] >> offset; xor[1] ^= xor[1] >> offset; xor[2] ^= xor[2] >> offset; xor[3] ^= xor[3] >> offset; xor[0] &= mask; xor[1] &= mask; xor[2] &= mask; xor[3] &= mask; xor[0] |= xor[0] << offset; xor[1] |= xor[1] << offset; xor[2] |= xor[2] << offset; xor[3] |= xor[3] << offset; ptr[0] ^= xor[0]; ptr[rowstride] ^= xor[1]; ptr[2 * rowstride] ^= xor[2]; ptr[3 * rowstride] ^= xor[3]; ptr += 4 * rowstride; } while (rest_count--) { word xor = *ptr; xor ^= xor >> offset; xor &= mask; *ptr ^= xor | (xor << offset); ptr += rowstride; } if ((count = mzd_rows_in_block(M, ++block)) <= 0) break; ptr = mzd_first_row_next_block(M, block); } } else { word* RESTRICT min_ptr; wi_t max_offset; if (min_bit == a_bit) { min_ptr = ptr + a_word; max_offset = b_word - a_word; } else { min_ptr = ptr + b_word; max_offset = a_word - b_word; } while(1) { wi_t const rowstride = M->rowstride; while(count--) { word xor = (min_ptr[0] ^ (min_ptr[max_offset] >> offset)) & mask; min_ptr[0] ^= xor; min_ptr[max_offset] ^= xor << offset; min_ptr += rowstride; } if ((count = mzd_rows_in_block(M, ++block)) <= 0) break; ptr = mzd_first_row_next_block(M, block); if (min_bit == a_bit) min_ptr = ptr + a_word; else min_ptr = ptr + b_word; } } __M4RI_DD_MZD(M); } int mzd_is_zero(mzd_t const *A) { word status = 0; word mask_end = A->high_bitmask; for (rci_t i = 0; i < A->nrows; ++i) { for (wi_t j = 0; j < A->width - 1; ++j) status |= A->rows[i][j]; status |= A->rows[i][A->width - 1] & mask_end; if(status) return 0; } return !status; } void mzd_copy_row(mzd_t *B, rci_t i, mzd_t const *A, rci_t j) { assert(B->ncols >= A->ncols); wi_t const width = MIN(B->width, A->width) - 1; word const *a = A->rows[j]; word *b = B->rows[i]; word const mask_end = __M4RI_LEFT_BITMASK(A->ncols % m4ri_radix); if (width != 0) { for(wi_t k = 0; k < width; ++k) b[k] = a[k]; b[width] = (b[width] & ~mask_end) | (a[width] & mask_end); } else { b[0] = b[0] | (a[0]& mask_end) | (b[0] & ~mask_end); } __M4RI_DD_ROW(B, i); } int mzd_find_pivot(mzd_t const *A, rci_t start_row, rci_t start_col, rci_t *r, rci_t *c) { rci_t const nrows = A->nrows; rci_t const ncols = A->ncols; word data = 0; rci_t row_candidate = 0; if(A->ncols - start_col < m4ri_radix) { for(rci_t j = start_col; j < A->ncols; j += m4ri_radix) { int const length = MIN(m4ri_radix, ncols - j); for(rci_t i = start_row; i < nrows; ++i) { word const curr_data = mzd_read_bits(A, i, j, length); if (m4ri_lesser_LSB(curr_data, data)) { row_candidate = i; data = curr_data; } } if(data) { *r = row_candidate; for(int l = 0; l < length; ++l) { if(__M4RI_GET_BIT(data, l)) { *c = j + l; break; } } __M4RI_DD_RCI(*r); __M4RI_DD_RCI(*c); __M4RI_DD_INT(1); return 1; } } } else { /* we definitely have more than one word */ /* handle first word */ int const bit_offset = (start_col % m4ri_radix); wi_t const word_offset = start_col / m4ri_radix; word const mask_begin = __M4RI_RIGHT_BITMASK(m4ri_radix-bit_offset); for(rci_t i = start_row; i < nrows; ++i) { word const curr_data = A->rows[i][word_offset] & mask_begin; if (m4ri_lesser_LSB(curr_data, data)) { row_candidate = i; data = curr_data; if(__M4RI_GET_BIT(data,bit_offset)) { break; } } } if(data) { *r = row_candidate; data >>= bit_offset; assert(data); for(int l = 0; l < (m4ri_radix - bit_offset); ++l) { if(__M4RI_GET_BIT(data, l)) { *c = start_col + l; break; } } __M4RI_DD_RCI(*r); __M4RI_DD_RCI(*c); __M4RI_DD_INT(1); return 1; } /* handle complete words */ for(wi_t wi = word_offset + 1; wi < A->width - 1; ++wi) { for(rci_t i = start_row; i < nrows; ++i) { word const curr_data = A->rows[i][wi]; if (m4ri_lesser_LSB(curr_data, data)) { row_candidate = i; data = curr_data; if(__M4RI_GET_BIT(data, 0)) break; } } if(data) { *r = row_candidate; for(int l = 0; l < m4ri_radix; ++l) { if(__M4RI_GET_BIT(data, l)) { *c = wi * m4ri_radix + l; break; } } __M4RI_DD_RCI(*r); __M4RI_DD_RCI(*c); __M4RI_DD_INT(1); return 1; } } /* handle last word */ int const end_offset = (A->ncols % m4ri_radix) ? (A->ncols % m4ri_radix) : m4ri_radix; word const mask_end = __M4RI_LEFT_BITMASK(end_offset % m4ri_radix); wi_t wi = A->width - 1; for(rci_t i = start_row; i < nrows; ++i) { word const curr_data = A->rows[i][wi] & mask_end; if (m4ri_lesser_LSB(curr_data, data)) { row_candidate = i; data = curr_data; if(__M4RI_GET_BIT(data,0)) break; } } if(data) { *r = row_candidate; for(int l = 0; l < end_offset; ++l) { if(__M4RI_GET_BIT(data, l)) { *c = wi * m4ri_radix + l; break; } } __M4RI_DD_RCI(*r); __M4RI_DD_RCI(*c); __M4RI_DD_INT(1); return 1; } } __M4RI_DD_RCI(*r); __M4RI_DD_RCI(*c); __M4RI_DD_INT(0); return 0; } #define MASK(c) (((uint64_t)(-1)) / (__M4RI_TWOPOW(__M4RI_TWOPOW(c)) + 1)) #define COUNT(x,c) ((x) & MASK(c)) + (((x) >> (__M4RI_TWOPOW(c))) & MASK(c)) static inline int m4ri_bitcount(word w) { uint64_t n = __M4RI_CONVERT_TO_UINT64_T(w); n = COUNT(n, 0); n = COUNT(n, 1); n = COUNT(n, 2); n = COUNT(n, 3); n = COUNT(n, 4); n = COUNT(n, 5); return (int)n; } double _mzd_density(mzd_t const *A, wi_t res, rci_t r, rci_t c) { size_t count = 0; size_t total = 0; if(A->width == 1) { for(rci_t i = r; i < A->nrows; ++i) for(rci_t j = c; j < A->ncols; ++j) if(mzd_read_bit(A, i, j)) ++count; return ((double)count)/(1.0 * A->ncols * A->nrows); } if(res == 0) res = A->width / 100; if (res < 1) res = 1; for(rci_t i = r; i < A->nrows; ++i) { word *truerow = A->rows[i]; for(rci_t j = c; j < m4ri_radix; ++j) if(mzd_read_bit(A, i, j)) ++count; total += m4ri_radix; for(wi_t j = MAX(1, c / m4ri_radix); j < A->width - 1; j += res) { count += m4ri_bitcount(truerow[j]); total += m4ri_radix; } for(int j = 0; j < A->ncols % m4ri_radix; ++j) if(mzd_read_bit(A, i, m4ri_radix * (A->ncols / m4ri_radix) + j)) ++count; total += A->ncols % m4ri_radix; } return (double)count / total; } double mzd_density(mzd_t const *A, wi_t res) { return _mzd_density(A, res, 0, 0); } rci_t mzd_first_zero_row(mzd_t const *A) { word const mask_end = __M4RI_LEFT_BITMASK(A->ncols % m4ri_radix); wi_t const end = A->width - 1; word *row; for(rci_t i = A->nrows - 1; i >= 0; --i) { row = A->rows[i]; word tmp = row[0]; for (wi_t j = 1; j < end; ++j) tmp |= row[j]; tmp |= row[end] & mask_end; if(tmp) { __M4RI_DD_INT(i + 1); return i + 1; } } __M4RI_DD_INT(0); return 0; } mzd_t *mzd_extract_u(mzd_t *U, mzd_t const *A) { rci_t k = MIN(A->nrows, A->ncols); if (U == NULL) U = mzd_submatrix(NULL, A, 0, 0, k, k); else assert(U->nrows == k && U->ncols == k); for(rci_t i=1; inrows; i++) { for(wi_t j=0; jrows[i][j] = 0; } if(i%m4ri_radix) mzd_clear_bits(U, i, (i/m4ri_radix)*m4ri_radix, i%m4ri_radix); } return U; } mzd_t *mzd_extract_l(mzd_t *L, mzd_t const *A) { rci_t k = MIN(A->nrows, A->ncols); if (L == NULL) L = mzd_submatrix(NULL, A, 0, 0, k, k); else assert(L->nrows == k && L->ncols == k); for(rci_t i=0; inrows-1; i++) { if(m4ri_radix - (i+1)%m4ri_radix) mzd_clear_bits(L, i, i+1, m4ri_radix - (i+1)%m4ri_radix); for(wi_t j=(i/m4ri_radix+1); jwidth; j++) { L->rows[i][j] = 0; } } return L; } m4ri-20140914/m4ri/graycode.c0000644000175000017500000000453612354166226012407 00000000000000/****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007 Gregory Bard * Copyright (C) 2007 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "misc.h" #include "graycode.h" code **m4ri_codebook = NULL; int m4ri_gray_code(int number, int length) { int lastbit = 0; int res = 0; for(int i = length - 1; i >= 0; --i) { int bit = number & (1 << i); res |= (lastbit >> 1) ^ bit; lastbit = bit; } return res; } void m4ri_build_code(int *ord, int *inc, int l) { for(int i = 0 ; i < (int)__M4RI_TWOPOW(l); ++i) { ord[i] = m4ri_gray_code(i, l); } for(int i = l; i > 0; --i) { for(int j = 1; j < (int)__M4RI_TWOPOW(i) + 1; ++j) { inc[j * __M4RI_TWOPOW(l - i) - 1] = l - i; } } } void m4ri_build_all_codes() { if (m4ri_codebook) { return; } m4ri_codebook=(code**)m4ri_mm_calloc(__M4RI_MAXKAY + 1, sizeof(code*)); for(int k = 1; k < __M4RI_MAXKAY + 1; ++k) { m4ri_codebook[k] = (code*)m4ri_mm_calloc(1, sizeof(code)); m4ri_codebook[k]->ord =(int*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(int)); m4ri_codebook[k]->inc =(int*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(int)); m4ri_build_code(m4ri_codebook[k]->ord, m4ri_codebook[k]->inc, k); } } void m4ri_destroy_all_codes() { if (!m4ri_codebook) { return; } for(int i = 1; i < __M4RI_MAXKAY + 1; ++i) { m4ri_mm_free(m4ri_codebook[i]->inc); m4ri_mm_free(m4ri_codebook[i]->ord); m4ri_mm_free(m4ri_codebook[i]); } m4ri_mm_free(m4ri_codebook); m4ri_codebook = NULL; } int m4ri_opt_k(int a, int b, int c) { int n = MIN(a, b); int res = MIN(__M4RI_MAXKAY, MAX(1, (int)(0.75 * (1 + log2_floor(n)))) ); return res; } m4ri-20140914/m4ri/strassen.c0000644000175000017500000005765612354166226012467 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Martin Albrecht * Copyright (C) 2008 Clement Pernet * Copyright (C) 2008 Marco Bodrato * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "graycode.h" #include "strassen.h" #include "parity.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif #if __M4RI_HAVE_OPENMP #include #endif // Returns true if a is closer to cutoff than a/2. static inline int closer(rci_t a, int cutoff) { return 3 * a < 4 * cutoff; } mzd_t *_mzd_mul_even(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { rci_t mmm, kkk, nnn; if(C->nrows == 0 || C->ncols == 0) return C; rci_t m = A->nrows; rci_t k = A->ncols; rci_t n = B->ncols; /* handle case first, where the input matrices are too small already */ if (closer(m, cutoff) || closer(k, cutoff) || closer(n, cutoff)) { /* we copy the matrices first since it is only constant memory overhead and improves data locality */ if(mzd_is_windowed(A)|mzd_is_windowed(B)|mzd_is_windowed(C)) { mzd_t *Abar = mzd_copy(NULL, A); mzd_t *Bbar = mzd_copy(NULL, B); mzd_t *Cbar = mzd_init(m, n); _mzd_mul_m4rm(Cbar, Abar, Bbar, 0, FALSE); mzd_copy(C, Cbar); mzd_free(Cbar); mzd_free(Bbar); mzd_free(Abar); } else { _mzd_mul_m4rm(C, A, B, 0, TRUE); } return C; } /* adjust cutting numbers to work on words */ rci_t mult = m4ri_radix; rci_t width = MIN(MIN(m, n), k) / 2; while (width > cutoff) { width /= 2; mult *= 2; } mmm = (((m - m % mult) / m4ri_radix) >> 1) * m4ri_radix; kkk = (((k - k % mult) / m4ri_radix) >> 1) * m4ri_radix; nnn = (((n - n % mult) / m4ri_radix) >> 1) * m4ri_radix; /* |A | |B | |C | * Compute | | x | | = | | */ { mzd_t const *A11 = mzd_init_window_const(A, 0, 0, mmm, kkk); mzd_t const *A12 = mzd_init_window_const(A, 0, kkk, mmm, 2*kkk); mzd_t const *A21 = mzd_init_window_const(A, mmm, 0, 2*mmm, kkk); mzd_t const *A22 = mzd_init_window_const(A, mmm, kkk, 2*mmm, 2*kkk); mzd_t const *B11 = mzd_init_window_const(B, 0, 0, kkk, nnn); mzd_t const *B12 = mzd_init_window_const(B, 0, nnn, kkk, 2*nnn); mzd_t const *B21 = mzd_init_window_const(B, kkk, 0, 2*kkk, nnn); mzd_t const *B22 = mzd_init_window_const(B, kkk, nnn, 2*kkk, 2*nnn); mzd_t *C11 = mzd_init_window(C, 0, 0, mmm, nnn); mzd_t *C12 = mzd_init_window(C, 0, nnn, mmm, 2*nnn); mzd_t *C21 = mzd_init_window(C, mmm, 0, 2*mmm, nnn); mzd_t *C22 = mzd_init_window(C, mmm, nnn, 2*mmm, 2*nnn); /** * \note See Marco Bodrato; "A Strassen-like Matrix Multiplication * Suited for Squaring and Highest Power Computation"; * http://bodrato.it/papres/#CIVV2008 for reference on the used * sequence of operations. */ /* change this to mzd_init(mmm, MAX(nnn,kkk)) to fix the todo below */ mzd_t *Wmk = mzd_init(mmm, kkk); mzd_t *Wkn = mzd_init(kkk, nnn); _mzd_add(Wkn, B22, B12); /* Wkn = B22 + B12 */ _mzd_add(Wmk, A22, A12); /* Wmk = A22 + A12 */ _mzd_mul_even(C21, Wmk, Wkn, cutoff);/* C21 = Wmk * Wkn */ _mzd_add(Wmk, A22, A21); /* Wmk = A22 - A21 */ _mzd_add(Wkn, B22, B21); /* Wkn = B22 - B21 */ _mzd_mul_even(C22, Wmk, Wkn, cutoff);/* C22 = Wmk * Wkn */ _mzd_add(Wkn, Wkn, B12); /* Wkn = Wkn + B12 */ _mzd_add(Wmk, Wmk, A12); /* Wmk = Wmk + A12 */ _mzd_mul_even(C11, Wmk, Wkn, cutoff);/* C11 = Wmk * Wkn */ _mzd_add(Wmk, Wmk, A11); /* Wmk = Wmk - A11 */ _mzd_mul_even(C12, Wmk, B12, cutoff);/* C12 = Wmk * B12 */ _mzd_add(C12, C12, C22); /* C12 = C12 + C22 */ /** * \todo ideally we would use the same Wmk throughout the function * but some called function doesn't like that and we end up with a * wrong result if we use virtual Wmk matrices. Ideally, this should * be fixed not worked around. The check whether the bug has been * fixed, use only one Wmk and check if mzd_mul(4096, 3528, * 4096, 2124) still returns the correct answer. */ mzd_free(Wmk); Wmk = mzd_mul(NULL, A12, B21, cutoff);/*Wmk = A12 * B21 */ _mzd_add(C11, C11, Wmk); /* C11 = C11 + Wmk */ _mzd_add(C12, C11, C12); /* C12 = C11 - C12 */ _mzd_add(C11, C21, C11); /* C11 = C21 - C11 */ _mzd_add(Wkn, Wkn, B11); /* Wkn = Wkn - B11 */ _mzd_mul_even(C21, A21, Wkn, cutoff); /* C21 = A21 * Wkn */ mzd_free(Wkn); _mzd_add(C21, C11, C21); /* C21 = C11 - C21 */ _mzd_add(C22, C22, C11); /* C22 = C22 + C11 */ _mzd_mul_even(C11, A11, B11, cutoff); /* C11 = A11 * B11 */ _mzd_add(C11, C11, Wmk); /* C11 = C11 + Wmk */ /* clean up */ mzd_free_window((mzd_t*)A11); mzd_free_window((mzd_t*)A12); mzd_free_window((mzd_t*)A21); mzd_free_window((mzd_t*)A22); mzd_free_window((mzd_t*)B11); mzd_free_window((mzd_t*)B12); mzd_free_window((mzd_t*)B21); mzd_free_window((mzd_t*)B22); mzd_free_window(C11); mzd_free_window(C12); mzd_free_window(C21); mzd_free_window(C22); mzd_free(Wmk); } /* deal with rest */ nnn *= 2; if (n > nnn) { /* |AA| | B| | C| * Compute |AA| x | B| = | C| */ mzd_t const *B_last_col = mzd_init_window_const(B, 0, nnn, k, n); mzd_t *C_last_col = mzd_init_window(C, 0, nnn, m, n); _mzd_mul_m4rm(C_last_col, A, B_last_col, 0, TRUE); mzd_free_window((mzd_t*)B_last_col); mzd_free_window(C_last_col); } mmm *= 2; if (m > mmm) { /* | | |B | | | * Compute |AA| x |B | = |C | */ mzd_t const *A_last_row = mzd_init_window_const(A, mmm, 0, m, k); mzd_t const *B_first_col= mzd_init_window_const(B, 0, 0, k, nnn); mzd_t *C_last_row = mzd_init_window(C, mmm, 0, m, nnn); _mzd_mul_m4rm(C_last_row, A_last_row, B_first_col, 0, TRUE); mzd_free_window((mzd_t*)A_last_row); mzd_free_window((mzd_t*)B_first_col); mzd_free_window(C_last_row); } kkk *= 2; if (k > kkk) { /* Add to | | | B| |C | * result |A | x | | = | | */ mzd_t const *A_last_col = mzd_init_window_const(A, 0, kkk, mmm, k); mzd_t const *B_last_row = mzd_init_window_const(B, kkk, 0, k, nnn); mzd_t *C_bulk = mzd_init_window(C, 0, 0, mmm, nnn); mzd_addmul_m4rm(C_bulk, A_last_col, B_last_row, 0); mzd_free_window((mzd_t*)A_last_col); mzd_free_window((mzd_t*)B_last_row); mzd_free_window(C_bulk); } __M4RI_DD_MZD(C); return C; } mzd_t *_mzd_sqr_even(mzd_t *C, mzd_t const *A, int cutoff) { rci_t m; m = A->nrows; /* handle case first, where the input matrices are too small already */ if (closer(m, cutoff)) { /* we copy the matrices first since it is only constant memory overhead and improves data locality */ if(mzd_is_windowed(A)|mzd_is_windowed(C)) { mzd_t *Abar = mzd_copy(NULL, A); mzd_t *Cbar = mzd_init(m, m); _mzd_mul_m4rm(Cbar, Abar, Abar, 0, FALSE); mzd_copy(C, Cbar); mzd_free(Cbar); mzd_free(Abar); } else { _mzd_mul_m4rm(C, A, A, 0, TRUE); } return C; } /* adjust cutting numbers to work on words */ rci_t mmm; { rci_t mult = m4ri_radix; rci_t width = m / 2; while (width > cutoff) { width /= 2; mult *= 2; } mmm = (((m - m % mult) / m4ri_radix) >> 1) * m4ri_radix; } /* |A | |A | |C | * Compute | | x | | = | | */ { mzd_t const *A11 = mzd_init_window_const(A, 0, 0, mmm, mmm); mzd_t const *A12 = mzd_init_window_const(A, 0, mmm, mmm, 2*mmm); mzd_t const *A21 = mzd_init_window_const(A, mmm, 0, 2*mmm, mmm); mzd_t const *A22 = mzd_init_window_const(A, mmm, mmm, 2*mmm, 2*mmm); mzd_t *C11 = mzd_init_window(C, 0, 0, mmm, mmm); mzd_t *C12 = mzd_init_window(C, 0, mmm, mmm, 2*mmm); mzd_t *C21 = mzd_init_window(C, mmm, 0, 2*mmm, mmm); mzd_t *C22 = mzd_init_window(C, mmm, mmm, 2*mmm, 2*mmm); /** * \note See Marco Bodrato; "A Strassen-like Matrix Multiplication * Suited for Squaring and Highest Power Computation"; * http://bodrato.it/papres/#CIVV2008 for reference on the used * sequence of operations. */ mzd_t *Wmk; mzd_t *Wkn = mzd_init(mmm, mmm); _mzd_add(Wkn, A22, A12); /* Wkn = A22 + A12 */ _mzd_sqr_even(C21, Wkn, cutoff); /* C21 = Wkn^2 */ _mzd_add(Wkn, A22, A21); /* Wkn = A22 - A21 */ _mzd_sqr_even(C22, Wkn, cutoff); /* C22 = Wkn^2 */ _mzd_add(Wkn, Wkn, A12); /* Wkn = Wkn + A12 */ _mzd_sqr_even(C11, Wkn, cutoff); /* C11 = Wkn^2 */ _mzd_add(Wkn, Wkn, A11); /* Wkn = Wkn - A11 */ _mzd_mul_even(C12, Wkn, A12, cutoff);/* C12 = Wkn * A12 */ _mzd_add(C12, C12, C22); /* C12 = C12 + C22 */ Wmk = mzd_mul(NULL, A12, A21, cutoff);/*Wmk = A12 * A21 */ _mzd_add(C11, C11, Wmk); /* C11 = C11 + Wmk */ _mzd_add(C12, C11, C12); /* C12 = C11 - C12 */ _mzd_add(C11, C21, C11); /* C11 = C21 - C11 */ _mzd_mul_even(C21, A21, Wkn, cutoff);/* C21 = A21 * Wkn */ mzd_free(Wkn); _mzd_add(C21, C11, C21); /* C21 = C11 - C21 */ _mzd_add(C22, C22, C11); /* C22 = C22 + C11 */ _mzd_sqr_even(C11, A11, cutoff); /* C11 = A11^2 */ _mzd_add(C11, C11, Wmk); /* C11 = C11 + Wmk */ /* clean up */ mzd_free_window((mzd_t*)A11); mzd_free_window((mzd_t*)A12); mzd_free_window((mzd_t*)A21); mzd_free_window((mzd_t*)A22); mzd_free_window(C11); mzd_free_window(C12); mzd_free_window(C21); mzd_free_window(C22); mzd_free(Wmk); } /* deal with rest */ mmm *= 2; if (m > mmm) { /* |AA| | A| | C| * Compute |AA| x | A| = | C| */ { mzd_t const *A_last_col = mzd_init_window_const(A, 0, mmm, m, m); mzd_t *C_last_col = mzd_init_window(C, 0, mmm, m, m); _mzd_mul_m4rm(C_last_col, A, A_last_col, 0, TRUE); mzd_free_window((mzd_t*)A_last_col); mzd_free_window(C_last_col); } /* | | |A | | | * Compute |AA| x |A | = |C | */ { mzd_t const *A_last_row = mzd_init_window_const(A, mmm, 0, m, m); mzd_t const *A_first_col= mzd_init_window_const(A, 0, 0, m, mmm); mzd_t *C_last_row = mzd_init_window(C, mmm, 0, m, mmm); _mzd_mul_m4rm(C_last_row, A_last_row, A_first_col, 0, TRUE); mzd_free_window((mzd_t*)A_last_row); mzd_free_window((mzd_t*)A_first_col); mzd_free_window(C_last_row); } /* Add to | | | A| |C | * result |A | x | | = | | */ { mzd_t const *A_last_col = mzd_init_window_const(A, 0, mmm, mmm, m); mzd_t const *A_last_row = mzd_init_window_const(A, mmm, 0, m, mmm); mzd_t *C_bulk = mzd_init_window(C, 0, 0, mmm, mmm); mzd_addmul_m4rm(C_bulk, A_last_col, A_last_row, 0); mzd_free_window((mzd_t*)A_last_col); mzd_free_window((mzd_t*)A_last_row); mzd_free_window(C_bulk); } } __M4RI_DD_MZD(C); return C; } mzd_t *mzd_mul(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { if(A->ncols != B->nrows) m4ri_die("mzd_mul: A ncols (%d) need to match B nrows (%d).\n", A->ncols, B->nrows); if (cutoff < 0) m4ri_die("mzd_mul: cutoff must be >= 0.\n"); if(cutoff == 0) { cutoff = __M4RI_STRASSEN_MUL_CUTOFF; } cutoff = cutoff / m4ri_radix * m4ri_radix; if (cutoff < m4ri_radix) { cutoff = m4ri_radix; }; if (C == NULL) { C = mzd_init(A->nrows, B->ncols); } else if (C->nrows != A->nrows || C->ncols != B->ncols){ m4ri_die("mzd_mul: C (%d x %d) has wrong dimensions, expected (%d x %d)\n", C->nrows, C->ncols, A->nrows, B->ncols); } C = (A == B) ? _mzd_sqr_even(C, A, cutoff) : _mzd_mul_even(C, A, B, cutoff); return C; } mzd_t *_mzd_addmul_even(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { /** * \todo make sure not to overwrite crap after ncols and before width * m4ri_radix */ if(C->nrows == 0 || C->ncols == 0) return C; rci_t m = A->nrows; rci_t k = A->ncols; rci_t n = B->ncols; /* handle case first, where the input matrices are too small already */ if (closer(m, cutoff) || closer(k, cutoff) || closer(n, cutoff)) { /* we copy the matrices first since it is only constant memory overhead and improves data locality */ if(mzd_is_windowed(A)|mzd_is_windowed(B)|mzd_is_windowed(C)) { mzd_t *Abar = mzd_copy(NULL, A); mzd_t *Bbar = mzd_copy(NULL, B); mzd_t *Cbar = mzd_copy(NULL, C); mzd_addmul_m4rm(Cbar, Abar, Bbar, 0); mzd_copy(C, Cbar); mzd_free(Cbar); mzd_free(Bbar); mzd_free(Abar); } else { mzd_addmul_m4rm(C, A, B, 0); } return C; } /* adjust cutting numbers to work on words */ rci_t mmm, kkk, nnn; { rci_t mult = m4ri_radix; rci_t width = MIN(MIN(m, n), k) / 2; while (width > cutoff) { width /= 2; mult *= 2; } mmm = (((m - m % mult) / m4ri_radix) >> 1) * m4ri_radix; kkk = (((k - k % mult) / m4ri_radix) >> 1) * m4ri_radix; nnn = (((n - n % mult) / m4ri_radix) >> 1) * m4ri_radix; } /* |C | |A | |B | * Compute | | += | | x | | */ { mzd_t const *A11 = mzd_init_window_const(A, 0, 0, mmm, kkk); mzd_t const *A12 = mzd_init_window_const(A, 0, kkk, mmm, 2*kkk); mzd_t const *A21 = mzd_init_window_const(A, mmm, 0, 2*mmm, kkk); mzd_t const *A22 = mzd_init_window_const(A, mmm, kkk, 2*mmm, 2*kkk); mzd_t const *B11 = mzd_init_window_const(B, 0, 0, kkk, nnn); mzd_t const *B12 = mzd_init_window_const(B, 0, nnn, kkk, 2*nnn); mzd_t const *B21 = mzd_init_window_const(B, kkk, 0, 2*kkk, nnn); mzd_t const *B22 = mzd_init_window_const(B, kkk, nnn, 2*kkk, 2*nnn); mzd_t *C11 = mzd_init_window(C, 0, 0, mmm, nnn); mzd_t *C12 = mzd_init_window(C, 0, nnn, mmm, 2*nnn); mzd_t *C21 = mzd_init_window(C, mmm, 0, 2*mmm, nnn); mzd_t *C22 = mzd_init_window(C, mmm, nnn, 2*mmm, 2*nnn); /** * \note See Marco Bodrato; "A Strassen-like Matrix Multiplication * Suited for Squaring and Highest Power Computation"; * http://bodrato.it/papres/#CIVV2008 for reference on the used * sequence of operations. */ mzd_t *S = mzd_init(mmm, kkk); mzd_t *T = mzd_init(kkk, nnn); mzd_t *U = mzd_init(mmm, nnn); _mzd_add(S, A22, A21); /* 1 S = A22 - A21 */ _mzd_add(T, B22, B21); /* 2 T = B22 - B21 */ _mzd_mul_even(U, S, T, cutoff); /* 3 U = S*T */ _mzd_add(C22, U, C22); /* 4 C22 = U + C22 */ _mzd_add(C12, U, C12); /* 5 C12 = U + C12 */ _mzd_mul_even(U, A12, B21, cutoff); /* 8 U = A12*B21 */ _mzd_add(C11, U, C11); /* 9 C11 = U + C11 */ _mzd_addmul_even(C11, A11, B11, cutoff); /* 11 C11 = A11*B11 + C11 */ _mzd_add(S, S, A12); /* 6 S = S - A12 */ _mzd_add(T, T, B12); /* 7 T = T - B12 */ _mzd_addmul_even(U, S, T, cutoff); /* 10 U = S*T + U */ _mzd_add(C12, C12, U); /* 15 C12 = U + C12 */ _mzd_add(S, A11, S); /* 12 S = A11 - S */ _mzd_addmul_even(C12, S, B12, cutoff); /* 14 C12 = S*B12 + C12 */ _mzd_add(T, B11, T); /* 13 T = B11 - T */ _mzd_addmul_even(C21, A21, T, cutoff); /* 16 C21 = A21*T + C21 */ _mzd_add(S, A22, A12); /* 17 S = A22 + A21 */ _mzd_add(T, B22, B12); /* 18 T = B22 + B21 */ _mzd_addmul_even(U, S, T, cutoff); /* 19 U = U - S*T */ _mzd_add(C21, C21, U); /* 20 C21 = C21 - U */ _mzd_add(C22, C22, U); /* 21 C22 = C22 - U */ /* clean up */ mzd_free_window((mzd_t*)A11); mzd_free_window((mzd_t*)A12); mzd_free_window((mzd_t*)A21); mzd_free_window((mzd_t*)A22); mzd_free_window((mzd_t*)B11); mzd_free_window((mzd_t*)B12); mzd_free_window((mzd_t*)B21); mzd_free_window((mzd_t*)B22); mzd_free_window(C11); mzd_free_window(C12); mzd_free_window(C21); mzd_free_window(C22); mzd_free(S); mzd_free(T); mzd_free(U); } /* deal with rest */ nnn *= 2; if (n > nnn) { /* | C| |AA| | B| * Compute | C| += |AA| x | B| */ mzd_t const *B_last_col = mzd_init_window_const(B, 0, nnn, k, n); mzd_t *C_last_col = mzd_init_window(C, 0, nnn, m, n); mzd_addmul_m4rm(C_last_col, A, B_last_col, 0); mzd_free_window((mzd_t*)B_last_col); mzd_free_window(C_last_col); } mmm *= 2; if (m > mmm) { /* | | | | |B | * Compute |C | += |AA| x |B | */ mzd_t const *A_last_row = mzd_init_window_const(A, mmm, 0, m, k); mzd_t const *B_first_col= mzd_init_window_const(B, 0, 0, k, nnn); mzd_t *C_last_row = mzd_init_window(C, mmm, 0, m, nnn); mzd_addmul_m4rm(C_last_row, A_last_row, B_first_col, 0); mzd_free_window((mzd_t*)A_last_row); mzd_free_window((mzd_t*)B_first_col); mzd_free_window(C_last_row); } kkk *= 2; if (k > kkk) { /* Add to | | | B| |C | * result |A | x | | = | | */ mzd_t const *A_last_col = mzd_init_window_const(A, 0, kkk, mmm, k); mzd_t const *B_last_row = mzd_init_window_const(B, kkk, 0, k, nnn); mzd_t *C_bulk = mzd_init_window(C, 0, 0, mmm, nnn); mzd_addmul_m4rm(C_bulk, A_last_col, B_last_row, 0); mzd_free_window((mzd_t*)A_last_col); mzd_free_window((mzd_t*)B_last_row); mzd_free_window(C_bulk); } __M4RI_DD_MZD(C); return C; } mzd_t *_mzd_addsqr_even(mzd_t *C, mzd_t const *A, int cutoff) { /** * \todo make sure not to overwrite crap after ncols and before width * m4ri_radix */ if(C->nrows == 0) return C; rci_t m = A->nrows; /* handle case first, where the input matrices are too small already */ if (closer(m, cutoff)) { /* we copy the matrices first since it is only constant memory overhead and improves data locality */ if(mzd_is_windowed(A)|mzd_is_windowed(C)) { mzd_t *Cbar = mzd_copy(NULL, C); mzd_t *Abar = mzd_copy(NULL, A); mzd_addmul_m4rm(Cbar, Abar, Abar, 0); mzd_copy(C, Cbar); mzd_free(Cbar); mzd_free(Abar); } else { mzd_addmul_m4rm(C, A, A, 0); } return C; } /* adjust cutting numbers to work on words */ rci_t mmm; { rci_t mult = m4ri_radix; rci_t width = m / 2; while (width > cutoff) { width /= 2; mult *= 2; } mmm = (((m - m % mult) / m4ri_radix) >> 1) * m4ri_radix; } /* |C | |A | |B | * Compute | | += | | x | | */ { mzd_t const *A11 = mzd_init_window_const(A, 0, 0, mmm, mmm); mzd_t const *A12 = mzd_init_window_const(A, 0, mmm, mmm, 2*mmm); mzd_t const *A21 = mzd_init_window_const(A, mmm, 0, 2*mmm, mmm); mzd_t const *A22 = mzd_init_window_const(A, mmm, mmm, 2*mmm, 2*mmm); mzd_t *C11 = mzd_init_window(C, 0, 0, mmm, mmm); mzd_t *C12 = mzd_init_window(C, 0, mmm, mmm, 2*mmm); mzd_t *C21 = mzd_init_window(C, mmm, 0, 2*mmm, mmm); mzd_t *C22 = mzd_init_window(C, mmm, mmm, 2*mmm, 2*mmm); /** * \note See Marco Bodrato; "A Strassen-like Matrix Multiplication * Suited for Squaring and Highest Power Computation"; on-line v. * http://bodrato.it/papres/#CIVV2008 for reference on the used * sequence of operations. */ mzd_t *S = mzd_init(mmm, mmm); mzd_t *U = mzd_init(mmm, mmm); _mzd_add(S, A22, A21); /* 1 S = A22 - A21 */ _mzd_sqr_even(U, S, cutoff); /* 3 U = S^2 */ _mzd_add(C22, U, C22); /* 4 C22 = U + C22 */ _mzd_add(C12, U, C12); /* 5 C12 = U + C12 */ _mzd_mul_even(U, A12, A21, cutoff); /* 8 U = A12*A21 */ _mzd_add(C11, U, C11); /* 9 C11 = U + C11 */ _mzd_addsqr_even(C11, A11, cutoff); /* 11 C11 = A11^2 + C11 */ _mzd_add(S, S, A12); /* 6 S = S + A12 */ _mzd_addsqr_even(U, S, cutoff); /* 10 U = S^2 + U */ _mzd_add(C12, C12, U); /* 15 C12 = U + C12 */ _mzd_add(S, A11, S); /* 12 S = A11 - S */ _mzd_addmul_even(C12, S, A12, cutoff); /* 14 C12 = S*B12 + C12 */ _mzd_addmul_even(C21, A21, S, cutoff); /* 16 C21 = A21*T + C21 */ _mzd_add(S, A22, A12); /* 17 S = A22 + A21 */ _mzd_addsqr_even(U, S, cutoff); /* 19 U = U - S^2 */ _mzd_add(C21, C21, U); /* 20 C21 = C21 - U3 */ _mzd_add(C22, C22, U); /* 21 C22 = C22 - U3 */ /* clean up */ mzd_free_window((mzd_t*)A11); mzd_free_window((mzd_t*)A12); mzd_free_window((mzd_t*)A21); mzd_free_window((mzd_t*)A22); mzd_free_window(C11); mzd_free_window(C12); mzd_free_window(C21); mzd_free_window(C22); mzd_free(S); mzd_free(U); } /* deal with rest */ mmm *= 2; if (m > mmm) { /* | C| |AA| | B| * Compute | C| += |AA| x | B| */ { mzd_t const *A_last_col = mzd_init_window_const(A, 0, mmm, m, m); mzd_t *C_last_col = mzd_init_window(C, 0, mmm, m, m); mzd_addmul_m4rm(C_last_col, A, A_last_col, 0); mzd_free_window((mzd_t*)A_last_col); mzd_free_window(C_last_col); } /* | | | | |B | * Compute |C | += |AA| x |B | */ { mzd_t const *A_last_row = mzd_init_window_const(A, mmm, 0, m, m); mzd_t const *A_first_col= mzd_init_window_const(A, 0, 0, m, mmm); mzd_t *C_last_row = mzd_init_window(C, mmm, 0, m, mmm); mzd_addmul_m4rm(C_last_row, A_last_row, A_first_col, 0); mzd_free_window((mzd_t*)A_last_row); mzd_free_window((mzd_t*)A_first_col); mzd_free_window(C_last_row); } /* Add to | | | B| |C | * result |A | x | | = | | */ { mzd_t const *A_last_col = mzd_init_window_const(A, 0, mmm, mmm, m); mzd_t const *A_last_row = mzd_init_window_const(A, mmm, 0, m, mmm); mzd_t *C_bulk = mzd_init_window(C, 0, 0, mmm, mmm); mzd_addmul_m4rm(C_bulk, A_last_col, A_last_row, 0); mzd_free_window((mzd_t*)A_last_col); mzd_free_window((mzd_t*)A_last_row); mzd_free_window(C_bulk); } } __M4RI_DD_MZD(C); return C; } mzd_t *_mzd_addmul(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { /** * Assumes that B and C are aligned in the same manner (as in a Schur complement) */ return (A == B) ? _mzd_addsqr_even(C, A, cutoff) : _mzd_addmul_even(C, A, B, cutoff); } mzd_t *mzd_addmul(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { if(A->ncols != B->nrows) m4ri_die("mzd_addmul: A ncols (%d) need to match B nrows (%d).\n", A->ncols, B->nrows); if (cutoff < 0) m4ri_die("mzd_addmul: cutoff must be >= 0.\n"); if(cutoff == 0) { cutoff = __M4RI_STRASSEN_MUL_CUTOFF; } cutoff = cutoff / m4ri_radix * m4ri_radix; if (cutoff < m4ri_radix) { cutoff = m4ri_radix; }; if (C == NULL) { C = mzd_init(A->nrows, B->ncols); } else if (C->nrows != A->nrows || C->ncols != B->ncols){ m4ri_die("mzd_addmul: C (%d x %d) has wrong dimensions, expected (%d x %d)\n", C->nrows, C->ncols, A->nrows, B->ncols); } if(A->nrows == 0 || A->ncols == 0 || B->ncols == 0) { __M4RI_DD_MZD(C); return C; } C = _mzd_addmul(C, A, B, cutoff); __M4RI_DD_MZD(C); return C; } m4ri-20140914/m4ri/mzp.c0000644000175000017500000003746312354166226011425 00000000000000/****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mzp.h" #include "mzd.h" mzp_t *mzp_init(rci_t length) { mzp_t *P = (mzp_t*)m4ri_mm_malloc(sizeof(mzp_t)); P->values = (rci_t*)m4ri_mm_malloc(sizeof(rci_t) * length); P->length = length; for (rci_t i = 0; i < length; ++i) { P->values[i] = i; } return P; } void mzp_free(mzp_t *P) { m4ri_mm_free(P->values); m4ri_mm_free(P); } mzp_t *mzp_init_window(mzp_t *P, rci_t begin, rci_t end){ mzp_t *window = (mzp_t *)m4ri_mm_malloc(sizeof(mzp_t)); window->values = P->values + begin; window->length = end - begin; __M4RI_DD_MZP(window); return window; } void mzp_free_window(mzp_t *condemned){ m4ri_mm_free(condemned); } mzp_t *mzp_copy(mzp_t *P, const mzp_t *Q) { if(P == NULL) P = mzp_init(Q->length); for(rci_t i=0; ilength; i++) P->values[i] = Q->values[i]; return P; } void mzp_set_ui(mzp_t *P, unsigned int value) { assert(value == 1); for (rci_t i = 0; i < P->length; ++i) { P->values[i] = i; } } void mzd_apply_p_left(mzd_t *A, mzp_t const *P) { if(A->ncols == 0) return; rci_t const length = MIN(P->length, A->nrows); for (rci_t i = 0; i < length; ++i) { assert(P->values[i] >= i); mzd_row_swap(A, i, P->values[i]); } } void mzd_apply_p_left_trans(mzd_t *A, mzp_t const *P) { if(A->ncols == 0) return; rci_t const length = MIN(P->length, A->nrows); for (rci_t i = length - 1; i >= 0; --i) { assert(P->values[i] >= i); mzd_row_swap(A, i, P->values[i]); } } /* optimised column swap operations */ static inline void mzd_write_col_to_rows_blockd(mzd_t *A, mzd_t const *B, rci_t const *permutation, word const *write_mask, rci_t const start_row, rci_t const stop_row, rci_t length) { for(rci_t i = 0; i < length; i += m4ri_radix) { /* optimisation for identity permutations */ if (write_mask[i / m4ri_radix] == m4ri_ffff) continue; int const todo = MIN(m4ri_radix, length - i); wi_t const a_word = i / m4ri_radix; wi_t words[m4ri_radix]; int bits[m4ri_radix]; word bitmasks[m4ri_radix]; /* we pre-compute bit access in advance */ for(int k = 0; k < todo; ++k) { rci_t const colb = permutation[i + k]; words[k] = colb / m4ri_radix; bits[k] = colb % m4ri_radix; bitmasks[k] = m4ri_one << bits[k]; } for (rci_t r = start_row; r < stop_row; ++r) { word const *Brow = B->rows[r-start_row]; word *Arow = A->rows[r]; register word value = 0; /* we gather the bits in a register word */ switch(todo-1) { case 63: value |= ((Brow[words[63]] & bitmasks[63]) >> bits[63]) << 63; case 62: value |= ((Brow[words[62]] & bitmasks[62]) >> bits[62]) << 62; case 61: value |= ((Brow[words[61]] & bitmasks[61]) >> bits[61]) << 61; case 60: value |= ((Brow[words[60]] & bitmasks[60]) >> bits[60]) << 60; case 59: value |= ((Brow[words[59]] & bitmasks[59]) >> bits[59]) << 59; case 58: value |= ((Brow[words[58]] & bitmasks[58]) >> bits[58]) << 58; case 57: value |= ((Brow[words[57]] & bitmasks[57]) >> bits[57]) << 57; case 56: value |= ((Brow[words[56]] & bitmasks[56]) >> bits[56]) << 56; case 55: value |= ((Brow[words[55]] & bitmasks[55]) >> bits[55]) << 55; case 54: value |= ((Brow[words[54]] & bitmasks[54]) >> bits[54]) << 54; case 53: value |= ((Brow[words[53]] & bitmasks[53]) >> bits[53]) << 53; case 52: value |= ((Brow[words[52]] & bitmasks[52]) >> bits[52]) << 52; case 51: value |= ((Brow[words[51]] & bitmasks[51]) >> bits[51]) << 51; case 50: value |= ((Brow[words[50]] & bitmasks[50]) >> bits[50]) << 50; case 49: value |= ((Brow[words[49]] & bitmasks[49]) >> bits[49]) << 49; case 48: value |= ((Brow[words[48]] & bitmasks[48]) >> bits[48]) << 48; case 47: value |= ((Brow[words[47]] & bitmasks[47]) >> bits[47]) << 47; case 46: value |= ((Brow[words[46]] & bitmasks[46]) >> bits[46]) << 46; case 45: value |= ((Brow[words[45]] & bitmasks[45]) >> bits[45]) << 45; case 44: value |= ((Brow[words[44]] & bitmasks[44]) >> bits[44]) << 44; case 43: value |= ((Brow[words[43]] & bitmasks[43]) >> bits[43]) << 43; case 42: value |= ((Brow[words[42]] & bitmasks[42]) >> bits[42]) << 42; case 41: value |= ((Brow[words[41]] & bitmasks[41]) >> bits[41]) << 41; case 40: value |= ((Brow[words[40]] & bitmasks[40]) >> bits[40]) << 40; case 39: value |= ((Brow[words[39]] & bitmasks[39]) >> bits[39]) << 39; case 38: value |= ((Brow[words[38]] & bitmasks[38]) >> bits[38]) << 38; case 37: value |= ((Brow[words[37]] & bitmasks[37]) >> bits[37]) << 37; case 36: value |= ((Brow[words[36]] & bitmasks[36]) >> bits[36]) << 36; case 35: value |= ((Brow[words[35]] & bitmasks[35]) >> bits[35]) << 35; case 34: value |= ((Brow[words[34]] & bitmasks[34]) >> bits[34]) << 34; case 33: value |= ((Brow[words[33]] & bitmasks[33]) >> bits[33]) << 33; case 32: value |= ((Brow[words[32]] & bitmasks[32]) >> bits[32]) << 32; case 31: value |= ((Brow[words[31]] & bitmasks[31]) >> bits[31]) << 31; case 30: value |= ((Brow[words[30]] & bitmasks[30]) >> bits[30]) << 30; case 29: value |= ((Brow[words[29]] & bitmasks[29]) >> bits[29]) << 29; case 28: value |= ((Brow[words[28]] & bitmasks[28]) >> bits[28]) << 28; case 27: value |= ((Brow[words[27]] & bitmasks[27]) >> bits[27]) << 27; case 26: value |= ((Brow[words[26]] & bitmasks[26]) >> bits[26]) << 26; case 25: value |= ((Brow[words[25]] & bitmasks[25]) >> bits[25]) << 25; case 24: value |= ((Brow[words[24]] & bitmasks[24]) >> bits[24]) << 24; case 23: value |= ((Brow[words[23]] & bitmasks[23]) >> bits[23]) << 23; case 22: value |= ((Brow[words[22]] & bitmasks[22]) >> bits[22]) << 22; case 21: value |= ((Brow[words[21]] & bitmasks[21]) >> bits[21]) << 21; case 20: value |= ((Brow[words[20]] & bitmasks[20]) >> bits[20]) << 20; case 19: value |= ((Brow[words[19]] & bitmasks[19]) >> bits[19]) << 19; case 18: value |= ((Brow[words[18]] & bitmasks[18]) >> bits[18]) << 18; case 17: value |= ((Brow[words[17]] & bitmasks[17]) >> bits[17]) << 17; case 16: value |= ((Brow[words[16]] & bitmasks[16]) >> bits[16]) << 16; case 15: value |= ((Brow[words[15]] & bitmasks[15]) >> bits[15]) << 15; case 14: value |= ((Brow[words[14]] & bitmasks[14]) >> bits[14]) << 14; case 13: value |= ((Brow[words[13]] & bitmasks[13]) >> bits[13]) << 13; case 12: value |= ((Brow[words[12]] & bitmasks[12]) >> bits[12]) << 12; case 11: value |= ((Brow[words[11]] & bitmasks[11]) >> bits[11]) << 11; case 10: value |= ((Brow[words[10]] & bitmasks[10]) >> bits[10]) << 10; case 9: value |= ((Brow[words[ 9]] & bitmasks[ 9]) >> bits[ 9]) << 9; case 8: value |= ((Brow[words[ 8]] & bitmasks[ 8]) >> bits[ 8]) << 8; case 7: value |= ((Brow[words[ 7]] & bitmasks[ 7]) >> bits[ 7]) << 7; case 6: value |= ((Brow[words[ 6]] & bitmasks[ 6]) >> bits[ 6]) << 6; case 5: value |= ((Brow[words[ 5]] & bitmasks[ 5]) >> bits[ 5]) << 5; case 4: value |= ((Brow[words[ 4]] & bitmasks[ 4]) >> bits[ 4]) << 4; case 3: value |= ((Brow[words[ 3]] & bitmasks[ 3]) >> bits[ 3]) << 3; case 2: value |= ((Brow[words[ 2]] & bitmasks[ 2]) >> bits[ 2]) << 2; case 1: value |= ((Brow[words[ 1]] & bitmasks[ 1]) >> bits[ 1]) << 1; case 0: value |= ((Brow[words[ 0]] & bitmasks[ 0]) >> bits[ 0]) << 0; default: break; } /* for(int k = 0; k < todo; ++k) { */ /* value |= ((Brow[words[k]] & bitmasks[k]) << bits[k]) >> k; */ /* } */ /* and write the word once */ Arow[a_word] |= value; } } __M4RI_DD_MZD(A); } /** * Implements both apply_p_right and apply_p_right_trans. */ void _mzd_apply_p_right_even(mzd_t *A, mzp_t const *P, rci_t start_row, rci_t start_col, int notrans) { if(A->nrows - start_row == 0) return; rci_t const length = MIN(P->length, A->ncols); wi_t const width = A->width; int step_size = MIN(A->nrows - start_row, MAX((__M4RI_CPU_L1_CACHE >> 3) / A->width, 1)); /* our temporary where we store the columns we want to swap around */ mzd_t *B = mzd_init(step_size, A->ncols); word *Arow; word *Brow; /* setup mathematical permutation */ rci_t *permutation = (rci_t*)m4ri_mm_calloc(A->ncols, sizeof(rci_t)); for(rci_t i = 0; i < A->ncols; ++i) permutation[i] = i; if (!notrans) { for(rci_t i = start_col; i < length; ++i) { rci_t t = permutation[i]; permutation[i] = permutation[P->values[i]]; permutation[P->values[i]] = t; } } else { for(rci_t i = start_col; i < length; ++i) { rci_t t = permutation[length - i - 1]; permutation[length - i - 1] = permutation[P->values[length - i - 1]]; permutation[P->values[length - i - 1]] = t; } } /* we have a bitmask to encode where to write to */ word *write_mask = (word*)m4ri_mm_calloc(width, sizeof(word)); for(rci_t i = 0; i < A->ncols; i += m4ri_radix) { int const todo = MIN(m4ri_radix, A->ncols - i); for(int k = 0; k < todo; ++k) { if(permutation[i + k] == i + k) { write_mask[i / m4ri_radix] |= m4ri_one << k; } } } write_mask[width-1] |= ~A->high_bitmask; for(rci_t i = start_row; i < A->nrows; i += step_size) { step_size = MIN(step_size, A->nrows - i); for(int k = 0; k < step_size; ++k) { Arow = A->rows[i+k]; Brow = B->rows[k]; /*copy row & clear those values which will be overwritten */ for(wi_t j = 0; j < width; ++j) { Brow[j] = Arow[j]; Arow[j] = Arow[j] & write_mask[j]; } } /* here we actually write out the permutation */ mzd_write_col_to_rows_blockd(A, B, permutation, write_mask, i, i + step_size, length); } m4ri_mm_free(permutation); m4ri_mm_free(write_mask); mzd_free(B); __M4RI_DD_MZD(A); } void _mzd_apply_p_right_trans(mzd_t *A, mzp_t const *P) { if(A->nrows == 0) return; rci_t const length = MIN(P->length, A->ncols); int const step_size = MAX((__M4RI_CPU_L1_CACHE >> 3) / A->width, 1); for(rci_t j = 0; j < A->nrows; j += step_size) { rci_t stop_row = MIN(j + step_size, A->nrows); for (rci_t i = 0; i < length; ++i) { assert(P->values[i] >= i); mzd_col_swap_in_rows(A, i, P->values[i], j, stop_row); } } /* for (i=0; ilength; i++) { */ /* assert(P->values[i] >= i); */ /* mzd_col_swap(A, i, P->values[i]); */ /* } */ __M4RI_DD_MZD(A); } void _mzd_apply_p_right(mzd_t *A, mzp_t const *P) { if(A->nrows == 0) return; int const step_size = MAX((__M4RI_CPU_L1_CACHE >> 3) / A->width, 1); for(rci_t j = 0; j < A->nrows; j += step_size) { rci_t stop_row = MIN(j + step_size, A->nrows); for (rci_t i = P->length - 1; i >= 0; --i) { assert(P->values[i] >= i); mzd_col_swap_in_rows(A, i, P->values[i], j, stop_row); } } /* long i; */ /* for (i=P->length-1; i>=0; i--) { */ /* assert(P->values[i] >= i); */ /* mzd_col_swap(A, i, P->values[i]); */ /* } */ __M4RI_DD_MZD(A); } void mzd_apply_p_right_trans(mzd_t *A, mzp_t const *P) { if(!A->nrows) return; _mzd_apply_p_right_even(A, P, 0, 0, 0); } void mzd_apply_p_right(mzd_t *A, mzp_t const *P) { if(!A->nrows) return; _mzd_apply_p_right_even(A, P, 0, 0, 1); } void mzd_apply_p_right_trans_even_capped(mzd_t *A, mzp_t const *P, rci_t start_row, rci_t start_col) { if(!A->nrows) return; _mzd_apply_p_right_even(A, P, start_row, start_col, 0); } void mzd_apply_p_right_even_capped(mzd_t *A, mzp_t const *P, rci_t start_row, rci_t start_col) { if(!A->nrows) return; _mzd_apply_p_right_even(A, P, start_row, start_col, 1); } void mzp_print(mzp_t const *P) { printf("[ "); for(rci_t i = 0; i < P->length; ++i) { printf("%zd ", (size_t)P->values[i]); } printf("]"); } void mzd_apply_p_right_trans_tri(mzd_t *A, mzp_t const *P) { assert(P->length == A->ncols); int const step_size = MAX((__M4RI_CPU_L1_CACHE >> 2) / A->width, 1); for(rci_t r = 0; r < A->nrows; r += step_size) { rci_t const row_bound = MIN(r + step_size, A->nrows); for (rci_t i =0 ; i < A->ncols; ++i) { assert(P->values[i] >= i); mzd_col_swap_in_rows(A, i, P->values[i], r, MIN(row_bound, i)); } } __M4RI_DD_MZD(A); } void _mzd_compress_l(mzd_t *A, rci_t r1, rci_t n1, rci_t r2) { /** * We are compressing this matrix \verbatim r1 n1 ------------------------------------------ | \ \____|___ | A01 | | \ | \ | | r1------------------------------------------ | | | | \ \_____ | | L1| | | \ \________| | | | | L2| | ------------------------------------------ \endverbatim * * to this matrix * \verbatim r1 n1 ------------------------------------------ | \ \____|___ | A01 | | \ | \ | | r1------------------------------------------ | \ | | \_____ | | \ | | \________| | | | | | ------------------------------------------ \endverbatim */ if (r1 == n1) return; #if 0 mzp_t *shift = mzp_init(A->ncols); for (rci_t i=r1,j=n1;ivalues[i] = j; } mzd_apply_p_right_trans_even_capped(A, shift, r1+r2, 0); mzp_free(shift); #else for (rci_t i = r1, j = n1; i < r1 + r2; ++i, ++j){ mzd_col_swap_in_rows(A, i, j, i, r1 + r2); } word tmp; wi_t block; for(rci_t i = r1 + r2; i < A->nrows; ++i) { rci_t j = r1; /* first we deal with the rest of the current word we need to write */ int const rest = m4ri_radix - (j % m4ri_radix); tmp = mzd_read_bits(A, i, n1, rest); mzd_clear_bits(A, i, j, rest); mzd_xor_bits(A, i, j, rest, tmp); j += rest; /* now each write is simply a word write */ block = (n1 + j - r1) / m4ri_radix; if (rest % m4ri_radix == 0) { for( ; j + m4ri_radix <= r1 + r2; j += m4ri_radix, ++block) { tmp = A->rows[i][block]; A->rows[i][j / m4ri_radix] = tmp; } } else { for(; j + m4ri_radix <= r1 + r2; j += m4ri_radix, ++block) { tmp = (A->rows[i][block] >> rest) | ( A->rows[i][block + 1] << (m4ri_radix - rest)); A->rows[i][j / m4ri_radix] = tmp; } } /* we deal with the remaining bits. While we could write past the end of r1+r2 here, but we have no guarantee that we can read past the end of n1+r2. */ if (j < r1 + r2) { tmp = mzd_read_bits(A, i, n1 + j - r1, r1 + r2 - j); A->rows[i][j / m4ri_radix] = tmp; } /* now clear the rest of L2 */ j = r1 + r2; mzd_clear_bits(A, i, j, m4ri_radix - (j % m4ri_radix)); j += m4ri_radix - (j % m4ri_radix); /* it's okay to write the full word, i.e. past n1+r2, because everything is zero there anyway. Thus, we can omit the code which deals with last few bits. */ for(; j < n1 + r2; j += m4ri_radix) { A->rows[i][j / m4ri_radix] = 0; } } #endif __M4RI_DD_MZD(A); } m4ri-20140914/m4ri/triangular.c0000644000175000017500000005200112405060061012733 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Clement Pernet * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "triangular.h" #include "triangular_russian.h" #include "strassen.h" #include "mzd.h" #include "parity.h" /***************** * UPPER RIGHT ****************/ /* * Assumes that U->ncols < 64 */ void _mzd_trsm_upper_right_base(mzd_t const *U, mzd_t *B); void mzd_trsm_upper_right(mzd_t const *U, mzd_t *B, const int cutoff) { if(U->nrows != B->ncols) m4ri_die("mzd_trsm_upper_right: U nrows (%d) need to match B ncols (%d).\n", U->nrows, B->ncols); if(U->nrows != U->ncols) m4ri_die("mzd_trsm_upper_right: U must be square and is found to be (%d) x (%d).\n", U->nrows, U->ncols); _mzd_trsm_upper_right(U, B, cutoff); } void _mzd_trsm_upper_right_trtri(mzd_t const *U, mzd_t *B) { mzd_t *u = mzd_extract_u(NULL, U); mzd_trtri_upper(u); mzd_t *C = mzd_mul(NULL, B, u, 0); mzd_copy(B, C); mzd_free(C); mzd_free(u); } void _mzd_trsm_upper_right(mzd_t const *U, mzd_t *B, const int cutoff) { rci_t const mb = B->nrows; rci_t const nb = B->ncols; if(nb <= m4ri_radix) { /* base case */ _mzd_trsm_upper_right_base(U, B); return; } else if(nb <= __M4RI_MUL_BLOCKSIZE) { _mzd_trsm_upper_right_trtri(U, B); return; } rci_t const nb1 = (((nb - 1) / m4ri_radix + 1) >> 1) * m4ri_radix; /** \verbatim _________ \U00| | \ |U01| \ | | \|___| \U11| \ | \ | \| _______ |B0 |B1 | |___|___| \endverbatim */ mzd_t *B0 = mzd_init_window(B, 0, 0, mb, nb1); mzd_t *B1 = mzd_init_window(B, 0, nb1, mb, nb); mzd_t const *U00 = mzd_init_window_const(U, 0, 0, nb1, nb1); mzd_t const *U01 = mzd_init_window_const(U, 0, nb1, nb1, nb); mzd_t const *U11 = mzd_init_window_const(U, nb1, nb1, nb, nb); _mzd_trsm_upper_right(U00, B0, cutoff); mzd_addmul (B1, B0, U01, cutoff); _mzd_trsm_upper_right(U11, B1, cutoff); mzd_free_window(B0); mzd_free_window(B1); mzd_free_window((mzd_t*)U00); mzd_free_window((mzd_t*)U01); mzd_free_window((mzd_t*)U11); __M4RI_DD_MZD(B); } void _mzd_trsm_upper_right_base(mzd_t const *U, mzd_t *B) { rci_t const mb = B->nrows; rci_t const nb = B->ncols; for(rci_t i = 1; i < nb; ++i) { /* Computes X_i = B_i + X_{0..i-1} U_{0..i-1,i} */ register word ucol = 0; for(rci_t k = 0; k < i; ++k) { if(__M4RI_GET_BIT(U->rows[k][0], i)) __M4RI_SET_BIT(ucol, k); } /* doing 64 dotproducts at a time, to use the m4ri_parity64 parallelism */ rci_t giantstep; word tmp[64]; for(giantstep = 0; giantstep + m4ri_radix < mb; giantstep += m4ri_radix) { #if 0 for(int babystep = 0; babystep < m4ri_radix; ++babystep) tmp[babystep] = B->rows[giantstep + babystep][0] & ucol; #else word **src = B->rows + giantstep; tmp[ 0] = src[ 0][0] & ucol, tmp[ 1] = src[ 1][0] & ucol, tmp[ 2] = src[ 2][0] & ucol, tmp[ 3] = src[ 3][0] & ucol; tmp[ 4] = src[ 4][0] & ucol, tmp[ 5] = src[ 5][0] & ucol, tmp[ 6] = src[ 6][0] & ucol, tmp[ 7] = src[ 7][0] & ucol; tmp[ 8] = src[ 8][0] & ucol, tmp[ 9] = src[ 9][0] & ucol, tmp[10] = src[10][0] & ucol, tmp[11] = src[11][0] & ucol; tmp[12] = src[12][0] & ucol, tmp[13] = src[13][0] & ucol, tmp[14] = src[14][0] & ucol, tmp[15] = src[15][0] & ucol; tmp[16] = src[16][0] & ucol, tmp[17] = src[17][0] & ucol, tmp[18] = src[18][0] & ucol, tmp[19] = src[19][0] & ucol; tmp[20] = src[20][0] & ucol, tmp[21] = src[21][0] & ucol, tmp[22] = src[22][0] & ucol, tmp[23] = src[23][0] & ucol; tmp[24] = src[24][0] & ucol, tmp[25] = src[25][0] & ucol, tmp[26] = src[26][0] & ucol, tmp[27] = src[27][0] & ucol; tmp[28] = src[28][0] & ucol, tmp[29] = src[29][0] & ucol, tmp[30] = src[30][0] & ucol, tmp[31] = src[31][0] & ucol; tmp[32] = src[32][0] & ucol, tmp[33] = src[33][0] & ucol, tmp[34] = src[34][0] & ucol, tmp[35] = src[35][0] & ucol; tmp[36] = src[36][0] & ucol, tmp[37] = src[37][0] & ucol, tmp[38] = src[38][0] & ucol, tmp[39] = src[39][0] & ucol; tmp[40] = src[40][0] & ucol, tmp[41] = src[41][0] & ucol, tmp[42] = src[42][0] & ucol, tmp[43] = src[43][0] & ucol; tmp[44] = src[44][0] & ucol, tmp[45] = src[45][0] & ucol, tmp[46] = src[46][0] & ucol, tmp[47] = src[47][0] & ucol; tmp[48] = src[48][0] & ucol, tmp[49] = src[49][0] & ucol, tmp[50] = src[50][0] & ucol, tmp[51] = src[51][0] & ucol; tmp[52] = src[52][0] & ucol, tmp[53] = src[53][0] & ucol, tmp[54] = src[54][0] & ucol, tmp[55] = src[55][0] & ucol; tmp[56] = src[56][0] & ucol, tmp[57] = src[57][0] & ucol, tmp[58] = src[58][0] & ucol, tmp[59] = src[59][0] & ucol; tmp[60] = src[60][0] & ucol, tmp[61] = src[61][0] & ucol, tmp[62] = src[62][0] & ucol, tmp[63] = src[63][0] & ucol; #endif word const dotprod = m4ri_parity64(tmp); #if 0 for(int babystep = 0; babystep < m4ri_radix; ++babystep) if(__M4RI_GET_BIT(dotprod, babystep)) __M4RI_FLIP_BIT(B->rows[giantstep + babystep][0], i); #else src[ 0][0] ^= ((dotprod>> 0)&m4ri_one)<> 1)&m4ri_one)<> 2)&m4ri_one)<> 3)&m4ri_one)<> 4)&m4ri_one)<> 5)&m4ri_one)<> 6)&m4ri_one)<> 7)&m4ri_one)<> 8)&m4ri_one)<> 9)&m4ri_one)<>10)&m4ri_one)<>11)&m4ri_one)<>12)&m4ri_one)<>13)&m4ri_one)<>14)&m4ri_one)<>15)&m4ri_one)<>16)&m4ri_one)<>17)&m4ri_one)<>18)&m4ri_one)<>19)&m4ri_one)<>20)&m4ri_one)<>21)&m4ri_one)<>22)&m4ri_one)<>23)&m4ri_one)<>24)&m4ri_one)<>25)&m4ri_one)<>26)&m4ri_one)<>27)&m4ri_one)<>28)&m4ri_one)<>29)&m4ri_one)<>30)&m4ri_one)<>31)&m4ri_one)<>32)&m4ri_one)<>33)&m4ri_one)<>34)&m4ri_one)<>35)&m4ri_one)<>36)&m4ri_one)<>37)&m4ri_one)<>38)&m4ri_one)<>39)&m4ri_one)<>40)&m4ri_one)<>41)&m4ri_one)<>42)&m4ri_one)<>43)&m4ri_one)<>44)&m4ri_one)<>45)&m4ri_one)<>46)&m4ri_one)<>47)&m4ri_one)<>48)&m4ri_one)<>49)&m4ri_one)<>50)&m4ri_one)<>51)&m4ri_one)<>52)&m4ri_one)<>53)&m4ri_one)<>54)&m4ri_one)<>55)&m4ri_one)<>56)&m4ri_one)<>57)&m4ri_one)<>58)&m4ri_one)<>59)&m4ri_one)<>60)&m4ri_one)<>61)&m4ri_one)<>62)&m4ri_one)<>63)&m4ri_one)<rows[giantstep + babystep][0] & ucol; for(int babystep = mb - giantstep; babystep < 64; ++babystep) tmp[babystep] = 0; word const dotprod = m4ri_parity64(tmp); for(int babystep = 0; giantstep + babystep < mb; ++babystep) if(__M4RI_GET_BIT(dotprod, babystep)) __M4RI_FLIP_BIT(B->rows[giantstep + babystep][0], i); } __M4RI_DD_MZD(B); } /***************** * LOWER RIGHT ****************/ void _mzd_trsm_lower_right_base(mzd_t const *L, mzd_t *B); void mzd_trsm_lower_right(mzd_t const *L, mzd_t *B, const int cutoff) { if(L->nrows != B->ncols) m4ri_die("mzd_trsm_lower_right: L nrows (%d) need to match B ncols (%d).\n", L->nrows, B->ncols); if(L->nrows != L->ncols) m4ri_die("mzd_trsm_lower_right: L must be square and is found to be (%d) x (%d).\n", L->nrows, L->ncols); _mzd_trsm_lower_right (L, B, cutoff); } void _mzd_trsm_lower_right(mzd_t const *L, mzd_t *B, const int cutoff) { rci_t const mb = B->nrows; rci_t const nb = B->ncols; if(nb <= m4ri_radix) { _mzd_trsm_lower_right_base (L, B); return; } rci_t const nb1 = (((nb - 1) / m4ri_radix + 1) >> 1) * m4ri_radix; /** \verbatim |\ | \ | \ |L00\ |____\ | |\ | | \ | | \ |L10 |L11\ |____|____\ _________ |B0 |B1 | |____|____| \endverbatim */ mzd_t *B0 = mzd_init_window(B, 0, 0, mb, nb1); mzd_t *B1 = mzd_init_window(B, 0, nb1, mb, nb); mzd_t const *L00 = mzd_init_window_const(L, 0, 0, nb1, nb1); mzd_t const *L10 = mzd_init_window_const(L, nb1, 0, nb, nb1); mzd_t const *L11 = mzd_init_window_const(L, nb1, nb1, nb, nb); _mzd_trsm_lower_right(L11, B1, cutoff); mzd_addmul (B0, B1, L10, cutoff); _mzd_trsm_lower_right(L00, B0, cutoff); mzd_free_window(B0); mzd_free_window(B1); mzd_free_window((mzd_t*)L00); mzd_free_window((mzd_t*)L10); mzd_free_window((mzd_t*)L11); __M4RI_DD_MZD(B); } void _mzd_trsm_lower_right_base(mzd_t const *L, mzd_t *B) { rci_t const mb = B->nrows; rci_t const nb = B->ncols; for(rci_t i = nb - 1; i >= 0; --i) { /* Computes X_i = B_i + X_{i+1,n} L_{i+1..n,i} */ register word ucol = 0; for(rci_t k = i + 1; k < nb; ++k) { if(__M4RI_GET_BIT(L->rows[k][0], i)) __M4RI_SET_BIT(ucol, k); } /* doing 64 dotproducts at a time, to use the parity64 parallelism */ rci_t giantstep; word tmp[64]; for(giantstep = 0; giantstep + m4ri_radix < mb; giantstep += m4ri_radix) { #if 0 for(int babystep = 0; babystep < m4ri_radix; ++babystep) tmp[babystep] = B->rows[giantstep + babystep][0] & ucol; #else word **src = B->rows + giantstep; tmp[ 0] = src[ 0][0] & ucol, tmp[ 1] = src[ 1][0] & ucol, tmp[ 2] = src[ 2][0] & ucol, tmp[ 3] = src[ 3][0] & ucol; tmp[ 4] = src[ 4][0] & ucol, tmp[ 5] = src[ 5][0] & ucol, tmp[ 6] = src[ 6][0] & ucol, tmp[ 7] = src[ 7][0] & ucol; tmp[ 8] = src[ 8][0] & ucol, tmp[ 9] = src[ 9][0] & ucol, tmp[10] = src[10][0] & ucol, tmp[11] = src[11][0] & ucol; tmp[12] = src[12][0] & ucol, tmp[13] = src[13][0] & ucol, tmp[14] = src[14][0] & ucol, tmp[15] = src[15][0] & ucol; tmp[16] = src[16][0] & ucol, tmp[17] = src[17][0] & ucol, tmp[18] = src[18][0] & ucol, tmp[19] = src[19][0] & ucol; tmp[20] = src[20][0] & ucol, tmp[21] = src[21][0] & ucol, tmp[22] = src[22][0] & ucol, tmp[23] = src[23][0] & ucol; tmp[24] = src[24][0] & ucol, tmp[25] = src[25][0] & ucol, tmp[26] = src[26][0] & ucol, tmp[27] = src[27][0] & ucol; tmp[28] = src[28][0] & ucol, tmp[29] = src[29][0] & ucol, tmp[30] = src[30][0] & ucol, tmp[31] = src[31][0] & ucol; tmp[32] = src[32][0] & ucol, tmp[33] = src[33][0] & ucol, tmp[34] = src[34][0] & ucol, tmp[35] = src[35][0] & ucol; tmp[36] = src[36][0] & ucol, tmp[37] = src[37][0] & ucol, tmp[38] = src[38][0] & ucol, tmp[39] = src[39][0] & ucol; tmp[40] = src[40][0] & ucol, tmp[41] = src[41][0] & ucol, tmp[42] = src[42][0] & ucol, tmp[43] = src[43][0] & ucol; tmp[44] = src[44][0] & ucol, tmp[45] = src[45][0] & ucol, tmp[46] = src[46][0] & ucol, tmp[47] = src[47][0] & ucol; tmp[48] = src[48][0] & ucol, tmp[49] = src[49][0] & ucol, tmp[50] = src[50][0] & ucol, tmp[51] = src[51][0] & ucol; tmp[52] = src[52][0] & ucol, tmp[53] = src[53][0] & ucol, tmp[54] = src[54][0] & ucol, tmp[55] = src[55][0] & ucol; tmp[56] = src[56][0] & ucol, tmp[57] = src[57][0] & ucol, tmp[58] = src[58][0] & ucol, tmp[59] = src[59][0] & ucol; tmp[60] = src[60][0] & ucol, tmp[61] = src[61][0] & ucol, tmp[62] = src[62][0] & ucol, tmp[63] = src[63][0] & ucol; #endif word const dotprod = m4ri_parity64(tmp); #if 0 for(int babystep = 0; babystep < m4ri_radix; ++babystep) if(__M4RI_GET_BIT(dotprod, babystep)) __M4RI_FLIP_BIT(B->rows[giantstep + babystep][0], i); #else src[ 0][0] ^= ((dotprod>> 0)&m4ri_one)<> 1)&m4ri_one)<> 2)&m4ri_one)<> 3)&m4ri_one)<> 4)&m4ri_one)<> 5)&m4ri_one)<> 6)&m4ri_one)<> 7)&m4ri_one)<> 8)&m4ri_one)<> 9)&m4ri_one)<>10)&m4ri_one)<>11)&m4ri_one)<>12)&m4ri_one)<>13)&m4ri_one)<>14)&m4ri_one)<>15)&m4ri_one)<>16)&m4ri_one)<>17)&m4ri_one)<>18)&m4ri_one)<>19)&m4ri_one)<>20)&m4ri_one)<>21)&m4ri_one)<>22)&m4ri_one)<>23)&m4ri_one)<>24)&m4ri_one)<>25)&m4ri_one)<>26)&m4ri_one)<>27)&m4ri_one)<>28)&m4ri_one)<>29)&m4ri_one)<>30)&m4ri_one)<>31)&m4ri_one)<>32)&m4ri_one)<>33)&m4ri_one)<>34)&m4ri_one)<>35)&m4ri_one)<>36)&m4ri_one)<>37)&m4ri_one)<>38)&m4ri_one)<>39)&m4ri_one)<>40)&m4ri_one)<>41)&m4ri_one)<>42)&m4ri_one)<>43)&m4ri_one)<>44)&m4ri_one)<>45)&m4ri_one)<>46)&m4ri_one)<>47)&m4ri_one)<>48)&m4ri_one)<>49)&m4ri_one)<>50)&m4ri_one)<>51)&m4ri_one)<>52)&m4ri_one)<>53)&m4ri_one)<>54)&m4ri_one)<>55)&m4ri_one)<>56)&m4ri_one)<>57)&m4ri_one)<>58)&m4ri_one)<>59)&m4ri_one)<>60)&m4ri_one)<>61)&m4ri_one)<>62)&m4ri_one)<>63)&m4ri_one)<rows[giantstep + babystep][0] & ucol; for(int babystep = mb - giantstep; babystep < 64; ++babystep) tmp[babystep] = 0; word const dotprod = m4ri_parity64(tmp); for(int babystep = 0; giantstep + babystep < mb; ++babystep) if(__M4RI_GET_BIT(dotprod, babystep)) __M4RI_FLIP_BIT(B->rows[giantstep + babystep][0], i); } __M4RI_DD_MZD(B); } /***************** * LOWER LEFT ****************/ void mzd_trsm_lower_left(mzd_t const *L, mzd_t *B, const int cutoff) { if(L->ncols != B->nrows) m4ri_die("mzd_trsm_lower_left: L ncols (%d) need to match B nrows (%d).\n", L->ncols, B->nrows); if(L->nrows != L->ncols) m4ri_die("mzd_trsm_lower_left: L must be square and is found to be (%d) x (%d).\n", L->nrows, L->ncols); _mzd_trsm_lower_left (L, B, cutoff); } void _mzd_trsm_lower_left(mzd_t const *L, mzd_t *B, const int cutoff) { rci_t const mb = B->nrows; rci_t const nb = B->ncols; int const nbrest = nb % m4ri_radix; if(mb <= m4ri_radix) { /* base case */ word const mask_end = __M4RI_LEFT_BITMASK(nbrest); for(rci_t i = 1; i < mb; ++i) { /* Computes X_i = B_i + L_{i,0..i-1} X_{0..i-1} */ word *Lrow = L->rows[i]; word *Brow = B->rows[i]; for (rci_t k = 0; k < i; ++k) { if (__M4RI_GET_BIT(Lrow[0], k)) { for(wi_t j = 0; j < B->width - 1; ++j) Brow[j] ^= B->rows[k][j]; Brow[B->width - 1] ^= B->rows[k][B->width - 1] & mask_end; } } } } else if(mb <= __M4RI_MUL_BLOCKSIZE) { _mzd_trsm_lower_left_russian(L, B, 0); } else { rci_t const mb1 = (((mb - 1) / m4ri_radix + 1) >> 1) * m4ri_radix; mzd_t *B0 = mzd_init_window(B, 0, 0, mb1, nb); mzd_t *B1 = mzd_init_window(B, mb1, 0, mb, nb); mzd_t const *L00 = mzd_init_window_const(L, 0, 0, mb1, mb1); mzd_t const *L10 = mzd_init_window_const(L, mb1, 0, mb, mb1); mzd_t const *L11 = mzd_init_window_const(L, mb1, mb1, mb, mb); _mzd_trsm_lower_left(L00, B0, cutoff); mzd_addmul (B1, L10, B0, cutoff); _mzd_trsm_lower_left(L11, B1, cutoff); mzd_free_window(B0); mzd_free_window(B1); mzd_free_window((mzd_t*)L00); mzd_free_window((mzd_t*)L10); mzd_free_window((mzd_t*)L11); } __M4RI_DD_MZD(B); } /***************** * UPPER LEFT ****************/ void mzd_trsm_upper_left(mzd_t const *U, mzd_t *B, const int cutoff) { if(U->ncols != B->nrows) m4ri_die("mzd_trsm_upper_left: U ncols (%d) need to match B nrows (%d).\n", U->ncols, B->nrows); if(U->nrows != U->ncols) m4ri_die("mzd_trsm_upper_left: U must be square and is found to be (%d) x (%d).\n", U->nrows, U->ncols); _mzd_trsm_upper_left(U, B, cutoff); } void _mzd_trsm_upper_left(mzd_t const *U, mzd_t *B, const int cutoff) { rci_t const mb = B->nrows; rci_t const nb = B->ncols; if(mb <= m4ri_radix) { /* base case */ word const mask_end = B->high_bitmask; // U[mb-1,mb-1] = 1, so no work required for i=mb-1 for(rci_t i = mb - 2; i >= 0; --i) { /* Computes X_i = B_i + U_{i,i+1..mb} X_{i+1..mb} */ word *Urow = U->rows[i]; word *Brow = B->rows[i]; for(rci_t k = i + 1; k < mb; ++k) { if(__M4RI_GET_BIT(Urow[0], k)){ for(wi_t j = 0; j < B->width - 1; ++j) Brow[j] ^= B->rows[k][j]; Brow[B->width - 1] ^= B->rows[k][B->width - 1] & mask_end; } } } } else if(mb <= __M4RI_MUL_BLOCKSIZE) { _mzd_trsm_upper_left_russian(U, B, 0); } else { rci_t const mb1 = (((mb-1) / m4ri_radix + 1) >> 1) * m4ri_radix; mzd_t *B0 = mzd_init_window(B, 0, 0, mb1, nb); mzd_t *B1 = mzd_init_window(B, mb1, 0, mb, nb); mzd_t const *U00 = mzd_init_window_const(U, 0, 0, mb1, mb1); mzd_t const *U01 = mzd_init_window_const(U, 0, mb1, mb1, mb); mzd_t const *U11 = mzd_init_window_const(U, mb1, mb1, mb, mb); _mzd_trsm_upper_left(U11, B1, cutoff); _mzd_addmul (B0, U01, B1, cutoff); _mzd_trsm_upper_left(U00, B0, cutoff); mzd_free_window(B0); mzd_free_window(B1); mzd_free_window((mzd_t*)U00); mzd_free_window((mzd_t*)U01); mzd_free_window((mzd_t*)U11); } __M4RI_DD_MZD(B); } mzd_t *mzd_trtri_upper(mzd_t *U) { if (U->nrows*U->ncols < __M4RI_CPU_L3_CACHE<<1) { mzd_trtri_upper_russian(U,0); } else { rci_t const n = U->nrows; rci_t n2 = (((n - 1) / m4ri_radix + 1) >> 1); #if __M4RI_HAVE_SSE2 if (n2%2) n2 += 1; #endif n2 *= m4ri_radix; assert(n2 < n); mzd_t *U00 = mzd_init_window(U, 0, 0, n2, n2); mzd_t *U01 = mzd_init_window(U, 0, n2, n2, n ); mzd_t *U11 = mzd_init_window(U, n2, n2 , n , n ); _mzd_trsm_upper_left( U00, U01, 0); _mzd_trsm_upper_right(U11, U01, 0); mzd_trtri_upper(U00); mzd_trtri_upper(U11); mzd_free_window((mzd_t*)U00); mzd_free_window((mzd_t*)U01); mzd_free_window((mzd_t*)U11); } return U; } m4ri-20140914/m4ri/triangular_russian.c0000644000175000017500000003542312354166226014525 00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "triangular_russian.h" #include "graycode.h" #include "brilliantrussian.h" #include "ple_russian.h" #include "xor.h" /** the number of tables used in TRSM decomposition **/ #define __M4RI_TRSM_NTABLES 8 void _mzd_trsm_upper_left_submatrix(mzd_t const *U, mzd_t *B, rci_t const start_row, int const k, word const mask_end) { for (rci_t i = 0; i < k; ++i) { for (rci_t j = 0; j < i; ++j) { if (mzd_read_bit(U, start_row+(k-i-1), start_row+(k-i)+j)) { word *a = B->rows[start_row+(k-i-1)]; word *b = B->rows[start_row+(k-i)+j]; wi_t ii; for(ii = 0; ii + 8 <= B->width - 1; ii += 8) { *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; } switch(B->width - ii) { case 8: *a++ ^= *b++; case 7: *a++ ^= *b++; case 6: *a++ ^= *b++; case 5: *a++ ^= *b++; case 4: *a++ ^= *b++; case 3: *a++ ^= *b++; case 2: *a++ ^= *b++; case 1: *a++ ^= (*b++ & mask_end); } } } } __M4RI_DD_MZD(B); } void _mzd_trsm_upper_left_russian(mzd_t const *U, mzd_t *B, int k) { wi_t const wide = B->width; word mask_end = __M4RI_LEFT_BITMASK(B->ncols % m4ri_radix); if(k == 0) { /* __M4RI_CPU_L2_CACHE == __M4RI_TRSM_NTABLES * 2^k * B->width * 8 */ k = (int)log2((__M4RI_CPU_L2_CACHE/8)/(double)B->width/(double)__M4RI_TRSM_NTABLES); rci_t const klog = round(0.75 * log2_floor(MIN(B->nrows, B->ncols))); if(klog < k) k = klog; if (k<2) k = 2; else if(k>8) k = 8; } int kk = __M4RI_TRSM_NTABLES * k; assert(kk <= m4ri_radix); mzd_t *T[__M4RI_TRSM_NTABLES]; rci_t *L[__M4RI_TRSM_NTABLES]; #ifdef __M4RI_HAVE_SSE2 mzd_t *Talign[__M4RI_TRSM_NTABLES]; int b_align = (__M4RI_ALIGNMENT(B->rows[0], 16) == 8); #endif for(int i=0; i<__M4RI_TRSM_NTABLES; i++) { #ifdef __M4RI_HAVE_SSE2 /* we make sure that T are aligned as C */ Talign[i] = mzd_init(__M4RI_TWOPOW(k), B->ncols + m4ri_radix); T[i] = mzd_init_window(Talign[i], 0, b_align*m4ri_radix, Talign[i]->nrows, B->ncols + b_align*m4ri_radix); #else T[i] = mzd_init(__M4RI_TWOPOW(k), B->ncols); #endif L[i] = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); } rci_t i = 0; for (; i < B->nrows - kk; i += kk) { _mzd_trsm_upper_left_submatrix(U, B, B->nrows-i-kk, kk, mask_end); switch(__M4RI_TRSM_NTABLES) { case 8: mzd_make_table(B, B->nrows - i - 8*k, 0, k, T[7], L[7]); case 7: mzd_make_table(B, B->nrows - i - 7*k, 0, k, T[6], L[6]); case 6: mzd_make_table(B, B->nrows - i - 6*k, 0, k, T[5], L[5]); case 5: mzd_make_table(B, B->nrows - i - 5*k, 0, k, T[4], L[4]); case 4: mzd_make_table(B, B->nrows - i - 4*k, 0, k, T[3], L[3]); case 3: mzd_make_table(B, B->nrows - i - 3*k, 0, k, T[2], L[2]); case 2: mzd_make_table(B, B->nrows - i - 2*k, 0, k, T[1], L[1]); case 1: mzd_make_table(B, B->nrows - i - 1*k, 0, k, T[0], L[0]); break; default: m4ri_die("__M4RI_TRSM_NTABLES must be <= 8 but got %d", __M4RI_TRSM_NTABLES); } for(rci_t j = 0; j < B->nrows - i - kk; ++j) { rci_t x; const word *t[__M4RI_TRSM_NTABLES]; switch(__M4RI_TRSM_NTABLES) { case 8: x = L[7][ mzd_read_bits_int(U, j, B->nrows - i - 8*k, k) ]; t[7] = T[7]->rows[x]; case 7: x = L[6][ mzd_read_bits_int(U, j, B->nrows - i - 7*k, k) ]; t[6] = T[6]->rows[x]; case 6: x = L[5][ mzd_read_bits_int(U, j, B->nrows - i - 6*k, k) ]; t[5] = T[5]->rows[x]; case 5: x = L[4][ mzd_read_bits_int(U, j, B->nrows - i - 5*k, k) ]; t[4] = T[4]->rows[x]; case 4: x = L[3][ mzd_read_bits_int(U, j, B->nrows - i - 4*k, k) ]; t[3] = T[3]->rows[x]; case 3: x = L[2][ mzd_read_bits_int(U, j, B->nrows - i - 3*k, k) ]; t[2] = T[2]->rows[x]; case 2: x = L[1][ mzd_read_bits_int(U, j, B->nrows - i - 2*k, k) ]; t[1] = T[1]->rows[x]; case 1: x = L[0][ mzd_read_bits_int(U, j, B->nrows - i - 1*k, k) ]; t[0] = T[0]->rows[x]; break; default: m4ri_die("__M4RI_TRSM_NTABLES must be <= 8 but got %d", __M4RI_TRSM_NTABLES); } word *b = B->rows[j]; switch(__M4RI_TRSM_NTABLES) { case 8: _mzd_combine_8(b, t, wide); break; case 7: _mzd_combine_7(b, t, wide); break; case 6: _mzd_combine_6(b, t, wide); break; case 5: _mzd_combine_5(b, t, wide); break; case 4: _mzd_combine_4(b, t, wide); break; case 3: _mzd_combine_3(b, t, wide); break; case 2: _mzd_combine_2(b, t, wide); break; case 1: _mzd_combine(b, t[0], wide); break; default: m4ri_die("__M4RI_TRSM_NTABLES must be <= 8 but got %d", __M4RI_TRSM_NTABLES); } } } /* handle stuff that doesn't fit in multiples of kk */ for ( ;i < B->nrows; i += k) { if (i > B->nrows - k) k = B->nrows - i; _mzd_trsm_upper_left_submatrix(U, B, B->nrows-i-k, k, mask_end); mzd_make_table(B, B->nrows - i - 1*k, 0, k, T[0], L[0]); for(rci_t j = 0; j < B->nrows - i - k; ++j) { rci_t const x0 = L[0][ mzd_read_bits_int(U, j, B->nrows - i - 1*k, k) ]; word *b = B->rows[j]; word *t0 = T[0]->rows[x0]; for (wi_t ii = 0; ii < wide; ++ii) b[ii] ^= t0[ii]; } } for(int i=0; i<__M4RI_TRSM_NTABLES; i++) { mzd_free(T[i]); #ifdef __M4RI_HAVE_SSE2 mzd_free(Talign[i]); #endif m4ri_mm_free(L[i]); } __M4RI_DD_MZD(B); } void _mzd_trsm_lower_left_submatrix(mzd_t const *L, mzd_t *B, rci_t const start_row, int const k, word const mask_end) { for (int i = 0; i < k; ++i) { for (int j = 0; j < i; ++j) { if (mzd_read_bit(L, start_row+i, start_row+j)) { word *a = B->rows[start_row+i]; word *b = B->rows[start_row+j]; wi_t ii; for(ii = 0; ii + 8 <= B->width - 1; ii += 8) { *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; *a++ ^= *b++; } switch(B->width - ii) { case 8: *a++ ^= *b++; case 7: *a++ ^= *b++; case 6: *a++ ^= *b++; case 5: *a++ ^= *b++; case 4: *a++ ^= *b++; case 3: *a++ ^= *b++; case 2: *a++ ^= *b++; case 1: *a++ ^= (*b++ & mask_end); } } } } __M4RI_DD_MZD(B); } void _mzd_trsm_lower_left_russian(mzd_t const *L, mzd_t *B, int k) { wi_t const wide = B->width; if(k == 0) { /* __M4RI_CPU_L2_CACHE == __M4RI_TRSM_NTABLES * 2^k * B->width * 8 */ k = (int)log2((__M4RI_CPU_L2_CACHE/8)/(double)B->width/(double)__M4RI_TRSM_NTABLES); rci_t const klog = round(0.75 * log2_floor(MIN(B->nrows, B->ncols))); if(klog < k) k = klog; if (k<2) k = 2; else if(k>8) k = 8; } int kk = __M4RI_TRSM_NTABLES * k; assert(kk <= m4ri_radix); mzd_t *T[__M4RI_TRSM_NTABLES]; rci_t *J[__M4RI_TRSM_NTABLES]; #ifdef __M4RI_HAVE_SSE2 /* we make sure that T are aligned as B, this is dirty, we need a function for this */ mzd_t *Talign[__M4RI_TRSM_NTABLES]; int b_align = (__M4RI_ALIGNMENT(B->rows[0], 16) == 8); #endif for(int i=0; i<__M4RI_TRSM_NTABLES; i++) { #ifdef __M4RI_HAVE_SSE2 Talign[i] = mzd_init(__M4RI_TWOPOW(k), B->ncols + m4ri_radix); T[i] = mzd_init_window(Talign[i], 0, b_align*m4ri_radix, Talign[i]->nrows, B->ncols + b_align*m4ri_radix); #else T[i] = mzd_init(__M4RI_TWOPOW(k), B->ncols); #endif J[i] = (rci_t*)m4ri_mm_calloc(__M4RI_TWOPOW(k), sizeof(rci_t)); } const word mask = __M4RI_LEFT_BITMASK(k); rci_t i = 0; for (; i < B->nrows - kk; i += kk) { _mzd_trsm_lower_left_submatrix(L, B, i, kk, B->high_bitmask); switch(__M4RI_TRSM_NTABLES) { case 8: mzd_make_table(B, i + 7*k, 0, k, T[7], J[7]); case 7: mzd_make_table(B, i + 6*k, 0, k, T[6], J[6]); case 6: mzd_make_table(B, i + 5*k, 0, k, T[5], J[5]); case 5: mzd_make_table(B, i + 4*k, 0, k, T[4], J[4]); case 4: mzd_make_table(B, i + 3*k, 0, k, T[3], J[3]); case 3: mzd_make_table(B, i + 2*k, 0, k, T[2], J[2]); case 2: mzd_make_table(B, i + 1*k, 0, k, T[1], J[1]); case 1: mzd_make_table(B, i + 0*k, 0, k, T[0], J[0]); break; default: m4ri_die("__M4RI_TRSM_NTABLES must be <= 8 but got %d", __M4RI_TRSM_NTABLES); } for(rci_t j = i+kk; j < B->nrows; ++j) { const word *t[__M4RI_TRSM_NTABLES]; word tmp = mzd_read_bits(L, j, i, kk); switch(__M4RI_TRSM_NTABLES) { case 8: t[7] = T[7]->rows[ J[7][ (tmp >> (7*k)) & mask ] ]; case 7: t[6] = T[6]->rows[ J[6][ (tmp >> (6*k)) & mask ] ]; case 6: t[5] = T[5]->rows[ J[5][ (tmp >> (5*k)) & mask ] ]; case 5: t[4] = T[4]->rows[ J[4][ (tmp >> (4*k)) & mask ] ]; case 4: t[3] = T[3]->rows[ J[3][ (tmp >> (3*k)) & mask ] ]; case 3: t[2] = T[2]->rows[ J[2][ (tmp >> (2*k)) & mask ] ]; case 2: t[1] = T[1]->rows[ J[1][ (tmp >> (1*k)) & mask ] ]; case 1: t[0] = T[0]->rows[ J[0][ (tmp >> (0*k)) & mask ] ]; break; default: m4ri_die("__M4RI_TRSM_NTABLES must be <= 8 but got %d", __M4RI_TRSM_NTABLES); } word *b = B->rows[j]; switch(__M4RI_TRSM_NTABLES) { case 8: _mzd_combine_8(b, t, wide); break; case 7: _mzd_combine_7(b, t, wide); break; case 6: _mzd_combine_6(b, t, wide); break; case 5: _mzd_combine_5(b, t, wide); break; case 4: _mzd_combine_4(b, t, wide); break; case 3: _mzd_combine_3(b, t, wide); break; case 2: _mzd_combine_2(b, t, wide); break; case 1: _mzd_combine(b, t[0], wide); break; default: m4ri_die("__M4RI_TRSM_NTABLES must be <= 8 but got %d", __M4RI_TRSM_NTABLES); } } } /* handle stuff that doesn't fit in multiples of kk */ for ( ;i < B->nrows; i += k) { if (i > B->nrows - k) k = B->nrows - i; _mzd_trsm_lower_left_submatrix(L, B, i, k, B->high_bitmask); mzd_make_table(B, i + 0*k, 0, k, T[0], J[0]); for(rci_t j = i+k; j < L->nrows; ++j) { rci_t const x0 = J[0][ mzd_read_bits_int(L, j, i, k) ]; word *b = B->rows[j]; word *t0 = T[0]->rows[x0]; for (wi_t ii = 0; ii < wide; ++ii) b[ii] ^= t0[ii]; } } for(int i=0; i<__M4RI_TRSM_NTABLES; i++) { mzd_free(T[i]); #ifdef __M4RI_HAVE_SSE2 mzd_free(Talign[i]); #endif m4ri_mm_free(J[i]); } __M4RI_DD_MZD(B); } void mzd_make_table_trtri(mzd_t const *M, rci_t r, rci_t c, int k, ple_table_t *Tb, rci_t startcol) { mzd_t *T = Tb->T; rci_t *L = Tb->E; assert(!(T->flags & mzd_flag_multiple_blocks)); wi_t const blockoffset = c / m4ri_radix; wi_t const blockoffset0 = startcol / m4ri_radix; assert(blockoffset - blockoffset0 <= 1); int const twokay= __M4RI_TWOPOW(k); wi_t const wide = T->width - blockoffset; wi_t const count = (wide + 7) / 8; int const entry_point = wide % 8; wi_t const next_row_offset = blockoffset + T->rowstride - T->width; word *ti, *ti1, *m; ti1 = T->rows[0] + blockoffset; ti = ti1 + T->rowstride; L[0] = 0; for (int i = 1; i < twokay; ++i) { T->rows[i][blockoffset0] = 0; /* we make sure that we can safely add from blockoffset0 */ rci_t rowneeded = r + m4ri_codebook[k]->inc[i - 1]; m = M->rows[rowneeded] + blockoffset; wi_t n = count; switch (entry_point) { case 0: do { *(ti++) = *(m++) ^ *(ti1++); case 7: *(ti++) = *(m++) ^ *(ti1++); case 6: *(ti++) = *(m++) ^ *(ti1++); case 5: *(ti++) = *(m++) ^ *(ti1++); case 4: *(ti++) = *(m++) ^ *(ti1++); case 3: *(ti++) = *(m++) ^ *(ti1++); case 2: *(ti++) = *(m++) ^ *(ti1++); case 1: *(ti++) = *(m++) ^ *(ti1++); } while (--n > 0); } ti += next_row_offset; ti1 += next_row_offset; L[m4ri_codebook[k]->ord[i]] = i; } Tb->B[0] = 0; for(int i=1; iord[i]); Tb->B[i] = mzd_read_bits(T, i, startcol, m4ri_radix); } } #define __M4RI_TRTRI_NTABLES 4 static inline void _mzd_trtri_upper_submatrix(mzd_t *A, rci_t pivot_r, rci_t elim_r, const int k) { for(rci_t i=pivot_r; incols ) mzd_row_add_offset(A, j, i, i+1); } mzd_t *mzd_trtri_upper_russian(mzd_t *A, int k) { assert(A->nrows == A->ncols); if (k == 0) { k = m4ri_opt_k(A->nrows, A->ncols, 0); if (k >= 7) k = 7; if (0.75 * __M4RI_TWOPOW(k) *A->ncols > __M4RI_CPU_L3_CACHE / 2.0) k -= 1; } const int kk = __M4RI_TRTRI_NTABLES*k; int k_[__M4RI_TRTRI_NTABLES]; for (int i=0; i<__M4RI_TRTRI_NTABLES; i++) k_[i] = k; ple_table_t *T[__M4RI_TRTRI_NTABLES]; mzd_t *U[__M4RI_TRTRI_NTABLES]; for(int i=0; i<__M4RI_TRTRI_NTABLES; i++) { T[i] = ple_table_init(k, A->ncols); U[i] = mzd_init(k, A->ncols); } /** dummy offsets table for _mzd_ple_to_e**/ rci_t id[m4ri_radix]; for(int i=0; inrows) { /*** * ---------------------------- * [ ....................... ] * [ ... U00 U01 U02 U03 ... ] * [ ... U10 U12 U13 ... ] * ---------------------------- r * [ ... U22 U23 ... ] * [ ... U33 ... ] * ---------------------------- * * Assume [ U00 U01 ] was already inverted and multiplied with [ U02 U03 ... ] * [ U10 ] [ U12 U13 ... ] * * We then invert U22 and construct a table for [U22 U23 ... ], then we * invert [U33] and multiply it with [U23]. Then we construct a table for [U23 ... ] **/ _mzd_trtri_upper_submatrix(A, r, r, k); _mzd_ple_to_e(U[0], A, r, r, k, id); mzd_make_table_trtri(U[0], 0, r, k, T[0], r); _mzd_trtri_upper_submatrix(A, r+k, r, k); _mzd_ple_to_e(U[1], A, r+k, r+k, k, id); mzd_make_table_trtri(U[1], 0, r+k, k, T[1], r); _mzd_trtri_upper_submatrix(A, r+2*k, r, k); _mzd_ple_to_e(U[2], A, r+2*k, r+2*k, k, id); mzd_make_table_trtri(U[2], 0, r+2*k, k, T[2], r); _mzd_trtri_upper_submatrix(A, r+3*k, r, k); _mzd_ple_to_e(U[3], A, r+3*k, r+3*k, k, id); mzd_make_table_trtri(U[3], 0, r+3*k, k, T[3], r); _mzd_process_rows_ple_4(A, 0, r, r, k_, (const ple_table_t** const)T); r += kk; } /** deal with the rest **/ while(r < A->nrows) { if (A->nrows - r < k) k = A->nrows - r; for(rci_t i=0; incols ) mzd_row_add_offset(A, r+j, r+i, r+i+1); _mzd_ple_to_e(U[0], A, r, r, k, id); mzd_make_table_trtri(U[0], 0, r, k, T[0], r); mzd_process_rows(A, 0, r, r, k, T[0]->T, T[0]->E); r += k; } for(int i=0; i<__M4RI_TRTRI_NTABLES; i++) { ple_table_free(T[i]); mzd_free(U[i]); } __M4RI_DD_MZD(A); return A; } m4ri-20140914/m4ri/ple.c0000644000175000017500000001726412354166226011374 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Clement Pernet * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "mzd.h" #include "triangular.h" #include "parity.h" #include "ple_russian.h" #include "strassen.h" #include "ple.h" rci_t mzd_ple(mzd_t *A, mzp_t *P, mzp_t *Q, int const cutoff) { if (P->length != A->nrows) m4ri_die("mzd_ple: Permutation P length (%d) must match A nrows (%d)\n", P->length, A->nrows); if (Q->length != A->ncols) m4ri_die("mzd_ple: Permutation Q length (%d) must match A ncols (%d)\n", Q->length, A->ncols); return _mzd_ple(A, P, Q, cutoff); } rci_t mzd_pluq (mzd_t *A, mzp_t *P, mzp_t *Q, int const cutoff) { if (P->length != A->nrows) m4ri_die("mzd_pluq: Permutation P length (%d) must match A nrows (%d)\n", P->length, A->nrows); if (Q->length != A->ncols) m4ri_die("mzd_pluq: Permutation Q length (%d) must match A ncols (%d)\n", Q->length, A->ncols); rci_t r = _mzd_pluq(A, P, Q, cutoff); return r; } rci_t _mzd_pluq(mzd_t *A, mzp_t *P, mzp_t *Q, int const cutoff) { rci_t r = _mzd_ple(A, P, Q, cutoff); if(r && r < A->nrows) { mzd_t *A0 = mzd_init_window(A, 0, 0, r, A->ncols); mzd_apply_p_right_trans_tri(A0, Q); mzd_free_window(A0); } else { mzd_apply_p_right_trans_tri(A, Q); } return r; } rci_t _mzd_ple(mzd_t *A, mzp_t *P, mzp_t *Q, int const cutoff) { rci_t ncols = A->ncols; #if 1 rci_t nrows = mzd_first_zero_row(A); for(rci_t i = nrows; i < A->nrows; ++i) P->values[i] = i; for(rci_t i = 0; i < A->ncols; ++i) Q->values[i] = i; if(!nrows) { return 0; } #else rci_t nrows = A->nrows; #endif if (ncols <= m4ri_radix || A->width * A->nrows <= __M4RI_PLE_CUTOFF) { /* this improves data locality and runtime considerably */ mzd_t *Abar = mzd_copy(NULL, A); rci_t r = _mzd_ple_russian(Abar, P, Q, 0); mzd_copy(A, Abar); mzd_free(Abar); return r; } { /* Block divide and conquer algorithm */ /* n1 * ------------------------------------------ * | A0 | A1 | * | | | * | | | * | | | * ------------------------------------------ */ rci_t n1 = (((ncols - 1) / m4ri_radix + 1) >> 1) * m4ri_radix; mzd_t *A0 = mzd_init_window(A, 0, 0, nrows, n1); mzd_t *A1 = mzd_init_window(A, 0, n1, nrows, ncols); /* First recursive call */ mzp_t *P1 = mzp_init_window(P, 0, nrows); mzp_t *Q1 = mzp_init_window(Q, 0, A0->ncols); rci_t r1 = _mzd_ple(A0, P1, Q1, cutoff); /* r1 n1 * ------------------------------------------ * | A00 | | A01 | * | | | | * r1------------------------------------------ * * | A10 | | A11 | * | | | | * ------------------------------------------ */ mzd_t *A00 = mzd_init_window(A, 0, 0, r1, r1); mzd_t *A10 = mzd_init_window(A, r1, 0, nrows, r1); mzd_t *A01 = mzd_init_window(A, 0, n1, r1, ncols); mzd_t *A11 = mzd_init_window(A, r1, n1, nrows, ncols); if (r1) { /* Computation of the Schur complement */ mzd_apply_p_left(A1, P1); _mzd_trsm_lower_left(A00, A01, cutoff); mzd_addmul(A11, A10, A01, cutoff); } mzp_free_window(P1); mzp_free_window(Q1); /* Second recursive call */ mzp_t *P2 = mzp_init_window(P, r1, nrows); mzp_t *Q2 = mzp_init_window(Q, n1, ncols); rci_t r2 = _mzd_ple(A11, P2, Q2, cutoff); /* n * ------------------- * | A0b | * | | * r1----------------- * | A1b | * | | * ------------------- */ /* Update A10 */ mzd_apply_p_left(A10, P2); /* Update P */ for (rci_t i = 0; i < nrows - r1; ++i) P2->values[i] += r1; // Update the A0b block (permutation + rotation) for(rci_t i = 0, j = n1; j < ncols; ++i, ++j) Q2->values[i] += n1; for(rci_t i = n1, j = r1; i < n1 + r2; ++i, ++j) Q->values[j] = Q->values[i]; /* Compressing L */ _mzd_compress_l(A, r1, n1, r2); mzp_free_window(Q2); mzp_free_window(P2); mzd_free_window(A0); mzd_free_window(A1); mzd_free_window(A00); mzd_free_window(A01); mzd_free_window(A10); mzd_free_window(A11); __M4RI_DD_MZD(A); __M4RI_DD_MZP(P); __M4RI_DD_MZP(Q); __M4RI_DD_RCI(r1 + r2); return r1 + r2; } } rci_t _mzd_pluq_naive(mzd_t *A, mzp_t *P, mzp_t *Q) { rci_t curr_pos = 0; for (curr_pos = 0; curr_pos < A->ncols; ) { int found = 0; /* search for some pivot */ rci_t i, j; for (j = curr_pos; j < A->ncols; ++j) { for (i = curr_pos; i< A->nrows; ++i ) { if (mzd_read_bit(A, i, j)) { found = 1; break; } } if(found) break; } if(found) { P->values[curr_pos] = i; Q->values[curr_pos] = j; mzd_row_swap(A, curr_pos, i); mzd_col_swap(A, curr_pos, j); /* clear below but preserve transformation matrix */ if (curr_pos +1 < A->ncols){ for(rci_t l = curr_pos + 1; l < A->nrows; ++l) { if (mzd_read_bit(A, l, curr_pos)) { mzd_row_add_offset(A, l, curr_pos, curr_pos + 1); } } } ++curr_pos; } else { break; } } for (rci_t i = curr_pos; i < A->nrows; ++i) P->values[i] = i; for (rci_t i = curr_pos; i < A->ncols; ++i) Q->values[i] = i; __M4RI_DD_MZD(A); __M4RI_DD_MZP(P); __M4RI_DD_MZP(Q); __M4RI_DD_RCI(curr_pos); return curr_pos; } rci_t _mzd_ple_naive(mzd_t *A, mzp_t *P, mzp_t *Q) { rci_t col_pos = 0; rci_t row_pos = 0; /* search for some pivot */ while (row_pos < A->nrows && col_pos < A->ncols) { int found = 0; rci_t i, j; for (j = col_pos; j < A->ncols; ++j) { for (i = row_pos; i < A->nrows; ++i) { if (mzd_read_bit(A, i, j)) { found = 1; break; } } if(found) break; } if(found) { P->values[row_pos] = i; Q->values[row_pos] = j; mzd_row_swap(A, row_pos, i); //mzd_col_swap(A, curr_pos, j); /* clear below but preserve transformation matrix */ if (j + 1 < A->ncols){ for(rci_t l = row_pos + 1; l < A->nrows; ++l) { if (mzd_read_bit(A, l, j)) { mzd_row_add_offset(A, l, row_pos, j + 1); } } } ++row_pos; col_pos = j + 1; } else { break; } } for (rci_t i = row_pos; i < A->nrows; ++i) P->values[i] = i; for (rci_t i = row_pos; i < A->ncols; ++i) Q->values[i] = i; /* Now compressing L */ for (rci_t j = 0; j < row_pos; ++j){ if (Q->values[j] > j) { // To be optimized by a copy_row function mzd_col_swap_in_rows (A,Q->values[j], j, j, A->nrows); } } __M4RI_DD_MZD(A); __M4RI_DD_MZP(P); __M4RI_DD_MZP(Q); __M4RI_DD_RCI(row_pos); return row_pos; } m4ri-20140914/m4ri/ple_russian.c0000644000175000017500000004332712405116371013130 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008-2011 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "m4ri_config.h" #if __M4RI_HAVE_SSE2 #include #endif #include "ple_russian.h" #include "brilliantrussian.h" #include "graycode.h" #include "xor.h" #ifndef NDEBUG #include "mmc.h" #endif /** the number of tables used in PLE decomposition **/ #define __M4RI_PLE_NTABLES 8 ple_table_t *ple_table_init(int k, rci_t ncols) { ple_table_t *T = (ple_table_t*)m4ri_mm_malloc(sizeof(ple_table_t)); T->T = mzd_init(__M4RI_TWOPOW(k), ncols); T->M = (rci_t*)m4ri_mm_malloc(__M4RI_TWOPOW(k)*sizeof(rci_t)); T->E = (rci_t*)m4ri_mm_malloc(__M4RI_TWOPOW(k)*sizeof(rci_t)); T->B = (word*)m4ri_mm_malloc(__M4RI_TWOPOW(k)*sizeof(word) ); return T; } void ple_table_free(ple_table_t *T) { m4ri_mm_free(T->B); m4ri_mm_free(T->M); m4ri_mm_free(T->E); mzd_free(T->T); m4ri_mm_free(T); } static inline rci_t _max_value(rci_t *data, int length) { rci_t max = 0; for(int i = 0; i < length; ++i) { max = MAX(max, data[i]); } return max; } static inline void _kk_setup(int const kk, int const knar, int *k_, int *knar_, int const *pivots, int const ntables) { assert((ntables <= __M4RI_PLE_NTABLES) & (ntables > 0)); int lb[__M4RI_PLE_NTABLES], ub[__M4RI_PLE_NTABLES]; int rem = kk % ntables; int s = 1; switch(ntables) { case 8: k_[ntables - 8] = kk / ntables + ((rem >= (ntables - s++)) ? 1 : 0); knar_[7] = 0; assert((k_[ntables - 8] > 0)); case 7: k_[ntables - 7] = kk / ntables + ((rem >= (ntables - s++)) ? 1 : 0); knar_[6] = 0; assert((k_[ntables - 7] > 0)); case 6: k_[ntables - 6] = kk / ntables + ((rem >= (ntables - s++)) ? 1 : 0); knar_[5] = 0; assert((k_[ntables - 6] > 0)); case 5: k_[ntables - 5] = kk / ntables + ((rem >= (ntables - s++)) ? 1 : 0); knar_[4] = 0; assert((k_[ntables - 5] > 0)); case 4: k_[ntables - 4] = kk / ntables + ((rem >= (ntables - s++)) ? 1 : 0); knar_[3] = 0; assert((k_[ntables - 4] > 0)); case 3: k_[ntables - 3] = kk / ntables + ((rem >= (ntables - s++)) ? 1 : 0); knar_[2] = 0; assert((k_[ntables - 3] > 0)); case 2: k_[ntables - 2] = kk / ntables + ((rem >= (ntables - s++)) ? 1 : 0); knar_[1] = 0; assert((k_[ntables - 2] > 0)); case 1: k_[ntables - 1] = kk / ntables; knar_[0] = 0; assert((k_[ntables - 1] > 0)); } lb[0] = 0; ub[0] = k_[0]; for(int i = 1; i < ntables; i++) { lb[i] = lb[i-1] + k_[i-1]; ub[i] = ub[i-1] + k_[i]; } for(int i=0; i= lb[j] && pivots[i] < ub[j]) { knar_[j]++; } } } int _mzd_ple_submatrix(mzd_t *A, rci_t const start_row, rci_t const stop_row, rci_t const start_col, int const k, mzp_t *P, mzp_t *Q, rci_t *pivots, rci_t *done, rci_t *done_row, wi_t const splitblock) { word bm[__M4RI_PLE_NTABLES * __M4RI_MAXKAY]; wi_t os[__M4RI_PLE_NTABLES * __M4RI_MAXKAY]; /* we're essentially constructing a submatrix but cheaply */ wi_t const width = A->width; rci_t const ncols = A->ncols; int const flags = A->flags; word high_bitmask = A->high_bitmask; if (A->width > splitblock) { A->width = splitblock; A->ncols = splitblock * m4ri_radix; A->flags &= mzd_flag_multiple_blocks; A->flags |= (mzd_flag_windowed_zerooffset | mzd_flag_windowed_zeroexcess); A->high_bitmask = m4ri_ffff; /* No need to set mzd_flag_windowed_ownsblocks, because we won't free A until it's elements are restored below. */ } int curr_pos; int rank = 0; for(curr_pos = 0; curr_pos < k; ++curr_pos) { os[curr_pos] = (start_col + curr_pos) / m4ri_radix; bm[curr_pos] = m4ri_one << ((start_col + curr_pos) % m4ri_radix); int found = 0; /* search for some pivot */ rci_t i; for(i = start_row + rank; i < stop_row; ++i) { word const tmp = mzd_read_bits(A, i, start_col, curr_pos + 1); if(tmp) { word *Arow = A->rows[i]; /* clear before but preserve transformation matrix */ for (rci_t l = 0; l < rank; ++l) if(done[l] < i) { if((Arow[os[pivots[l]]] & bm[pivots[l]])) mzd_row_add_offset(A, i, start_row + l, start_col + pivots[l] + 1); done[l] = i; /* encode up to which row we added for l already */ } if(mzd_read_bit(A, i, start_col + curr_pos)) { found = 1; break; } } } if (found) { P->values[start_row + rank] = i; mzd_row_swap(A, i, start_row + rank); Q->values[start_row + rank] = start_col + curr_pos; pivots[rank] = curr_pos; done[rank] = i; rank++; } } /* finish submatrix */ *done_row = _max_value(done, rank); for(rci_t c2 = 0; c2 < rank && start_col + pivots[c2] < A->ncols -1; ++c2) for(rci_t r2 = done[c2] + 1; r2 <= *done_row; ++r2) if(mzd_read_bit(A, r2, start_col + pivots[c2])) mzd_row_add_offset(A, r2, start_row + c2, start_col + pivots[c2] + 1); /* reset to original size */ A->ncols = ncols; A->width = width; A->flags = flags; A->high_bitmask = high_bitmask; __M4RI_DD_MZD(A); __M4RI_DD_MZP(P); __M4RI_DD_MZP(Q); __M4RI_DD_INT(curr_pos); return rank; } /* create a table of all 2^k linear combinations */ void mzd_make_table_ple(mzd_t const *A, rci_t r, rci_t writecol, int k, int knar, ple_table_t *table, rci_t *offsets, int base, rci_t readcol) { mzd_t *T = table->T; rci_t *E = table->E; rci_t *M = table->M; word *B = table->B; // Note that this restricts the number of columns of any matrix to __M4RI_MAX_MZD_BLOCKSIZE * // radix / twokay = 268 million. assert(!(T->flags & mzd_flag_multiple_blocks)); wi_t const writeblock = writecol / m4ri_radix; wi_t const readblock = readcol / m4ri_radix; assert(writeblock - readblock <= 1); int const twokay = __M4RI_TWOPOW(knar); wi_t const wide = T->width - writeblock; wi_t const count = (wide + 7) / 8; int const entry_point = wide % 8; wi_t const next_row_offset = writeblock + T->rowstride - T->width; word *a; word *ti1 = T->rows[0] + writeblock; word *ti = ti1 + T->rowstride; M[0] = 0; E[0] = 0; B[0] = 0; for (int i = 1; i < twokay; ++i) { T->rows[i][readblock] = 0; /* we make sure that we can safely add from readblock */ rci_t rowneeded = r + m4ri_codebook[knar]->inc[i - 1]; a = A->rows[rowneeded] + writeblock; /* Duff's device loop unrolling */ wi_t n = count; switch (entry_point) { case 0: do { *(ti++) = *(a++) ^ *(ti1++); case 7: *(ti++) = *(a++) ^ *(ti1++); case 6: *(ti++) = *(a++) ^ *(ti1++); case 5: *(ti++) = *(a++) ^ *(ti1++); case 4: *(ti++) = *(a++) ^ *(ti1++); case 3: *(ti++) = *(a++) ^ *(ti1++); case 2: *(ti++) = *(a++) ^ *(ti1++); case 1: *(ti++) = *(a++) ^ *(ti1++); } while (--n > 0); } ti += next_row_offset; ti1 += next_row_offset; /* U is a basis but not the canonical basis, so we need to read what element we just created from T */ E[ mzd_read_bits_int(T, i, writecol, k) ] = i; M[ m4ri_spread_bits(m4ri_codebook[k]->ord[i], offsets, knar, base) ] = i; } /* We need fix the table to update the transformation matrix correctly; e.g. if the first row has [1 0 1] and we clear a row below with [1 0 1] we need to encode that this row is cleared by adding the first row only ([1 0 0]). */ int const bits_to_read = MIN(m4ri_radix, T->ncols - readcol); for(int i = 1; i < twokay; ++i) { word const fix = m4ri_spread_bits(__M4RI_CONVERT_TO_WORD(m4ri_codebook[k]->ord[i]), offsets, knar, base); mzd_xor_bits(T, i, writecol, k, fix); B[i] = mzd_read_bits(T, i, readcol, bits_to_read); } __M4RI_DD_MZD(T); __M4RI_DD_RCI_ARRAY(E, twokay); __M4RI_DD_RCI_ARRAY(M, twokay); } #define N 2 #include "ple_russian_template.h" #undef N #define N 3 #include "ple_russian_template.h" #undef N #define N 4 #include "ple_russian_template.h" #undef N #define N 5 #include "ple_russian_template.h" #undef N #define N 6 #include "ple_russian_template.h" #undef N #define N 7 #include "ple_russian_template.h" #undef N #define N 8 #include "ple_russian_template.h" #undef N void _mzd_ple_a10(mzd_t *A, mzp_t const *P, rci_t const start_row, rci_t const start_col, wi_t const addblock, int const k, rci_t *pivots) { if(addblock == A->width) return; /* perform needed row swaps */ for(rci_t i = start_row; i < start_row + k; ++i) { _mzd_row_swap(A, i, P->values[i], addblock); } for(int i = 1; i < k; ++i) { word const tmp = mzd_read_bits(A, start_row + i, start_col, pivots[i]); word *target = A->rows[start_row + i]; for(int j = 0; j < i; ++j) { if((tmp & m4ri_one << pivots[j])) { word const *source = A->rows[start_row + j]; for(wi_t w = addblock; w < A->width; ++w) { target[w] ^= source[w]; } } } } __M4RI_DD_MZD(A); __M4RI_DD_MZP(P); } void _mzd_ple_a11_1(mzd_t *A, rci_t const start_row, rci_t const stop_row, rci_t const start_col, wi_t const addblock, int const k, ple_table_t const *T0) { wi_t const wide = A->width - addblock; if (wide <= 0) return; for(rci_t i = start_row; i < stop_row; ++i) { rci_t x0 = T0->M[mzd_read_bits_int(A,i,start_col, k)]; word const *s0 = T0->T->rows[x0] + addblock; word *t = A->rows[i] + addblock; _mzd_combine(t, s0, wide); } __M4RI_DD_MZD(A); } /* extract E from A for table creation */ mzd_t *_mzd_ple_to_e(mzd_t *E, mzd_t const *A, rci_t r, rci_t c, int k, rci_t *offsets) { /* this function call is now rather cheap, but it could be avoided completetly if needed */ rci_t startcol = (c / m4ri_radix) * m4ri_radix; mzd_submatrix(E, A, r, 0, r+k, A->ncols); for(rci_t i = 0; i < k; ++i) { for(rci_t j = startcol; j < c + offsets[i]; j+=m4ri_radix) mzd_clear_bits(E, i, j, MIN(c + offsets[i] - j, m4ri_radix)); } __M4RI_DD_MZD(E); return E; } /* method of many people factorisation */ rci_t _mzd_ple_russian(mzd_t *A, mzp_t *P, mzp_t *Q, int k) { rci_t const nrows = A->nrows; rci_t const ncols = A->ncols; rci_t curr_row = 0; rci_t curr_col = 0; rci_t done_row = 0; int knar = 0; /** compute good k **/ if(k == 0) { /* __M4RI_CPU_L2_CACHE == __M4RI_PLE_NTABLES * 2^k * B->width * 8 */ k = (int)log2((__M4RI_CPU_L2_CACHE/8)/(double)A->width/(double)__M4RI_PLE_NTABLES); rci_t const klog = round(0.75 * log2_floor(MIN(nrows, ncols))); if(klog < k) k = klog; if (k<2) k = 2; else if(k>8) k = 8; } int kk = __M4RI_PLE_NTABLES * k; assert(kk <= m4ri_radix); /** initialise permutations as identity **/ for(rci_t i = 0; i < ncols; ++i) Q->values[i] = i; for(rci_t i = 0; i < nrows; ++i) P->values[i] = i; ple_table_t *T[__M4RI_PLE_NTABLES]; for(int i=0; i<__M4RI_PLE_NTABLES; i++) T[i] = ple_table_init(k, ncols); mzd_t *U = mzd_init(kk, ncols); /* these are the elimination lookups */ rci_t *done = (rci_t*)m4ri_mm_malloc(kk * sizeof(rci_t)); rci_t *pivots = (rci_t*)m4ri_mm_malloc(kk * sizeof(rci_t)); /** * The algorithm proceeds as follows */ while(curr_col < ncols && curr_row < nrows) { if(curr_col + kk > ncols) kk = ncols - curr_col; /** * 1. compute PLE factorisation for the knar x knar submatrix A00 \verbatim m4ri_radix * splitblock -------------------------------------- | A00 | A10 | | | | -------------------------------------- knar | A01 | A11 | | | | -------------------------------------- done_row | A02 | A12 | | | | | | | | | | | | | | | | -------------------------------------- \endverbatim */ /* + 8 blocks comes from 64 byte cache line, rest is minimum required and maximum possible */ wi_t splitblock = MIN( MAX( (curr_col + kk) / m4ri_radix + 1, (curr_col / m4ri_radix) + 8 ), A->width ); knar = _mzd_ple_submatrix(A, curr_row, nrows, curr_col, kk, P, Q, pivots, done, &done_row, splitblock); /** * 2. update A10 */ _mzd_ple_a10(A, P, curr_row, curr_col, splitblock, knar, pivots); /** * 3. extract U from A0 = (A00 | A10) */ _mzd_ple_to_e(U, A, curr_row, curr_col, knar, pivots); // treat no-pivot-was-found case if (knar == 0) { curr_col += kk; curr_row += knar; rci_t i = curr_row; rci_t j = curr_col; int found = mzd_find_pivot(A, curr_row, curr_col, &i, &j); if(found) { P->values[curr_row] = i; Q->values[curr_row] = j; mzd_row_swap(A, curr_row, i); wi_t const wrd = j / m4ri_radix; word const bm = m4ri_one << (j % m4ri_radix); if (j + 1 < A->ncols) for(rci_t l = curr_row + 1; l < nrows; ++l) if(A->rows[l][wrd] & bm) mzd_row_add_offset(A, l, curr_row, j + 1); curr_col = j + 1; ++curr_row; } else { break; } continue; } int k_[__M4RI_PLE_NTABLES], knar_[__M4RI_PLE_NTABLES], ntables = 0; if (__M4RI_PLE_NTABLES >= 8 && kk >= 7*k && kk >= 8) ntables = 8; else if (__M4RI_PLE_NTABLES >= 7 && kk >= 6*k && kk >= 7) ntables = 7; else if (__M4RI_PLE_NTABLES >= 6 && kk >= 5*k && kk >= 6) ntables = 6; else if (__M4RI_PLE_NTABLES >= 5 && kk >= 4*k && kk >= 5) ntables = 5; else if (__M4RI_PLE_NTABLES >= 4 && kk >= 3*k && kk >= 4) ntables = 4; else if (__M4RI_PLE_NTABLES >= 3 && kk >= 2*k && kk >= 3) ntables = 3; else if (__M4RI_PLE_NTABLES >= 2 && kk >= k && kk >= 2) ntables = 2; else ntables = 1; _kk_setup(kk, knar, k_, knar_, pivots, ntables); /** * 4. generate multiplication and inversion tables T amd E from U */ rci_t i_knar = 0; rci_t i_curr_col = curr_col; rci_t *i_pivots = pivots; int i_base = 0; for(int i=0; iT, T[0]->E); break; default: m4ri_die("ntables = %d not supported.\n",ntables); } curr_col += kk; curr_row += knar; } /* Now compressing L */ for (rci_t j = 0; j < curr_row; ++j){ if (Q->values[j] > j) { mzd_col_swap_in_rows(A, Q->values[j], j, j, curr_row); } } mzp_t *Qbar = mzp_init_window(Q, 0, curr_row); mzd_apply_p_right_trans_even_capped(A, Qbar, curr_row, 0); mzp_free_window(Qbar); mzd_free(U); for(int i=0; i<__M4RI_PLE_NTABLES; i++) { ple_table_free(T[i]); } m4ri_mm_free(done); m4ri_mm_free(pivots); __M4RI_DD_MZD(A); __M4RI_DD_MZP(P); __M4RI_DD_MZP(Q); __M4RI_DD_RCI(curr_row); return curr_row; } rci_t _mzd_pluq_russian(mzd_t *A, mzp_t *P, mzp_t *Q, int const k) { rci_t r = _mzd_ple_russian(A, P, Q, k); mzd_apply_p_right_trans_tri(A, Q); return r; } m4ri-20140914/m4ri/solve.c0000644000175000017500000001245412354166226011740 00000000000000 /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2008 Jean-Guillaume.Dumas@imag.fr * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "solve.h" #include "strassen.h" #include "ple.h" #include "triangular.h" #include "mzp.h" int mzd_solve_left(mzd_t *A, mzd_t *B, int const cutoff, int const inconsistency_check) { if(A->ncols > B->nrows) m4ri_die("mzd_solve_left: A ncols (%d) must be smaller than B nrows (%d).\n", A->ncols, B->nrows); return _mzd_solve_left(A, B, cutoff, inconsistency_check); } int mzd_pluq_solve_left (mzd_t const *A, rci_t rank, mzp_t const *P, mzp_t const *Q, mzd_t *B, int const cutoff, int const inconsistency_check) { if(A->ncols > B->nrows) m4ri_die("mzd_pluq_solve_left: A ncols (%d) need to be lower than B nrows (%d).\n", A->ncols, B->nrows); if(P->length != A->nrows) m4ri_die("mzd_pluq_solve_left: A nrows (%d) need to match P size (%d).\n", A->nrows, P->length); if(Q->length != A->ncols) m4ri_die("mzd_pluq_solve_left: A ncols (%d) need to match Q size (%d).\n", A->ncols, P->length); return _mzd_pluq_solve_left (A, rank, P, Q, B, cutoff, inconsistency_check); } int _mzd_pluq_solve_left(mzd_t const *A, rci_t rank, mzp_t const *P, mzp_t const *Q, mzd_t *B, int const cutoff, int const inconsistency_check) { /** A is supposed to store L lower triangular and U upper triangular * B is modified in place * (Bi's in the comments are just modified versions of B) * PLUQ = A * 1) P B2 = B1 * 2) L B3 = B2 * 3) U B4 = B3 * 4) Q B5 = B4 */ int retval = 0; /* P B2 = B1 or B2 = P^T B1 */ mzd_apply_p_left(B, P); /* L B3 = B2 */ /* view on the upper part of L */ mzd_t const *LU = mzd_init_window_const(A, 0, 0, rank, rank); mzd_t *Y1 = mzd_init_window(B, 0, 0, rank, B->ncols); mzd_trsm_lower_left(LU, Y1, cutoff); if (inconsistency_check) { /* Check for inconsistency */ /** FASTER without this check; update with the lower part of L */ mzd_t const *H = mzd_init_window_const(A, rank, 0, A->nrows, rank); mzd_t *Y2 = mzd_init_window(B, rank, 0, A->nrows, B->ncols); if(A->nrows < B->nrows) { mzd_t *Y3 = mzd_init_window(B, A->nrows, 0, B->nrows, B->ncols); mzd_set_ui(Y3, 0); mzd_free_window(Y3); } mzd_addmul(Y2, H, Y1, cutoff); /* * test whether Y2 is the zero matrix */ if(!mzd_is_zero(Y2)) { retval = -1; } mzd_free_window((mzd_t*)H); mzd_free_window(Y2); } /* U B4 = B3 */ mzd_trsm_upper_left(LU, Y1, cutoff); mzd_free_window((mzd_t*)LU); mzd_free_window(Y1); if (!inconsistency_check) { /** Default is to set the undefined bits to zero if inconsistency * has been checked then Y2 bits are already all zeroes thus this * clearing is not needed */ for(rci_t i = rank; i < B->nrows; ++i) { for(rci_t j = 0; j < B->ncols; j += m4ri_radix) { mzd_clear_bits(B, i, j, MIN(m4ri_radix, B->ncols - j)); } } } /* Q B5 = B4 or B5 = Q^T B4 */ mzd_apply_p_left_trans(B, Q); /* P L U Q B5 = B1 */ __M4RI_DD_MZD(B); __M4RI_DD_INT(retval); return retval; } int _mzd_solve_left(mzd_t *A, mzd_t *B, int const cutoff, int const inconsistency_check) { /** * B is modified in place * (Bi's in the comments are just modified versions of B) * 1) PLUQ = A * 2) P B2 = B1 * 3) L B3 = B2 * 4) U B4 = B3 * 5) Q B5 = B4 */ mzp_t *P = mzp_init(A->nrows); mzp_t *Q = mzp_init(A->ncols); /* PLUQ = A */ rci_t rank = _mzd_pluq(A, P, Q, cutoff); /* 2, 3, 4, 5 */ int retval = mzd_pluq_solve_left(A, rank, P, Q, B, cutoff, inconsistency_check); mzp_free(P); mzp_free(Q); __M4RI_DD_MZD(A); __M4RI_DD_MZD(B); return retval; } mzd_t *mzd_kernel_left_pluq(mzd_t *A, int const cutoff) { mzp_t *P = mzp_init(A->nrows); mzp_t *Q = mzp_init(A->ncols); rci_t r = mzd_pluq(A, P, Q, cutoff); if (r == A->ncols) { mzp_free(P); mzp_free(Q); __M4RI_DD_MZD(A); return NULL; } mzd_t *U = mzd_init_window(A, 0, 0, r, r); mzd_t *R = mzd_init(A->ncols, A->ncols - r); mzd_t *RU = mzd_init_window(R, 0, 0, r, R->ncols); for(rci_t i=0; i< r ; i++) { for(rci_t j=0; j< RU->ncols; j+=m4ri_radix) { const int workload = MIN(m4ri_radix, RU->ncols - j); mzd_xor_bits(RU, i, j, workload, mzd_read_bits(A, i, r + j, workload)); } } mzd_trsm_upper_left(U, RU, cutoff); for(rci_t i = 0; i < R->ncols; ++i) { mzd_write_bit(R, r + i, i, 1); } mzd_apply_p_left_trans(R, Q); mzp_free(P); mzp_free(Q); mzd_free_window(RU); mzd_free_window(U); __M4RI_DD_MZD(A); __M4RI_DD_MZD(R); return R; } m4ri-20140914/m4ri/echelonform.c0000644000175000017500000000701612354166226013107 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2010 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "echelonform.h" #include "brilliantrussian.h" #include "ple.h" #include "triangular.h" rci_t mzd_echelonize(mzd_t *A, int full) { return _mzd_echelonize_m4ri(A, full, 0, 1, __M4RI_ECHELONFORM_CROSSOVER_DENSITY); } rci_t mzd_echelonize_m4ri(mzd_t *A, int full, int k) { return _mzd_echelonize_m4ri(A, full, k, 0, 1.0); } rci_t mzd_echelonize_pluq(mzd_t *A, int full) { mzp_t *P = mzp_init(A->nrows); mzp_t *Q = mzp_init(A->ncols); rci_t r; if(full) { #if 0 r = mzd_pluq(A, P, Q, 0); mzd_t *U = mzd_init_window(A, 0, 0, r, r); mzd_t *B = mzd_init_window(A, 0, r, r, A->ncols); if(r!=A->ncols) mzd_trsm_upper_left(U, B, 0); if(r) mzd_set_ui(U, 0); for(rci_t i = 0; i < r; ++i) mzd_write_bit(A, i, i, 1); mzd_free_window(U); mzd_free_window(B); if(r) { mzd_t *A0 = mzd_init_window(A, 0, 0, r, A->ncols); mzd_apply_p_right(A0, Q); mzd_free_window(A0); } else { mzd_apply_p_right(A, Q); } #else r = mzd_pluq(A, P, Q, 0); mzd_t *U = mzd_init_window(A, 0, 0, r, r); const rci_t r_radix = m4ri_radix*(r/m4ri_radix); if(r_radix == r && r!=A->ncols) { mzd_t *B = mzd_init_window(A, 0, r, r, A->ncols); if(r!=A->ncols) mzd_trsm_upper_left(U, B, 0); mzd_free_window(B); } else if (r_radix != r && r!=A->ncols) { assert(r_radix < r); if(A->ncols > r_radix+m4ri_radix) { mzd_t *B0 = mzd_submatrix(NULL, A, 0, r_radix, r, r_radix+m4ri_radix); mzd_t *B0w = mzd_init_window( A, 0, r_radix, r, r_radix+m4ri_radix); mzd_t *B1 = mzd_init_window(A, 0, r_radix+m4ri_radix, r, A->ncols); mzd_trsm_upper_left(U, B0, 0); mzd_trsm_upper_left(U, B1, 0); mzd_copy(B0w, B0); mzd_free(B0); mzd_free_window(B0w); mzd_free_window(B1); } else { mzd_t *B = mzd_submatrix(NULL, A, 0, r_radix, r, A->ncols); mzd_t *Bw = mzd_init_window(A, 0, r_radix, r, A->ncols); mzd_trsm_upper_left(U, B, 0); mzd_copy(Bw, B); mzd_free_window(Bw); mzd_free(B); } } mzd_set_ui(U, 1); mzd_free_window(U); if(r) { mzd_t *A0 = mzd_init_window(A, 0, 0, r, A->ncols); mzd_apply_p_right(A0, Q); mzd_free_window(A0); } #endif } else { r = mzd_ple(A, P, Q, 0); for(rci_t i = 0; i < r; ++i) { for(rci_t j = 0; j <= i; j += m4ri_radix) { int const length = MIN(m4ri_radix, i - j + 1); mzd_clear_bits(A, i, j, length); } mzd_write_bit(A, i, Q->values[i], 1); } } if(r != A->nrows) { mzd_t *R = mzd_init_window(A, r, 0, A->nrows, A->ncols); mzd_set_ui(R, 0); mzd_free_window(R); } mzp_free(P); mzp_free(Q); __M4RI_DD_MZD(A); __M4RI_DD_RCI(r); return r; } m4ri-20140914/m4ri/mmc.c0000644000175000017500000000610712354166226011362 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2007, 2008 Gregory Bard * Copyright (C) 2008 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mmc.h" #ifdef __M4RI_ENABLE_MMC /** * The actual memory block cache. */ mmb_t m4ri_mmc_cache[__M4RI_MMC_NBLOCKS]; #endif // __M4RI_ENABLE_MMC /** * \brief Allocate size bytes. * * \param size Number of bytes. * * \return pointer to allocated memory block. */ void *m4ri_mmc_malloc(size_t size) { #ifdef __M4RI_ENABLE_MMC void *ret = NULL; #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif mmb_t *mm = m4ri_mmc_cache; if (size <= __M4RI_MMC_THRESHOLD) { for (int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if(mm[i].size == size) { ret = mm[i].data; mm[i].data = NULL; mm[i].size = 0; break; } } } #if __M4RI_HAVE_OPENMP } #endif if (ret) return ret; else return m4ri_mm_malloc(size); #else // __M4RI_ENABLE_MMC return m4ri_mm_malloc(size); #endif // __M4RI_ENABLE_MMC } /** * \brief Free the data pointed to by condemned of the given size. * * \param condemned Pointer to memory. * \param size Number of bytes. */ void m4ri_mmc_free(void *condemned, size_t size) { #ifdef __M4RI_ENABLE_MMC #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif static int j = 0; mmb_t *mm = m4ri_mmc_cache; if (size < __M4RI_MMC_THRESHOLD) { for(int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if(mm[i].size == 0) { mm[i].size = size; mm[i].data = condemned; goto done; } } m4ri_mm_free(mm[j].data); mm[j].size = size; mm[j].data = condemned; j = (j+1) % __M4RI_MMC_NBLOCKS; } else { m4ri_mm_free(condemned); } done: ; #if __M4RI_HAVE_OPENMP } #endif // __M4RI_HAVE_OPENMP #else // __M4RI_ENABLE_MMC m4ri_mm_free(condemned); #endif // __M4RI_ENABLE_MMC } /** * \brief Cleans up memory block cache. * * This function is called automatically when the shared library is unloaded. * * \warning Not thread safe. */ void m4ri_mmc_cleanup(void) { #ifdef __M4RI_ENABLE_MMC #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif mmb_t *mm = m4ri_mmc_cache; for(int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if (mm[i].size) m4ri_mm_free(mm[i].data); mm[i].size = 0; } #if __M4RI_HAVE_OPENMP } #endif // __M4RI_HAVE_OPENMP #endif // __M4RI_ENABLE_MMC } m4ri-20140914/m4ri/debug_dump.c0000644000175000017500000001144312405100616012704 00000000000000/****************************************************************************** * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2011 Carlo Wood * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ ******************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mzd.h" #include "mzp.h" #if __M4RI_DEBUG_DUMP static unsigned long dd_sequence_number = 0; static void entry(char const* function, char const* file, int line) { #if !__M4RI_DD_QUIET printf("Sequence#: %ld; %s @ %s:%d; ", dd_sequence_number, function, file, line); #endif ++dd_sequence_number; } static inline void consistency_check_row(mzd_t const *M, rci_t row) { assert(row >= 0 && row < M->nrows); assert(M->rows[row] == mzd_row(M, row)); if (mzd_is_windowed(M)) return; // Check that the excess bits are zero. assert((M->rows[row][M->width - 1] & ~M->high_bitmask) == 0); // Check that the padding bits are zero, if any. assert(M->width == M->rowstride || M->rows[row][M->width] == 0); } static void consistency_check(mzd_t const *M) { assert(M->nrows >= 0 && M->ncols >= 0); assert(M->width * m4ri_radix >= M->ncols); assert((M->width - 1) * m4ri_radix < M->ncols); assert(M->width < mzd_paddingwidth || (M->rowstride & 1) == 0); //assert((M->blockrows_mask + 1) == (1 << M->blockrows_log)); assert((1 << M->blockrows_log) * M->rowstride <= __M4RI_MAX_MZD_BLOCKSIZE); assert((1 << M->blockrows_log) * M->rowstride > __M4RI_MAX_MZD_BLOCKSIZE / 2); assert((M->width > 1 && M->high_bitmask == __M4RI_LEFT_BITMASK((M->ncols) % m4ri_radix)) || (M->width < 2 && M->high_bitmask == __M4RI_MIDDLE_BITMASK(M->ncols, 0))); assert(((M->flags & mzd_flag_nonzero_excess) == 0) == ((M->ncols % m4ri_radix == 0))); assert((M->flags & mzd_flag_windowed_zeroexcess) == 0 || ((M->ncols) % m4ri_radix == 0)); assert((((M->flags & mzd_flag_multiple_blocks) == 0) == (mzd_row_to_block(M, M->nrows - 1) == 0))); int n = 0; rci_t counted = 0; word* ptr = mzd_first_row(M); int row_count = mzd_rows_in_block(M, 0); while(1) { while (row_count--) { assert(ptr == M->rows[counted++]); ptr += M->rowstride; } ++n; row_count = mzd_rows_in_block(M, n); if (row_count <= 0) break; ptr = mzd_first_row_next_block(M, n); } assert(M->ncols == 0 || counted == M->nrows); if (mzd_is_windowed(M)) return; assert(M->rowstride == M->width || (M->rowstride == M->width + 1 && M->width >= mzd_paddingwidth)); for (rci_t r = 0; r < M->nrows; ++r) { consistency_check_row(M, r); } } void m4ri_dd_int(char const* function, char const* file, int line, int i) { entry(function, file, line); #if !__M4RI_DD_QUIET printf("int: %d\n", i); #endif } void m4ri_dd_rci(char const* function, char const* file, int line, rci_t rci) { entry(function, file, line); #if !__M4RI_DD_QUIET printf("rci: %d\n", rci); #endif } void m4ri_dd_rci_array(char const* function, char const* file, int line, rci_t *rciptr, int len) { entry(function, file, line); #if !__M4RI_DD_QUIET word hash = 0; for (int i = 0; i < len; ++i) hash ^= rotate_word(rciptr[i], i % m4ri_radix); printf("rci array (size %d) hash: %llx\n", len, hash); #endif } void m4ri_dd_rawrow(char const* function, char const* file, int line, word const* rowptr, wi_t wide) { entry(function, file, line); #if !__M4RI_DD_QUIET word hash = calculate_hash(rowptr, wide); printf("raw row (%d words) hash: %llx\n", wide, hash); #endif } void m4ri_dd_row(char const* function, char const* file, int line, mzd_t const* M, rci_t row) { entry(function, file, line); consistency_check_row(M, row); #if !__M4RI_DD_QUIET word hash = calculate_hash(M->rows[row], M->width); printf("row %d hash: %llx\n", row, hash); #endif } void m4ri_dd_mzd(char const* function, char const* file, int line, mzd_t const* M) { entry(function, file, line); consistency_check(M); #if !__M4RI_DD_QUIET word hash = 0; for (rci_t r = 0; r < M->nrows; ++r) hash ^= rotate_word(calculate_hash(M->rows[r], M->width), r % m4ri_radix); printf("mzd hash: %llx\n", hash); #endif } void m4ri_dd_mzp(char const* function, char const* file, int line, mzp_t const* P) { entry(function, file, line); #if !__M4RI_DD_QUIET word hash = 0; for (rci_t i = 0; i < P->length; ++i) hash ^= rotate_word(P->values[i], i % m4ri_radix); printf("mzp hash: %llx\n", hash); #endif } #endif m4ri-20140914/m4ri/io.c0000644000175000017500000002530312354166226011214 00000000000000/******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2011 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "m4ri_config.h" #if __M4RI_HAVE_LIBPNG #include #endif //__M4RI_HAVE_LIBPNG #include "io.h" #include "echelonform.h" void mzd_info(const mzd_t *A, int do_rank) { printf("nrows: %6zu, ncols: %6zu, density: %6.5f, hash: 0x%016zx",(size_t)A->nrows,(size_t)A->ncols,mzd_density(A,1),mzd_hash(A)); if(do_rank) { mzd_t *AA = mzd_copy(NULL, A); printf(", rank: %6zu\n",(size_t)mzd_echelonize(AA,0)); mzd_free(AA); } else { printf("\n"); } } #define SAFECHAR (m4ri_radix + m4ri_radix / 4 + 1) void mzd_print(mzd_t const *M) { char temp[SAFECHAR]; for (rci_t i = 0; i < M->nrows; ++i) { printf("["); word *row = M->rows[i]; for (wi_t j = 0; j < M->width - 1; ++j) { m4ri_word_to_str(temp, row[j], 1); printf("%s|", temp); } row = row + M->width - 1; int const wide = (M->ncols % m4ri_radix) ? M->ncols % m4ri_radix : m4ri_radix; for (int j = 0; j < wide; ++j) { if(j != 0 && (j % 4) == 0) printf(":"); if (__M4RI_GET_BIT(*row, j)) printf("1"); else printf(" "); } printf("]\n"); } } void mzd_print_row(mzd_t const *M, const rci_t i) { char temp[SAFECHAR]; printf("["); word *row = M->rows[i]; for (wi_t j = 0; j < M->width - 1; ++j) { m4ri_word_to_str(temp, row[j], 1); printf("%s|", temp); } row = row + M->width - 1; int const wide = (M->ncols % m4ri_radix) ? M->ncols % m4ri_radix : m4ri_radix; for (int j = 0; j < wide; ++j) { if(j != 0 && (j % 4) == 0) printf(":"); if (__M4RI_GET_BIT(*row, j)) printf("1"); else printf(" "); } printf("]\n"); } #if __M4RI_HAVE_LIBPNG #define PNGSIGSIZE 8 mzd_t * mzd_from_png(const char *fn, int verbose) { int retval = 0; mzd_t *A = NULL; png_byte pngsig[PNGSIGSIZE]; FILE *fh = fopen(fn,"rb"); if (!fh) { if (verbose) printf("Could not open file '%s' for reading\n",fn); return NULL; }; if (fread((char*)pngsig, PNGSIGSIZE, 1, fh) != 1) { if (verbose) printf("Could not read file '%s'\n",fn); retval = 1; goto from_png_close_fh; } if (png_sig_cmp(pngsig, 0, PNGSIGSIZE) != 0) { if (verbose) printf("'%s' is not a PNG file.\n",fn); retval = 2; goto from_png_close_fh; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { if (verbose) printf("failed to initialise PNG read struct.\n"); retval = 3; goto from_png_close_fh; } png_set_user_limits(png_ptr, 0x7fffffffL, 0x7fffffffL); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { if (verbose) printf("failed to initialise PNG info struct\n"); retval = 3; goto from_png_destroy_read_struct; } png_init_io(png_ptr, fh); png_set_sig_bytes(png_ptr, PNGSIGSIZE); png_read_info(png_ptr, info_ptr); const png_uint_32 m = png_get_image_height(png_ptr, info_ptr); const png_uint_32 n = png_get_image_width(png_ptr, info_ptr); const png_uint_32 bit_depth = png_get_bit_depth(png_ptr, info_ptr); const png_uint_32 channels = png_get_channels(png_ptr, info_ptr); const png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr); const png_uint_32 compression_type = png_get_compression_type(png_ptr, info_ptr); const png_uint_32 interlace_type = png_get_interlace_type(png_ptr, info_ptr); if (interlace_type != PNG_INTERLACE_NONE) { if (verbose) printf("interlaced images not supported\n"); goto from_png_destroy_read_struct; }; if (verbose) printf("reading %u x %u matrix (bit depth: %u, channels: %u, color type: %u, compression type: %u)\n",(unsigned int)m, (unsigned int)n, (unsigned int)bit_depth, (unsigned int)channels, (unsigned int)color_type, (unsigned int)compression_type); if(color_type != 0 && color_type != 3) { if (verbose) printf("only graycscale and palette colors are supported.\n"); goto from_png_destroy_read_struct; } A = mzd_init(m, n); const word bitmask_end = A->high_bitmask; png_bytep row = m4ri_mm_calloc(sizeof(char),n/8+1); word tmp; wi_t j; png_set_packswap(png_ptr); //png_set_invert_mono(png_ptr); for(rci_t i=0; iwidth-1; j++) { tmp = ((word)row[8*j+7])<<56 | ((word)row[8*j+6])<<48 \ | ((word)row[8*j+5])<<40 | ((word)row[8*j+4])<<32 \ | ((word)row[8*j+3])<<24 | ((word)row[8*j+2])<<16 \ | ((word)row[8*j+1])<< 8 | ((word)row[8*j+0])<< 0; A->rows[i][j] = ~tmp; } tmp = 0; switch((n/8 + ((n%8) ? 1 : 0))%8) { case 0: tmp |= ((word)row[8*j+7])<<56; case 7: tmp |= ((word)row[8*j+6])<<48; case 6: tmp |= ((word)row[8*j+5])<<40; case 5: tmp |= ((word)row[8*j+4])<<32; case 4: tmp |= ((word)row[8*j+3])<<24; case 3: tmp |= ((word)row[8*j+2])<<16; case 2: tmp |= ((word)row[8*j+1])<< 8; case 1: tmp |= ((word)row[8*j+0])<< 0; }; A->rows[i][j] |= (~tmp & bitmask_end); } m4ri_mm_free(row); png_read_end(png_ptr, NULL); from_png_destroy_read_struct: png_destroy_read_struct(&png_ptr, &info_ptr,(png_infopp)0); from_png_close_fh: fclose(fh); if (retval != 0 && A) { mzd_free(A); return NULL; } else { return A; } } int mzd_to_png(const mzd_t *A, const char *fn, int compression_level, const char *comment, int verbose) { FILE *fh = fopen(fn, "wb"); if (!fh) { if(verbose) printf("Could not open file '%s' for writing\n",fn); return 1; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { if(verbose) printf("failed to initialise PNG write struct.\n"); fclose(fh); return 3; } png_set_user_limits(png_ptr, 0x7fffffffL, 0x7fffffffL); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { if (verbose) printf("failed to initialise PNG info struct\n"); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fh); return 3; } if (setjmp(png_jmpbuf(png_ptr))) { if (verbose) printf("error writing PNG file\n"); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fh); return 1; } png_init_io(png_ptr, fh); png_set_compression_level(png_ptr, compression_level); png_set_IHDR(png_ptr, info_ptr, A->ncols, A->nrows, 1, \ PNG_COLOR_TYPE_GRAY, \ PNG_INTERLACE_NONE, \ PNG_COMPRESSION_TYPE_DEFAULT, \ PNG_FILTER_TYPE_DEFAULT); png_text txt_ptr[3]; char pdate[21]; time_t ptime=time(NULL); struct tm *ltime=localtime(&ptime); sprintf(pdate,"%04d/%02d/%02d %02d:%02d:%02d",ltime->tm_year+1900,ltime->tm_mon+1,ltime->tm_mday,ltime->tm_hour,ltime->tm_min,ltime->tm_sec); txt_ptr[0].key="Software"; txt_ptr[0].text="M4RI"; txt_ptr[0].compression=PNG_TEXT_COMPRESSION_NONE; txt_ptr[1].key="Date"; txt_ptr[1].text=pdate; txt_ptr[1].compression=PNG_TEXT_COMPRESSION_NONE; txt_ptr[2].key="Comment"; txt_ptr[2].text=(char*)comment; txt_ptr[2].compression=PNG_TEXT_COMPRESSION_NONE; png_set_text(png_ptr, info_ptr, txt_ptr, 3); png_write_info(png_ptr, info_ptr); png_set_packswap(png_ptr); png_set_invert_mono(png_ptr); png_bytep row = m4ri_mm_calloc(sizeof(char),A->ncols/8+8); wi_t j=0; word tmp = 0; for(rci_t i=0; inrows; i++) { word *rowptr = A->rows[i]; for(j=0; jwidth-1; j++) { tmp = rowptr[j]; row[8*j+0] = (png_byte)((tmp>> 0) & 0xff); row[8*j+1] = (png_byte)((tmp>> 8) & 0xff); row[8*j+2] = (png_byte)((tmp>>16) & 0xff); row[8*j+3] = (png_byte)((tmp>>24) & 0xff); row[8*j+4] = (png_byte)((tmp>>32) & 0xff); row[8*j+5] = (png_byte)((tmp>>40) & 0xff); row[8*j+6] = (png_byte)((tmp>>48) & 0xff); row[8*j+7] = (png_byte)((tmp>>56) & 0xff); } tmp = rowptr[j]; switch( (A->ncols/8 + ((A->ncols%8) ? 1 : 0)) %8 ) { case 0: row[8*j+7] = (png_byte)((tmp>>56) & 0xff); case 7: row[8*j+6] = (png_byte)((tmp>>48) & 0xff); case 6: row[8*j+5] = (png_byte)((tmp>>40) & 0xff); case 5: row[8*j+4] = (png_byte)((tmp>>32) & 0xff); case 4: row[8*j+3] = (png_byte)((tmp>>24) & 0xff); case 3: row[8*j+2] = (png_byte)((tmp>>16) & 0xff); case 2: row[8*j+1] = (png_byte)((tmp>> 8) & 0xff); case 1: row[8*j+0] = (png_byte)((tmp>> 0) & 0xff); }; png_write_row(png_ptr, row); } m4ri_mm_free(row); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fh); return 0; } #endif //__M4RI_HAVE_LIBPNG mzd_t *mzd_from_jcf(const char *fn, int verbose) { int retval = 0; mzd_t *A = NULL; FILE *fh = fopen(fn,"r"); rci_t m,n; long p = 0; long nonzero = 0; if (!fh) { if (verbose) printf("Could not open file '%s' for reading\n",fn); return NULL; } if (fscanf(fh, "%d %d %ld\n%ld\n\n",&m,&n,&p,&nonzero) != 4) { if (verbose) printf("File '%s' does not seem to be in JCF format.",fn); retval = 1; goto from_jcf_close_fh; } if(p != 2) { if (verbose) printf("Expected p==2 but found p==%ld\n",p); retval = 1; goto from_jcf_close_fh; } if (verbose) printf("reading %lu x %lu matrix with at most %ld non-zero entries (density at most: %6.5f)\n", (unsigned long)m, (unsigned long)n, (unsigned long)nonzero, ((double)nonzero)/((double)m*n)); A = mzd_init(m,n); long i = -1; long j = 0; while(fscanf(fh,"%ld\n",&j) == 1) { if (j<0) { i++, j = -j; } if (((j-1) >= n) || (i>= m)) m4ri_die("trying to write to (%ld,%ld) in %ld x %ld matrix\n", i, j-1, m, n); mzd_write_bit(A, i, j-1, 1); }; from_jcf_close_fh: fclose(fh); if(retval != 0 && A) { mzd_free(A); return NULL; } else { return A; } } mzd_t *mzd_from_str(rci_t m, rci_t n, const char *str) { int idx = 0; mzd_t *A = mzd_init(m, n); for(rci_t i=0; inrows; i++) { for(rci_t j=0; jncols; j++) { mzd_write_bit(A, i, j, str[idx++] == '1'); } } return A; } m4ri-20140914/m4ri/djb.c0000644000175000017500000001140512405042607011333 00000000000000/* * \author Martin Kunev original implementation of C99 heap * \author Martin Albrecht adapted to M4RI + DJB map */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include static inline int mzd_compare_rows_revlex(const mzd_t *A, rci_t a, rci_t b) { for(wi_t j=A->width-1; j>=0; j--) { if (A->rows[a][j] < A->rows[b][j]) return 0; if (A->rows[a][j] > A->rows[b][j]) return 1; } return 1; } /** * \brief A Heap */ typedef struct heap { unsigned int size; /*!< Size of the allocated memory (in number of items) */ unsigned int count; /*!< Count of the elements in the heap */ rci_t *data; /*!< Array with the elements */ } heap_t; // Returns the biggest element in the heap #define heap_front(h) (*(h)->data) void heap_free(heap_t *h) { free(h->data); free(h); } static const unsigned int heap_base_size = 4; // Prepares the heap for use heap_t *heap_init() { heap_t * h = (heap_t*)malloc(sizeof(heap_t)); if (h == NULL) m4ri_die("malloc failed.\n"); *h = (heap_t){ .size = heap_base_size, .count = 0, .data = malloc(sizeof(rci_t) * heap_base_size) }; if (h->data == NULL) m4ri_die("malloc failed.\n"); return h; } // Inserts element to the heap void heap_push(struct heap *restrict h, rci_t value, const mzd_t *A) { unsigned int index, parent; // Resize the heap if it is too small to hold all the data if (h->count == h->size) { h->size <<= 1; h->data = realloc(h->data, sizeof(rci_t) * h->size); if (h->data == NULL) m4ri_die("realloc failed.\n"); } // Find out where to put the element and put it for(index = h->count++; index; index = parent) { parent = (index - 1) >> 1; if (mzd_compare_rows_revlex(A, h->data[parent], value)) break; h->data[index] = h->data[parent]; } h->data[index] = value; } // Removes the biggest element from the heap void heap_pop(struct heap *restrict h, const mzd_t *A) { unsigned int index, swap, other; // Remove the biggest element rci_t temp = h->data[--h->count]; // Resize the heap if it's consuming too much memory if ((h->count <= (h->size >> 2)) && (h->size > heap_base_size)) { h->size >>= 1; h->data = realloc(h->data, sizeof(rci_t) * h->size); if (h->data == NULL) m4ri_die("realloc failed.\n"); } // Reorder the elements for(index = 0; 1; index = swap) { // Find the child to swap with swap = (index << 1) + 1; if (swap >= h->count) break; // If there are no children, the heap is reordered other = swap + 1; if ((other < h->count) && mzd_compare_rows_revlex(A, h->data[other], h->data[swap])) swap = other; if (mzd_compare_rows_revlex(A, temp, h->data[swap])) break; // If the bigger child is less than or equal to its parent, the heap is reordered h->data[index] = h->data[swap]; } h->data[index] = temp; } djb_t *djb_compile(mzd_t *A) { heap_t *h = heap_init(); rci_t m = A->nrows; rci_t n = A->ncols; djb_t *z = djb_init(m, n); for (rci_t i=0; i < m; i++) heap_push(h, i, A); // sort by mzd_compare_rows_revlex while (n > 0) { if (mzd_read_bit(A, heap_front(h), n - 1) == 0) { --n; continue; } rci_t temp = heap_front(h); heap_pop(h, A); if (m >= 2 && mzd_read_bit(A, heap_front(h), n - 1)) { mzd_row_add(A, heap_front(h), temp); djb_push_back(z, temp, heap_front(h), source_target); } else { mzd_write_bit(A, temp, n-1, 0); djb_push_back(z, temp, n-1, source_source); } heap_push(h, temp, A); } heap_free(h); return z; } void djb_apply_mzd(djb_t *m, mzd_t *W, const mzd_t *V) { assert(W->width == V->width); rci_t i = m->length; while (i > 0) { --i; if (m->srctyp[i] == source_source) { _mzd_combine(mzd_row(W, m->target[i]), mzd_row(V, m->source[i]), W->width); } else { _mzd_combine(mzd_row(W, m->target[i]), mzd_row(W, m->source[i]), W->width); } } } void djb_print(djb_t *m) { int *iszero = m4ri_mm_malloc(sizeof(int)*m->nrows); for(int i = 0; i < m->nrows; ++i) iszero[i] = 1; rci_t i = m->length; while (i > 0) { --i; if (iszero[m->target[i]]) { if (m->srctyp[i] == source_source) { printf("cpy src[%d] to dst[%d]\n", m->source[i], m->target[i]); } else { printf("cpy dst[%d] to dst[%d]\n", m->source[i], m->target[i]); } iszero[m->target[i]] = 0; } else { if (m->srctyp[i] == source_source) { printf("add src[%d] to dst[%d]\n", m->source[i], m->target[i]); } else { printf("add dst[%d] to dst[%d]\n", m->source[i], m->target[i]); } } } m4ri_mm_free(iszero); } m4ri-20140914/m4ri/mp.c0000644000175000017500000002506612405060273011217 00000000000000 /******************************************************************* * * M4RI: Linear Algebra over GF(2) * * Copyright (C) 2014 Martin Albrecht * * Distributed under the terms of the GNU General Public License (GPL) * version 2 or higher. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * The full text of the GPL is available at: * * http://www.gnu.org/licenses/ * ********************************************************************/ #include "m4ri_config.h" #include "misc.h" #include "mp.h" #include "brilliantrussian.h" #include "strassen.h" #if __M4RI_HAVE_OPENMP #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif #include // Returns true if a is closer to cutoff than a/2. static inline int closer(rci_t a, int cutoff) { return 3 * a < 4 * cutoff; } mzd_t *_mzd_addmul_mp4(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { /** * \todo make sure not to overwrite crap after ncols and before width * m4ri_radix */ rci_t a = A->nrows; rci_t b = A->ncols; rci_t c = B->ncols; /* handle case first, where the input matrices are too small already */ if (closer(A->nrows, cutoff) || closer(A->ncols, cutoff) || closer(B->ncols, cutoff)) { /* we copy the matrix first since it is only constant memory overhead and improves data locality, if you remove it make sure there are no speed regressions */ /* C = _mzd_mul_m4rm(C, A, B, 0, TRUE); */ mzd_t *Cbar = mzd_init(C->nrows, C->ncols); Cbar = _mzd_mul_m4rm(Cbar, A, B, 0, FALSE); mzd_add(C, C, Cbar); mzd_free(Cbar); return C; } /* adjust cutting numbers to work on words */ { rci_t mult = 2 * m4ri_radix; a -= a % mult; b -= b % mult; c -= c % mult; } rci_t anr = ((a / m4ri_radix) >> 1) * m4ri_radix; rci_t anc = ((b / m4ri_radix) >> 1) * m4ri_radix; rci_t bnr = anc; rci_t bnc = ((c / m4ri_radix) >> 1) * m4ri_radix; mzd_t const *A00 = mzd_init_window_const(A, 0, 0, anr, anc); mzd_t const *A01 = mzd_init_window_const(A, 0, anc, anr, 2*anc); mzd_t const *A10 = mzd_init_window_const(A, anr, 0, 2*anr, anc); mzd_t const *A11 = mzd_init_window_const(A, anr, anc, 2*anr, 2*anc); mzd_t const *B00 = mzd_init_window_const(B, 0, 0, bnr, bnc); mzd_t const *B01 = mzd_init_window_const(B, 0, bnc, bnr, 2*bnc); mzd_t const *B10 = mzd_init_window_const(B, bnr, 0, 2*bnr, bnc); mzd_t const *B11 = mzd_init_window_const(B, bnr, bnc, 2*bnr, 2*bnc); mzd_t *C00 = mzd_init_window(C, 0, 0, anr, bnc); mzd_t *C01 = mzd_init_window(C, 0, bnc, anr, 2*bnc); mzd_t *C10 = mzd_init_window(C, anr, 0, 2*anr, bnc); mzd_t *C11 = mzd_init_window(C, anr, bnc, 2*anr, 2*bnc); #pragma omp parallel sections { #pragma omp section { _mzd_addmul_even(C00, A00, B00, cutoff); _mzd_addmul_even(C00, A01, B10, cutoff); } #pragma omp section { _mzd_addmul_even(C01, A00, B01, cutoff); _mzd_addmul_even(C01, A01, B11, cutoff); } #pragma omp section { _mzd_addmul_even(C10, A10, B00, cutoff); _mzd_addmul_even(C10, A11, B10, cutoff); } #pragma omp section { _mzd_addmul_even(C11, A10, B01, cutoff); _mzd_addmul_even(C11, A11, B11, cutoff); } } /* deal with rest */ if (B->ncols > 2 * bnc) { mzd_t const *B_last_col = mzd_init_window_const(B, 0, 2*bnc, A->ncols, B->ncols); mzd_t *C_last_col = mzd_init_window(C, 0, 2*bnc, A->nrows, C->ncols); mzd_addmul_m4rm(C_last_col, A, B_last_col, 0); mzd_free_window((mzd_t*)B_last_col); mzd_free_window(C_last_col); } if (A->nrows > 2 * anr) { mzd_t const *A_last_row = mzd_init_window_const(A, 2*anr, 0, A->nrows, A->ncols); mzd_t const *B_bulk = mzd_init_window_const(B, 0, 0, B->nrows, 2*bnc); mzd_t *C_last_row = mzd_init_window(C, 2*anr, 0, C->nrows, 2*bnc); mzd_addmul_m4rm(C_last_row, A_last_row, B_bulk, 0); mzd_free_window((mzd_t*)A_last_row); mzd_free_window((mzd_t*)B_bulk); mzd_free_window(C_last_row); } if (A->ncols > 2 * anc) { mzd_t const *A_last_col = mzd_init_window_const(A, 0, 2*anc, 2*anr, A->ncols); mzd_t const *B_last_row = mzd_init_window_const(B, 2*bnr, 0, B->nrows, 2*bnc); mzd_t *C_bulk = mzd_init_window(C, 0, 0, 2*anr, 2*bnc); mzd_addmul_m4rm(C_bulk, A_last_col, B_last_row, 0); mzd_free_window((mzd_t*)A_last_col); mzd_free_window((mzd_t*)B_last_row); mzd_free_window(C_bulk); } /* clean up */ mzd_free_window((mzd_t*)A00); mzd_free_window((mzd_t*)A01); mzd_free_window((mzd_t*)A10); mzd_free_window((mzd_t*)A11); mzd_free_window((mzd_t*)B00); mzd_free_window((mzd_t*)B01); mzd_free_window((mzd_t*)B10); mzd_free_window((mzd_t*)B11); mzd_free_window(C00); mzd_free_window(C01); mzd_free_window(C10); mzd_free_window(C11); __M4RI_DD_MZD(C); return C; } mzd_t *_mzd_mul_mp4(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { /** * \todo make sure not to overwrite crap after ncols and before width * m4ri_radix */ rci_t a = A->nrows; rci_t b = A->ncols; rci_t c = B->ncols; /* handle case first, where the input matrices are too small already */ if (closer(A->nrows, cutoff) || closer(A->ncols, cutoff) || closer(B->ncols, cutoff)) { /* we copy the matrix first since it is only constant memory overhead and improves data locality, if you remove it make sure there are no speed regressions */ /* C = _mzd_mul_m4rm(C, A, B, 0, TRUE); */ mzd_t *Cbar = mzd_init(C->nrows, C->ncols); Cbar = _mzd_mul_m4rm(Cbar, A, B, 0, FALSE); mzd_copy(C, Cbar); mzd_free(Cbar); return C; } /* adjust cutting numbers to work on words */ { rci_t mult = 2 * m4ri_radix; a -= a % mult; b -= b % mult; c -= c % mult; } rci_t anr = ((a / m4ri_radix) >> 1) * m4ri_radix; rci_t anc = ((b / m4ri_radix) >> 1) * m4ri_radix; rci_t bnr = anc; rci_t bnc = ((c / m4ri_radix) >> 1) * m4ri_radix; mzd_t const *A00 = mzd_init_window_const(A, 0, 0, anr, anc); mzd_t const *A01 = mzd_init_window_const(A, 0, anc, anr, 2*anc); mzd_t const *A10 = mzd_init_window_const(A, anr, 0, 2*anr, anc); mzd_t const *A11 = mzd_init_window_const(A, anr, anc, 2*anr, 2*anc); mzd_t const *B00 = mzd_init_window_const(B, 0, 0, bnr, bnc); mzd_t const *B01 = mzd_init_window_const(B, 0, bnc, bnr, 2*bnc); mzd_t const *B10 = mzd_init_window_const(B, bnr, 0, 2*bnr, bnc); mzd_t const *B11 = mzd_init_window_const(B, bnr, bnc, 2*bnr, 2*bnc); mzd_t *C00 = mzd_init_window(C, 0, 0, anr, bnc); mzd_t *C01 = mzd_init_window(C, 0, bnc, anr, 2*bnc); mzd_t *C10 = mzd_init_window(C, anr, 0, 2*anr, bnc); mzd_t *C11 = mzd_init_window(C, anr, bnc, 2*anr, 2*bnc); #pragma omp parallel sections { #pragma omp section { _mzd_mul_even(C00, A00, B00, cutoff); _mzd_addmul_even(C00, A01, B10, cutoff); } #pragma omp section { _mzd_mul_even(C01, A00, B01, cutoff); _mzd_addmul_even(C01, A01, B11, cutoff); } #pragma omp section { _mzd_mul_even(C10, A10, B00, cutoff); _mzd_addmul_even(C10, A11, B10, cutoff); } #pragma omp section { _mzd_mul_even(C11, A10, B01, cutoff); _mzd_addmul_even(C11, A11, B11, cutoff); } } /* deal with rest */ if (B->ncols > 2 * bnc) { mzd_t const *B_last_col = mzd_init_window_const(B, 0, 2*bnc, A->ncols, B->ncols); mzd_t *C_last_col = mzd_init_window(C, 0, 2*bnc, A->nrows, C->ncols); mzd_addmul_m4rm(C_last_col, A, B_last_col, 0); mzd_free_window((mzd_t*)B_last_col); mzd_free_window(C_last_col); } if (A->nrows > 2 * anr) { mzd_t const *A_last_row = mzd_init_window_const(A, 2*anr, 0, A->nrows, A->ncols); mzd_t const *B_bulk = mzd_init_window_const(B, 0, 0, B->nrows, 2*bnc); mzd_t *C_last_row = mzd_init_window(C, 2*anr, 0, C->nrows, 2*bnc); mzd_addmul_m4rm(C_last_row, A_last_row, B_bulk, 0); mzd_free_window((mzd_t*)A_last_row); mzd_free_window((mzd_t*)B_bulk); mzd_free_window(C_last_row); } if (A->ncols > 2 * anc) { mzd_t const *A_last_col = mzd_init_window_const(A, 0, 2*anc, 2*anr, A->ncols); mzd_t const *B_last_row = mzd_init_window_const(B, 2*bnr, 0, B->nrows, 2*bnc); mzd_t *C_bulk = mzd_init_window(C, 0, 0, 2*anr, 2*bnc); mzd_addmul_m4rm(C_bulk, A_last_col, B_last_row, 0); mzd_free_window((mzd_t*)A_last_col); mzd_free_window((mzd_t*)B_last_row); mzd_free_window(C_bulk); } /* clean up */ mzd_free_window((mzd_t*)A00); mzd_free_window((mzd_t*)A01); mzd_free_window((mzd_t*)A10); mzd_free_window((mzd_t*)A11); mzd_free_window((mzd_t*)B00); mzd_free_window((mzd_t*)B01); mzd_free_window((mzd_t*)B10); mzd_free_window((mzd_t*)B11); mzd_free_window(C00); mzd_free_window(C01); mzd_free_window(C10); mzd_free_window(C11); __M4RI_DD_MZD(C); return C; } mzd_t *mzd_mul_mp(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { if(A->ncols != B->nrows) m4ri_die("mzd_mul_mp: A ncols (%d) need to match B nrows (%d).\n", A->ncols, B->nrows); if (cutoff < 0) m4ri_die("mzd_mul_mp: cutoff must be >= 0.\n"); if(cutoff == 0) { cutoff = __M4RI_STRASSEN_MUL_CUTOFF; } cutoff = cutoff / m4ri_radix * m4ri_radix; if (cutoff < m4ri_radix) { cutoff = m4ri_radix; }; if (C == NULL) { C = mzd_init(A->nrows, B->ncols); } else if (C->nrows != A->nrows || C->ncols != B->ncols){ m4ri_die("mzd_mul_mp: C (%d x %d) has wrong dimensions, expected (%d x %d)\n", C->nrows, C->ncols, A->nrows, B->ncols); } _mzd_mul_mp4(C, A, B, cutoff); return C; } mzd_t *mzd_addmul_mp(mzd_t *C, mzd_t const *A, mzd_t const *B, int cutoff) { if(A->ncols != B->nrows) m4ri_die("mzd_addmul_mp: A ncols (%d) need to match B nrows (%d).\n", A->ncols, B->nrows); if (cutoff < 0) m4ri_die("mzd_addmul_mp: cutoff must be >= 0.\n"); if(cutoff == 0) { cutoff = __M4RI_STRASSEN_MUL_CUTOFF; } cutoff = cutoff / m4ri_radix * m4ri_radix; if (cutoff < m4ri_radix) { cutoff = m4ri_radix; }; if (C == NULL) { C = mzd_init(A->nrows, B->ncols); } else if (C->nrows != A->nrows || C->ncols != B->ncols){ m4ri_die("mzd_addmul_mp: C (%d x %d) has wrong dimensions, expected (%d x %d)\n", C->nrows, C->ncols, A->nrows, B->ncols); } if(A->nrows == 0 || A->ncols == 0 || B->ncols == 0) { __M4RI_DD_MZD(C); return C; } C = _mzd_addmul_mp4(C, A, B, cutoff); __M4RI_DD_MZD(C); return C; } #endif //__M4RI_HAVE_OPENMP m4ri-20140914/m4ri/Doxyfile0000644000175000017500000030500112405042776012143 00000000000000# Doxyfile 1.8.7 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = M4RI # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = 1.0.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = ../doc/ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = "" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = ../testsuite # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = NO # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = YES # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /