diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml
new file mode 100644
index 0000000..c8844d9
--- /dev/null
+++ b/.github/workflows/ccpp.yml
@@ -0,0 +1,23 @@
+name: C/C++ CI
+
+on: [push]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install python moduels
+ run: sudo apt update && sudo apt install -y libeigen3-dev python3-setuptools && pip3 install pybind11 pytest numpy scipy cython
+ - name: Compile Bybind
+ run: export CPATH=/usr/include/eigen3 && cd examples/python && source build.sh
+ - name: Test Bybind
+ run: |
+ cd examples/python
+ python3 -m pytest -s -v test.py
+ - name: Run cython
+ run: |
+ cd examples/cython
+ python3 setup.py build_ext --inplace && python3 -m pytest -s -v test.py
diff --git a/.gitignore b/.gitignore
index acb8847..46759a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,10 @@
build*/*
*.so
public/
+<<<<<<< HEAD
+*.exe
+=======
+>>>>>>> master
# Eclispe setting --- do not ignore *.cproject and *.project
*/**/.settings
@@ -91,7 +95,11 @@ DocProject/Help/Html2
DocProject/Help/html
# Cmake, make and compiled objects on unix
+<<<<<<< HEAD
+#*.cmake
+=======
*.cmake
+>>>>>>> master
*.c.o
*/CMakeFiles/*
*/Makefile
@@ -141,6 +149,8 @@ Assets/AssetStoreTools*
# Visual Studio cache directory
.vs/
+<<<<<<< HEAD
+=======
# Visual Studio Code cache directory
.vscode/*
!.vscode/settings.json
@@ -152,6 +162,7 @@ Assets/AssetStoreTools*
# Local History for Visual Studio Code
.history/
+>>>>>>> master
# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
@@ -185,3 +196,49 @@ sysinfo.txt
# Office
~*.pptx
+<<<<<<< HEAD
+
+#Cython https://github.com/cython/cython/blob/master/.gitignore
+*.pyc
+*.pyo
+__pycache__
+*.o
+
+.*cache*/
+
+*/cython/*.c
+
+/TEST_TMP/
+/build/
+/cython_build/
+/wheelhouse*/
+!tests/build/
+/dist/
+.gitrev
+.coverage
+*.patch
+*.diff
+*.orig
+*.prof
+*.rej
+*.log
+*.dep
+*.swp
+*~
+callgrind.out.*
+
+.ipynb_checkpoints
+
+# Jetbrains IDE project files
+/.idea
+/*.iml
+
+# Pytest
+.cache
+.pytest_cache
+.mypy_cache
+<<<<<<< HEAD
+=======
+=======
+>>>>>>> master
+>>>>>>> cmakeWin
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 591e8be..e025eef 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,94 +1,92 @@
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
-# ##### # # # #
-# #### ##### ###### # # # # # # # #
-# # # # # # ## # # # # # #
-# # # # # ##### # # # # #### # ### #
-# # # ##### # # # # # # # # # # #
-# # # # # # ## # # # # # # #
-# #### # ###### # # ##### ##### # # #
-# #
-# This file is part of openGJK. #
-# #
-# openGJK 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 #
-# any later version. #
-# #
-# openGJK 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 Foobar. If not, see . #
-# #
-# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
-# Copyright (C) Mattia Montanari 2018 - 2019 #
-# http://iel.eng.ox.ac.uk/?page_id=504 #
-# #
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
-
-cmake_minimum_required(VERSION 3.5)
-project(openGJK)
-
-set(CMAKE_C_STANDARD 11)
-
-message("[${CMAKE_PROJECT_NAME}] Welcome, please change user options if needed.")
-
-# APPLY DEFAULT SETTINGS
-if(NOT CMAKE_BUILD_TYPE)
- message("[${CMAKE_PROJECT_NAME}] Use default CMAKE_BUILD_TYPE")
- set(CMAKE_BUILD_TYPE Release)
-endif()
-
-
-# PLATFORM-SPECIFIC SETTING
-if (UNIX)
- find_library(M_LIB m)
- set(CMAKE_C_FLAGS "-lm")
- set(CMAKE_CXX_FLAGS "-lm")
-else ()
- set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
-endif ()
-
-# COMPILER SETTING
-IF(CMAKE_BUILD_TYPE MATCHES Release)
- set(CMAKE_BUILD_TYPE Release)
-ELSEIF(CMAKE_BUILD_TYPE MATCHES Debug)
- set(CMAKE_BUILD_TYPE Debug)
-ENDIF()
-
-if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- # using GCC
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -finline-functions")
- set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG")
- set(CMAKE_CXX_FLAGS_RELEASE "-O3")
-
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra -finline-functions")
- set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG")
- set(CMAKE_C_FLAGS_RELEASE "-O3")
-
- add_compile_options(-static-libgcc -static-libstdc++ )
- add_definitions(-DMT)
-elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- # using Visual Studio C++
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4131 /wd4701 /wd4255 /wd4710 /wd4820 /wd4711 /wd5045")
- set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1")
- set(CMAKE_CXX_FLAGS_RELEASE "/Ox")
-
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4131 /wd4701 /wd4255 /wd4710 /wd4820 /wd4711 /wd5045")
- set(CMAKE_C_FLAGS_DEBUG "-DDEBUG /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1")
- set(CMAKE_C_FLAGS_RELEASE "/Ox")
-
- set(CMAKE_SUPPRESS_REGENERATION true)
-
- endif()
-
-# DEBUG FLAGS
-IF(CMAKE_BUILD_TYPE MATCHES Debug)
- add_definitions(-DDEBUG)
-ENDIF()
-
-# INCLUDE LIBRARY AND EXAMPLE DIR
-add_subdirectory(lib)
-add_subdirectory(example1_c)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# ##### # # # #
+# #### ##### ###### # # # # # # # #
+# # # # # # ## # # # # # #
+# # # # # ##### # # # # #### # ### #
+# # # ##### # # # # # # # # # # #
+# # # # # # ## # # # # # # #
+# #### # ###### # # ##### ##### # # #
+# #
+# This file is part of openGJK. #
+# #
+# OpenGJK 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 #
+# any later version. #
+# #
+# OpenGJK 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 OpenGJK. If not, see . #
+# #
+# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
+# Copyright (C) Mattia Montanari 2018 - 2020 #
+# http://iel.eng.ox.ac.uk/?page_id=504 #
+# #
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+
+cmake_minimum_required(VERSION 3.13)
+
+set(CMAKE_POLICY_DEFAULT_CMP0079 NEW)
+set(LIBRARY_VERSION "2.0.3")
+
+project(openGJKlib VERSION ${LIBRARY_VERSION} LANGUAGES C)
+
+set(CMAKE_C_STANDARD 11)
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+include(CMakeDefaults)
+include(CompilerFlags)
+include(PlatformDefaults)
+
+message( "[${PROJECT_NAME}] CMake setting ..")
+message(STATUS "Version : " ${CMAKE_PROJECT_VERSION} )
+message(STATUS "Build type : " ${CMAKE_BUILD_TYPE} )
+
+# Specify project specific and user custum options
+include(CMakeProjectOptions)
+
+set( SOURCE_FILES src/openGJK.c )
+set( SOURCE_HEADS include/openGJK/openGJK.h)
+
+IF(BUILD_STATIC_LIB)
+ add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES} ${SOURCE_HEADS})
+ add_definitions(-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=FALSE)
+ELSE()
+ add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${SOURCE_HEADS})
+ add_definitions(-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE)
+ENDIF(BUILD_STATIC_LIB)
+
+set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER ${SOURCE_HEADS})
+
+# Add compiler flags
+include(CompilerFlags)
+
+# Install setup
+install(TARGETS ${PROJECT_NAME} PERMISSIONS WORLD_WRITE )
+
+find_package(OpenMP REQUIRED)
+if (OPENMP_FOUND)
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
+endif()
+
+# Link include file
+target_include_directories( ${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
+
+target_link_libraries(${PROJECT_NAME} ${CMOCKA_LIBRARY} )
+
+set(DESTDIR "/usr")
+INSTALL(TARGETS ${PROJECT_NAME}
+ LIBRARY DESTINATION "${DESTDIR}/lib"
+ PUBLIC_HEADER DESTINATION "${DESTDIR}/include"
+)
+
+if (WITH_EXAMPLES)
+ add_subdirectory(examples/c)
+endif (WITH_EXAMPLES)
+
+message(STATUS "Completed CMake setting for ${PROJECT_NAME}" )
\ No newline at end of file
diff --git a/COPYING b/COPYING
index 94a9ed0..818433e 100644
--- a/COPYING
+++ b/COPYING
@@ -1,674 +1,674 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- 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 .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000..8bf2815
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,151 @@
+# How to compile openGJK
+
+Using openGJK is very simple. This guide will help you getting started compiling and using openGJK.
+
+## Requirements
+
+### Common requirements
+
+1. A C compiler
+2. [CMake](http://www.cmake.org) version 3.5 or above
+
+## Building
+First, you need to configure the compilation, using CMake.
+
+1. Go inside the `build` dir. Create it if it doesn't exist.
+2. Move into `build` dir and use `cmake ..`. On Windows you can specify `cmake -G "Visual Studio 15 2017 Win64" ..`, on Unix `cmake -G "Unix Makefiles" ..`.
+
+### CMake standard options
+
+- CMAKE_BUILD_TYPE: The type of build (can be Debug or Release)
+- CMAKE_C_COMPILER: The path to the C compiler
+
+### CMake options defined for openGJK
+
+Options are defined in the following files:
+
+- CmakeOptions.cmake
+
+They can be changed with the -D option:
+
+`cmake -DVERSION_ACCURATE=ON ..`
+
+In addition to passing options on the command line, you can browse and edit
+CMake options using `cmakesetup` (Windows), `cmake-gui` or `ccmake` (GNU/Linux
+and MacOS X).
+
+- Go to the build dir
+- On Windows: run `cmakesetup`
+- On GNU/Linux and MacOS X: run `ccmake ..`
+
+### Install and run
+
+If all above building commands were executed from `build`, the openGJK library can be found in the `build/src` directory.
+You can run the binaries in `build/examples/*`.
+
+To install the library copy the header file openGJK.h and the binaries in a folder accessible in the search path by all users (on Unix this would normally be /usr/local).
+
+## Testing
+
+ TO REWRITE!!
+
+As mention above you can turn on the unit tests and make it possible to easily
+execute them:
+
+`cmake -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=ON ..`
+
+After that you can simply call `make test` in the build directory or if you
+want more output simply call `ctest -V`.
+
+If you want to enable the generation of coverage files you can do this by
+using the following options:
+
+`cmake -DCMAKE_BUILD_TYPE=Profiling -DUNIT_TESTING=ON ..`
+
+After building it you will see that you have several coverage options in
+
+`make help`
+
+You should have `make ExperimentalCoverage` and running it will create
+coverage files. The result is stored in Testing directory.
+
+## Examples
+
+
+This section presents three examples on how to use openGJK with C, C# and Matlab.
+
+### C
+This example illustrates how to include openGJK in an existing C
+ program.
+
+All files for the example are in the `example1_c` folder. The executable built with
+ CMake reads the coordinates of two polytopes from the input files,
+ respectively userP.dat and userQ.dat, and computes the minimum distance
+ between them.
+
+Notice that the input files must be in the folder from which the executable
+ is launched, otherwise an error is returned.
+
+You can edit the coordinates in the input file to test different
+ polytopes; just remember to edit also the first number in the files
+ that corresponds to the numbers of vertices that the program will read.
+
+### Matlab
+This example illustrates how to invoke openGJK as a regular built-in
+ Matlab function. You will need to build mex files (find out the requisites from [Mathworks documentation](https://uk.mathworks.com/help/matlab/matlab_external/what-you-need-to-build-mex-files.html)).
+
+
+Open Matlab and cd into the `example2_mex` folder. By running the
+ script `runme.m`, Matlab will first compile a mex file (telling you
+ about the name of the mex file generated) and will call the script
+ `main.m`. This invokes openGJK within Matlab and illustrates the
+ result.
+
+The mex file may be copied and called from any other Matlab project.
+
+### C# #
+This example illustrates how to invoke openGJK in an applications written in C#. You will need [mono](http://www.mono-project.com/) and Microsoft Visual Studio toolchain for C# on Windows.
+
+The only file required is in the `example3_csharp` folder. This can be compiled in Unix
+ with mono, or in Windows using Visual Studio. Notice that, however, the openGJK library
+ is compiled for a specific architecture (usually x64), and this breaks the portability
+ of the .NET application compiled in this example.
+
+Below are the steps for compiling the C# application on Windows and Linux. Both
+ procedures assume the dynamic library of openGJK has been already compiled.
+
+#### Compile on Windows
+ 1. Move into the folder `example3_csharp` and create a new folder `example3`.
+ 2. Copy into this folder the openGJK library or make it available in any directory.
+ 3. Open Visual Studio and create a new project. As project type select **Console App (.NET Framework)**.
+ 4. Add to this project the `main.cs` file
+ 5. Set x64 as the target platform, compile the application and run it.
+
+
+#### Compile on Linux
+ 1. Move into the folder `example3_csharp` and create a new folder `example3`.
+ 2. Copy into this folder the openGJK library or install is so that is available in any directory.
+ 3. Move into that new folder and open a terminal.
+ 4. Type `mcs -out:example3demo -d:UNIX ../main.cs`
+ 5. Run the example by typing `mono example3demo`
+
+## API user reference
+
+```double gjk( struct bodyA, struct bodyB, struct simplex)```
+
+### Documentation
+The folder `doc` contains a Doxygen file for generating the documentation of the whole
+ library. To build the documentation cd into `doc` and call Doxygen from the command line simply by typing `doxygen`. If correctly installed, Doxygen will create html documentation with graphs illustrating the call stack of the functions of the library.
+
+### Parameters
+* **bodyA** The first body.
+* **bodyB** The second body.
+* **simplex** The simplex used the GJK algorithm at the first iteration.
+
+### Returns
+* **double** the minimum distance between bodyA and bodyB.
+
+### Description
+The function `gjk` computes the minimum Euclidean distance between two bodies using the
+ GJK algorithm. Note that the simplex used at the first iteration may be initialised by the user, but this is not necessary.
+
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..818433e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/README.md b/README.md
index d7b50d3..cc40ddb 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,13 @@
Hello!
-=======
-I'll never have enough time for this project, but contributes are welcome! Please check out [docs and more details here](https://www.mattiamontanari.com/opengjk/).
+This is a simple and reliable C implementation of the Gilbert-Johnson-Keerthi (GJK) algorithm, [docs and details are available here](https://www.mattiamontanari.com/opengjk/).
-The best code is in dev branch - Enjoy!
+All contributes are all welcome. For instance you could add:
+ - Support for other shapes: quadrics and splines (easy)
+ - More python examples and test (easy)
+ - EPA algorithm (hard)
> openGJK, Copyright (c) 2018-2021
>
-> Department of Engineering Science. University of Oxford, UK.
+> Department of Engineering Science. University of Oxford, UK.
\ No newline at end of file
diff --git a/lib/CMakeLists.txt b/cmake/CMakeDefaults.cmake
similarity index 61%
rename from lib/CMakeLists.txt
rename to cmake/CMakeDefaults.cmake
index 7748490..f69fe89 100644
--- a/lib/CMakeLists.txt
+++ b/cmake/CMakeDefaults.cmake
@@ -28,53 +28,24 @@
# #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# Include srcdir and builddir in include path to save typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in every subdir
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
-project (openGJKlib)
+# Put the include dirs which are in the source or build tree
+# before all other include dirs, so the headers in the sources
+# are prefered over the already installed ones
+# since cmake 2.4.1
+set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
-set(CMAKE_C_STANDARD 11)
+# Use colored output
+set(CMAKE_COLOR_MAKEFILE ON)
-# SELECT USER OPTIONS
-option(VERSION_ACCURATE "Reduce speed to maximise accuracy (OFF)" OFF )
+# Create the compile command database for clang by default
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-# APPLY USER OPTIONS
-IF(VERSION_ACCURATE)
- set(USE_PREDICATES ON)
- set(openGJK_VERSION "Accurate")
-ELSE()
- set(USE_PREDICATES OFF)
- set(openGJK_VERSION "Fast")
-ENDIF()
+# Always build with -fPIC
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-# COMPILE
-message( "[${CMAKE_PROJECT_NAME}] Compiling ..")
-message(STATUS "Version (Accurate,Fast): " ${openGJK_VERSION} )
-message(STATUS "Build type (Debug,Release): " ${CMAKE_BUILD_TYPE} )
-
-# Select source files
-set( SOURCE_FILES src/openGJK.c )
-set( SOURCE_HEADS include/openGJK/openGJK.h)
-
-IF(USE_PREDICATES)
- # for adpative floating-point artim.
- set( SOURCE_FILES ${SOURCE_FILES} ext/predicates.c)
- set( SOURCE_HEADS ${SOURCE_HEADS} ext/predicates.h)
- # Add flag for adpative floating-point artim.
- add_definitions(-DADAPTIVEFP)
-ENDIF()
-
-# Create the (dynamic) library
-add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES} ${SOURCE_HEADS})
-add_definitions(-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=FALSE)
-
-# Link include file
-target_include_directories( ${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
-
-IF(USE_PREDICATES)
- # for adpative floating-point artim.
- target_include_directories( ${PROJECT_NAME}
- PUBLIC ${PROJECT_SOURCE_DIR}/ext
- )
-ENDIF()
-
-# Report
-message( ".. DONE!")
+# Avoid source tree pollution
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
\ No newline at end of file
diff --git a/example1_c/CMakeLists.txt b/cmake/CMakeProjectOptions.cmake
similarity index 79%
rename from example1_c/CMakeLists.txt
rename to cmake/CMakeProjectOptions.cmake
index b9c3497..27fd9c5 100644
--- a/example1_c/CMakeLists.txt
+++ b/cmake/CMakeProjectOptions.cmake
@@ -14,7 +14,7 @@
# the Free Software Foundation, either version 3 of the License, or #
# any later version. #
# #
-# openGJK is distributed in the hope that it will be useful, #
+# openGJK 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. #
@@ -23,23 +23,22 @@
# along with Foobar. If not, see . #
# #
# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
-# Copyright (C) Mattia Montanari 2018 - 2019 #
+# Copyright (C) Mattia Montanari 2018 - 2020 #
# http://iel.eng.ox.ac.uk/?page_id=504 #
# #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
-project(openGJKdemo)
+option(WITH_STATIC_LIB "Build static lib" OFF)
+option(WITH_EXAMPLES "Build C example" ON)
-message( "[${CMAKE_PROJECT_NAME}] Compiling the executable ..")
+# Default build type
+set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Release")
-# Set source file
-set(SOURCE_FILES main.c )
+# APPLY USER OPTIONS
+IF (WITH_STATIC_LIB)
+ set(BUILD_STATIC_LIB ON)
+ENDIF (WITH_STATIC_LIB)
-# Create the executable
-add_executable(demo ${SOURCE_FILES})
-
-# Link to openGJK
-target_link_libraries(demo openGJKlib )
-
-# Report
-message( ".. executable DONE!")
\ No newline at end of file
+# FEEDBACK
+message(STATUS " Build static lib (ON): " ${WITH_STATIC_LIB})
+message(STATUS " Build C examples (ON): " ${WITH_EXAMPLES})
\ No newline at end of file
diff --git a/cmake/COPYING-CMAKE-SCRIPTS b/cmake/COPYING-CMAKE-SCRIPTS
new file mode 100644
index 0000000..4b41776
--- /dev/null
+++ b/cmake/COPYING-CMAKE-SCRIPTS
@@ -0,0 +1,22 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cmake/CompilerChecks.cmake b/cmake/CompilerChecks.cmake
new file mode 100644
index 0000000..b326807
--- /dev/null
+++ b/cmake/CompilerChecks.cmake
@@ -0,0 +1,109 @@
+include(AddCCompilerFlag)
+include(CheckCCompilerFlagSSP)
+
+if (UNIX)
+ #
+ # Check for -Werror turned on if possible
+ #
+ # This will prevent that compiler flags are detected incorrectly.
+ #
+ check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
+ if (REQUIRED_FLAGS_WERROR)
+ set(CMAKE_REQUIRED_FLAGS "-Werror")
+
+ if (PICKY_DEVELOPER)
+ list(APPEND SUPPORTED_COMPILER_FLAGS "-Werror")
+ endif()
+ endif()
+
+ add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wcast-align" SUPPORTED_COMPILER_FLAGS)
+ #add_c_compiler_flag("-Wcast-qual" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=address" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wstrict-prototypes" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=strict-prototypes" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wwrite-strings" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=write-strings" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror-implicit-function-declaration" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wpointer-arith" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=pointer-arith" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wdeclaration-after-statement" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=declaration-after-statement" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wreturn-type" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=return-type" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wuninitialized" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=uninitialized" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wimplicit-fallthrough" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=strict-overflow" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wmissing-field-initializers" SUPPORTED_COMPILER_FLAGS)
+
+ check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT)
+ if (REQUIRED_FLAGS_WFORMAT)
+ list(APPEND SUPPORTED_COMPILER_FLAGS "-Wformat")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wformat")
+ endif()
+ add_c_compiler_flag("-Wformat-security" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS)
+
+ # Allow zero for a variadic macro argument
+ string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID)
+ if ("${_C_COMPILER_ID}" STREQUAL "clang")
+ add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS)
+ endif()
+
+ add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS)
+
+ if (CMAKE_BUILD_TYPE)
+ string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
+ if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
+ add_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" SUPPORTED_COMPILER_FLAGS)
+ endif()
+ endif()
+
+ check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
+ if (WITH_STACK_PROTECTOR_STRONG)
+ list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
+ # This is needed as Solaris has a seperate libssp
+ if (SOLARIS)
+ list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong")
+ endif()
+ else (WITH_STACK_PROTECTOR_STRONG)
+ check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
+ if (WITH_STACK_PROTECTOR)
+ list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
+ # This is needed as Solaris has a seperate libssp
+ if (SOLARIS)
+ list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
+ endif()
+ endif()
+ endif (WITH_STACK_PROTECTOR_STRONG)
+
+ check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
+ if (WITH_STACK_CLASH_PROTECTION)
+ list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
+ endif()
+
+ if (PICKY_DEVELOPER)
+ add_c_compiler_flag("-Wno-error=deprecated-declarations" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wno-error=tautological-compare" SUPPORTED_COMPILER_FLAGS)
+ endif()
+
+ # Unset CMAKE_REQUIRED_FLAGS
+ unset(CMAKE_REQUIRED_FLAGS)
+endif()
+
+if (MSVC)
+ add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("/D _CRT_NONSTDC_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("/D _CRT_SECURE_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
+endif()
+
+set(DEFAULT_C_COMPILE_FLAGS ${SUPPORTED_COMPILER_FLAGS} CACHE INTERNAL "Default C Compiler Flags" FORCE)
+set(DEFAULT_LINK_FLAGS ${SUPPORTED_LINKER_FLAGS} CACHE INTERNAL "Default C Linker Flags" FORCE)
diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake
new file mode 100644
index 0000000..29cf75b
--- /dev/null
+++ b/cmake/CompilerFlags.cmake
@@ -0,0 +1,103 @@
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# ##### # # # #
+# #### ##### ###### # # # # # # # #
+# # # # # # ## # # # # # #
+# # # # # ##### # # # # #### # ### #
+# # # ##### # # # # # # # # # # #
+# # # # # # ## # # # # # # #
+# #### # ###### # # ##### ##### # # #
+# #
+# This file is part of openGJK. #
+# #
+# openGJK 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 #
+# any later version. #
+# #
+# openGJK 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 openGJK. If not, see . #
+# #
+# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
+# Copyright (C) Mattia Montanari 2018 - 2019 #
+# http://iel.eng.ox.ac.uk/?page_id=504 #
+# #
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+
+
+# PLATFORM-SPECIFIC SETTING
+if (UNIX)
+ find_library(M_LIB m)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lm")
+else ()
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+endif ()
+
+if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
+ # using GCC
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra -Werror")
+
+ add_compile_options(-static-libgcc -static-libstdc++ )
+ add_definitions(-DMT)
+
+elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
+
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4131 /wd4701 /wd4255 /wd4710 /wd4820 /wd4711 /wd5045")
+ set(CMAKE_C_FLAGS_DEBUG "-DDEBUG /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1")
+ set(CMAKE_C_FLAGS_RELEASE "/Ox")
+
+ set(CMAKE_SUPPRESS_REGENERATION true)
+
+endif()
+
+if (UNIX AND NOT WIN32)
+
+ # Activate with: -DCMAKE_BUILD_TYPE=Debug
+ set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG -Wall -Wextra -Werror"
+ CACHE STRING "Flags used by the C compiler during DEBUG builds.")
+
+ # Activate with: -DCMAKE_BUILD_TYPE=Release
+ set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall -finline-functions -Wextra -Werror"
+ CACHE STRING "Flags used by the C compiler during RELEASE builds.")
+
+ # Activate with: -DCMAKE_BUILD_TYPE=Profiling
+ set(CMAKE_C_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
+ CACHE STRING "Flags used by the C compiler during PROFILING builds.")
+ set(CMAKE_CXX_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
+ CACHE STRING "Flags used by the CXX compiler during PROFILING builds.")
+ set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
+ CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
+ set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
+ CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
+ set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
+ CACHE STRING "Flags used by the linker during PROFILING builds.")
+
+ # Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer
+ set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
+ CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.")
+ set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
+ CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.")
+ set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
+ CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
+ set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
+ CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
+ set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
+ CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.")
+
+ # Activate with: -DCMAKE_BUILD_TYPE=MemorySanitizer
+ set(CMAKE_C_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer"
+ CACHE STRING "Flags used by the C compiler during MEMORYSANITIZER builds.")
+ set(CMAKE_CXX_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer"
+ CACHE STRING "Flags used by the CXX compiler during MEMORYSANITIZER builds.")
+ set(CMAKE_SHARED_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory"
+ CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.")
+ set(CMAKE_MODULE_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory"
+ CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.")
+ set(CMAKE_EXEC_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory"
+ CACHE STRING "Flags used by the linker during MEMORYSANITIZER builds.")
+
+endif()
diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake
new file mode 100644
index 0000000..fe8da35
--- /dev/null
+++ b/cmake/ConfigureChecks.cmake
@@ -0,0 +1,149 @@
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckFunctionExists)
+include(CheckLibraryExists)
+include(CheckTypeSize)
+include(CheckCXXSourceCompiles)
+include(CheckStructHasMember)
+include(TestBigEndian)
+
+set(PACKAGE ${PROJECT_NAME})
+set(VERSION ${PROJECT_VERSION})
+set(DATADIR ${DATA_INSTALL_DIR})
+set(LIBDIR ${CMAKE_INSTALL_LIBDIR})
+set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
+set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
+
+set(BINARYDIR ${CMAKE_BINARY_DIR})
+set(SOURCEDIR ${CMAKE_SOURCE_DIR})
+
+function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
+ # Remove whitespaces from the argument.
+ # This is needed for CC="ccache gcc" cmake ..
+ string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}")
+
+ execute_process(
+ COMMAND
+ ${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion
+ OUTPUT_VARIABLE _COMPILER_VERSION
+ )
+
+ string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
+ _COMPILER_VERSION ${_COMPILER_VERSION})
+
+ set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
+endfunction()
+
+if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
+ compiler_dumpversion(GNUCC_VERSION)
+ if (NOT GNUCC_VERSION EQUAL 34)
+ check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
+ endif (NOT GNUCC_VERSION EQUAL 34)
+endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
+
+# DEFINITIONS
+if (SOLARIS)
+ add_definitions(-D__EXTENSIONS__)
+endif (SOLARIS)
+
+# HEADER FILES
+check_include_file(assert.h HAVE_ASSERT_H)
+check_include_file(inttypes.h HAVE_INTTYPES_H)
+check_include_file(io.h HAVE_IO_H)
+check_include_file(malloc.h HAVE_MALLOC_H)
+check_include_file(memory.h HAVE_MEMORY_H)
+check_include_file(setjmp.h HAVE_SETJMP_H)
+check_include_file(signal.h HAVE_SIGNAL_H)
+check_include_file(stdarg.h HAVE_STDARG_H)
+check_include_file(stddef.h HAVE_STDDEF_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(stdio.h HAVE_STDIO_H)
+check_include_file(stdlib.h HAVE_STDLIB_H)
+check_include_file(string.h HAVE_STRING_H)
+check_include_file(strings.h HAVE_STRINGS_H)
+check_include_file(sys/stat.h HAVE_SYS_STAT_H)
+check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(time.h HAVE_TIME_H)
+check_include_file(unistd.h HAVE_UNISTD_H)
+
+if (HAVE_TIME_H)
+ check_struct_has_member("struct timespec" tv_sec "time.h" HAVE_STRUCT_TIMESPEC)
+endif (HAVE_TIME_H)
+
+# FUNCTIONS
+check_function_exists(calloc HAVE_CALLOC)
+check_function_exists(exit HAVE_EXIT)
+check_function_exists(fprintf HAVE_FPRINTF)
+check_function_exists(free HAVE_FREE)
+check_function_exists(longjmp HAVE_LONGJMP)
+check_function_exists(siglongjmp HAVE_SIGLONGJMP)
+check_function_exists(malloc HAVE_MALLOC)
+check_function_exists(memcpy HAVE_MEMCPY)
+check_function_exists(memset HAVE_MEMSET)
+check_function_exists(printf HAVE_PRINTF)
+check_function_exists(setjmp HAVE_SETJMP)
+check_function_exists(signal HAVE_SIGNAL)
+check_function_exists(strsignal HAVE_STRSIGNAL)
+check_function_exists(strcmp HAVE_STRCMP)
+check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
+
+if (WIN32)
+ check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
+ check_function_exists(_vsnprintf HAVE__VSNPRINTF)
+ check_function_exists(_snprintf HAVE__SNPRINTF)
+ check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
+ check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF)
+ check_symbol_exists(vsnprintf stdio.h HAVE_VSNPRINTF)
+else (WIN32)
+ check_function_exists(sprintf HAVE_SNPRINTF)
+ check_function_exists(vsnprintf HAVE_VSNPRINTF)
+endif (WIN32)
+
+find_library(RT_LIBRARY rt)
+if (RT_LIBRARY AND NOT LINUX AND NOT ANDROID)
+ set(CMOCKA_REQUIRED_LIBRARIES ${RT_LIBRARY} CACHE INTERNAL "cmocka required system libraries")
+endif ()
+
+# OPTIONS
+check_c_source_compiles("
+__thread int tls;
+
+int main(void) {
+ return 0;
+}" HAVE_GCC_THREAD_LOCAL_STORAGE)
+
+if (WIN32)
+check_c_source_compiles("
+__declspec(thread) int tls;
+
+int main(void) {
+ return 0;
+}" HAVE_MSVC_THREAD_LOCAL_STORAGE)
+endif(WIN32)
+
+if (HAVE_TIME_H AND HAVE_STRUCT_TIMESPEC AND HAVE_CLOCK_GETTIME)
+ if (RT_LIBRARY)
+ set(CMAKE_REQUIRED_LIBRARIES ${RT_LIBRARY})
+ endif()
+
+ check_c_source_compiles("
+#include
+
+int main(void) {
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ return 0;
+}" HAVE_CLOCK_REALTIME)
+
+ # reset cmake requirements
+ set(CMAKE_REQUIRED_INCLUDES)
+ set(CMAKE_REQUIRED_LIBRARIES)
+endif ()
+
+# ENDIAN
+if (NOT WIN32)
+ set(WORDS_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
+ test_big_endian(WORDS_BIGENDIAN)
+endif (NOT WIN32)
diff --git a/cmake/PlatformDefaults.cmake b/cmake/PlatformDefaults.cmake
new file mode 100644
index 0000000..46c3185
--- /dev/null
+++ b/cmake/PlatformDefaults.cmake
@@ -0,0 +1,21 @@
+# Set system vars
+
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(LINUX TRUE)
+endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ set(FREEBSD TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+
+if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
+ set(OPENBSD TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
+
+if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
+ set(NETBSD TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
+
+if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+ set(SOLARIS TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt
new file mode 100644
index 0000000..01be2ad
--- /dev/null
+++ b/examples/c/CMakeLists.txt
@@ -0,0 +1,67 @@
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# ##### # # # #
+# #### ##### ###### # # # # # # # #
+# # # # # # ## # # # # # #
+# # # # # ##### # # # # #### # ### #
+# # # ##### # # # # # # # # # # #
+# # # # # # ## # # # # # # #
+# #### # ###### # # ##### ##### # # #
+# #
+# This file is part of openGJK. #
+# #
+# openGJK 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 #
+# any later version. #
+# #
+# openGJK 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 openGJK. If not, see . #
+# #
+# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
+# Copyright (C) Mattia Montanari 2018 - 2019 #
+# http://iel.eng.ox.ac.uk/?page_id=504 #
+# #
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+
+project(openGJKdemo VERSION 1.0.0 LANGUAGES C)
+
+set(APPLICATION_NAME ${PROJECT_NAME})
+set(CMAKE_C_STANDARD 11)
+set(TEST_NAME ${PROJECT_NAME}_CTEST)
+
+message( "[${PROJECT_NAME}] CMake setting ..")
+
+# Set source file
+set(SOURCE_FILES main.c )
+
+# Create the executable
+add_executable(demo ${SOURCE_FILES})
+
+# Copy input files for this example after build
+add_custom_command(
+ TARGET demo POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/userP.dat
+ ${CMAKE_CURRENT_BINARY_DIR}/userP.dat )
+add_custom_command(
+ TARGET demo POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/userQ.dat
+ ${CMAKE_CURRENT_BINARY_DIR}/userQ.dat )
+
+# PLATFORM-SPECIFIC SETTING
+if (UNIX)
+ find_library(M_LIB m)
+ # Link to openGJK and math library
+ target_link_libraries(demo openGJKlib m)
+else ()
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+ target_link_libraries(demo openGJKlib)
+endif ()
+
+message(STATUS "Completed CMake setting for ${PROJECT_NAME}" )
\ No newline at end of file
diff --git a/example1_c/main.c b/examples/c/main.c
similarity index 81%
rename from example1_c/main.c
rename to examples/c/main.c
index 82701a6..7606bd1 100644
--- a/example1_c/main.c
+++ b/examples/c/main.c
@@ -1,177 +1,178 @@
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * ##### # # # *
- * #### ##### ###### # # # # # # # *
- * # # # # # ## # # # # # *
- * # # # # ##### # # # # #### # ### *
- * # # ##### # # # # # # # # # # *
- * # # # # # ## # # # # # # *
- * #### # ###### # # ##### ##### # # *
- * *
- * This file is part of openGJK. *
- * *
- * openGJK 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 *
- * any later version. *
- * *
- * openGJK 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 Foobar. If not, see . *
- * *
- * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
- * Copyright (C) Mattia Montanari 2018 - 2019 *
- * http://iel.eng.ox.ac.uk/?page_id=504 *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * *
- * This file runs an example to illustrate how to invoke the openGJK lib *
- * within a C program. An executable called 'demo' can be compiled with *
- * CMake. This reads the coordinates of two polytopes from the input *
- * files userP.dat and userQ.dat, respectively, and returns the minimum *
- * distance between them computed using the openGJK library. *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/**
- * @file main.c
- * @author Mattia Montanari
- * @date April 2018
- * @brief File illustrating an application that invokes openGJK.
- *
- */
-
-#define _CRT_HAS_CXX17 0
-#include
-
-/* For importing openGJK this is Step 1: include header in subfolder. */
-#include "openGJK/openGJK.h"
-
-#ifndef WIN32
-#define fscanf_s fscanf
-#endif
-
-/**
-* @brief Function for reading input file with body's coordinates.
-*
-*/
-int readinput ( const char *inputfile, double ***pts, int * out ) {
- int npoints = 0;
- int idx = 0;
- FILE *fp;
-
- /* Open file. */
-#ifdef WIN32
- errno_t err;
- if ((err = fopen_s(&fp, inputfile, "r")) != 0) {
-#else
- if ((fp = fopen(inputfile, "r")) == NULL) {
-#endif
- fprintf(stdout, "ERROR: input file %s not found!\n", inputfile);
- fprintf(stdout, " -> The file must be in the folder from which this program is launched\n\n");
- return 1;
- }
-
- /* Read number of input vertices. */
- if (fscanf_s(fp, "%d", &npoints) != 1)
- return 1;
-
- /* Allocate memory. */
- double **arr = (double **)malloc(npoints * sizeof(double *));
- for (int i=0; i. *
+ * *
+ * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
+ * Copyright (C) Mattia Montanari 2018 - 2019 *
+ * http://iel.eng.ox.ac.uk/?page_id=504 *
+ * *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
+ * *
+ * This file runs an example to illustrate how to invoke the openGJK lib *
+ * within a C program. An executable called 'demo' can be compiled with *
+ * CMake. This reads the coordinates of two polytopes from the input *
+ * files userP.dat and userQ.dat, respectively, and returns the minimum *
+ * distance between them computed using the openGJK library. *
+ * *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+ /**
+ * @file main.c
+ * @author Mattia Montanari
+ * @date April 2018
+ * @brief File illustrating an application that invokes openGJK.
+ *
+ */
+
+#define _CRT_HAS_CXX17 0
+#include
+#include
+
+ /* For importing openGJK this is Step 1: include header in subfolder. */
+#include "openGJK/openGJK.h"
+
+#ifndef WIN32
+#define fscanf_s fscanf
+#endif
+
+/**
+* @brief Function for reading input file with body's coordinates.
+*
+*/
+int readinput(const char *inputfile, double ***pts, int * out) {
+ int npoints = 0;
+ int idx = 0;
+ FILE *fp;
+
+ /* Open file. */
+#ifdef WIN32
+ errno_t err;
+ if ((err = fopen_s(&fp, inputfile, "r")) != 0) {
+#else
+ if ((fp = fopen(inputfile, "r")) == NULL) {
+#endif
+ fprintf(stdout, "ERROR: input file %s not found!\n", inputfile);
+ fprintf(stdout, " -> The file must be in the folder from which this program is launched\n\n");
+ return 1;
+ }
+
+ /* Read number of input vertices. */
+ if (fscanf(fp, "%d", &npoints) != 1)
+ return 1;
+
+ /* Allocate memory. */
+ double **arr = (double **)malloc(npoints * sizeof(double *));
+ for (int i = 0; i < npoints; i++)
+ arr[i] = (double *)malloc(3 * sizeof(double));
+
+ /* Read and store vertices' coordinates. */
+ for (idx = 0; idx < npoints; idx++)
+ {
+ if (fscanf(fp, "%lf %lf %lf\n", &arr[idx][0], &arr[idx][1], &arr[idx][2]) != 3)
+ return 1;
+ }
+
+ /* Close file. */
+ fclose(fp);
+
+ /* Pass pointers. */
+ *pts = arr;
+ *out = idx;
+
+ return (0);
+}
+
+
+/**
+* @brief Main program of example1_c (described in Section 3.1 of the paper).
+*
+*/
+int main() {
+ /* Squared distance computed by openGJK. */
+ double dd;
+ /* Structure of simplex used by openGJK. */
+ struct simplex s;
+ /* Number of vertices defining body 1 and body 2, respectively. */
+ int nvrtx1,
+ nvrtx2;
+ /* Structures of body 1 and body 2, respectively. */
+ struct bd bd1;
+ struct bd bd2;
+ /* Specify name of input files for body 1 and body 2, respectively. */
+ char inputfileA[40] = "userP.dat",
+ inputfileB[40] = "userQ.dat";
+ /* Pointers to vertices' coordinates of body 1 and body 2, respectively. */
+ double(**vrtx1) = NULL,
+ (**vrtx2) = NULL;
+
+ /* For importing openGJK this is Step 2: adapt the data structure for the
+ * two bodies that will be passed to the GJK procedure. */
+
+ /* Import coordinates of object 1. */
+ if (readinput(inputfileA, &vrtx1, &nvrtx1))
+ return (1);
+ bd1.coord = vrtx1;
+ bd1.numpoints = nvrtx1;
+
+ /* Import coordinates of object 2. */
+ if (readinput(inputfileB, &vrtx2, &nvrtx2))
+ return (1);
+ bd2.coord = vrtx2;
+ bd2.numpoints = nvrtx2;
+
+ /* Initialise simplex as empty */
+ s.nvrtx = 0;
+
+#ifdef DEBUG
+ /* Verify input of body A. */
+ for (int i = 0; i < bd1.numpoints; ++i) {
+ printf("%.2f ", vrtx1[i][0]);
+ printf("%.2f ", vrtx1[i][1]);
+ printf("%.2f\n", bd1.coord[i][2]);
+ }
+
+ /* Verify input of body B. */
+ for (int i = 0; i < bd2.numpoints; ++i) {
+ printf("%.2f ", bd2.coord[i][0]);
+ printf("%.2f ", bd2.coord[i][1]);
+ printf("%.2f\n", bd2.coord[i][2]);
+ }
+#endif
+
+ /* For importing openGJK this is Step 3: invoke the GJK procedure. */
+ /* Compute squared distance using GJK algorithm. */
+ dd = gjk(bd1, bd2, &s);
+
+ /* Print distance between objects. */
+ printf("Distance between bodies %f\n", dd);
+
+ /* Free memory */
+ for (int i = 0; i < bd1.numpoints; i++)
+ free(bd1.coord[i]);
+ free(bd1.coord);
+ for (int i = 0; i < bd2.numpoints; i++)
+ free(bd2.coord[i]);
+ free(bd2.coord);
+
+ return (0);
+}
diff --git a/example1_c/userP.dat b/examples/c/userP.dat
similarity index 91%
rename from example1_c/userP.dat
rename to examples/c/userP.dat
index 4d97faa..fa37eba 100644
--- a/example1_c/userP.dat
+++ b/examples/c/userP.dat
@@ -1,10 +1,10 @@
-9
-0.0 5.5 0.0
-2.3 1.0 -2.0
-8.1 4.0 2.4
-4.3 5.0 2.2
-2.5 1.0 2.3
-7.1 1.0 2.4
-1.0 1.5 0.3
-3.3 0.5 0.3
-6.0 1.4 0.2
+9
+0.0 5.5 0.0
+2.3 1.0 -2.0
+8.1 4.0 2.4
+4.3 5.0 2.2
+2.5 1.0 2.3
+7.1 1.0 2.4
+1.0 1.5 0.3
+3.3 0.5 0.3
+6.0 1.4 0.2
diff --git a/example1_c/userQ.dat b/examples/c/userQ.dat
similarity index 93%
rename from example1_c/userQ.dat
rename to examples/c/userQ.dat
index daaef2d..16e94a1 100644
--- a/example1_c/userQ.dat
+++ b/examples/c/userQ.dat
@@ -1,10 +1,10 @@
-9
--0.0 -5.5 0.0
--2.3 -1.0 2.0
--8.1 -4.0 -2.4
--4.3 -5.0 -2.2
--2.5 -1.0 -2.3
--7.1 -1.0 -2.4
--1.0 -1.5 -0.3
--3.3 -0.5 -0.3
--6.0 -1.4 -0.2
+9
+-0.0 -5.5 0.0
+-2.3 -1.0 2.0
+-8.1 -4.0 -2.4
+-4.3 -5.0 -2.2
+-2.5 -1.0 -2.3
+-7.1 -1.0 -2.4
+-1.0 -1.5 -0.3
+-3.3 -0.5 -0.3
+-6.0 -1.4 -0.2
diff --git a/example3_csharp/main.cs b/examples/cs/main.cs
similarity index 93%
rename from example3_csharp/main.cs
rename to examples/cs/main.cs
index a342be9..086fa1a 100644
--- a/example3_csharp/main.cs
+++ b/examples/cs/main.cs
@@ -1,67 +1,63 @@
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * ##### # # # *
- * #### ##### ###### # # # # # # # *
- * # # # # # ## # # # # # *
- * # # # # ##### # # # # #### # ### *
- * # # ##### # # # # # # # # # # *
- * # # # # # ## # # # # # # *
- * #### # ###### # # ##### ##### # # *
- * *
- * This file is part of openGJK. *
- * *
- * openGJK 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 *
- * any later version. *
- * *
- * openGJK 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 Foobar. If not, see . *
- * *
- * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
- * Copyright (C) Mattia Montanari 2018 - 2019 *
- * http://iel.eng.ox.ac.uk/?page_id=504 *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-using System;
-
-using System.Runtime.InteropServices;
-
-public class Tester
-{
-
-
-#if UNIX
- [DllImport("libopenGJKlib.so", EntryPoint="csFunction", CallingConvention = CallingConvention.StdCall)]
-#else
- [DllImport("openGJKlib", EntryPoint = "csFunction", CallingConvention = CallingConvention.StdCall)]
-#endif
- static extern double gjk(int na, double [,] ia, int nb, double [,] ib);
-
- public static void Main(string[] args)
- {
- double dist;
- // Define array A with coordinates
- int nCoordsA = 9;
- var inCoordsA = new double[3,9] { {0.0 , 2.3 , 8.1 , 4.3 ,2.5 , 7.1 , 1.0 , 3.3 , 6.0} , { 5.5 , 1.0 , 4.0 , 5.0 ,1.0, 1.0, 1.5, 0.5 , 1.4} ,{ 0.0 , -2.0, 2.4, 2.2, 2.3 , 2.4 , 0.3 , 0.3 , 0.2} };
-
- // Define array B with coordinates
- int nCoordsB = 9;
- var inCoordsB = new double[3,9] { {-0.0 , -2.3 , -8.1 , -4.3 ,-2.5 , -7.1 , -1.0 , -3.3 , -6.0} , { -5.5 , -1.0 ,- 4.0 ,- 5.0 ,-1.0, -1.0, -1.5, -0.5 , -1.4} ,{ -0.0 , 2.0, -2.4, -2.2, -2.3 , -2.4 , -0.3 , -0.3 , -0.2} };
-
- // Invoke GJK to compute distance
- dist = gjk( nCoordsA, inCoordsA, nCoordsB, inCoordsB );
-
- // Output results
- var s = string.Format("{0:0.##}", dist);
- var message = string.Format("The distance between {0} is {1}","A and B",s);
- Console.WriteLine(message);
- Console.WriteLine("Press any key to exit");
- Console.ReadLine();
- }
-}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
+ * ##### # # # *
+ * #### ##### ###### # # # # # # # *
+ * # # # # # ## # # # # # *
+ * # # # # ##### # # # # #### # ### *
+ * # # ##### # # # # # # # # # # *
+ * # # # # # ## # # # # # # *
+ * #### # ###### # # ##### ##### # # *
+ * *
+ * This file is part of openGJK. *
+ * *
+ * openGJK 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 *
+ * any later version. *
+ * *
+ * openGJK 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 Foobar. If not, see . *
+ * *
+ * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
+ * Copyright (C) Mattia Montanari 2018 - 2019 *
+ * http://iel.eng.ox.ac.uk/?page_id=504 *
+ * *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+using System;
+
+using System.Runtime.InteropServices;
+
+public class Tester
+{
+
+ [DllImport("libopenGJKlib", EntryPoint="csFunction", CallingConvention = CallingConvention.StdCall)]
+
+ static extern double gjk(int na, double [,] ia, int nb, double [,] ib);
+
+ public static void Main(string[] args)
+ {
+ double dist;
+ // Define array A with coordinates
+ int nCoordsA = 9;
+ var inCoordsA = new double[3,9] { {0.0 , 2.3 , 8.1 , 4.3 ,2.5 , 7.1 , 1.0 , 3.3 , 6.0} , { 5.5 , 1.0 , 4.0 , 5.0 ,1.0, 1.0, 1.5, 0.5 , 1.4} ,{ 0.0 , -2.0, 2.4, 2.2, 2.3 , 2.4 , 0.3 , 0.3 , 0.2} };
+
+ // Define array B with coordinates
+ int nCoordsB = 9;
+ var inCoordsB = new double[3,9] { {-0.0 , -2.3 , -8.1 , -4.3 ,-2.5 , -7.1 , -1.0 , -3.3 , -6.0} , { -5.5 , -1.0 ,- 4.0 ,- 5.0 ,-1.0, -1.0, -1.5, -0.5 , -1.4} ,{ -0.0 , 2.0, -2.4, -2.2, -2.3 , -2.4 , -0.3 , -0.3 , -0.2} };
+
+ // Invoke GJK to compute distance
+ dist = gjk( nCoordsA, inCoordsA, nCoordsB, inCoordsB );
+
+ // Output results
+ var s = string.Format("{0:0.##}", dist);
+ var message = string.Format("The distance between {0} is {1}","A and B",s);
+ Console.WriteLine(message);
+ Console.WriteLine("Press any key to exit");
+ Console.ReadLine();
+ }
+}
diff --git a/examples/cython/openGJK_cython.pxd b/examples/cython/openGJK_cython.pxd
new file mode 100644
index 0000000..ea7a1ae
--- /dev/null
+++ b/examples/cython/openGJK_cython.pxd
@@ -0,0 +1,44 @@
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# ##### # # # #
+# #### ##### ###### # # # # # # # #
+# # # # # # ## # # # # # #
+# # # # # ##### # # # # #### # ### #
+# # # ##### # # # # # # # # # # #
+# # # # # # ## # # # # # # #
+# #### # ###### # # ##### ##### # # #
+# #
+# This file is part of openGJK. #
+# #
+# OpenGJK 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 #
+# any later version. #
+# #
+# OpenGJK 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 OpenGJK. If not, see . #
+# #
+# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
+# Copyright (C) Mattia Montanari 2018 - 2020 #
+# http://iel.eng.ox.ac.uk/?page_id=504 #
+# #
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+
+# Declare C function and data types
+cdef extern from "openGJK.h":
+ struct bd:
+ int numpoints
+ double s[3]
+ double ** coord
+
+ struct simplex:
+ int nvrtx
+ double vrtx[4][3]
+ int wids[4]
+ double lambdas[4]
+
+ double gjk(bd bd1, bd bd2, simplex *s)
diff --git a/examples/cython/openGJK_cython.pyx b/examples/cython/openGJK_cython.pyx
new file mode 100644
index 0000000..4ee60e5
--- /dev/null
+++ b/examples/cython/openGJK_cython.pyx
@@ -0,0 +1,111 @@
+#!python
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# ##### # # # #
+# #### ##### ###### # # # # # # # #
+# # # # # # ## # # # # # #
+# # # # # ##### # # # # #### # ### #
+# # # ##### # # # # # # # # # # #
+# # # # # # ## # # # # # # #
+# #### # ###### # # ##### ##### # # #
+# #
+# This file is part of openGJK. #
+# #
+# OpenGJK 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 #
+# any later version. #
+# #
+# OpenGJK 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 OpenGJK. If not, see . #
+# #
+# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
+# Copyright (C) Mattia Montanari 2018 - 2020 #
+# http://iel.eng.ox.ac.uk/?page_id=504 #
+# #
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+
+# cython: language_level=3
+# distutils: sources = ../../src/openGJK.c
+# distutils: include_dirs = ../../include/openGJK
+
+cimport openGJK_cython
+
+import numpy as np
+from libc.stdlib cimport free, malloc
+from cpython.mem cimport PyMem_Malloc, PyMem_Free
+
+# Create Python function
+def pygjk(bod1, bod2):
+
+ # Declare data types
+ cdef:
+ simplex s
+ bd bd1
+ bd bd2
+ double dist2
+
+ # Convert 1D array to 2D, if any
+ if bod1.ndim < 2:
+ bod1 = np.append([bod1], [[1.,1.,1.]], axis = 0)
+ bd1.numpoints = np.size(bod1,0) - 1
+ else:
+ bd1.numpoints = np.size(bod1,0)
+
+
+ if bod2.ndim < 2:
+ bod2 = np.append([bod2], [[1.,1.,1.]], axis = 0)
+ bd2.numpoints = np.size(bod2,0) - 1
+ else:
+ bd2.numpoints = np.size(bod2,0)
+
+
+ # Allocate memory for bodies
+ bd1.coord = malloc(bd1.numpoints * sizeof(double *))
+ if not bd1.coord:
+ raise NameError('Not enough memory for bd1.coord')
+ for i in range(0, bd1.numpoints):
+ bd1.coord[i] = malloc(3 * sizeof(double))
+ if not bd1.coord[i]:
+ raise NameError('Not enough memory for bd1.coord[]')
+
+ bd2.coord = malloc(bd2.numpoints * sizeof(double *))
+ if not bd2.coord:
+ raise NameError('Not enough memory for bd2.coord')
+ for j in range(0, bd2.numpoints):
+ bd2.coord[j] = malloc(3 * sizeof(double))
+ if not bd2.coord[j]:
+ raise NameError('Not enough memory for bd2.coord[]')
+
+ # Create numpy-array MemoryView
+ cdef:
+ double [:,:] narr1 = bod1
+ double [:,:] narr2 = bod2
+
+ # Assign coordinate values
+ for i in range(0, bd1.numpoints):
+ for j in range(0,3):
+ bd1.coord[i][j] = narr1[i,j]
+
+ for i in range(0, bd2.numpoints):
+ for j in range(0,3):
+ bd2.coord[i][j] = narr2[i,j]
+
+ # Call C function
+ dist2 = gjk(bd1, bd2, &s)
+
+ # Free the memory
+ for ii in range(0, bd1.numpoints):
+ free(bd1.coord[ii])
+ free(bd1.coord)
+
+ for jj in range(0, bd2.numpoints):
+ free(bd2.coord[jj])
+ free(bd2.coord)
+
+ return dist2
+
diff --git a/examples/cython/pygjk_trial.py b/examples/cython/pygjk_trial.py
new file mode 100644
index 0000000..3b68b7a
--- /dev/null
+++ b/examples/cython/pygjk_trial.py
@@ -0,0 +1,38 @@
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# ##### # # # #
+# #### ##### ###### # # # # # # # #
+# # # # # # ## # # # # # #
+# # # # # ##### # # # # #### # ### #
+# # # ##### # # # # # # # # # # #
+# # # # # # ## # # # # # # #
+# #### # ###### # # ##### ##### # # #
+# #
+# This file is part of openGJK. #
+# #
+# OpenGJK 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 #
+# any later version. #
+# #
+# OpenGJK 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 OpenGJK. If not, see . #
+# #
+# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
+# Copyright (C) Mattia Montanari 2018 - 2020 #
+# http://iel.eng.ox.ac.uk/?page_id=504 #
+# #
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+
+import numpy as np
+import openGJK_cython as opengjk
+
+a = np.array([[1.,1.,1.],[1.,1.,1.]])
+b = np.array([[11.,1.,1.],[1.,1.,1.]])
+d = opengjk.pygjk(a,b)
+
+print(d)
\ No newline at end of file
diff --git a/examples/cython/setup.py b/examples/cython/setup.py
new file mode 100644
index 0000000..801ff67
--- /dev/null
+++ b/examples/cython/setup.py
@@ -0,0 +1,44 @@
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+# ##### # # # #
+# #### ##### ###### # # # # # # # #
+# # # # # # ## # # # # # #
+# # # # # ##### # # # # #### # ### #
+# # # ##### # # # # # # # # # # #
+# # # # # # ## # # # # # # #
+# #### # ###### # # ##### ##### # # #
+# #
+# This file is part of openGJK. #
+# #
+# OpenGJK 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 #
+# any later version. #
+# #
+# OpenGJK 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 OpenGJK. If not, see . #
+# #
+# openGJK: open-source Gilbert-Johnson-Keerthi algorithm #
+# Copyright (C) Mattia Montanari 2018 - 2020 #
+# http://iel.eng.ox.ac.uk/?page_id=504 #
+# #
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
+
+from setuptools import Extension, setup
+from Cython.Build import cythonize
+
+exts = Extension(
+ "openGJK_cython",
+ sources = ["openGJK_cython.pyx"],
+ extra_compile_args=['-I../../include/','-fopenmp'],
+ extra_link_args=['-fopenmp'],
+)
+
+setup(
+ name='openGJK-cython-version',
+ ext_modules = cythonize( [exts] )
+)
\ No newline at end of file
diff --git a/examples/cython/test.py b/examples/cython/test.py
new file mode 100644
index 0000000..aba5508
--- /dev/null
+++ b/examples/cython/test.py
@@ -0,0 +1,185 @@
+import openGJK_cython as opengjk
+from scipy.spatial.transform import Rotation as R
+import numpy as np
+import pytest
+#from IPython import embed
+
+def settol():
+ return 1e-12
+
+def distance_point_to_line_3D(P1, P2, point):
+ """
+ distance from point to line
+ """
+ return np.linalg.norm(np.cross(P2-P1, P1-point))/np.linalg.norm(P2-P1)
+
+
+def distance_point_to_plane_3D(P1, P2, P3, point):
+ """
+ Distance from point to plane
+ """
+ return np.abs(np.dot(np.cross(P2-P1, P3-P1) /
+ np.linalg.norm(np.cross(P2-P1, P3-P1)), point-P2))
+
+
+@pytest.mark.parametrize("delta", [0.1, 1e-12, 0, -2])
+def test_line_point_distance(delta):
+ line = np.array([[0.1, 0.2, 0.3], [0.5, 0.8, 0.7]], dtype=np.float64)
+ point_on_line = line[0] + 0.27*(line[1]-line[0])
+ normal = np.cross(line[0], line[1])
+ point = point_on_line + delta * normal
+ distance = opengjk.pygjk(line, point)
+ actual_distance = distance_point_to_line_3D(
+ line[0], line[1], point)
+ print(distance, actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [0.1, 1e-12, 0])
+def test_line_line_distance(delta):
+ line = np.array([[-0.5, -0.7, -0.3], [1, 2, 3]], dtype=np.float64)
+ point_on_line = line[0] + 0.38*(line[1]-line[0])
+ normal = np.cross(line[0], line[1])
+ point = point_on_line + delta * normal
+ line_2 = np.array([point, [2, 5, 6]], dtype=np.float64)
+ distance = opengjk.pygjk(line, line_2)
+ actual_distance = distance_point_to_line_3D(
+ line[0], line[1], line_2[0])
+ print(distance, actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [0.1**(3*i) for i in range(6)])
+def test_tri_distance(delta):
+ tri_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0]], dtype=np.float64)
+ tri_2 = np.array([[1, delta, 0], [3, 1.2, 0], [
+ 1, 1, 0]], dtype=np.float64)
+ P1 = tri_1[2]
+ P2 = tri_1[1]
+ point = tri_2[0]
+ actual_distance = distance_point_to_line_3D(P1, P2, point)
+ distance = opengjk.pygjk(tri_1, tri_2)
+ print("Computed distance ", distance, "Actual distance ", actual_distance)
+
+ #embed()
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [0.1*0.1**(3*i) for i in range(6)])
+def test_quad_distance2d(delta):
+ quad_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0],
+ [1, 1, 0]], dtype=np.float64)
+ quad_2 = np.array([[0, 1+delta, 0], [2, 2, 0],
+ [2, 4, 0], [4, 4, 0]], dtype=np.float64)
+ P1 = quad_1[2]
+ P2 = quad_1[3]
+ point = quad_2[0]
+ actual_distance = distance_point_to_line_3D(P1, P2, point)
+ distance = opengjk.pygjk(quad_1, quad_2)
+ print("Computed distance ", distance, "Actual distance ", actual_distance)
+
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [1*0.5**(3*i) for i in range(7)])
+def test_tetra_distance_3d(delta):
+ tetra_1 = np.array([[0, 0, 0.2], [1, 0, 0.1], [0, 1, 0.3],
+ [0, 0, 1]], dtype=np.float64)
+ tetra_2 = np.array([[0, 0, -3], [1, 0, -3], [0, 1, -3],
+ [0.5, 0.3, -delta]], dtype=np.float64)
+ actual_distance = distance_point_to_plane_3D(tetra_1[0], tetra_1[1],
+ tetra_1[2], tetra_2[3])
+ distance = opengjk.pygjk(tetra_1, tetra_2)
+ print("Computed distance ", distance, "Actual distance ", actual_distance)
+
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [(-1)**i*np.sqrt(2)*0.1**(3*i)
+ for i in range(6)])
+def test_tetra_collision_3d(delta):
+ tetra_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0],
+ [0, 0, 1]], dtype=np.float64)
+ tetra_2 = np.array([[0, 0, -3], [1, 0, -3], [0, 1, -3],
+ [0.5, 0.3, -delta]], dtype=np.float64)
+ actual_distance = distance_point_to_plane_3D(tetra_1[0], tetra_1[1],
+ tetra_1[2], tetra_2[3])
+ distance = opengjk.pygjk(tetra_1, tetra_2)
+
+ if delta < 0:
+ assert(np.isclose(distance, 0, atol=settol()))
+ else:
+ print("Computed distance ", distance,
+ "Actual distance ", actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol()))
+
+
+@pytest.mark.parametrize("delta", [0, -0.1, -0.49, -0.51])
+def test_hex_collision_3d(delta):
+ hex_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0],
+ [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]],
+ dtype=np.float64)
+ P0 = np.array([1.5+delta, 1.5+delta, 0.5], dtype=np.float64)
+ P1 = np.array([2, 2, 1], dtype=np.float64)
+ P2 = np.array([2, 1.25, 0.25], dtype=np.float64)
+ P3 = P1 + P2 - P0
+ quad_1 = np.array([P0, P1, P2, P3], dtype=np.float64)
+ n = (np.cross(quad_1[1]-quad_1[0], quad_1[2]-quad_1[0]) /
+ np.linalg.norm(
+ np.cross(quad_1[1]-quad_1[0],
+ quad_1[2]-quad_1[0])))
+ quad_2 = quad_1 + n
+ hex_2 = np.zeros((8, 3), dtype=np.float64)
+ hex_2[:4, :] = quad_1
+ hex_2[4:, :] = quad_2
+ actual_distance = np.linalg.norm(
+ np.array([1, 1, P0[2]], dtype=np.float64)-hex_2[0])
+ distance = opengjk.pygjk(hex_1, hex_2)
+
+ if P0[0] < 1:
+ assert(np.isclose(distance, 0, atol=settol()))
+ else:
+ print("Computed distance ", distance,
+ "Actual distance ", actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol()))
+
+
+@pytest.mark.parametrize("c0", [0, 1, 2, 3])
+@pytest.mark.parametrize("c1", [0, 1, 2, 3])
+def test_cube_distance(c0, c1):
+ cubes = [np.array([[-1, -1, -1], [1, -1, -1], [-1, 1, -1], [1, 1, -1],
+ [-1, -1, 1], [1, -1, 1], [-1, 1, 1], [1, 1, 1]],
+ dtype=np.float64)]
+
+ r = R.from_euler('z', 45, degrees=True)
+ cubes.append(r.apply(cubes[0]))
+ r = R.from_euler('y', np.arctan2(1.0, np.sqrt(2)))
+ cubes.append(r.apply(cubes[1]))
+ r = R.from_euler('y', 45, degrees=True)
+ cubes.append(r.apply(cubes[0]))
+
+ dx = cubes[c0][:,0].max() - cubes[c1][:,0].min()
+ cube0 = cubes[c0]
+
+ for delta in [1e8, 1.0, 1e-4, 1e-8, 1e-12]:
+ cube1 = cubes[c1] + np.array([dx + delta, 0, 0])
+ distance = opengjk.pygjk(cube0, cube1)
+ print(distance, delta)
+ assert(np.isclose(distance, delta))
+
+def test_random_objects():
+ for i in range(1, 8):
+ for j in range(1, 8):
+ for k in range(1000):
+ arr1 = np.random.rand(i, 3)
+ arr2 = np.random.rand(j, 3)
+ opengjk.pygjk(arr1, arr2)
+
+
+def test_large_random_objects():
+ for i in range(1, 8):
+ for j in range(1, 8):
+ for k in range(1000):
+ arr1 = 10000.0*np.random.rand(i, 3)
+ arr2 = 10000.0*np.random.rand(j, 3)
+ opengjk.pygjk(arr1, arr2)
diff --git a/example2_mex/main.m b/examples/matlab/main.m
similarity index 98%
rename from example2_mex/main.m
rename to examples/matlab/main.m
index b979c8b..b128667 100644
--- a/example2_mex/main.m
+++ b/examples/matlab/main.m
@@ -1,78 +1,78 @@
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
-% ##### # # # %
-% #### ##### ###### # # # # # # # %
-% # # # # # ## # # # # # %
-% # # # # ##### # # # # #### # ### %
-% # # ##### # # # # # # # # # # %
-% # # # # # ## # # # # # # %
-% #### # ###### # # ##### ##### # # %
-% %
-% This file is part of openGJK. %
-% %
-% openGJK 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 %
-% any later version. %
-% %
-% openGJK 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 Foobar. If not, see . %
-% %
-% openGJK: open-source Gilbert-Johnson-Keerthi algorithm %
-% Copyright (C) Mattia Montanari 2018 - 2019 %
-% http://iel.eng.ox.ac.uk/?page_id=504 %
-% %
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
-% %
-% This file runs an example to illustrate how to cll the openGJK library %
-% withing Matlab. It assumes that a mex file openGJK is availalbe, see %
-% the runme.m script for information on how to compile it. %
-% The example computes the minimum distance between two polytopes in 3D, %
-% A and B, both defined as a list of points. %
-% %
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
-
-% DEFINE BODY A AS 3xN MATRIX, WHERE N IS THE NUMBER OF VERTICES OF BODY A
-A = [ 0.0 2.3 8.1 4.3 2.5 7.1 1.0 3.3 6.0
- 5.5 1.0 4.0 5.0 1.0 1.0 1.5 0.5 1.4
- 0.0 -2.0 2.4 2.2 2.3 2.4 0.3 0.3 0.2];
-
-% DEFINE BODY B IN THE OPPOSITE QUADRANT OF BODY A
-B = -A;
-
-% COMPUTE MINIMUM DISTANCE AND RETURN VALUE
-dist = openGJK( A, B );
-fprintf('The minimum distance between A and B is %.2f\n',dist);
-
-% VISUALISE RESULTS
-% .. create new figure
-figure('units','centimeters', 'WindowStyle','normal', 'color','w',...
- 'Position',[0 8.5 9 6],'defaultAxesColorOrder',parula,...
- 'Renderer','opengl')
-% .. adjust properties
-axis equal tight off; hold all;
-% .. display body A
-DT = delaunayTriangulation(A');
-[K,~] = convexHull(DT);
-trisurf(K,DT.Points(:,1),DT.Points(:,2),DT.Points(:,3),...
- 'EdgeColor','none','FaceColor',[.4 1 .9 ],...
- 'FaceLighting','flat' )
-% .. display body B
-DT = delaunayTriangulation(B');
-[K,~] = convexHull(DT);
-trisurf(K,DT.Points(:,1),DT.Points(:,2),DT.Points(:,3),...
- 'EdgeColor','none','FaceColor',[.4 1 .8 ],...
- 'FaceLighting','flat' )
-% .. represent the computed distance as a sphere
-[x,y,z] = sphere(100);
-surf(x.*dist/2,y.*dist/2,z.*dist/2,'facecolor',[.9 .9 .9],...
- 'EdgeColor','none','FaceLighting','flat','SpecularColorReflectance',0,...
- 'SpecularStrength',1,'SpecularExponent',10,'facealpha',.7)
-% ... adjust point of view
-view(42,21)
-% ... add light
-light('Position',[5 -10 20],'Style','local');
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
+% ##### # # # %
+% #### ##### ###### # # # # # # # %
+% # # # # # ## # # # # # %
+% # # # # ##### # # # # #### # ### %
+% # # ##### # # # # # # # # # # %
+% # # # # # ## # # # # # # %
+% #### # ###### # # ##### ##### # # %
+% %
+% This file is part of openGJK. %
+% %
+% openGJK 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 %
+% any later version. %
+% %
+% openGJK 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 Foobar. If not, see . %
+% %
+% openGJK: open-source Gilbert-Johnson-Keerthi algorithm %
+% Copyright (C) Mattia Montanari 2018 - 2019 %
+% http://iel.eng.ox.ac.uk/?page_id=504 %
+% %
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
+% %
+% This file runs an example to illustrate how to cll the openGJK library %
+% withing Matlab. It assumes that a mex file openGJK is availalbe, see %
+% the runme.m script for information on how to compile it. %
+% The example computes the minimum distance between two polytopes in 3D, %
+% A and B, both defined as a list of points. %
+% %
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
+
+% DEFINE BODY A AS 3xN MATRIX, WHERE N IS THE NUMBER OF VERTICES OF BODY A
+A = [ 0.0 2.3 8.1 4.3 2.5 7.1 1.0 3.3 6.0
+ 5.5 1.0 4.0 5.0 1.0 1.0 1.5 0.5 1.4
+ 0.0 -2.0 2.4 2.2 2.3 2.4 0.3 0.3 0.2];
+
+% DEFINE BODY B IN THE OPPOSITE QUADRANT OF BODY A
+B = -A;
+
+% COMPUTE MINIMUM DISTANCE AND RETURN VALUE
+dist = openGJK( A, B );
+fprintf('The minimum distance between A and B is %.2f\n',dist);
+
+% VISUALISE RESULTS
+% .. create new figure
+figure('units','centimeters', 'WindowStyle','normal', 'color','w',...
+ 'Position',[0 8.5 9 6],'defaultAxesColorOrder',parula,...
+ 'Renderer','opengl')
+% .. adjust properties
+axis equal tight off; hold all;
+% .. display body A
+DT = delaunayTriangulation(A');
+[K,~] = convexHull(DT);
+trisurf(K,DT.Points(:,1),DT.Points(:,2),DT.Points(:,3),...
+ 'EdgeColor','none','FaceColor',[.4 1 .9 ],...
+ 'FaceLighting','flat' )
+% .. display body B
+DT = delaunayTriangulation(B');
+[K,~] = convexHull(DT);
+trisurf(K,DT.Points(:,1),DT.Points(:,2),DT.Points(:,3),...
+ 'EdgeColor','none','FaceColor',[.4 1 .8 ],...
+ 'FaceLighting','flat' )
+% .. represent the computed distance as a sphere
+[x,y,z] = sphere(100);
+surf(x.*dist/2,y.*dist/2,z.*dist/2,'facecolor',[.9 .9 .9],...
+ 'EdgeColor','none','FaceLighting','flat','SpecularColorReflectance',0,...
+ 'SpecularStrength',1,'SpecularExponent',10,'facealpha',.7)
+% ... adjust point of view
+view(42,21)
+% ... add light
+light('Position',[5 -10 20],'Style','local');
diff --git a/example2_mex/runme.m b/examples/matlab/runme.m
similarity index 94%
rename from example2_mex/runme.m
rename to examples/matlab/runme.m
index a90f6d8..ff6e21c 100644
--- a/example2_mex/runme.m
+++ b/examples/matlab/runme.m
@@ -1,79 +1,79 @@
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
-% ##### # # # %
-% #### ##### ###### # # # # # # # %
-% # # # # # ## # # # # # %
-% # # # # ##### # # # # #### # ### %
-% # # ##### # # # # # # # # # # %
-% # # # # # ## # # # # # # %
-% #### # ###### # # ##### ##### # # %
-% %
-% This file is part of openGJK. %
-% %
-% openGJK 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 %
-% any later version. %
-% %
-% openGJK 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 Foobar. If not, see . %
-% %
-% openGJK: open-source Gilbert-Johnson-Keerthi algorithm %
-% Copyright (C) Mattia Montanari 2018 - 2019 %
-% http://iel.eng.ox.ac.uk/?page_id=504 %
-% %
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
-% %
-% This file compiles a mex function from the openGJK library and runs an %
-% example. If the mex function cannot be compiled an error is returned. %
-% %
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
-
-% CLEAR ALL VARIABLES
-clearvars
-
-% SELECT OPTIMISATION FLAG - FASTER BUT NOT SUITABLE FOR DEBUGGING
-if 0
- optflug = '-g'; %#ok<*UNRCH>
-else
- optflug = '-O';
-end
-% SELECT SILET COMPILATION MODE.
-if 1
- silflag = '-silent';
-else
- silflag = '-v';
-end
-
-% TRY COMPILING MEX FILE
-fprintf('Compiling mex function... ')
-try
-mex(fullfile('..','lib','src','openGJK.c'),... % Source of openGJK
- '-largeArrayDims', ... % Support large arrays
- optflug, ... % Compiler flag for debug/optimisation
- fullfile('-I..','lib','include'),... % Folder to header files
- '-outdir', pwd,... % Ouput directory for writing mex function
- '-output', 'openGJK',... % Name of ouput mex file
- '-DMATLABDOESMEXSTUFF',... % Define variable for mex function in source files
- silflag ) % Silent/verbose flag
-
- % File compiled without errors. Return path and name of mex file
- fprintf('completed!\n')
- fprintf('The following mex file has been generated:')
- fprintf('\t%s\n',[pwd,filesep,'openGJK.',mexext])
-catch
- % Build failed, refer to documentation
- fprintf('\n\n ERROR DETECTED! Mex file cannot be compiled.\n')
- fprintf('\tFor more information, see ')
- fprintf('this documentation page.\n\n')
- return
-end
-
-% RUN EXAMPLE
-fprintf('Running example... ')
-main
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
+% ##### # # # %
+% #### ##### ###### # # # # # # # %
+% # # # # # ## # # # # # %
+% # # # # ##### # # # # #### # ### %
+% # # ##### # # # # # # # # # # %
+% # # # # # ## # # # # # # %
+% #### # ###### # # ##### ##### # # %
+% %
+% This file is part of openGJK. %
+% %
+% openGJK 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 %
+% any later version. %
+% %
+% openGJK 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 Foobar. If not, see . %
+% %
+% openGJK: open-source Gilbert-Johnson-Keerthi algorithm %
+% Copyright (C) Mattia Montanari 2018 - 2019 %
+% http://iel.eng.ox.ac.uk/?page_id=504 %
+% %
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
+% %
+% This file compiles a mex function from the openGJK library and runs an %
+% example. If the mex function cannot be compiled an error is returned. %
+% %
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
+
+% CLEAR ALL VARIABLES
+clearvars
+
+% SELECT OPTIMISATION FLAG - FASTER BUT NOT SUITABLE FOR DEBUGGING
+if 0
+ optflug = '-g'; %#ok<*UNRCH>
+else
+ optflug = '-O';
+end
+% SELECT SILET COMPILATION MODE.
+if 1
+ silflag = '-silent';
+else
+ silflag = '-v';
+end
+
+% TRY COMPILING MEX FILE
+fprintf('Compiling mex function... ')
+try
+mex(fullfile('..','..','src','openGJK.c'),... % Source of openGJK
+ '-largeArrayDims', ... % Support large arrays
+ optflug, ... % Compiler flag for debug/optimisation
+ fullfile('-I..','..','include'),... % Folder to header files
+ '-outdir', pwd,... % Ouput directory for writing mex function
+ '-output', 'openGJK',... % Name of ouput mex file
+ '-DMATLABDOESMEXSTUFF',... % Define variable for mex function in source files
+ silflag ) % Silent/verbose flag
+
+ % File compiled without errors. Return path and name of mex file
+ fprintf('completed!\n')
+ fprintf('The following mex file has been generated:')
+ fprintf('\t%s\n',[pwd,filesep,'openGJK.',mexext])
+catch
+ % Build failed, refer to documentation
+ fprintf('\n\n ERROR DETECTED! Mex file cannot be compiled.\n')
+ fprintf('\tFor more information, see ')
+ fprintf('this documentation page.\n\n')
+ return
+end
+
+% RUN EXAMPLE
+fprintf('Running example... ')
+main
fprintf('completed!\n')
\ No newline at end of file
diff --git a/examples/python/build.sh b/examples/python/build.sh
new file mode 100755
index 0000000..b789d71
--- /dev/null
+++ b/examples/python/build.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+g++ -Wall -fPIC -fopenmp -shared `python3 -m pybind11 --includes` -I ../../include -I/usr/include/eigen3 pyopenGJK.cpp ../../src/openGJK.c -o opengjkc`python3-config --extension-suffix`
\ No newline at end of file
diff --git a/examples/python/pyopenGJK.cpp b/examples/python/pyopenGJK.cpp
new file mode 100644
index 0000000..f1a69d1
--- /dev/null
+++ b/examples/python/pyopenGJK.cpp
@@ -0,0 +1,31 @@
+#include "openGJK/openGJK.h"
+#include
+#include
+namespace py = pybind11;
+
+PYBIND11_MODULE(opengjkc, m)
+{
+ m.def("gjk",
+ [](Eigen::Array& arr1,
+ Eigen::Array& arr2)
+ -> double {
+ struct simplex s;
+ struct bd bd1;
+ struct bd bd2;
+ bd1.numpoints = arr1.rows();
+ std::vector arr1_rows(arr1.rows());
+ for (int i = 0; i < arr1.rows(); ++i)
+ arr1_rows[i] = arr1.row(i).data();
+ bd1.coord = arr1_rows.data();
+
+ bd2.numpoints = arr2.rows();
+ std::vector arr2_rows(arr2.rows());
+ for (int i = 0; i < arr2.rows(); ++i)
+ arr2_rows[i] = arr2.row(i).data();
+ bd2.coord = arr2_rows.data();
+
+ double a = gjk(bd1, bd2, &s);
+
+ return a;
+ });
+}
\ No newline at end of file
diff --git a/examples/python/test.py b/examples/python/test.py
new file mode 100644
index 0000000..e9fb20d
--- /dev/null
+++ b/examples/python/test.py
@@ -0,0 +1,185 @@
+import opengjkc as opengjk
+from scipy.spatial.transform import Rotation as R
+import numpy as np
+import pytest
+#from IPython import embed
+
+def settol():
+ return 1e-12
+
+def distance_point_to_line_3D(P1, P2, point):
+ """
+ distance from point to line
+ """
+ return np.linalg.norm(np.cross(P2-P1, P1-point))/np.linalg.norm(P2-P1)
+
+
+def distance_point_to_plane_3D(P1, P2, P3, point):
+ """
+ Distance from point to plane
+ """
+ return np.abs(np.dot(np.cross(P2-P1, P3-P1) /
+ np.linalg.norm(np.cross(P2-P1, P3-P1)), point-P2))
+
+
+@pytest.mark.parametrize("delta", [0.1, 1e-12, 0, -2])
+def test_line_point_distance(delta):
+ line = np.array([[0.1, 0.2, 0.3], [0.5, 0.8, 0.7]], dtype=np.float64)
+ point_on_line = line[0] + 0.27*(line[1]-line[0])
+ normal = np.cross(line[0], line[1])
+ point = point_on_line + delta * normal
+ distance = opengjk.gjk(line, point)
+ actual_distance = distance_point_to_line_3D(
+ line[0], line[1], point)
+ print(distance, actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [0.1, 1e-12, 0])
+def test_line_line_distance(delta):
+ line = np.array([[-0.5, -0.7, -0.3], [1, 2, 3]], dtype=np.float64)
+ point_on_line = line[0] + 0.38*(line[1]-line[0])
+ normal = np.cross(line[0], line[1])
+ point = point_on_line + delta * normal
+ line_2 = np.array([point, [2, 5, 6]], dtype=np.float64)
+ distance = opengjk.gjk(line, line_2)
+ actual_distance = distance_point_to_line_3D(
+ line[0], line[1], line_2[0])
+ print(distance, actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [0.1**(3*i) for i in range(6)])
+def test_tri_distance(delta):
+ tri_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0]], dtype=np.float64)
+ tri_2 = np.array([[1, delta, 0], [3, 1.2, 0], [
+ 1, 1, 0]], dtype=np.float64)
+ P1 = tri_1[2]
+ P2 = tri_1[1]
+ point = tri_2[0]
+ actual_distance = distance_point_to_line_3D(P1, P2, point)
+ distance = opengjk.gjk(tri_1, tri_2)
+ print("Computed distance ", distance, "Actual distance ", actual_distance)
+
+ #embed()
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [0.1*0.1**(3*i) for i in range(6)])
+def test_quad_distance2d(delta):
+ quad_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0],
+ [1, 1, 0]], dtype=np.float64)
+ quad_2 = np.array([[0, 1+delta, 0], [2, 2, 0],
+ [2, 4, 0], [4, 4, 0]], dtype=np.float64)
+ P1 = quad_1[2]
+ P2 = quad_1[3]
+ point = quad_2[0]
+ actual_distance = distance_point_to_line_3D(P1, P2, point)
+ distance = opengjk.gjk(quad_1, quad_2)
+ print("Computed distance ", distance, "Actual distance ", actual_distance)
+
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [1*0.5**(3*i) for i in range(7)])
+def test_tetra_distance_3d(delta):
+ tetra_1 = np.array([[0, 0, 0.2], [1, 0, 0.1], [0, 1, 0.3],
+ [0, 0, 1]], dtype=np.float64)
+ tetra_2 = np.array([[0, 0, -3], [1, 0, -3], [0, 1, -3],
+ [0.5, 0.3, -delta]], dtype=np.float64)
+ actual_distance = distance_point_to_plane_3D(tetra_1[0], tetra_1[1],
+ tetra_1[2], tetra_2[3])
+ distance = opengjk.gjk(tetra_1, tetra_2)
+ print("Computed distance ", distance, "Actual distance ", actual_distance)
+
+ assert(np.isclose(distance, actual_distance, atol=settol() ))
+
+
+@pytest.mark.parametrize("delta", [(-1)**i*np.sqrt(2)*0.1**(3*i)
+ for i in range(6)])
+def test_tetra_collision_3d(delta):
+ tetra_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0],
+ [0, 0, 1]], dtype=np.float64)
+ tetra_2 = np.array([[0, 0, -3], [1, 0, -3], [0, 1, -3],
+ [0.5, 0.3, -delta]], dtype=np.float64)
+ actual_distance = distance_point_to_plane_3D(tetra_1[0], tetra_1[1],
+ tetra_1[2], tetra_2[3])
+ distance = opengjk.gjk(tetra_1, tetra_2)
+
+ if delta < 0:
+ assert(np.isclose(distance, 0, atol=settol()))
+ else:
+ print("Computed distance ", distance,
+ "Actual distance ", actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol()))
+
+
+@pytest.mark.parametrize("delta", [0, -0.1, -0.49, -0.51])
+def test_hex_collision_3d(delta):
+ hex_1 = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0],
+ [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]],
+ dtype=np.float64)
+ P0 = np.array([1.5+delta, 1.5+delta, 0.5], dtype=np.float64)
+ P1 = np.array([2, 2, 1], dtype=np.float64)
+ P2 = np.array([2, 1.25, 0.25], dtype=np.float64)
+ P3 = P1 + P2 - P0
+ quad_1 = np.array([P0, P1, P2, P3], dtype=np.float64)
+ n = (np.cross(quad_1[1]-quad_1[0], quad_1[2]-quad_1[0]) /
+ np.linalg.norm(
+ np.cross(quad_1[1]-quad_1[0],
+ quad_1[2]-quad_1[0])))
+ quad_2 = quad_1 + n
+ hex_2 = np.zeros((8, 3), dtype=np.float64)
+ hex_2[:4, :] = quad_1
+ hex_2[4:, :] = quad_2
+ actual_distance = np.linalg.norm(
+ np.array([1, 1, P0[2]], dtype=np.float64)-hex_2[0])
+ distance = opengjk.gjk(hex_1, hex_2)
+
+ if P0[0] < 1:
+ assert(np.isclose(distance, 0, atol=settol()))
+ else:
+ print("Computed distance ", distance,
+ "Actual distance ", actual_distance)
+ assert(np.isclose(distance, actual_distance, atol=settol()))
+
+
+@pytest.mark.parametrize("c0", [0, 1, 2, 3])
+@pytest.mark.parametrize("c1", [0, 1, 2, 3])
+def test_cube_distance(c0, c1):
+ cubes = [np.array([[-1, -1, -1], [1, -1, -1], [-1, 1, -1], [1, 1, -1],
+ [-1, -1, 1], [1, -1, 1], [-1, 1, 1], [1, 1, 1]],
+ dtype=np.float64)]
+
+ r = R.from_euler('z', 45, degrees=True)
+ cubes.append(r.apply(cubes[0]))
+ r = R.from_euler('y', np.arctan2(1.0, np.sqrt(2)))
+ cubes.append(r.apply(cubes[1]))
+ r = R.from_euler('y', 45, degrees=True)
+ cubes.append(r.apply(cubes[0]))
+
+ dx = cubes[c0][:,0].max() - cubes[c1][:,0].min()
+ cube0 = cubes[c0]
+
+ for delta in [1e8, 1.0, 1e-4, 1e-8, 1e-12]:
+ cube1 = cubes[c1] + np.array([dx + delta, 0, 0])
+ distance = opengjk.gjk(cube0, cube1)
+ print(distance, delta)
+ assert(np.isclose(distance, delta))
+
+def test_random_objects():
+ for i in range(1, 8):
+ for j in range(1, 8):
+ for k in range(1000):
+ arr1 = np.random.rand(i, 3)
+ arr2 = np.random.rand(j, 3)
+ opengjk.gjk(arr1, arr2)
+
+
+def test_large_random_objects():
+ for i in range(1, 8):
+ for j in range(1, 8):
+ for k in range(1000):
+ arr1 = 10000.0*np.random.rand(i, 3)
+ arr2 = 10000.0*np.random.rand(j, 3)
+ opengjk.gjk(arr1, arr2)
diff --git a/include/openGJK/openGJK.h b/include/openGJK/openGJK.h
new file mode 100644
index 0000000..71455f8
--- /dev/null
+++ b/include/openGJK/openGJK.h
@@ -0,0 +1,52 @@
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
+* ##### # # # *
+* #### ##### ###### # # # # # # # *
+* # # # # # ## # # # # # *
+* # # # # ##### # # # # #### # ### *
+* # # ##### # # # # # # # # # # *
+* # # # # # ## # # # # # # *
+* #### # ###### # # ##### ##### # # *
+* *
+* Edward Garemo and Mattia Montanari *
+* University of Oxford 2019 *
+* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
+* *
+* This is the header file for the openGJK.c file. It defines the openGJK *
+* function and it two important structures: bd and simplex. *
+* *
+* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#ifndef __OPENGJK_H__
+#define __OPENGJK_H__
+
+#include
+#include
+#include "math.h"
+
+/**
+* @brief Structure of a body.
+*/
+struct bd {
+ int numpoints; /**< Number of points defining the body. */
+ double s[3]; /**< Support mapping computed last. */
+ double **coord; /**< Pointer to pointer to the points' coordinates. */
+};
+
+
+/**
+* @brief Structure for a simplex.
+*/
+struct simplex {
+ int nvrtx; /**< Number of simplex's vertices. */
+ double vrtx[4][3]; /**< Coordinates of simplex's vertices. */
+ int wids[4]; /**< Label of the simplex's vertices. */
+ double lambdas[4]; /**< Barycentric coordiantes for each vertex. */
+};
+
+/**
+ * @brief The GJK algorithm which returns the minimum distance between
+ * two bodies.
+ */
+extern double gjk(struct bd, struct bd, struct simplex *);
+
+#endif
\ No newline at end of file
diff --git a/lib/ext/predicates.c b/lib/ext/predicates.c
deleted file mode 100644
index 95bead5..0000000
--- a/lib/ext/predicates.c
+++ /dev/null
@@ -1,4271 +0,0 @@
-/*****************************************************************************/
-/* */
-/* Routines for Arbitrary Precision Floating-point Arithmetic */
-/* and Fast Robust Geometric Predicates */
-/* (predicates.c) */
-/* */
-/* May 18, 1996 */
-/* */
-/* Placed in the public domain by */
-/* Jonathan Richard Shewchuk */
-/* School of Computer Science */
-/* Carnegie Mellon University */
-/* 5000 Forbes Avenue */
-/* Pittsburgh, Pennsylvania 15213-3891 */
-/* jrs@cs.cmu.edu */
-/* */
-/* This file contains C implementation of algorithms for exact addition */
-/* and multiplication of floating-point numbers, and predicates for */
-/* robustly performing the orientation and incircle tests used in */
-/* computational geometry. The algorithms and underlying theory are */
-/* described in Jonathan Richard Shewchuk. "Adaptive Precision Floating- */
-/* Point Arithmetic and Fast Robust Geometric Predicates." Technical */
-/* Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon */
-/* University, Pittsburgh, Pennsylvania, May 1996. (Submitted to */
-/* Discrete & Computational Geometry.) */
-/* */
-/* This file, the paper listed above, and other information are available */
-/* from the Web page http://www.cs.cmu.edu/~quake/robust.html . */
-/* */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/* */
-/* Using this code: */
-/* */
-/* First, read the short or long version of the paper (from the Web page */
-/* above). */
-/* */
-/* Be sure to call exactinit() once, before calling any of the arithmetic */
-/* functions or geometric predicates. Also be sure to turn on the */
-/* optimizer when compiling this file. */
-/* */
-/* */
-/* Several geometric predicates are defined. Their parameters are all */
-/* points. Each point is an array of two or three floating-point */
-/* numbers. The geometric predicates, described in the papers, are */
-/* */
-/* orient2d(pa, pb, pc) */
-/* orient2dfast(pa, pb, pc) */
-/* orient3d(pa, pb, pc, pd) */
-/* orient3dfast(pa, pb, pc, pd) */
-/* incircle(pa, pb, pc, pd) */
-/* incirclefast(pa, pb, pc, pd) */
-/* insphere(pa, pb, pc, pd, pe) */
-/* inspherefast(pa, pb, pc, pd, pe) */
-/* */
-/* Those with suffix "fast" are approximate, non-robust versions. Those */
-/* without the suffix are adaptive precision, robust versions. There */
-/* are also versions with the suffices "exact" and "slow", which are */
-/* non-adaptive, exact arithmetic versions, which I use only for timings */
-/* in my arithmetic papers. */
-/* */
-/* */
-/* An expansion is represented by an array of floating-point numbers, */
-/* sorted from smallest to largest magnitude (possibly with interspersed */
-/* zeros). The length of each expansion is stored as a separate integer, */
-/* and each arithmetic function returns an integer which is the length */
-/* of the expansion it created. */
-/* */
-/* Several arithmetic functions are defined. Their parameters are */
-/* */
-/* e, f Input expansions */
-/* elen, flen Lengths of input expansions (must be >= 1) */
-/* h Output expansion */
-/* b Input scalar */
-/* */
-/* The arithmetic functions are */
-/* */
-/* grow_expansion(elen, e, b, h) */
-/* grow_expansion_zeroelim(elen, e, b, h) */
-/* expansion_sum(elen, e, flen, f, h) */
-/* expansion_sum_zeroelim1(elen, e, flen, f, h) */
-/* expansion_sum_zeroelim2(elen, e, flen, f, h) */
-/* fast_expansion_sum(elen, e, flen, f, h) */
-/* fast_expansion_sum_zeroelim(elen, e, flen, f, h) */
-/* linear_expansion_sum(elen, e, flen, f, h) */
-/* linear_expansion_sum_zeroelim(elen, e, flen, f, h) */
-/* scale_expansion(elen, e, b, h) */
-/* scale_expansion_zeroelim(elen, e, b, h) */
-/* compress(elen, e, h) */
-/* */
-/* All of these are described in the long version of the paper; some are */
-/* described in the short version. All return an integer that is the */
-/* length of h. Those with suffix _zeroelim perform zero elimination, */
-/* and are recommended over their counterparts. The procedure */
-/* fast_expansion_sum_zeroelim() (or linear_expansion_sum_zeroelim() on */
-/* processors that do not use the round-to-even tiebreaking rule) is */
-/* recommended over expansion_sum_zeroelim(). Each procedure has a */
-/* little note next to it (in the code below) that tells you whether or */
-/* not the output expansion may be the same array as one of the input */
-/* expansions. */
-/* */
-/* */
-/* If you look around below, you'll also find macros for a bunch of */
-/* simple unrolled arithmetic operations, and procedures for printing */
-/* expansions (commented out because they don't work with all C */
-/* compilers) and for generating random floating-point numbers whose */
-/* significand bits are all random. Most of the macros have undocumented */
-/* requirements that certain of their parameters should not be the same */
-/* variable; for safety, better to make sure all the parameters are */
-/* distinct variables. Feel free to send email to jrs@cs.cmu.edu if you */
-/* have questions. */
-/* */
-/*****************************************************************************/
-
-#include "predicates.h"
-
-/* On some machines, the exact arithmetic routines might be defeated by the */
-/* use of internal extended precision floating-point registers. Sometimes */
-/* this problem can be fixed by defining certain values to be volatile, */
-/* thus forcing them to be stored to memory and rounded off. This isn't */
-/* a great solution, though, as it slows the arithmetic down. */
-/* */
-/* To try this out, write "#define INEXACT volatile" below. Normally, */
-/* however, INEXACT should be defined to be nothing. ("#define INEXACT".) */
-
-#define INEXACT /* Nothing */
-/* #define INEXACT volatile */
-
-#define REAL double /* float or double */
-#define REALPRINT doubleprint
-#define REALRAND doublerand
-#define NARROWRAND narrowdoublerand
-#define UNIFORMRAND uniformdoublerand
-
-/* Which of the following two methods of finding the absolute values is */
-/* fastest is compiler-dependent. A few compilers can inline and optimize */
-/* the fabs() call; but most will incur the overhead of a function call, */
-/* which is disastrously slow. A faster way on IEEE machines might be to */
-/* mask the appropriate bit, but that's difficult to do in C. */
-
-#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
-/* #define Absolute(a) fabs(a) */
-
-/* Many of the operations are broken up into two pieces, a main part that */
-/* performs an approximate operation, and a "tail" that computes the */
-/* roundoff error of that operation. */
-/* */
-/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */
-/* Split(), and Two_Product() are all implemented as described in the */
-/* reference. Each of these macros requires certain variables to be */
-/* defined in the calling routine. The variables `bvirt', `c', `abig', */
-/* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */
-/* they store the result of an operation that may incur roundoff error. */
-/* The input parameter `x' (or the highest numbered `x_' parameter) must */
-/* also be declared `INEXACT'. */
-
-#define Fast_Two_Sum_Tail(a, b, x, y) \
- bvirt = x - a; \
- y = b - bvirt
-
-#define Fast_Two_Sum(a, b, x, y) \
- x = (REAL) (a + b); \
- Fast_Two_Sum_Tail(a, b, x, y)
-
-#define Fast_Two_Diff_Tail(a, b, x, y) \
- bvirt = a - x; \
- y = bvirt - b
-
-#define Fast_Two_Diff(a, b, x, y) \
- x = (REAL) (a - b); \
- Fast_Two_Diff_Tail(a, b, x, y)
-
-#define Two_Sum_Tail(a, b, x, y) \
- bvirt = (REAL) (x - a); \
- avirt = x - bvirt; \
- bround = b - bvirt; \
- around = a - avirt; \
- y = around + bround
-
-#define Two_Sum(a, b, x, y) \
- x = (REAL) (a + b); \
- Two_Sum_Tail(a, b, x, y)
-
-#define Two_Diff_Tail(a, b, x, y) \
- bvirt = (REAL) (a - x); \
- avirt = x + bvirt; \
- bround = bvirt - b; \
- around = a - avirt; \
- y = around + bround
-
-#define Two_Diff(a, b, x, y) \
- x = (REAL) (a - b); \
- Two_Diff_Tail(a, b, x, y)
-
-#define Split(a, ahi, alo) \
- c = (REAL) (splitter * a); \
- abig = (REAL) (c - a); \
- ahi = c - abig; \
- alo = a - ahi
-
-#define Two_Product_Tail(a, b, x, y) \
- Split(a, ahi, alo); \
- Split(b, bhi, blo); \
- err1 = x - (ahi * bhi); \
- err2 = err1 - (alo * bhi); \
- err3 = err2 - (ahi * blo); \
- y = (alo * blo) - err3
-
-#define Two_Product(a, b, x, y) \
- x = (REAL) (a * b); \
- Two_Product_Tail(a, b, x, y)
-
-/* Two_Product_Presplit() is Two_Product() where one of the inputs has */
-/* already been split. Avoids redundant splitting. */
-
-#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
- x = (REAL) (a * b); \
- Split(a, ahi, alo); \
- err1 = x - (ahi * bhi); \
- err2 = err1 - (alo * bhi); \
- err3 = err2 - (ahi * blo); \
- y = (alo * blo) - err3
-
-/* Two_Product_2Presplit() is Two_Product() where both of the inputs have */
-/* already been split. Avoids redundant splitting. */
-
-#define Two_Product_2Presplit(a, ahi, alo, b, bhi, blo, x, y) \
- x = (REAL) (a * b); \
- err1 = x - (ahi * bhi); \
- err2 = err1 - (alo * bhi); \
- err3 = err2 - (ahi * blo); \
- y = (alo * blo) - err3
-
-/* Square() can be done more quickly than Two_Product(). */
-
-#define Square_Tail(a, x, y) \
- Split(a, ahi, alo); \
- err1 = x - (ahi * ahi); \
- err3 = err1 - ((ahi + ahi) * alo); \
- y = (alo * alo) - err3
-
-#define Square(a, x, y) \
- x = (REAL) (a * a); \
- Square_Tail(a, x, y)
-
-/* Macros for summing expansions of various fixed lengths. These are all */
-/* unrolled versions of Expansion_Sum(). */
-
-#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
- Two_Sum(a0, b , _i, x0); \
- Two_Sum(a1, _i, x2, x1)
-
-#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
- Two_Diff(a0, b , _i, x0); \
- Two_Sum( a1, _i, x2, x1)
-
-#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
- Two_One_Sum(a1, a0, b0, _j, _0, x0); \
- Two_One_Sum(_j, _0, b1, x3, x2, x1)
-
-#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
- Two_One_Diff(a1, a0, b0, _j, _0, x0); \
- Two_One_Diff(_j, _0, b1, x3, x2, x1)
-
-#define Four_One_Sum(a3, a2, a1, a0, b, x4, x3, x2, x1, x0) \
- Two_One_Sum(a1, a0, b , _j, x1, x0); \
- Two_One_Sum(a3, a2, _j, x4, x3, x2)
-
-#define Four_Two_Sum(a3, a2, a1, a0, b1, b0, x5, x4, x3, x2, x1, x0) \
- Four_One_Sum(a3, a2, a1, a0, b0, _k, _2, _1, _0, x0); \
- Four_One_Sum(_k, _2, _1, _0, b1, x5, x4, x3, x2, x1)
-
-#define Four_Four_Sum(a3, a2, a1, a0, b4, b3, b1, b0, x7, x6, x5, x4, x3, x2, \
- x1, x0) \
- Four_Two_Sum(a3, a2, a1, a0, b1, b0, _l, _2, _1, _0, x1, x0); \
- Four_Two_Sum(_l, _2, _1, _0, b4, b3, x7, x6, x5, x4, x3, x2)
-
-#define Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b, x8, x7, x6, x5, x4, \
- x3, x2, x1, x0) \
- Four_One_Sum(a3, a2, a1, a0, b , _j, x3, x2, x1, x0); \
- Four_One_Sum(a7, a6, a5, a4, _j, x8, x7, x6, x5, x4)
-
-#define Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, x9, x8, x7, \
- x6, x5, x4, x3, x2, x1, x0) \
- Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b0, _k, _6, _5, _4, _3, _2, \
- _1, _0, x0); \
- Eight_One_Sum(_k, _6, _5, _4, _3, _2, _1, _0, b1, x9, x8, x7, x6, x5, x4, \
- x3, x2, x1)
-
-#define Eight_Four_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b4, b3, b1, b0, x11, \
- x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0) \
- Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, _l, _6, _5, _4, _3, \
- _2, _1, _0, x1, x0); \
- Eight_Two_Sum(_l, _6, _5, _4, _3, _2, _1, _0, b4, b3, x11, x10, x9, x8, \
- x7, x6, x5, x4, x3, x2)
-
-/* Macros for multiplying expansions of various fixed lengths. */
-
-#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
- Split(b, bhi, blo); \
- Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
- Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
- Two_Sum(_i, _0, _k, x1); \
- Fast_Two_Sum(_j, _k, x3, x2)
-
-#define Four_One_Product(a3, a2, a1, a0, b, x7, x6, x5, x4, x3, x2, x1, x0) \
- Split(b, bhi, blo); \
- Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
- Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
- Two_Sum(_i, _0, _k, x1); \
- Fast_Two_Sum(_j, _k, _i, x2); \
- Two_Product_Presplit(a2, b, bhi, blo, _j, _0); \
- Two_Sum(_i, _0, _k, x3); \
- Fast_Two_Sum(_j, _k, _i, x4); \
- Two_Product_Presplit(a3, b, bhi, blo, _j, _0); \
- Two_Sum(_i, _0, _k, x5); \
- Fast_Two_Sum(_j, _k, x7, x6)
-
-#define Two_Two_Product(a1, a0, b1, b0, x7, x6, x5, x4, x3, x2, x1, x0) \
- Split(a0, a0hi, a0lo); \
- Split(b0, bhi, blo); \
- Two_Product_2Presplit(a0, a0hi, a0lo, b0, bhi, blo, _i, x0); \
- Split(a1, a1hi, a1lo); \
- Two_Product_2Presplit(a1, a1hi, a1lo, b0, bhi, blo, _j, _0); \
- Two_Sum(_i, _0, _k, _1); \
- Fast_Two_Sum(_j, _k, _l, _2); \
- Split(b1, bhi, blo); \
- Two_Product_2Presplit(a0, a0hi, a0lo, b1, bhi, blo, _i, _0); \
- Two_Sum(_1, _0, _k, x1); \
- Two_Sum(_2, _k, _j, _1); \
- Two_Sum(_l, _j, _m, _2); \
- Two_Product_2Presplit(a1, a1hi, a1lo, b1, bhi, blo, _j, _0); \
- Two_Sum(_i, _0, _n, _0); \
- Two_Sum(_1, _0, _i, x2); \
- Two_Sum(_2, _i, _k, _1); \
- Two_Sum(_m, _k, _l, _2); \
- Two_Sum(_j, _n, _k, _0); \
- Two_Sum(_1, _0, _j, x3); \
- Two_Sum(_2, _j, _i, _1); \
- Two_Sum(_l, _i, _m, _2); \
- Two_Sum(_1, _k, _i, x4); \
- Two_Sum(_2, _i, _k, x5); \
- Two_Sum(_m, _k, x7, x6)
-
-/* An expansion of length two can be squared more quickly than finding the */
-/* product of two different expansions of length two, and the result is */
-/* guaranteed to have no more than six (rather than eight) components. */
-
-#define Two_Square(a1, a0, x5, x4, x3, x2, x1, x0) \
- Square(a0, _j, x0); \
- _0 = a0 + a0; \
- Two_Product(a1, _0, _k, _1); \
- Two_One_Sum(_k, _1, _j, _l, _2, x1); \
- Square(a1, _j, _1); \
- Two_Two_Sum(_j, _1, _l, _2, x5, x4, x3, x2)
-
-REAL splitter; /* = 2^ceiling(p / 2) + 1. Used to split floats in half. */
-REAL epsilon; /* = 2^(-p). Used to estimate roundoff errors. */
-/* A set of coefficients used to calculate maximum roundoff errors. */
-REAL resulterrbound;
-REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
-REAL o3derrboundA, o3derrboundB, o3derrboundC;
-REAL iccerrboundA, iccerrboundB, iccerrboundC;
-REAL isperrboundA, isperrboundB, isperrboundC;
-
-/*****************************************************************************/
-/* */
-/* doubleprint() Print the bit representation of a double. */
-/* */
-/* Useful for debugging exact arithmetic routines. */
-/* */
-/*****************************************************************************/
-
-/*
-void doubleprint(number)
-double number;
-{
- unsigned long long no;
- unsigned long long sign, expo;
- int exponent;
- int i, bottomi;
-
- no = *(unsigned long long *) &number;
- sign = no & 0x8000000000000000ll;
- expo = (no >> 52) & 0x7ffll;
- exponent = (int) expo;
- exponent = exponent - 1023;
- if (sign) {
- printf("-");
- } else {
- printf(" ");
- }
- if (exponent == -1023) {
- printf(
- "0.0000000000000000000000000000000000000000000000000000_ ( )");
- } else {
- printf("1.");
- bottomi = -1;
- for (i = 0; i < 52; i++) {
- if (no & 0x0008000000000000ll) {
- printf("1");
- bottomi = i;
- } else {
- printf("0");
- }
- no <<= 1;
- }
- printf("_%d (%d)", exponent, exponent - 1 - bottomi);
- }
-}
-*/
-
-/*****************************************************************************/
-/* */
-/* floatprint() Print the bit representation of a float. */
-/* */
-/* Useful for debugging exact arithmetic routines. */
-/* */
-/*****************************************************************************/
-
-/*
-void floatprint(number)
-float number;
-{
- unsigned no;
- unsigned sign, expo;
- int exponent;
- int i, bottomi;
-
- no = *(unsigned *) &number;
- sign = no & 0x80000000;
- expo = (no >> 23) & 0xff;
- exponent = (int) expo;
- exponent = exponent - 127;
- if (sign) {
- printf("-");
- } else {
- printf(" ");
- }
- if (exponent == -127) {
- printf("0.00000000000000000000000_ ( )");
- } else {
- printf("1.");
- bottomi = -1;
- for (i = 0; i < 23; i++) {
- if (no & 0x00400000) {
- printf("1");
- bottomi = i;
- } else {
- printf("0");
- }
- no <<= 1;
- }
- printf("_%3d (%3d)", exponent, exponent - 1 - bottomi);
- }
-}
-*/
-
-/*****************************************************************************/
-/* */
-/* expansion_print() Print the bit representation of an expansion. */
-/* */
-/* Useful for debugging exact arithmetic routines. */
-/* */
-/*****************************************************************************/
-
-/*
-void expansion_print(elen, e)
-int elen;
-REAL *e;
-{
- int i;
-
- for (i = elen - 1; i >= 0; i--) {
- REALPRINT(e[i]);
- if (i > 0) {
- printf(" +\n");
- } else {
- printf("\n");
- }
- }
-}
-*/
-
-/*****************************************************************************/
-/* */
-/* doublerand() Generate a double with random 53-bit significand and a */
-/* random exponent in [0, 511]. */
-/* */
-/*****************************************************************************/
-
-double doublerand()
-{
- double result;
- double expo;
- long a, b, c;
- long i;
-
- a = rand();
- b = rand();
- c = rand();
- result = (double) (a - 1073741824) * 8388608.0 + (double) (b >> 8);
- for (i = 512, expo = 2; i <= 131072; i *= 2, expo = expo * expo) {
- if (c & i) {
- result *= expo;
- }
- }
- return result;
-}
-
-/*****************************************************************************/
-/* */
-/* narrowdoublerand() Generate a double with random 53-bit significand */
-/* and a random exponent in [0, 7]. */
-/* */
-/*****************************************************************************/
-
-double narrowdoublerand()
-{
- double result;
- double expo;
- long a, b, c;
- long i;
-
- a = rand();
- b = rand();
- c = rand();
- result = (double) (a - 1073741824) * 8388608.0 + (double) (b >> 8);
- for (i = 512, expo = 2; i <= 2048; i *= 2, expo = expo * expo) {
- if (c & i) {
- result *= expo;
- }
- }
- return result;
-}
-
-/*****************************************************************************/
-/* */
-/* uniformdoublerand() Generate a double with random 53-bit significand. */
-/* */
-/*****************************************************************************/
-
-double uniformdoublerand()
-{
- double result;
- long a, b;
-
- a = rand();
- b = rand();
- result = (double) (a - 1073741824) * 8388608.0 + (double) (b >> 8);
- return result;
-}
-
-/*****************************************************************************/
-/* */
-/* floatrand() Generate a float with random 24-bit significand and a */
-/* random exponent in [0, 63]. */
-/* */
-/*****************************************************************************/
-
-float floatrand()
-{
- float result;
- float expo;
- long a, c;
- long i;
-
- a = rand();
- c = rand();
- result = (float) ((a - 1073741824) >> 6);
- for (i = 512, expo = 2; i <= 16384; i *= 2, expo = expo * expo) {
- if (c & i) {
- result *= expo;
- }
- }
- return result;
-}
-
-/*****************************************************************************/
-/* */
-/* narrowfloatrand() Generate a float with random 24-bit significand and */
-/* a random exponent in [0, 7]. */
-/* */
-/*****************************************************************************/
-
-float narrowfloatrand()
-{
- float result;
- float expo;
- long a, c;
- long i;
-
- a = rand();
- c = rand();
- result = (float) ((a - 1073741824) >> 6);
- for (i = 512, expo = 2; i <= 2048; i *= 2, expo = expo * expo) {
- if (c & i) {
- result *= expo;
- }
- }
- return result;
-}
-
-/*****************************************************************************/
-/* */
-/* uniformfloatrand() Generate a float with random 24-bit significand. */
-/* */
-/*****************************************************************************/
-
-float uniformfloatrand()
-{
- float result;
- long a;
-
- a = rand();
- result = (float) ((a - 1073741824) >> 6);
- return result;
-}
-
-/*****************************************************************************/
-/* */
-/* exactinit() Initialize the variables used for exact arithmetic. */
-/* */
-/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */
-/* floating-point arithmetic. `epsilon' bounds the relative roundoff */
-/* error. It is used for floating-point error analysis. */
-/* */
-/* `splitter' is used to split floating-point numbers into two half- */
-/* length significands for exact multiplication. */
-/* */
-/* I imagine that a highly optimizing compiler might be too smart for its */
-/* own good, and somehow cause this routine to fail, if it pretends that */
-/* floating-point arithmetic is too much like real arithmetic. */
-/* */
-/* Don't change this routine unless you fully understand it. */
-/* */
-/*****************************************************************************/
-
-void exactinit()
-{
- REAL half;
- REAL check, lastcheck;
- int every_other;
-
- every_other = 1;
- half = 0.5;
- epsilon = 1.0;
- splitter = 1.0;
- check = 1.0;
- /* Repeatedly divide `epsilon' by two until it is too small to add to */
- /* one without causing roundoff. (Also check if the sum is equal to */
- /* the previous sum, for machines that round up instead of using exact */
- /* rounding. Not that this library will work on such machines anyway. */
- do {
- lastcheck = check;
- epsilon *= half;
- if (every_other) {
- splitter *= 2.0;
- }
- every_other = !every_other;
- check = 1.0 + epsilon;
- } while ((check != 1.0) && (check != lastcheck));
- splitter += 1.0;
-
- /* Error bounds for orientation and incircle tests. */
- resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
- ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
- ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
- ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
- o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
- o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
- o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
- iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
- iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
- iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
- isperrboundA = (16.0 + 224.0 * epsilon) * epsilon;
- isperrboundB = (5.0 + 72.0 * epsilon) * epsilon;
- isperrboundC = (71.0 + 1408.0 * epsilon) * epsilon * epsilon;
-}
-
-/*****************************************************************************/
-/* */
-/* grow_expansion() Add a scalar to an expansion. */
-/* */
-/* Sets h = e + b. See the long version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
-/* properties as well. (That is, if e has one of these properties, so */
-/* will h.) */
-/* */
-/*****************************************************************************/
-
-int grow_expansion(elen, e, b, h) /* e and h can be the same. */
- int elen;
- REAL *e;
- REAL b;
- REAL *h;
-{
- REAL Q;
- INEXACT REAL Qnew;
- int eindex;
- REAL enow;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
-
- Q = b;
- for (eindex = 0; eindex < elen; eindex++) {
- enow = e[eindex];
- Two_Sum(Q, enow, Qnew, h[eindex]);
- Q = Qnew;
- }
- h[eindex] = Q;
- return eindex + 1;
-}
-
-/*****************************************************************************/
-/* */
-/* grow_expansion_zeroelim() Add a scalar to an expansion, eliminating */
-/* zero components from the output expansion. */
-/* */
-/* Sets h = e + b. See the long version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
-/* properties as well. (That is, if e has one of these properties, so */
-/* will h.) */
-/* */
-/*****************************************************************************/
-
-int grow_expansion_zeroelim(elen, e, b, h) /* e and h can be the same. */
- int elen;
- REAL *e;
- REAL b;
- REAL *h;
-{
- REAL Q, hh;
- INEXACT REAL Qnew;
- int eindex, hindex;
- REAL enow;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
-
- hindex = 0;
- Q = b;
- for (eindex = 0; eindex < elen; eindex++) {
- enow = e[eindex];
- Two_Sum(Q, enow, Qnew, hh);
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- if ((Q != 0.0) || (hindex == 0)) {
- h[hindex++] = Q;
- }
- return hindex;
-}
-
-/*****************************************************************************/
-/* */
-/* expansion_sum() Sum two expansions. */
-/* */
-/* Sets h = e + f. See the long version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), maintains the nonadjacent property as well. (That is, */
-/* if e has one of these properties, so will h.) Does NOT maintain the */
-/* strongly nonoverlapping property. */
-/* */
-/*****************************************************************************/
-
-int expansion_sum(elen, e, flen, f, h)
-/* e and h can be the same, but f and h cannot. */
- int elen;
- REAL *e;
- int flen;
- REAL *f;
- REAL *h;
-{
- REAL Q;
- INEXACT REAL Qnew;
- int findex, hindex, hlast;
- REAL hnow;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
-
- Q = f[0];
- for (hindex = 0; hindex < elen; hindex++) {
- hnow = e[hindex];
- Two_Sum(Q, hnow, Qnew, h[hindex]);
- Q = Qnew;
- }
- h[hindex] = Q;
- hlast = hindex;
- for (findex = 1; findex < flen; findex++) {
- Q = f[findex];
- for (hindex = findex; hindex <= hlast; hindex++) {
- hnow = h[hindex];
- Two_Sum(Q, hnow, Qnew, h[hindex]);
- Q = Qnew;
- }
- h[++hlast] = Q;
- }
- return hlast + 1;
-}
-
-/*****************************************************************************/
-/* */
-/* expansion_sum_zeroelim1() Sum two expansions, eliminating zero */
-/* components from the output expansion. */
-/* */
-/* Sets h = e + f. See the long version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), maintains the nonadjacent property as well. (That is, */
-/* if e has one of these properties, so will h.) Does NOT maintain the */
-/* strongly nonoverlapping property. */
-/* */
-/*****************************************************************************/
-
-int expansion_sum_zeroelim1(elen, e, flen, f, h)
-/* e and h can be the same, but f and h cannot. */
- int elen;
- REAL *e;
- int flen;
- REAL *f;
- REAL *h;
-{
- REAL Q;
- INEXACT REAL Qnew;
- int index, findex, hindex, hlast;
- REAL hnow;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
-
- Q = f[0];
- for (hindex = 0; hindex < elen; hindex++) {
- hnow = e[hindex];
- Two_Sum(Q, hnow, Qnew, h[hindex]);
- Q = Qnew;
- }
- h[hindex] = Q;
- hlast = hindex;
- for (findex = 1; findex < flen; findex++) {
- Q = f[findex];
- for (hindex = findex; hindex <= hlast; hindex++) {
- hnow = h[hindex];
- Two_Sum(Q, hnow, Qnew, h[hindex]);
- Q = Qnew;
- }
- h[++hlast] = Q;
- }
- hindex = -1;
- for (index = 0; index <= hlast; index++) {
- hnow = h[index];
- if (hnow != 0.0) {
- h[++hindex] = hnow;
- }
- }
- if (hindex == -1) {
- return 1;
- } else {
- return hindex + 1;
- }
-}
-
-/*****************************************************************************/
-/* */
-/* expansion_sum_zeroelim2() Sum two expansions, eliminating zero */
-/* components from the output expansion. */
-/* */
-/* Sets h = e + f. See the long version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), maintains the nonadjacent property as well. (That is, */
-/* if e has one of these properties, so will h.) Does NOT maintain the */
-/* strongly nonoverlapping property. */
-/* */
-/*****************************************************************************/
-
-int expansion_sum_zeroelim2(elen, e, flen, f, h)
-/* e and h can be the same, but f and h cannot. */
- int elen;
- REAL *e;
- int flen;
- REAL *f;
- REAL *h;
-{
- REAL Q, hh;
- INEXACT REAL Qnew;
- int eindex, findex, hindex, hlast;
- REAL enow;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
-
- hindex = 0;
- Q = f[0];
- for (eindex = 0; eindex < elen; eindex++) {
- enow = e[eindex];
- Two_Sum(Q, enow, Qnew, hh);
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- h[hindex] = Q;
- hlast = hindex;
- for (findex = 1; findex < flen; findex++) {
- hindex = 0;
- Q = f[findex];
- for (eindex = 0; eindex <= hlast; eindex++) {
- enow = h[eindex];
- Two_Sum(Q, enow, Qnew, hh);
- Q = Qnew;
- if (hh != 0) {
- h[hindex++] = hh;
- }
- }
- h[hindex] = Q;
- hlast = hindex;
- }
- return hlast + 1;
-}
-
-/*****************************************************************************/
-/* */
-/* fast_expansion_sum() Sum two expansions. */
-/* */
-/* Sets h = e + f. See the long version of my paper for details. */
-/* */
-/* If round-to-even is used (as with IEEE 754), maintains the strongly */
-/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
-/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
-/* properties. */
-/* */
-/*****************************************************************************/
-
-int fast_expansion_sum(elen, e, flen, f, h) /* h cannot be e or f. */
- int elen;
- REAL *e;
- int flen;
- REAL *f;
- REAL *h;
-{
- REAL Q;
- INEXACT REAL Qnew;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- int eindex, findex, hindex;
- REAL enow, fnow;
-
- enow = e[0];
- fnow = f[0];
- eindex = findex = 0;
- if ((fnow > enow) == (fnow > -enow)) {
- Q = enow;
- enow = e[++eindex];
- } else {
- Q = fnow;
- fnow = f[++findex];
- }
- hindex = 0;
- if ((eindex < elen) && (findex < flen)) {
- if ((fnow > enow) == (fnow > -enow)) {
- Fast_Two_Sum(enow, Q, Qnew, h[0]);
- enow = e[++eindex];
- } else {
- Fast_Two_Sum(fnow, Q, Qnew, h[0]);
- fnow = f[++findex];
- }
- Q = Qnew;
- hindex = 1;
- while ((eindex < elen) && (findex < flen)) {
- if ((fnow > enow) == (fnow > -enow)) {
- Two_Sum(Q, enow, Qnew, h[hindex]);
- enow = e[++eindex];
- } else {
- Two_Sum(Q, fnow, Qnew, h[hindex]);
- fnow = f[++findex];
- }
- Q = Qnew;
- hindex++;
- }
- }
- while (eindex < elen) {
- Two_Sum(Q, enow, Qnew, h[hindex]);
- enow = e[++eindex];
- Q = Qnew;
- hindex++;
- }
- while (findex < flen) {
- Two_Sum(Q, fnow, Qnew, h[hindex]);
- fnow = f[++findex];
- Q = Qnew;
- hindex++;
- }
- h[hindex] = Q;
- return hindex + 1;
-}
-
-/*****************************************************************************/
-/* */
-/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
-/* components from the output expansion. */
-/* */
-/* Sets h = e + f. See the long version of my paper for details. */
-/* */
-/* If round-to-even is used (as with IEEE 754), maintains the strongly */
-/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
-/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
-/* properties. */
-/* */
-/*****************************************************************************/
-
-int fast_expansion_sum_zeroelim(elen, e, flen, f, h) /* h cannot be e or f. */
- int elen;
- REAL *e;
- int flen;
- REAL *f;
- REAL *h;
-{
- REAL Q;
- INEXACT REAL Qnew;
- INEXACT REAL hh;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- int eindex, findex, hindex;
- REAL enow, fnow;
-
- enow = e[0];
- fnow = f[0];
- eindex = findex = 0;
- if ((fnow > enow) == (fnow > -enow)) {
- Q = enow;
- enow = e[++eindex];
- } else {
- Q = fnow;
- fnow = f[++findex];
- }
- hindex = 0;
- if ((eindex < elen) && (findex < flen)) {
- if ((fnow > enow) == (fnow > -enow)) {
- Fast_Two_Sum(enow, Q, Qnew, hh);
- enow = e[++eindex];
- } else {
- Fast_Two_Sum(fnow, Q, Qnew, hh);
- fnow = f[++findex];
- }
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- while ((eindex < elen) && (findex < flen)) {
- if ((fnow > enow) == (fnow > -enow)) {
- Two_Sum(Q, enow, Qnew, hh);
- enow = e[++eindex];
- } else {
- Two_Sum(Q, fnow, Qnew, hh);
- fnow = f[++findex];
- }
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- }
- while (eindex < elen) {
- Two_Sum(Q, enow, Qnew, hh);
- enow = e[++eindex];
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- while (findex < flen) {
- Two_Sum(Q, fnow, Qnew, hh);
- fnow = f[++findex];
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- if ((Q != 0.0) || (hindex == 0)) {
- h[hindex++] = Q;
- }
- return hindex;
-}
-
-/*****************************************************************************/
-/* */
-/* linear_expansion_sum() Sum two expansions. */
-/* */
-/* Sets h = e + f. See either version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. (That is, if e is */
-/* nonoverlapping, h will be also.) */
-/* */
-/*****************************************************************************/
-
-int linear_expansion_sum(elen, e, flen, f, h) /* h cannot be e or f. */
- int elen;
- REAL *e;
- int flen;
- REAL *f;
- REAL *h;
-{
- REAL Q, q;
- INEXACT REAL Qnew;
- INEXACT REAL R;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- int eindex, findex, hindex;
- REAL enow, fnow;
- REAL g0;
-
- enow = e[0];
- fnow = f[0];
- eindex = findex = 0;
- if ((fnow > enow) == (fnow > -enow)) {
- g0 = enow;
- enow = e[++eindex];
- } else {
- g0 = fnow;
- fnow = f[++findex];
- }
- if ((eindex < elen) && ((findex >= flen)
- || ((fnow > enow) == (fnow > -enow)))) {
- Fast_Two_Sum(enow, g0, Qnew, q);
- enow = e[++eindex];
- } else {
- Fast_Two_Sum(fnow, g0, Qnew, q);
- fnow = f[++findex];
- }
- Q = Qnew;
- for (hindex = 0; hindex < elen + flen - 2; hindex++) {
- if ((eindex < elen) && ((findex >= flen)
- || ((fnow > enow) == (fnow > -enow)))) {
- Fast_Two_Sum(enow, q, R, h[hindex]);
- enow = e[++eindex];
- } else {
- Fast_Two_Sum(fnow, q, R, h[hindex]);
- fnow = f[++findex];
- }
- Two_Sum(Q, R, Qnew, q);
- Q = Qnew;
- }
- h[hindex] = q;
- h[hindex + 1] = Q;
- return hindex + 2;
-}
-
-/*****************************************************************************/
-/* */
-/* linear_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
-/* components from the output expansion. */
-/* */
-/* Sets h = e + f. See either version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. (That is, if e is */
-/* nonoverlapping, h will be also.) */
-/* */
-/*****************************************************************************/
-
-int linear_expansion_sum_zeroelim(elen, e, flen, f, h)/* h cannot be e or f. */
- int elen;
- REAL *e;
- int flen;
- REAL *f;
- REAL *h;
-{
- REAL Q, q, hh;
- INEXACT REAL Qnew;
- INEXACT REAL R;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- int eindex, findex, hindex;
- int count;
- REAL enow, fnow;
- REAL g0;
-
- enow = e[0];
- fnow = f[0];
- eindex = findex = 0;
- hindex = 0;
- if ((fnow > enow) == (fnow > -enow)) {
- g0 = enow;
- enow = e[++eindex];
- } else {
- g0 = fnow;
- fnow = f[++findex];
- }
- if ((eindex < elen) && ((findex >= flen)
- || ((fnow > enow) == (fnow > -enow)))) {
- Fast_Two_Sum(enow, g0, Qnew, q);
- enow = e[++eindex];
- } else {
- Fast_Two_Sum(fnow, g0, Qnew, q);
- fnow = f[++findex];
- }
- Q = Qnew;
- for (count = 2; count < elen + flen; count++) {
- if ((eindex < elen) && ((findex >= flen)
- || ((fnow > enow) == (fnow > -enow)))) {
- Fast_Two_Sum(enow, q, R, hh);
- enow = e[++eindex];
- } else {
- Fast_Two_Sum(fnow, q, R, hh);
- fnow = f[++findex];
- }
- Two_Sum(Q, R, Qnew, q);
- Q = Qnew;
- if (hh != 0) {
- h[hindex++] = hh;
- }
- }
- if (q != 0) {
- h[hindex++] = q;
- }
- if ((Q != 0.0) || (hindex == 0)) {
- h[hindex++] = Q;
- }
- return hindex;
-}
-
-/*****************************************************************************/
-/* */
-/* scale_expansion() Multiply an expansion by a scalar. */
-/* */
-/* Sets h = be. See either version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
-/* properties as well. (That is, if e has one of these properties, so */
-/* will h.) */
-/* */
-/*****************************************************************************/
-
-int scale_expansion(elen, e, b, h) /* e and h cannot be the same. */
- int elen;
- REAL *e;
- REAL b;
- REAL *h;
-{
- INEXACT REAL Q;
- INEXACT REAL sum;
- INEXACT REAL product1;
- REAL product0;
- int eindex, hindex;
- REAL enow;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
-
- Split(b, bhi, blo);
- Two_Product_Presplit(e[0], b, bhi, blo, Q, h[0]);
- hindex = 1;
- for (eindex = 1; eindex < elen; eindex++) {
- enow = e[eindex];
- Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
- Two_Sum(Q, product0, sum, h[hindex]);
- hindex++;
- Two_Sum(product1, sum, Q, h[hindex]);
- hindex++;
- }
- h[hindex] = Q;
- return elen + elen;
-}
-
-/*****************************************************************************/
-/* */
-/* scale_expansion_zeroelim() Multiply an expansion by a scalar, */
-/* eliminating zero components from the */
-/* output expansion. */
-/* */
-/* Sets h = be. See either version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
-/* properties as well. (That is, if e has one of these properties, so */
-/* will h.) */
-/* */
-/*****************************************************************************/
-
-int scale_expansion_zeroelim(elen, e, b, h) /* e and h cannot be the same. */
- int elen;
- REAL *e;
- REAL b;
- REAL *h;
-{
- INEXACT REAL Q, sum;
- REAL hh;
- INEXACT REAL product1;
- REAL product0;
- int eindex, hindex;
- REAL enow;
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
-
- Split(b, bhi, blo);
- Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
- hindex = 0;
- if (hh != 0) {
- h[hindex++] = hh;
- }
- for (eindex = 1; eindex < elen; eindex++) {
- enow = e[eindex];
- Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
- Two_Sum(Q, product0, sum, hh);
- if (hh != 0) {
- h[hindex++] = hh;
- }
- Fast_Two_Sum(product1, sum, Q, hh);
- if (hh != 0) {
- h[hindex++] = hh;
- }
- }
- if ((Q != 0.0) || (hindex == 0)) {
- h[hindex++] = Q;
- }
- return hindex;
-}
-
-/*****************************************************************************/
-/* */
-/* compress() Compress an expansion. */
-/* */
-/* See the long version of my paper for details. */
-/* */
-/* Maintains the nonoverlapping property. If round-to-even is used (as */
-/* with IEEE 754), then any nonoverlapping expansion is converted to a */
-/* nonadjacent expansion. */
-/* */
-/*****************************************************************************/
-
-int compress(elen, e, h) /* e and h may be the same. */
- int elen;
- REAL *e;
- REAL *h;
-{
- REAL Q, q;
- INEXACT REAL Qnew;
- int eindex, hindex;
- INEXACT REAL bvirt;
- REAL enow, hnow;
- int top, bottom;
-
- bottom = elen - 1;
- Q = e[bottom];
- for (eindex = elen - 2; eindex >= 0; eindex--) {
- enow = e[eindex];
- Fast_Two_Sum(Q, enow, Qnew, q);
- if (q != 0) {
- h[bottom--] = Qnew;
- Q = q;
- } else {
- Q = Qnew;
- }
- }
- top = 0;
- for (hindex = bottom + 1; hindex < elen; hindex++) {
- hnow = h[hindex];
- Fast_Two_Sum(hnow, Q, Qnew, q);
- if (q != 0) {
- h[top++] = q;
- }
- Q = Qnew;
- }
- h[top] = Q;
- return top + 1;
-}
-
-/*****************************************************************************/
-/* */
-/* estimate() Produce a one-word estimate of an expansion's value. */
-/* */
-/* See either version of my paper for details. */
-/* */
-/*****************************************************************************/
-
-REAL estimate(elen, e)
- int elen;
- REAL *e;
-{
- REAL Q;
- int eindex;
-
- Q = e[0];
- for (eindex = 1; eindex < elen; eindex++) {
- Q += e[eindex];
- }
- return Q;
-}
-
-/*****************************************************************************/
-/* */
-/* orient2dfast() Approximate 2D orientation test. Nonrobust. */
-/* orient2dexact() Exact 2D orientation test. Robust. */
-/* orient2dslow() Another exact 2D orientation test. Robust. */
-/* orient2d() Adaptive exact 2D orientation test. Robust. */
-/* */
-/* Return a positive value if the points pa, pb, and pc occur */
-/* in counterclockwise order; a negative value if they occur */
-/* in clockwise order; and zero if they are collinear. The */
-/* result is also a rough approximation of twice the signed */
-/* area of the triangle defined by the three points. */
-/* */
-/* Only the first and last routine should be used; the middle two are for */
-/* timings. */
-/* */
-/* The last three use exact arithmetic to ensure a correct answer. The */
-/* result returned is the determinant of a matrix. In orient2d() only, */
-/* this determinant is computed adaptively, in the sense that exact */
-/* arithmetic is used only to the degree it is needed to ensure that the */
-/* returned value has the correct sign. Hence, orient2d() is usually quite */
-/* fast, but will run more slowly when the input points are collinear or */
-/* nearly so. */
-/* */
-/*****************************************************************************/
-
-REAL orient2dfast(pa, pb, pc)
- REAL *pa;
- REAL *pb;
- REAL *pc;
-{
- REAL acx, bcx, acy, bcy;
-
- acx = pa[0] - pc[0];
- bcx = pb[0] - pc[0];
- acy = pa[1] - pc[1];
- bcy = pb[1] - pc[1];
- return acx * bcy - acy * bcx;
-}
-
-REAL orient2dexact(pa, pb, pc)
- REAL *pa;
- REAL *pb;
- REAL *pc;
-{
- INEXACT REAL axby1, axcy1, bxcy1, bxay1, cxay1, cxby1;
- REAL axby0, axcy0, bxcy0, bxay0, cxay0, cxby0;
- REAL aterms[4], bterms[4], cterms[4];
- INEXACT REAL aterms3, bterms3, cterms3;
- REAL v[8], w[12];
- int vlength, wlength;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j;
- REAL _0;
-
- Two_Product(pa[0], pb[1], axby1, axby0);
- Two_Product(pa[0], pc[1], axcy1, axcy0);
- Two_Two_Diff(axby1, axby0, axcy1, axcy0,
- aterms3, aterms[2], aterms[1], aterms[0]);
- aterms[3] = aterms3;
-
- Two_Product(pb[0], pc[1], bxcy1, bxcy0);
- Two_Product(pb[0], pa[1], bxay1, bxay0);
- Two_Two_Diff(bxcy1, bxcy0, bxay1, bxay0,
- bterms3, bterms[2], bterms[1], bterms[0]);
- bterms[3] = bterms3;
-
- Two_Product(pc[0], pa[1], cxay1, cxay0);
- Two_Product(pc[0], pb[1], cxby1, cxby0);
- Two_Two_Diff(cxay1, cxay0, cxby1, cxby0,
- cterms3, cterms[2], cterms[1], cterms[0]);
- cterms[3] = cterms3;
-
- vlength = fast_expansion_sum_zeroelim(4, aterms, 4, bterms, v);
- wlength = fast_expansion_sum_zeroelim(vlength, v, 4, cterms, w);
-
- return w[wlength - 1];
-}
-
-REAL orient2dslow(pa, pb, pc)
- REAL *pa;
- REAL *pb;
- REAL *pc;
-{
- INEXACT REAL acx, acy, bcx, bcy;
- REAL acxtail, acytail;
- REAL bcxtail, bcytail;
- REAL negate, negatetail;
- REAL axby[8], bxay[8];
- INEXACT REAL axby7, bxay7;
- REAL deter[16];
- int deterlen;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL a0hi, a0lo, a1hi, a1lo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j, _k, _l, _m, _n;
- REAL _0, _1, _2;
-
- Two_Diff(pa[0], pc[0], acx, acxtail);
- Two_Diff(pa[1], pc[1], acy, acytail);
- Two_Diff(pb[0], pc[0], bcx, bcxtail);
- Two_Diff(pb[1], pc[1], bcy, bcytail);
-
- Two_Two_Product(acx, acxtail, bcy, bcytail,
- axby7, axby[6], axby[5], axby[4],
- axby[3], axby[2], axby[1], axby[0]);
- axby[7] = axby7;
- negate = -acy;
- negatetail = -acytail;
- Two_Two_Product(bcx, bcxtail, negate, negatetail,
- bxay7, bxay[6], bxay[5], bxay[4],
- bxay[3], bxay[2], bxay[1], bxay[0]);
- bxay[7] = bxay7;
-
- deterlen = fast_expansion_sum_zeroelim(8, axby, 8, bxay, deter);
-
- return deter[deterlen - 1];
-}
-
-REAL orient2dadapt(pa, pb, pc, detsum)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL detsum;
-{
- INEXACT REAL acx, acy, bcx, bcy;
- REAL acxtail, acytail, bcxtail, bcytail;
- INEXACT REAL detleft, detright;
- REAL detlefttail, detrighttail;
- REAL det, errbound;
- REAL B[4], C1[8], C2[12], D[16];
- INEXACT REAL B3;
- int C1length, C2length, Dlength;
- REAL u[4];
- INEXACT REAL u3;
- INEXACT REAL s1, t1;
- REAL s0, t0;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j;
- REAL _0;
-
- acx = (REAL) (pa[0] - pc[0]);
- bcx = (REAL) (pb[0] - pc[0]);
- acy = (REAL) (pa[1] - pc[1]);
- bcy = (REAL) (pb[1] - pc[1]);
-
- Two_Product(acx, bcy, detleft, detlefttail);
- Two_Product(acy, bcx, detright, detrighttail);
-
- Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
- B3, B[2], B[1], B[0]);
- B[3] = B3;
-
- det = estimate(4, B);
- errbound = ccwerrboundB * detsum;
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
- Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
- Two_Diff_Tail(pa[1], pc[1], acy, acytail);
- Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
-
- if ((acxtail == 0.0) && (acytail == 0.0)
- && (bcxtail == 0.0) && (bcytail == 0.0)) {
- return det;
- }
-
- errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
- det += (acx * bcytail + bcy * acxtail)
- - (acy * bcxtail + bcx * acytail);
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- Two_Product(acxtail, bcy, s1, s0);
- Two_Product(acytail, bcx, t1, t0);
- Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
-
- Two_Product(acx, bcytail, s1, s0);
- Two_Product(acy, bcxtail, t1, t0);
- Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
-
- Two_Product(acxtail, bcytail, s1, s0);
- Two_Product(acytail, bcxtail, t1, t0);
- Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
-
- return(D[Dlength - 1]);
-}
-
-REAL orient2d(pa, pb, pc)
- REAL *pa;
- REAL *pb;
- REAL *pc;
-{
- REAL detleft, detright, det;
- REAL detsum, errbound;
-
- detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
- detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
- det = detleft - detright;
-
- if (detleft > 0.0) {
- if (detright <= 0.0) {
- return det;
- } else {
- detsum = detleft + detright;
- }
- } else if (detleft < 0.0) {
- if (detright >= 0.0) {
- return det;
- } else {
- detsum = -detleft - detright;
- }
- } else {
- return det;
- }
-
- errbound = ccwerrboundA * detsum;
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- return orient2dadapt(pa, pb, pc, detsum);
-}
-
-/*****************************************************************************/
-/* */
-/* orient3dfast() Approximate 3D orientation test. Nonrobust. */
-/* orient3dexact() Exact 3D orientation test. Robust. */
-/* orient3dslow() Another exact 3D orientation test. Robust. */
-/* orient3d() Adaptive exact 3D orientation test. Robust. */
-/* */
-/* Return a positive value if the point pd lies below the */
-/* plane passing through pa, pb, and pc; "below" is defined so */
-/* that pa, pb, and pc appear in counterclockwise order when */
-/* viewed from above the plane. Returns a negative value if */
-/* pd lies above the plane. Returns zero if the points are */
-/* coplanar. The result is also a rough approximation of six */
-/* times the signed volume of the tetrahedron defined by the */
-/* four points. */
-/* */
-/* Only the first and last routine should be used; the middle two are for */
-/* timings. */
-/* */
-/* The last three use exact arithmetic to ensure a correct answer. The */
-/* result returned is the determinant of a matrix. In orient3d() only, */
-/* this determinant is computed adaptively, in the sense that exact */
-/* arithmetic is used only to the degree it is needed to ensure that the */
-/* returned value has the correct sign. Hence, orient3d() is usually quite */
-/* fast, but will run more slowly when the input points are coplanar or */
-/* nearly so. */
-/* */
-/*****************************************************************************/
-
-REAL orient3dfast(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- REAL adx, bdx, cdx;
- REAL ady, bdy, cdy;
- REAL adz, bdz, cdz;
-
- adx = pa[0] - pd[0];
- bdx = pb[0] - pd[0];
- cdx = pc[0] - pd[0];
- ady = pa[1] - pd[1];
- bdy = pb[1] - pd[1];
- cdy = pc[1] - pd[1];
- adz = pa[2] - pd[2];
- bdz = pb[2] - pd[2];
- cdz = pc[2] - pd[2];
-
- return adx * (bdy * cdz - bdz * cdy)
- + bdx * (cdy * adz - cdz * ady)
- + cdx * (ady * bdz - adz * bdy);
-}
-
-REAL orient3dexact(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- INEXACT REAL axby1, bxcy1, cxdy1, dxay1, axcy1, bxdy1;
- INEXACT REAL bxay1, cxby1, dxcy1, axdy1, cxay1, dxby1;
- REAL axby0, bxcy0, cxdy0, dxay0, axcy0, bxdy0;
- REAL bxay0, cxby0, dxcy0, axdy0, cxay0, dxby0;
- REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4];
- REAL temp8[8];
- int templen;
- REAL abc[12], bcd[12], cda[12], dab[12];
- int abclen, bcdlen, cdalen, dablen;
- REAL adet[24], bdet[24], cdet[24], ddet[24];
- int alen, blen, clen, dlen;
- REAL abdet[48], cddet[48];
- int ablen, cdlen;
- REAL deter[96];
- int deterlen;
- int i;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j;
- REAL _0;
-
- Two_Product(pa[0], pb[1], axby1, axby0);
- Two_Product(pb[0], pa[1], bxay1, bxay0);
- Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]);
-
- Two_Product(pb[0], pc[1], bxcy1, bxcy0);
- Two_Product(pc[0], pb[1], cxby1, cxby0);
- Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]);
-
- Two_Product(pc[0], pd[1], cxdy1, cxdy0);
- Two_Product(pd[0], pc[1], dxcy1, dxcy0);
- Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]);
-
- Two_Product(pd[0], pa[1], dxay1, dxay0);
- Two_Product(pa[0], pd[1], axdy1, axdy0);
- Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]);
-
- Two_Product(pa[0], pc[1], axcy1, axcy0);
- Two_Product(pc[0], pa[1], cxay1, cxay0);
- Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]);
-
- Two_Product(pb[0], pd[1], bxdy1, bxdy0);
- Two_Product(pd[0], pb[1], dxby1, dxby0);
- Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]);
-
- templen = fast_expansion_sum_zeroelim(4, cd, 4, da, temp8);
- cdalen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, cda);
- templen = fast_expansion_sum_zeroelim(4, da, 4, ab, temp8);
- dablen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, dab);
- for (i = 0; i < 4; i++) {
- bd[i] = -bd[i];
- ac[i] = -ac[i];
- }
- templen = fast_expansion_sum_zeroelim(4, ab, 4, bc, temp8);
- abclen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, abc);
- templen = fast_expansion_sum_zeroelim(4, bc, 4, cd, temp8);
- bcdlen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, bcd);
-
- alen = scale_expansion_zeroelim(bcdlen, bcd, pa[2], adet);
- blen = scale_expansion_zeroelim(cdalen, cda, -pb[2], bdet);
- clen = scale_expansion_zeroelim(dablen, dab, pc[2], cdet);
- dlen = scale_expansion_zeroelim(abclen, abc, -pd[2], ddet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
- deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, deter);
-
- return deter[deterlen - 1];
-}
-
-REAL orient3dslow(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- INEXACT REAL adx, ady, adz, bdx, bdy, bdz, cdx, cdy, cdz;
- REAL adxtail, adytail, adztail;
- REAL bdxtail, bdytail, bdztail;
- REAL cdxtail, cdytail, cdztail;
- REAL negate, negatetail;
- INEXACT REAL axby7, bxcy7, axcy7, bxay7, cxby7, cxay7;
- REAL axby[8], bxcy[8], axcy[8], bxay[8], cxby[8], cxay[8];
- REAL temp16[16], temp32[32], temp32t[32];
- int temp16len, temp32len, temp32tlen;
- REAL adet[64], bdet[64], cdet[64];
- int alen, blen, clen;
- REAL abdet[128];
- int ablen;
- REAL deter[192];
- int deterlen;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL a0hi, a0lo, a1hi, a1lo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j, _k, _l, _m, _n;
- REAL _0, _1, _2;
-
- Two_Diff(pa[0], pd[0], adx, adxtail);
- Two_Diff(pa[1], pd[1], ady, adytail);
- Two_Diff(pa[2], pd[2], adz, adztail);
- Two_Diff(pb[0], pd[0], bdx, bdxtail);
- Two_Diff(pb[1], pd[1], bdy, bdytail);
- Two_Diff(pb[2], pd[2], bdz, bdztail);
- Two_Diff(pc[0], pd[0], cdx, cdxtail);
- Two_Diff(pc[1], pd[1], cdy, cdytail);
- Two_Diff(pc[2], pd[2], cdz, cdztail);
-
- Two_Two_Product(adx, adxtail, bdy, bdytail,
- axby7, axby[6], axby[5], axby[4],
- axby[3], axby[2], axby[1], axby[0]);
- axby[7] = axby7;
- negate = -ady;
- negatetail = -adytail;
- Two_Two_Product(bdx, bdxtail, negate, negatetail,
- bxay7, bxay[6], bxay[5], bxay[4],
- bxay[3], bxay[2], bxay[1], bxay[0]);
- bxay[7] = bxay7;
- Two_Two_Product(bdx, bdxtail, cdy, cdytail,
- bxcy7, bxcy[6], bxcy[5], bxcy[4],
- bxcy[3], bxcy[2], bxcy[1], bxcy[0]);
- bxcy[7] = bxcy7;
- negate = -bdy;
- negatetail = -bdytail;
- Two_Two_Product(cdx, cdxtail, negate, negatetail,
- cxby7, cxby[6], cxby[5], cxby[4],
- cxby[3], cxby[2], cxby[1], cxby[0]);
- cxby[7] = cxby7;
- Two_Two_Product(cdx, cdxtail, ady, adytail,
- cxay7, cxay[6], cxay[5], cxay[4],
- cxay[3], cxay[2], cxay[1], cxay[0]);
- cxay[7] = cxay7;
- negate = -cdy;
- negatetail = -cdytail;
- Two_Two_Product(adx, adxtail, negate, negatetail,
- axcy7, axcy[6], axcy[5], axcy[4],
- axcy[3], axcy[2], axcy[1], axcy[0]);
- axcy[7] = axcy7;
-
- temp16len = fast_expansion_sum_zeroelim(8, bxcy, 8, cxby, temp16);
- temp32len = scale_expansion_zeroelim(temp16len, temp16, adz, temp32);
- temp32tlen = scale_expansion_zeroelim(temp16len, temp16, adztail, temp32t);
- alen = fast_expansion_sum_zeroelim(temp32len, temp32, temp32tlen, temp32t,
- adet);
-
- temp16len = fast_expansion_sum_zeroelim(8, cxay, 8, axcy, temp16);
- temp32len = scale_expansion_zeroelim(temp16len, temp16, bdz, temp32);
- temp32tlen = scale_expansion_zeroelim(temp16len, temp16, bdztail, temp32t);
- blen = fast_expansion_sum_zeroelim(temp32len, temp32, temp32tlen, temp32t,
- bdet);
-
- temp16len = fast_expansion_sum_zeroelim(8, axby, 8, bxay, temp16);
- temp32len = scale_expansion_zeroelim(temp16len, temp16, cdz, temp32);
- temp32tlen = scale_expansion_zeroelim(temp16len, temp16, cdztail, temp32t);
- clen = fast_expansion_sum_zeroelim(temp32len, temp32, temp32tlen, temp32t,
- cdet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- deterlen = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, deter);
-
- return deter[deterlen - 1];
-}
-
-REAL orient3dadapt(pa, pb, pc, pd, permanent)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
- REAL permanent;
-{
- INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
- REAL det, errbound;
-
- INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
- REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
- REAL bc[4], ca[4], ab[4];
- INEXACT REAL bc3, ca3, ab3;
- REAL adet[8], bdet[8], cdet[8];
- int alen, blen, clen;
- REAL abdet[16];
- int ablen;
- REAL *finnow, *finother, *finswap;
- REAL fin1[192], fin2[192];
- int finlength;
-
- REAL adxtail, bdxtail, cdxtail;
- REAL adytail, bdytail, cdytail;
- REAL adztail, bdztail, cdztail;
- INEXACT REAL at_blarge, at_clarge;
- INEXACT REAL bt_clarge, bt_alarge;
- INEXACT REAL ct_alarge, ct_blarge;
- REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
- int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
- INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
- INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
- REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
- REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
- INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
- INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
- REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
- REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
- REAL bct[8], cat[8], abt[8];
- int bctlen, catlen, abtlen;
- INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
- INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
- REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
- REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
- REAL u[4], v[12], w[16];
- INEXACT REAL u3;
- int vlength, wlength;
- REAL negate;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j, _k;
- REAL _0;
-
- adx = (REAL) (pa[0] - pd[0]);
- bdx = (REAL) (pb[0] - pd[0]);
- cdx = (REAL) (pc[0] - pd[0]);
- ady = (REAL) (pa[1] - pd[1]);
- bdy = (REAL) (pb[1] - pd[1]);
- cdy = (REAL) (pc[1] - pd[1]);
- adz = (REAL) (pa[2] - pd[2]);
- bdz = (REAL) (pb[2] - pd[2]);
- cdz = (REAL) (pc[2] - pd[2]);
-
- Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
- Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
- Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
- bc[3] = bc3;
- alen = scale_expansion_zeroelim(4, bc, adz, adet);
-
- Two_Product(cdx, ady, cdxady1, cdxady0);
- Two_Product(adx, cdy, adxcdy1, adxcdy0);
- Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
- ca[3] = ca3;
- blen = scale_expansion_zeroelim(4, ca, bdz, bdet);
-
- Two_Product(adx, bdy, adxbdy1, adxbdy0);
- Two_Product(bdx, ady, bdxady1, bdxady0);
- Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
- ab[3] = ab3;
- clen = scale_expansion_zeroelim(4, ab, cdz, cdet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
-
- det = estimate(finlength, fin1);
- errbound = o3derrboundB * permanent;
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
- Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
- Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
- Two_Diff_Tail(pa[1], pd[1], ady, adytail);
- Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
- Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
- Two_Diff_Tail(pa[2], pd[2], adz, adztail);
- Two_Diff_Tail(pb[2], pd[2], bdz, bdztail);
- Two_Diff_Tail(pc[2], pd[2], cdz, cdztail);
-
- if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
- && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)
- && (adztail == 0.0) && (bdztail == 0.0) && (cdztail == 0.0)) {
- return det;
- }
-
- errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
- det += (adz * ((bdx * cdytail + cdy * bdxtail)
- - (bdy * cdxtail + cdx * bdytail))
- + adztail * (bdx * cdy - bdy * cdx))
- + (bdz * ((cdx * adytail + ady * cdxtail)
- - (cdy * adxtail + adx * cdytail))
- + bdztail * (cdx * ady - cdy * adx))
- + (cdz * ((adx * bdytail + bdy * adxtail)
- - (ady * bdxtail + bdx * adytail))
- + cdztail * (adx * bdy - ady * bdx));
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- finnow = fin1;
- finother = fin2;
-
- if (adxtail == 0.0) {
- if (adytail == 0.0) {
- at_b[0] = 0.0;
- at_blen = 1;
- at_c[0] = 0.0;
- at_clen = 1;
- } else {
- negate = -adytail;
- Two_Product(negate, bdx, at_blarge, at_b[0]);
- at_b[1] = at_blarge;
- at_blen = 2;
- Two_Product(adytail, cdx, at_clarge, at_c[0]);
- at_c[1] = at_clarge;
- at_clen = 2;
- }
- } else {
- if (adytail == 0.0) {
- Two_Product(adxtail, bdy, at_blarge, at_b[0]);
- at_b[1] = at_blarge;
- at_blen = 2;
- negate = -adxtail;
- Two_Product(negate, cdy, at_clarge, at_c[0]);
- at_c[1] = at_clarge;
- at_clen = 2;
- } else {
- Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
- Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
- Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
- at_blarge, at_b[2], at_b[1], at_b[0]);
- at_b[3] = at_blarge;
- at_blen = 4;
- Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
- Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
- Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
- at_clarge, at_c[2], at_c[1], at_c[0]);
- at_c[3] = at_clarge;
- at_clen = 4;
- }
- }
- if (bdxtail == 0.0) {
- if (bdytail == 0.0) {
- bt_c[0] = 0.0;
- bt_clen = 1;
- bt_a[0] = 0.0;
- bt_alen = 1;
- } else {
- negate = -bdytail;
- Two_Product(negate, cdx, bt_clarge, bt_c[0]);
- bt_c[1] = bt_clarge;
- bt_clen = 2;
- Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
- bt_a[1] = bt_alarge;
- bt_alen = 2;
- }
- } else {
- if (bdytail == 0.0) {
- Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
- bt_c[1] = bt_clarge;
- bt_clen = 2;
- negate = -bdxtail;
- Two_Product(negate, ady, bt_alarge, bt_a[0]);
- bt_a[1] = bt_alarge;
- bt_alen = 2;
- } else {
- Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
- Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
- Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
- bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
- bt_c[3] = bt_clarge;
- bt_clen = 4;
- Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
- Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
- Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
- bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
- bt_a[3] = bt_alarge;
- bt_alen = 4;
- }
- }
- if (cdxtail == 0.0) {
- if (cdytail == 0.0) {
- ct_a[0] = 0.0;
- ct_alen = 1;
- ct_b[0] = 0.0;
- ct_blen = 1;
- } else {
- negate = -cdytail;
- Two_Product(negate, adx, ct_alarge, ct_a[0]);
- ct_a[1] = ct_alarge;
- ct_alen = 2;
- Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
- ct_b[1] = ct_blarge;
- ct_blen = 2;
- }
- } else {
- if (cdytail == 0.0) {
- Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
- ct_a[1] = ct_alarge;
- ct_alen = 2;
- negate = -cdxtail;
- Two_Product(negate, bdy, ct_blarge, ct_b[0]);
- ct_b[1] = ct_blarge;
- ct_blen = 2;
- } else {
- Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
- Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
- Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
- ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
- ct_a[3] = ct_alarge;
- ct_alen = 4;
- Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
- Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
- Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
- ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
- ct_b[3] = ct_blarge;
- ct_blen = 4;
- }
- }
-
- bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
- wlength = scale_expansion_zeroelim(bctlen, bct, adz, w);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
- catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
- wlength = scale_expansion_zeroelim(catlen, cat, bdz, w);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
- abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
- wlength = scale_expansion_zeroelim(abtlen, abt, cdz, w);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
- if (adztail != 0.0) {
- vlength = scale_expansion_zeroelim(4, bc, adztail, v);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdztail != 0.0) {
- vlength = scale_expansion_zeroelim(4, ca, bdztail, v);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdztail != 0.0) {
- vlength = scale_expansion_zeroelim(4, ab, cdztail, v);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- if (adxtail != 0.0) {
- if (bdytail != 0.0) {
- Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
- Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (cdztail != 0.0) {
- Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if (cdytail != 0.0) {
- negate = -adxtail;
- Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
- Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (bdztail != 0.0) {
- Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- }
- if (bdxtail != 0.0) {
- if (cdytail != 0.0) {
- Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
- Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (adztail != 0.0) {
- Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if (adytail != 0.0) {
- negate = -bdxtail;
- Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
- Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (cdztail != 0.0) {
- Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- }
- if (cdxtail != 0.0) {
- if (adytail != 0.0) {
- Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
- Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (bdztail != 0.0) {
- Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if (bdytail != 0.0) {
- negate = -cdxtail;
- Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
- Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (adztail != 0.0) {
- Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- }
-
- if (adztail != 0.0) {
- wlength = scale_expansion_zeroelim(bctlen, bct, adztail, w);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdztail != 0.0) {
- wlength = scale_expansion_zeroelim(catlen, cat, bdztail, w);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdztail != 0.0) {
- wlength = scale_expansion_zeroelim(abtlen, abt, cdztail, w);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- return finnow[finlength - 1];
-}
-
-REAL orient3d(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
- REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
- REAL det;
- REAL permanent, errbound;
-
- adx = pa[0] - pd[0];
- bdx = pb[0] - pd[0];
- cdx = pc[0] - pd[0];
- ady = pa[1] - pd[1];
- bdy = pb[1] - pd[1];
- cdy = pc[1] - pd[1];
- adz = pa[2] - pd[2];
- bdz = pb[2] - pd[2];
- cdz = pc[2] - pd[2];
-
- bdxcdy = bdx * cdy;
- cdxbdy = cdx * bdy;
-
- cdxady = cdx * ady;
- adxcdy = adx * cdy;
-
- adxbdy = adx * bdy;
- bdxady = bdx * ady;
-
- det = adz * (bdxcdy - cdxbdy)
- + bdz * (cdxady - adxcdy)
- + cdz * (adxbdy - bdxady);
-
- permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adz)
- + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdz)
- + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdz);
- errbound = o3derrboundA * permanent;
- if ((det > errbound) || (-det > errbound)) {
- return det;
- }
-
- return orient3dadapt(pa, pb, pc, pd, permanent);
-}
-
-/*****************************************************************************/
-/* */
-/* incirclefast() Approximate 2D incircle test. Nonrobust. */
-/* incircleexact() Exact 2D incircle test. Robust. */
-/* incircleslow() Another exact 2D incircle test. Robust. */
-/* incircle() Adaptive exact 2D incircle test. Robust. */
-/* */
-/* Return a positive value if the point pd lies inside the */
-/* circle passing through pa, pb, and pc; a negative value if */
-/* it lies outside; and zero if the four points are cocircular.*/
-/* The points pa, pb, and pc must be in counterclockwise */
-/* order, or the sign of the result will be reversed. */
-/* */
-/* Only the first and last routine should be used; the middle two are for */
-/* timings. */
-/* */
-/* The last three use exact arithmetic to ensure a correct answer. The */
-/* result returned is the determinant of a matrix. In incircle() only, */
-/* this determinant is computed adaptively, in the sense that exact */
-/* arithmetic is used only to the degree it is needed to ensure that the */
-/* returned value has the correct sign. Hence, incircle() is usually quite */
-/* fast, but will run more slowly when the input points are cocircular or */
-/* nearly so. */
-/* */
-/*****************************************************************************/
-
-REAL incirclefast(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- REAL adx, ady, bdx, bdy, cdx, cdy;
- REAL abdet, bcdet, cadet;
- REAL alift, blift, clift;
-
- adx = pa[0] - pd[0];
- ady = pa[1] - pd[1];
- bdx = pb[0] - pd[0];
- bdy = pb[1] - pd[1];
- cdx = pc[0] - pd[0];
- cdy = pc[1] - pd[1];
-
- abdet = adx * bdy - bdx * ady;
- bcdet = bdx * cdy - cdx * bdy;
- cadet = cdx * ady - adx * cdy;
- alift = adx * adx + ady * ady;
- blift = bdx * bdx + bdy * bdy;
- clift = cdx * cdx + cdy * cdy;
-
- return alift * bcdet + blift * cadet + clift * abdet;
-}
-
-REAL incircleexact(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- INEXACT REAL axby1, bxcy1, cxdy1, dxay1, axcy1, bxdy1;
- INEXACT REAL bxay1, cxby1, dxcy1, axdy1, cxay1, dxby1;
- REAL axby0, bxcy0, cxdy0, dxay0, axcy0, bxdy0;
- REAL bxay0, cxby0, dxcy0, axdy0, cxay0, dxby0;
- REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4];
- REAL temp8[8];
- int templen;
- REAL abc[12], bcd[12], cda[12], dab[12];
- int abclen, bcdlen, cdalen, dablen;
- REAL det24x[24], det24y[24], det48x[48], det48y[48];
- int xlen, ylen;
- REAL adet[96], bdet[96], cdet[96], ddet[96];
- int alen, blen, clen, dlen;
- REAL abdet[192], cddet[192];
- int ablen, cdlen;
- REAL deter[384];
- int deterlen;
- int i;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j;
- REAL _0;
-
- Two_Product(pa[0], pb[1], axby1, axby0);
- Two_Product(pb[0], pa[1], bxay1, bxay0);
- Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]);
-
- Two_Product(pb[0], pc[1], bxcy1, bxcy0);
- Two_Product(pc[0], pb[1], cxby1, cxby0);
- Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]);
-
- Two_Product(pc[0], pd[1], cxdy1, cxdy0);
- Two_Product(pd[0], pc[1], dxcy1, dxcy0);
- Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]);
-
- Two_Product(pd[0], pa[1], dxay1, dxay0);
- Two_Product(pa[0], pd[1], axdy1, axdy0);
- Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]);
-
- Two_Product(pa[0], pc[1], axcy1, axcy0);
- Two_Product(pc[0], pa[1], cxay1, cxay0);
- Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]);
-
- Two_Product(pb[0], pd[1], bxdy1, bxdy0);
- Two_Product(pd[0], pb[1], dxby1, dxby0);
- Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]);
-
- templen = fast_expansion_sum_zeroelim(4, cd, 4, da, temp8);
- cdalen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, cda);
- templen = fast_expansion_sum_zeroelim(4, da, 4, ab, temp8);
- dablen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, dab);
- for (i = 0; i < 4; i++) {
- bd[i] = -bd[i];
- ac[i] = -ac[i];
- }
- templen = fast_expansion_sum_zeroelim(4, ab, 4, bc, temp8);
- abclen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, abc);
- templen = fast_expansion_sum_zeroelim(4, bc, 4, cd, temp8);
- bcdlen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, bcd);
-
- xlen = scale_expansion_zeroelim(bcdlen, bcd, pa[0], det24x);
- xlen = scale_expansion_zeroelim(xlen, det24x, pa[0], det48x);
- ylen = scale_expansion_zeroelim(bcdlen, bcd, pa[1], det24y);
- ylen = scale_expansion_zeroelim(ylen, det24y, pa[1], det48y);
- alen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, adet);
-
- xlen = scale_expansion_zeroelim(cdalen, cda, pb[0], det24x);
- xlen = scale_expansion_zeroelim(xlen, det24x, -pb[0], det48x);
- ylen = scale_expansion_zeroelim(cdalen, cda, pb[1], det24y);
- ylen = scale_expansion_zeroelim(ylen, det24y, -pb[1], det48y);
- blen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, bdet);
-
- xlen = scale_expansion_zeroelim(dablen, dab, pc[0], det24x);
- xlen = scale_expansion_zeroelim(xlen, det24x, pc[0], det48x);
- ylen = scale_expansion_zeroelim(dablen, dab, pc[1], det24y);
- ylen = scale_expansion_zeroelim(ylen, det24y, pc[1], det48y);
- clen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, cdet);
-
- xlen = scale_expansion_zeroelim(abclen, abc, pd[0], det24x);
- xlen = scale_expansion_zeroelim(xlen, det24x, -pd[0], det48x);
- ylen = scale_expansion_zeroelim(abclen, abc, pd[1], det24y);
- ylen = scale_expansion_zeroelim(ylen, det24y, -pd[1], det48y);
- dlen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, ddet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
- deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, deter);
-
- return deter[deterlen - 1];
-}
-
-REAL incircleslow(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
- REAL adxtail, bdxtail, cdxtail;
- REAL adytail, bdytail, cdytail;
- REAL negate, negatetail;
- INEXACT REAL axby7, bxcy7, axcy7, bxay7, cxby7, cxay7;
- REAL axby[8], bxcy[8], axcy[8], bxay[8], cxby[8], cxay[8];
- REAL temp16[16];
- int temp16len;
- REAL detx[32], detxx[64], detxt[32], detxxt[64], detxtxt[64];
- int xlen, xxlen, xtlen, xxtlen, xtxtlen;
- REAL x1[128], x2[192];
- int x1len, x2len;
- REAL dety[32], detyy[64], detyt[32], detyyt[64], detytyt[64];
- int ylen, yylen, ytlen, yytlen, ytytlen;
- REAL y1[128], y2[192];
- int y1len, y2len;
- REAL adet[384], bdet[384], cdet[384], abdet[768], deter[1152];
- int alen, blen, clen, ablen, deterlen;
- int i;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL a0hi, a0lo, a1hi, a1lo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j, _k, _l, _m, _n;
- REAL _0, _1, _2;
-
- Two_Diff(pa[0], pd[0], adx, adxtail);
- Two_Diff(pa[1], pd[1], ady, adytail);
- Two_Diff(pb[0], pd[0], bdx, bdxtail);
- Two_Diff(pb[1], pd[1], bdy, bdytail);
- Two_Diff(pc[0], pd[0], cdx, cdxtail);
- Two_Diff(pc[1], pd[1], cdy, cdytail);
-
- Two_Two_Product(adx, adxtail, bdy, bdytail,
- axby7, axby[6], axby[5], axby[4],
- axby[3], axby[2], axby[1], axby[0]);
- axby[7] = axby7;
- negate = -ady;
- negatetail = -adytail;
- Two_Two_Product(bdx, bdxtail, negate, negatetail,
- bxay7, bxay[6], bxay[5], bxay[4],
- bxay[3], bxay[2], bxay[1], bxay[0]);
- bxay[7] = bxay7;
- Two_Two_Product(bdx, bdxtail, cdy, cdytail,
- bxcy7, bxcy[6], bxcy[5], bxcy[4],
- bxcy[3], bxcy[2], bxcy[1], bxcy[0]);
- bxcy[7] = bxcy7;
- negate = -bdy;
- negatetail = -bdytail;
- Two_Two_Product(cdx, cdxtail, negate, negatetail,
- cxby7, cxby[6], cxby[5], cxby[4],
- cxby[3], cxby[2], cxby[1], cxby[0]);
- cxby[7] = cxby7;
- Two_Two_Product(cdx, cdxtail, ady, adytail,
- cxay7, cxay[6], cxay[5], cxay[4],
- cxay[3], cxay[2], cxay[1], cxay[0]);
- cxay[7] = cxay7;
- negate = -cdy;
- negatetail = -cdytail;
- Two_Two_Product(adx, adxtail, negate, negatetail,
- axcy7, axcy[6], axcy[5], axcy[4],
- axcy[3], axcy[2], axcy[1], axcy[0]);
- axcy[7] = axcy7;
-
-
- temp16len = fast_expansion_sum_zeroelim(8, bxcy, 8, cxby, temp16);
-
- xlen = scale_expansion_zeroelim(temp16len, temp16, adx, detx);
- xxlen = scale_expansion_zeroelim(xlen, detx, adx, detxx);
- xtlen = scale_expansion_zeroelim(temp16len, temp16, adxtail, detxt);
- xxtlen = scale_expansion_zeroelim(xtlen, detxt, adx, detxxt);
- for (i = 0; i < xxtlen; i++) {
- detxxt[i] *= 2.0;
- }
- xtxtlen = scale_expansion_zeroelim(xtlen, detxt, adxtail, detxtxt);
- x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1);
- x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2);
-
- ylen = scale_expansion_zeroelim(temp16len, temp16, ady, dety);
- yylen = scale_expansion_zeroelim(ylen, dety, ady, detyy);
- ytlen = scale_expansion_zeroelim(temp16len, temp16, adytail, detyt);
- yytlen = scale_expansion_zeroelim(ytlen, detyt, ady, detyyt);
- for (i = 0; i < yytlen; i++) {
- detyyt[i] *= 2.0;
- }
- ytytlen = scale_expansion_zeroelim(ytlen, detyt, adytail, detytyt);
- y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1);
- y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2);
-
- alen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, adet);
-
-
- temp16len = fast_expansion_sum_zeroelim(8, cxay, 8, axcy, temp16);
-
- xlen = scale_expansion_zeroelim(temp16len, temp16, bdx, detx);
- xxlen = scale_expansion_zeroelim(xlen, detx, bdx, detxx);
- xtlen = scale_expansion_zeroelim(temp16len, temp16, bdxtail, detxt);
- xxtlen = scale_expansion_zeroelim(xtlen, detxt, bdx, detxxt);
- for (i = 0; i < xxtlen; i++) {
- detxxt[i] *= 2.0;
- }
- xtxtlen = scale_expansion_zeroelim(xtlen, detxt, bdxtail, detxtxt);
- x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1);
- x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2);
-
- ylen = scale_expansion_zeroelim(temp16len, temp16, bdy, dety);
- yylen = scale_expansion_zeroelim(ylen, dety, bdy, detyy);
- ytlen = scale_expansion_zeroelim(temp16len, temp16, bdytail, detyt);
- yytlen = scale_expansion_zeroelim(ytlen, detyt, bdy, detyyt);
- for (i = 0; i < yytlen; i++) {
- detyyt[i] *= 2.0;
- }
- ytytlen = scale_expansion_zeroelim(ytlen, detyt, bdytail, detytyt);
- y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1);
- y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2);
-
- blen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, bdet);
-
-
- temp16len = fast_expansion_sum_zeroelim(8, axby, 8, bxay, temp16);
-
- xlen = scale_expansion_zeroelim(temp16len, temp16, cdx, detx);
- xxlen = scale_expansion_zeroelim(xlen, detx, cdx, detxx);
- xtlen = scale_expansion_zeroelim(temp16len, temp16, cdxtail, detxt);
- xxtlen = scale_expansion_zeroelim(xtlen, detxt, cdx, detxxt);
- for (i = 0; i < xxtlen; i++) {
- detxxt[i] *= 2.0;
- }
- xtxtlen = scale_expansion_zeroelim(xtlen, detxt, cdxtail, detxtxt);
- x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1);
- x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2);
-
- ylen = scale_expansion_zeroelim(temp16len, temp16, cdy, dety);
- yylen = scale_expansion_zeroelim(ylen, dety, cdy, detyy);
- ytlen = scale_expansion_zeroelim(temp16len, temp16, cdytail, detyt);
- yytlen = scale_expansion_zeroelim(ytlen, detyt, cdy, detyyt);
- for (i = 0; i < yytlen; i++) {
- detyyt[i] *= 2.0;
- }
- ytytlen = scale_expansion_zeroelim(ytlen, detyt, cdytail, detytyt);
- y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1);
- y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2);
-
- clen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, cdet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- deterlen = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, deter);
-
- return deter[deterlen - 1];
-}
-
-REAL incircleadapt(pa, pb, pc, pd, permanent)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
- REAL permanent;
-{
- INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
- REAL det, errbound;
-
- INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
- REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
- REAL bc[4], ca[4], ab[4];
- INEXACT REAL bc3, ca3, ab3;
- REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
- int axbclen, axxbclen, aybclen, ayybclen, alen;
- REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
- int bxcalen, bxxcalen, bycalen, byycalen, blen;
- REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
- int cxablen, cxxablen, cyablen, cyyablen, clen;
- REAL abdet[64];
- int ablen;
- REAL fin1[1152], fin2[1152];
- REAL *finnow, *finother, *finswap;
- int finlength;
-
- REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
- INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
- REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
- REAL aa[4], bb[4], cc[4];
- INEXACT REAL aa3, bb3, cc3;
- INEXACT REAL ti1, tj1;
- REAL ti0, tj0;
- REAL u[4], v[4];
- INEXACT REAL u3, v3;
- REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
- REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
- int temp8len, temp16alen, temp16blen, temp16clen;
- int temp32alen, temp32blen, temp48len, temp64len;
- REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
- int axtbblen, axtcclen, aytbblen, aytcclen;
- REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
- int bxtaalen, bxtcclen, bytaalen, bytcclen;
- REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
- int cxtaalen, cxtbblen, cytaalen, cytbblen;
- REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
- int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
- REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
- int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
- REAL axtbctt[8], aytbctt[8], bxtcatt[8];
- REAL bytcatt[8], cxtabtt[8], cytabtt[8];
- int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
- REAL abt[8], bct[8], cat[8];
- int abtlen, bctlen, catlen;
- REAL abtt[4], bctt[4], catt[4];
- int abttlen, bcttlen, cattlen;
- INEXACT REAL abtt3, bctt3, catt3;
- REAL negate;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j;
- REAL _0;
-
- adx = (REAL) (pa[0] - pd[0]);
- bdx = (REAL) (pb[0] - pd[0]);
- cdx = (REAL) (pc[0] - pd[0]);
- ady = (REAL) (pa[1] - pd[1]);
- bdy = (REAL) (pb[1] - pd[1]);
- cdy = (REAL) (pc[1] - pd[1]);
-
- Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
- Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
- Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
- bc[3] = bc3;
- axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
- axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
- aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
- ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
- alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
-
- Two_Product(cdx, ady, cdxady1, cdxady0);
- Two_Product(adx, cdy, adxcdy1, adxcdy0);
- Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
- ca[3] = ca3;
- bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
- bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
- bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
- byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
- blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
-
- Two_Product(adx, bdy, adxbdy1, adxbdy0);
- Two_Product(bdx, ady, bdxady1, bdxady0);
- Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
- ab[3] = ab3;
- cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
- cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
- cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
- cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
- clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
-
- det = estimate(finlength, fin1);
- errbound = iccerrboundB * permanent;
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
- Two_Diff_Tail(pa[1], pd[1], ady, adytail);
- Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
- Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
- Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
- Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
- if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
- && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
- return det;
- }
-
- errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
- det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
- - (bdy * cdxtail + cdx * bdytail))
- + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
- + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
- - (cdy * adxtail + adx * cdytail))
- + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
- + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
- - (ady * bdxtail + bdx * adytail))
- + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- finnow = fin1;
- finother = fin2;
-
- if ((bdxtail != 0.0) || (bdytail != 0.0)
- || (cdxtail != 0.0) || (cdytail != 0.0)) {
- Square(adx, adxadx1, adxadx0);
- Square(ady, adyady1, adyady0);
- Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
- aa[3] = aa3;
- }
- if ((cdxtail != 0.0) || (cdytail != 0.0)
- || (adxtail != 0.0) || (adytail != 0.0)) {
- Square(bdx, bdxbdx1, bdxbdx0);
- Square(bdy, bdybdy1, bdybdy0);
- Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
- bb[3] = bb3;
- }
- if ((adxtail != 0.0) || (adytail != 0.0)
- || (bdxtail != 0.0) || (bdytail != 0.0)) {
- Square(cdx, cdxcdx1, cdxcdx0);
- Square(cdy, cdycdy1, cdycdy0);
- Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
- cc[3] = cc3;
- }
-
- if (adxtail != 0.0) {
- axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
- temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
- temp16a);
-
- axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
- temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
-
- axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
- temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
-
- temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (adytail != 0.0) {
- aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
- temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
- temp16a);
-
- aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
- temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
-
- aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
- temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
-
- temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdxtail != 0.0) {
- bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
- temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
- temp16a);
-
- bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
- temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
-
- bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
- temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
-
- temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdytail != 0.0) {
- bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
- temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
- temp16a);
-
- bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
- temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
-
- bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
- temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
-
- temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdxtail != 0.0) {
- cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
- temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
- temp16a);
-
- cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
- temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
-
- cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
- temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
-
- temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdytail != 0.0) {
- cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
- temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
- temp16a);
-
- cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
- temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
-
- cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
- temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
-
- temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- if ((adxtail != 0.0) || (adytail != 0.0)) {
- if ((bdxtail != 0.0) || (bdytail != 0.0)
- || (cdxtail != 0.0) || (cdytail != 0.0)) {
- Two_Product(bdxtail, cdy, ti1, ti0);
- Two_Product(bdx, cdytail, tj1, tj0);
- Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- negate = -bdy;
- Two_Product(cdxtail, negate, ti1, ti0);
- negate = -bdytail;
- Two_Product(cdx, negate, tj1, tj0);
- Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
- v[3] = v3;
- bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
-
- Two_Product(bdxtail, cdytail, ti1, ti0);
- Two_Product(cdxtail, bdytail, tj1, tj0);
- Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
- bctt[3] = bctt3;
- bcttlen = 4;
- } else {
- bct[0] = 0.0;
- bctlen = 1;
- bctt[0] = 0.0;
- bcttlen = 1;
- }
-
- if (adxtail != 0.0) {
- temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
- axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
- temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
- temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (bdytail != 0.0) {
- temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
- temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
- temp16a);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
- temp16a, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdytail != 0.0) {
- temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
- temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
- temp16a);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
- temp16a, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
- temp32a);
- axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
- temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
- temp16a);
- temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
- temp16b);
- temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32b);
- temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
- temp64, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (adytail != 0.0) {
-#ifndef WIN32
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
- temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
- aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
- temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
- temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
-
- temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
- temp32a);
- aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
- temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
- temp16a);
- temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
- temp16b);
- temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32b);
- temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
- temp64, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if ((bdxtail != 0.0) || (bdytail != 0.0)) {
- if ((cdxtail != 0.0) || (cdytail != 0.0)
- || (adxtail != 0.0) || (adytail != 0.0)) {
- Two_Product(cdxtail, ady, ti1, ti0);
- Two_Product(cdx, adytail, tj1, tj0);
- Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- negate = -cdy;
- Two_Product(adxtail, negate, ti1, ti0);
- negate = -cdytail;
- Two_Product(adx, negate, tj1, tj0);
- Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
- v[3] = v3;
- catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
-
- Two_Product(cdxtail, adytail, ti1, ti0);
- Two_Product(adxtail, cdytail, tj1, tj0);
- Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
- catt[3] = catt3;
- cattlen = 4;
- } else {
- cat[0] = 0.0;
- catlen = 1;
- catt[0] = 0.0;
- cattlen = 1;
- }
-
- if (bdxtail != 0.0) {
- temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
- bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
- temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
- temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (cdytail != 0.0) {
- temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
- temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
- temp16a);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
- temp16a, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (adytail != 0.0) {
- temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
- temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
- temp16a);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
- temp16a, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
- temp32a);
- bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
- temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
- temp16a);
- temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
- temp16b);
- temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32b);
- temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
- temp64, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdytail != 0.0) {
-#ifndef WIN32
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
- temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
- bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
- temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
- temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
-
- temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
- temp32a);
- bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
- temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
- temp16a);
- temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
- temp16b);
- temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32b);
- temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
- temp64, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if ((cdxtail != 0.0) || (cdytail != 0.0)) {
- if ((adxtail != 0.0) || (adytail != 0.0)
- || (bdxtail != 0.0) || (bdytail != 0.0)) {
- Two_Product(adxtail, bdy, ti1, ti0);
- Two_Product(adx, bdytail, tj1, tj0);
- Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- negate = -ady;
- Two_Product(bdxtail, negate, ti1, ti0);
- negate = -adytail;
- Two_Product(bdx, negate, tj1, tj0);
- Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
- v[3] = v3;
- abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
-
- Two_Product(adxtail, bdytail, ti1, ti0);
- Two_Product(bdxtail, adytail, tj1, tj0);
- Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
- abtt[3] = abtt3;
- abttlen = 4;
- } else {
- abt[0] = 0.0;
- abtlen = 1;
- abtt[0] = 0.0;
- abttlen = 1;
- }
-
- if (cdxtail != 0.0) {
-#ifndef WIN32
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
- temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
- cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
- temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
- temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (adytail != 0.0) {
- temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
- temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
- temp16a);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
- temp16a, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdytail != 0.0) {
- temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
- temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
- temp16a);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
- temp16a, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
- temp32a);
- cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
- temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
- temp16a);
- temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
- temp16b);
- temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32b);
- temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
- temp64, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdytail != 0.0) {
-#ifndef WIN32
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
- temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
- cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
- temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
- temp32a);
- temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp32alen, temp32a, temp48);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
- temp48, finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
-
- temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
- temp32a);
- cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
- temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
- temp16a);
- temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
- temp16b);
- temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
- temp16blen, temp16b, temp32b);
- temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64);
- finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
- temp64, finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
-
- return finnow[finlength - 1];
-}
-
-REAL incircle(pa, pb, pc, pd)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
-{
- REAL adx, bdx, cdx, ady, bdy, cdy;
- REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
- REAL alift, blift, clift;
- REAL det;
- REAL permanent, errbound;
-
- adx = pa[0] - pd[0];
- bdx = pb[0] - pd[0];
- cdx = pc[0] - pd[0];
- ady = pa[1] - pd[1];
- bdy = pb[1] - pd[1];
- cdy = pc[1] - pd[1];
-
- bdxcdy = bdx * cdy;
- cdxbdy = cdx * bdy;
- alift = adx * adx + ady * ady;
-
- cdxady = cdx * ady;
- adxcdy = adx * cdy;
- blift = bdx * bdx + bdy * bdy;
-
- adxbdy = adx * bdy;
- bdxady = bdx * ady;
- clift = cdx * cdx + cdy * cdy;
-
- det = alift * (bdxcdy - cdxbdy)
- + blift * (cdxady - adxcdy)
- + clift * (adxbdy - bdxady);
-
- permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
- + (Absolute(cdxady) + Absolute(adxcdy)) * blift
- + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
- errbound = iccerrboundA * permanent;
- if ((det > errbound) || (-det > errbound)) {
- return det;
- }
-
- return incircleadapt(pa, pb, pc, pd, permanent);
-}
-
-/*****************************************************************************/
-/* */
-/* inspherefast() Approximate 3D insphere test. Nonrobust. */
-/* insphereexact() Exact 3D insphere test. Robust. */
-/* insphereslow() Another exact 3D insphere test. Robust. */
-/* insphere() Adaptive exact 3D insphere test. Robust. */
-/* */
-/* Return a positive value if the point pe lies inside the */
-/* sphere passing through pa, pb, pc, and pd; a negative value */
-/* if it lies outside; and zero if the five points are */
-/* cospherical. The points pa, pb, pc, and pd must be ordered */
-/* so that they have a positive orientation (as defined by */
-/* orient3d()), or the sign of the result will be reversed. */
-/* */
-/* Only the first and last routine should be used; the middle two are for */
-/* timings. */
-/* */
-/* The last three use exact arithmetic to ensure a correct answer. The */
-/* result returned is the determinant of a matrix. In insphere() only, */
-/* this determinant is computed adaptively, in the sense that exact */
-/* arithmetic is used only to the degree it is needed to ensure that the */
-/* returned value has the correct sign. Hence, insphere() is usually quite */
-/* fast, but will run more slowly when the input points are cospherical or */
-/* nearly so. */
-/* */
-/*****************************************************************************/
-
-REAL inspherefast(pa, pb, pc, pd, pe)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
- REAL *pe;
-{
- REAL aex, bex, cex, dex;
- REAL aey, bey, cey, dey;
- REAL aez, bez, cez, dez;
- REAL alift, blift, clift, dlift;
- REAL ab, bc, cd, da, ac, bd;
- REAL abc, bcd, cda, dab;
-
- aex = pa[0] - pe[0];
- bex = pb[0] - pe[0];
- cex = pc[0] - pe[0];
- dex = pd[0] - pe[0];
- aey = pa[1] - pe[1];
- bey = pb[1] - pe[1];
- cey = pc[1] - pe[1];
- dey = pd[1] - pe[1];
- aez = pa[2] - pe[2];
- bez = pb[2] - pe[2];
- cez = pc[2] - pe[2];
- dez = pd[2] - pe[2];
-
- ab = aex * bey - bex * aey;
- bc = bex * cey - cex * bey;
- cd = cex * dey - dex * cey;
- da = dex * aey - aex * dey;
-
- ac = aex * cey - cex * aey;
- bd = bex * dey - dex * bey;
-
- abc = aez * bc - bez * ac + cez * ab;
- bcd = bez * cd - cez * bd + dez * bc;
- cda = cez * da + dez * ac + aez * cd;
- dab = dez * ab + aez * bd + bez * da;
-
- alift = aex * aex + aey * aey + aez * aez;
- blift = bex * bex + bey * bey + bez * bez;
- clift = cex * cex + cey * cey + cez * cez;
- dlift = dex * dex + dey * dey + dez * dez;
-
- return (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
-}
-
-REAL insphereexact(pa, pb, pc, pd, pe)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
- REAL *pe;
-{
- INEXACT REAL axby1, bxcy1, cxdy1, dxey1, exay1;
- INEXACT REAL bxay1, cxby1, dxcy1, exdy1, axey1;
- INEXACT REAL axcy1, bxdy1, cxey1, dxay1, exby1;
- INEXACT REAL cxay1, dxby1, excy1, axdy1, bxey1;
- REAL axby0, bxcy0, cxdy0, dxey0, exay0;
- REAL bxay0, cxby0, dxcy0, exdy0, axey0;
- REAL axcy0, bxdy0, cxey0, dxay0, exby0;
- REAL cxay0, dxby0, excy0, axdy0, bxey0;
- REAL ab[4], bc[4], cd[4], de[4], ea[4];
- REAL ac[4], bd[4], ce[4], da[4], eb[4];
- REAL temp8a[8], temp8b[8], temp16[16];
- int temp8alen, temp8blen, temp16len;
- REAL abc[24], bcd[24], cde[24], dea[24], eab[24];
- REAL abd[24], bce[24], cda[24], deb[24], eac[24];
- int abclen, bcdlen, cdelen, dealen, eablen;
- int abdlen, bcelen, cdalen, deblen, eaclen;
- REAL temp48a[48], temp48b[48];
- int temp48alen, temp48blen;
- REAL abcd[96], bcde[96], cdea[96], deab[96], eabc[96];
- int abcdlen, bcdelen, cdealen, deablen, eabclen;
- REAL temp192[192];
- REAL det384x[384], det384y[384], det384z[384];
- int xlen, ylen, zlen;
- REAL detxy[768];
- int xylen;
- REAL adet[1152], bdet[1152], cdet[1152], ddet[1152], edet[1152];
- int alen, blen, clen, dlen, elen;
- REAL abdet[2304], cddet[2304], cdedet[3456];
- int ablen, cdlen;
- REAL deter[5760];
- int deterlen;
- int i;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j;
- REAL _0;
-
- Two_Product(pa[0], pb[1], axby1, axby0);
- Two_Product(pb[0], pa[1], bxay1, bxay0);
- Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]);
-
- Two_Product(pb[0], pc[1], bxcy1, bxcy0);
- Two_Product(pc[0], pb[1], cxby1, cxby0);
- Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]);
-
- Two_Product(pc[0], pd[1], cxdy1, cxdy0);
- Two_Product(pd[0], pc[1], dxcy1, dxcy0);
- Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]);
-
- Two_Product(pd[0], pe[1], dxey1, dxey0);
- Two_Product(pe[0], pd[1], exdy1, exdy0);
- Two_Two_Diff(dxey1, dxey0, exdy1, exdy0, de[3], de[2], de[1], de[0]);
-
- Two_Product(pe[0], pa[1], exay1, exay0);
- Two_Product(pa[0], pe[1], axey1, axey0);
- Two_Two_Diff(exay1, exay0, axey1, axey0, ea[3], ea[2], ea[1], ea[0]);
-
- Two_Product(pa[0], pc[1], axcy1, axcy0);
- Two_Product(pc[0], pa[1], cxay1, cxay0);
- Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]);
-
- Two_Product(pb[0], pd[1], bxdy1, bxdy0);
- Two_Product(pd[0], pb[1], dxby1, dxby0);
- Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]);
-
- Two_Product(pc[0], pe[1], cxey1, cxey0);
- Two_Product(pe[0], pc[1], excy1, excy0);
- Two_Two_Diff(cxey1, cxey0, excy1, excy0, ce[3], ce[2], ce[1], ce[0]);
-
- Two_Product(pd[0], pa[1], dxay1, dxay0);
- Two_Product(pa[0], pd[1], axdy1, axdy0);
- Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]);
-
- Two_Product(pe[0], pb[1], exby1, exby0);
- Two_Product(pb[0], pe[1], bxey1, bxey0);
- Two_Two_Diff(exby1, exby0, bxey1, bxey0, eb[3], eb[2], eb[1], eb[0]);
-
- temp8alen = scale_expansion_zeroelim(4, bc, pa[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, ac, -pb[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, ab, pc[2], temp8a);
- abclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- abc);
-
- temp8alen = scale_expansion_zeroelim(4, cd, pb[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, bd, -pc[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, bc, pd[2], temp8a);
- bcdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- bcd);
-
- temp8alen = scale_expansion_zeroelim(4, de, pc[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, ce, -pd[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, cd, pe[2], temp8a);
- cdelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- cde);
-
- temp8alen = scale_expansion_zeroelim(4, ea, pd[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, da, -pe[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, de, pa[2], temp8a);
- dealen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- dea);
-
- temp8alen = scale_expansion_zeroelim(4, ab, pe[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, eb, -pa[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, ea, pb[2], temp8a);
- eablen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- eab);
-
- temp8alen = scale_expansion_zeroelim(4, bd, pa[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, da, pb[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, ab, pd[2], temp8a);
- abdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- abd);
-
- temp8alen = scale_expansion_zeroelim(4, ce, pb[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, eb, pc[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, bc, pe[2], temp8a);
- bcelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- bce);
-
- temp8alen = scale_expansion_zeroelim(4, da, pc[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, ac, pd[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, cd, pa[2], temp8a);
- cdalen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- cda);
-
- temp8alen = scale_expansion_zeroelim(4, eb, pd[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, bd, pe[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, de, pb[2], temp8a);
- deblen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- deb);
-
- temp8alen = scale_expansion_zeroelim(4, ac, pe[2], temp8a);
- temp8blen = scale_expansion_zeroelim(4, ce, pa[2], temp8b);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
- temp16);
- temp8alen = scale_expansion_zeroelim(4, ea, pc[2], temp8a);
- eaclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
- eac);
-
- temp48alen = fast_expansion_sum_zeroelim(cdelen, cde, bcelen, bce, temp48a);
- temp48blen = fast_expansion_sum_zeroelim(deblen, deb, bcdlen, bcd, temp48b);
- for (i = 0; i < temp48blen; i++) {
- temp48b[i] = -temp48b[i];
- }
- bcdelen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
- temp48blen, temp48b, bcde);
- xlen = scale_expansion_zeroelim(bcdelen, bcde, pa[0], temp192);
- xlen = scale_expansion_zeroelim(xlen, temp192, pa[0], det384x);
- ylen = scale_expansion_zeroelim(bcdelen, bcde, pa[1], temp192);
- ylen = scale_expansion_zeroelim(ylen, temp192, pa[1], det384y);
- zlen = scale_expansion_zeroelim(bcdelen, bcde, pa[2], temp192);
- zlen = scale_expansion_zeroelim(zlen, temp192, pa[2], det384z);
- xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
- alen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, adet);
-
- temp48alen = fast_expansion_sum_zeroelim(dealen, dea, cdalen, cda, temp48a);
- temp48blen = fast_expansion_sum_zeroelim(eaclen, eac, cdelen, cde, temp48b);
- for (i = 0; i < temp48blen; i++) {
- temp48b[i] = -temp48b[i];
- }
- cdealen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
- temp48blen, temp48b, cdea);
- xlen = scale_expansion_zeroelim(cdealen, cdea, pb[0], temp192);
- xlen = scale_expansion_zeroelim(xlen, temp192, pb[0], det384x);
- ylen = scale_expansion_zeroelim(cdealen, cdea, pb[1], temp192);
- ylen = scale_expansion_zeroelim(ylen, temp192, pb[1], det384y);
- zlen = scale_expansion_zeroelim(cdealen, cdea, pb[2], temp192);
- zlen = scale_expansion_zeroelim(zlen, temp192, pb[2], det384z);
- xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
- blen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, bdet);
-
- temp48alen = fast_expansion_sum_zeroelim(eablen, eab, deblen, deb, temp48a);
- temp48blen = fast_expansion_sum_zeroelim(abdlen, abd, dealen, dea, temp48b);
- for (i = 0; i < temp48blen; i++) {
- temp48b[i] = -temp48b[i];
- }
- deablen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
- temp48blen, temp48b, deab);
- xlen = scale_expansion_zeroelim(deablen, deab, pc[0], temp192);
- xlen = scale_expansion_zeroelim(xlen, temp192, pc[0], det384x);
- ylen = scale_expansion_zeroelim(deablen, deab, pc[1], temp192);
- ylen = scale_expansion_zeroelim(ylen, temp192, pc[1], det384y);
- zlen = scale_expansion_zeroelim(deablen, deab, pc[2], temp192);
- zlen = scale_expansion_zeroelim(zlen, temp192, pc[2], det384z);
- xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
- clen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, cdet);
-
- temp48alen = fast_expansion_sum_zeroelim(abclen, abc, eaclen, eac, temp48a);
- temp48blen = fast_expansion_sum_zeroelim(bcelen, bce, eablen, eab, temp48b);
- for (i = 0; i < temp48blen; i++) {
- temp48b[i] = -temp48b[i];
- }
- eabclen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
- temp48blen, temp48b, eabc);
- xlen = scale_expansion_zeroelim(eabclen, eabc, pd[0], temp192);
- xlen = scale_expansion_zeroelim(xlen, temp192, pd[0], det384x);
- ylen = scale_expansion_zeroelim(eabclen, eabc, pd[1], temp192);
- ylen = scale_expansion_zeroelim(ylen, temp192, pd[1], det384y);
- zlen = scale_expansion_zeroelim(eabclen, eabc, pd[2], temp192);
- zlen = scale_expansion_zeroelim(zlen, temp192, pd[2], det384z);
- xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
- dlen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, ddet);
-
- temp48alen = fast_expansion_sum_zeroelim(bcdlen, bcd, abdlen, abd, temp48a);
- temp48blen = fast_expansion_sum_zeroelim(cdalen, cda, abclen, abc, temp48b);
- for (i = 0; i < temp48blen; i++) {
- temp48b[i] = -temp48b[i];
- }
- abcdlen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
- temp48blen, temp48b, abcd);
- xlen = scale_expansion_zeroelim(abcdlen, abcd, pe[0], temp192);
- xlen = scale_expansion_zeroelim(xlen, temp192, pe[0], det384x);
- ylen = scale_expansion_zeroelim(abcdlen, abcd, pe[1], temp192);
- ylen = scale_expansion_zeroelim(ylen, temp192, pe[1], det384y);
- zlen = scale_expansion_zeroelim(abcdlen, abcd, pe[2], temp192);
- zlen = scale_expansion_zeroelim(zlen, temp192, pe[2], det384z);
- xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
- elen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, edet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
- cdelen = fast_expansion_sum_zeroelim(cdlen, cddet, elen, edet, cdedet);
- deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdelen, cdedet, deter);
-
- return deter[deterlen - 1];
-}
-
-REAL insphereslow(pa, pb, pc, pd, pe)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
- REAL *pe;
-{
- INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez;
- REAL aextail, bextail, cextail, dextail;
- REAL aeytail, beytail, ceytail, deytail;
- REAL aeztail, beztail, ceztail, deztail;
- REAL negate, negatetail;
- INEXACT REAL axby7, bxcy7, cxdy7, dxay7, axcy7, bxdy7;
- INEXACT REAL bxay7, cxby7, dxcy7, axdy7, cxay7, dxby7;
- REAL axby[8], bxcy[8], cxdy[8], dxay[8], axcy[8], bxdy[8];
- REAL bxay[8], cxby[8], dxcy[8], axdy[8], cxay[8], dxby[8];
- REAL ab[16], bc[16], cd[16], da[16], ac[16], bd[16];
- int ablen, bclen, cdlen, dalen, aclen, bdlen;
- REAL temp32a[32], temp32b[32], temp64a[64], temp64b[64], temp64c[64];
- int temp32alen, temp32blen, temp64alen, temp64blen, temp64clen;
- REAL temp128[128], temp192[192];
- int temp128len, temp192len;
- REAL detx[384], detxx[768], detxt[384], detxxt[768], detxtxt[768];
- int xlen, xxlen, xtlen, xxtlen, xtxtlen;
- REAL x1[1536], x2[2304];
- int x1len, x2len;
- REAL dety[384], detyy[768], detyt[384], detyyt[768], detytyt[768];
- int ylen, yylen, ytlen, yytlen, ytytlen;
- REAL y1[1536], y2[2304];
- int y1len, y2len;
- REAL detz[384], detzz[768], detzt[384], detzzt[768], detztzt[768];
- int zlen, zzlen, ztlen, zztlen, ztztlen;
- REAL z1[1536], z2[2304];
- int z1len, z2len;
- REAL detxy[4608];
- int xylen;
- REAL adet[6912], bdet[6912], cdet[6912], ddet[6912];
- int alen, blen, clen, dlen;
- REAL abdet[13824], cddet[13824], deter[27648];
- int deterlen;
- int i;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL a0hi, a0lo, a1hi, a1lo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j, _k, _l, _m, _n;
- REAL _0, _1, _2;
-
- Two_Diff(pa[0], pe[0], aex, aextail);
- Two_Diff(pa[1], pe[1], aey, aeytail);
- Two_Diff(pa[2], pe[2], aez, aeztail);
- Two_Diff(pb[0], pe[0], bex, bextail);
- Two_Diff(pb[1], pe[1], bey, beytail);
- Two_Diff(pb[2], pe[2], bez, beztail);
- Two_Diff(pc[0], pe[0], cex, cextail);
- Two_Diff(pc[1], pe[1], cey, ceytail);
- Two_Diff(pc[2], pe[2], cez, ceztail);
- Two_Diff(pd[0], pe[0], dex, dextail);
- Two_Diff(pd[1], pe[1], dey, deytail);
- Two_Diff(pd[2], pe[2], dez, deztail);
-
- Two_Two_Product(aex, aextail, bey, beytail,
- axby7, axby[6], axby[5], axby[4],
- axby[3], axby[2], axby[1], axby[0]);
- axby[7] = axby7;
- negate = -aey;
- negatetail = -aeytail;
- Two_Two_Product(bex, bextail, negate, negatetail,
- bxay7, bxay[6], bxay[5], bxay[4],
- bxay[3], bxay[2], bxay[1], bxay[0]);
- bxay[7] = bxay7;
- ablen = fast_expansion_sum_zeroelim(8, axby, 8, bxay, ab);
- Two_Two_Product(bex, bextail, cey, ceytail,
- bxcy7, bxcy[6], bxcy[5], bxcy[4],
- bxcy[3], bxcy[2], bxcy[1], bxcy[0]);
- bxcy[7] = bxcy7;
- negate = -bey;
- negatetail = -beytail;
- Two_Two_Product(cex, cextail, negate, negatetail,
- cxby7, cxby[6], cxby[5], cxby[4],
- cxby[3], cxby[2], cxby[1], cxby[0]);
- cxby[7] = cxby7;
- bclen = fast_expansion_sum_zeroelim(8, bxcy, 8, cxby, bc);
- Two_Two_Product(cex, cextail, dey, deytail,
- cxdy7, cxdy[6], cxdy[5], cxdy[4],
- cxdy[3], cxdy[2], cxdy[1], cxdy[0]);
- cxdy[7] = cxdy7;
- negate = -cey;
- negatetail = -ceytail;
- Two_Two_Product(dex, dextail, negate, negatetail,
- dxcy7, dxcy[6], dxcy[5], dxcy[4],
- dxcy[3], dxcy[2], dxcy[1], dxcy[0]);
- dxcy[7] = dxcy7;
- cdlen = fast_expansion_sum_zeroelim(8, cxdy, 8, dxcy, cd);
- Two_Two_Product(dex, dextail, aey, aeytail,
- dxay7, dxay[6], dxay[5], dxay[4],
- dxay[3], dxay[2], dxay[1], dxay[0]);
- dxay[7] = dxay7;
- negate = -dey;
- negatetail = -deytail;
- Two_Two_Product(aex, aextail, negate, negatetail,
- axdy7, axdy[6], axdy[5], axdy[4],
- axdy[3], axdy[2], axdy[1], axdy[0]);
- axdy[7] = axdy7;
- dalen = fast_expansion_sum_zeroelim(8, dxay, 8, axdy, da);
- Two_Two_Product(aex, aextail, cey, ceytail,
- axcy7, axcy[6], axcy[5], axcy[4],
- axcy[3], axcy[2], axcy[1], axcy[0]);
- axcy[7] = axcy7;
- negate = -aey;
- negatetail = -aeytail;
- Two_Two_Product(cex, cextail, negate, negatetail,
- cxay7, cxay[6], cxay[5], cxay[4],
- cxay[3], cxay[2], cxay[1], cxay[0]);
- cxay[7] = cxay7;
- aclen = fast_expansion_sum_zeroelim(8, axcy, 8, cxay, ac);
- Two_Two_Product(bex, bextail, dey, deytail,
- bxdy7, bxdy[6], bxdy[5], bxdy[4],
- bxdy[3], bxdy[2], bxdy[1], bxdy[0]);
- bxdy[7] = bxdy7;
- negate = -bey;
- negatetail = -beytail;
- Two_Two_Product(dex, dextail, negate, negatetail,
- dxby7, dxby[6], dxby[5], dxby[4],
- dxby[3], dxby[2], dxby[1], dxby[0]);
- dxby[7] = dxby7;
- bdlen = fast_expansion_sum_zeroelim(8, bxdy, 8, dxby, bd);
-
- temp32alen = scale_expansion_zeroelim(cdlen, cd, -bez, temp32a);
- temp32blen = scale_expansion_zeroelim(cdlen, cd, -beztail, temp32b);
- temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64a);
- temp32alen = scale_expansion_zeroelim(bdlen, bd, cez, temp32a);
- temp32blen = scale_expansion_zeroelim(bdlen, bd, ceztail, temp32b);
- temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64b);
- temp32alen = scale_expansion_zeroelim(bclen, bc, -dez, temp32a);
- temp32blen = scale_expansion_zeroelim(bclen, bc, -deztail, temp32b);
- temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64c);
- temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a,
- temp64blen, temp64b, temp128);
- temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c,
- temp128len, temp128, temp192);
- xlen = scale_expansion_zeroelim(temp192len, temp192, aex, detx);
- xxlen = scale_expansion_zeroelim(xlen, detx, aex, detxx);
- xtlen = scale_expansion_zeroelim(temp192len, temp192, aextail, detxt);
- xxtlen = scale_expansion_zeroelim(xtlen, detxt, aex, detxxt);
- for (i = 0; i < xxtlen; i++) {
- detxxt[i] *= 2.0;
- }
- xtxtlen = scale_expansion_zeroelim(xtlen, detxt, aextail, detxtxt);
- x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1);
- x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2);
- ylen = scale_expansion_zeroelim(temp192len, temp192, aey, dety);
- yylen = scale_expansion_zeroelim(ylen, dety, aey, detyy);
- ytlen = scale_expansion_zeroelim(temp192len, temp192, aeytail, detyt);
- yytlen = scale_expansion_zeroelim(ytlen, detyt, aey, detyyt);
- for (i = 0; i < yytlen; i++) {
- detyyt[i] *= 2.0;
- }
- ytytlen = scale_expansion_zeroelim(ytlen, detyt, aeytail, detytyt);
- y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1);
- y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2);
- zlen = scale_expansion_zeroelim(temp192len, temp192, aez, detz);
- zzlen = scale_expansion_zeroelim(zlen, detz, aez, detzz);
- ztlen = scale_expansion_zeroelim(temp192len, temp192, aeztail, detzt);
- zztlen = scale_expansion_zeroelim(ztlen, detzt, aez, detzzt);
- for (i = 0; i < zztlen; i++) {
- detzzt[i] *= 2.0;
- }
- ztztlen = scale_expansion_zeroelim(ztlen, detzt, aeztail, detztzt);
- z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1);
- z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2);
- xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy);
- alen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, adet);
-
- temp32alen = scale_expansion_zeroelim(dalen, da, cez, temp32a);
- temp32blen = scale_expansion_zeroelim(dalen, da, ceztail, temp32b);
- temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64a);
- temp32alen = scale_expansion_zeroelim(aclen, ac, dez, temp32a);
- temp32blen = scale_expansion_zeroelim(aclen, ac, deztail, temp32b);
- temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64b);
- temp32alen = scale_expansion_zeroelim(cdlen, cd, aez, temp32a);
- temp32blen = scale_expansion_zeroelim(cdlen, cd, aeztail, temp32b);
- temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64c);
- temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a,
- temp64blen, temp64b, temp128);
- temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c,
- temp128len, temp128, temp192);
- xlen = scale_expansion_zeroelim(temp192len, temp192, bex, detx);
- xxlen = scale_expansion_zeroelim(xlen, detx, bex, detxx);
- xtlen = scale_expansion_zeroelim(temp192len, temp192, bextail, detxt);
- xxtlen = scale_expansion_zeroelim(xtlen, detxt, bex, detxxt);
- for (i = 0; i < xxtlen; i++) {
- detxxt[i] *= 2.0;
- }
- xtxtlen = scale_expansion_zeroelim(xtlen, detxt, bextail, detxtxt);
- x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1);
- x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2);
- ylen = scale_expansion_zeroelim(temp192len, temp192, bey, dety);
- yylen = scale_expansion_zeroelim(ylen, dety, bey, detyy);
- ytlen = scale_expansion_zeroelim(temp192len, temp192, beytail, detyt);
- yytlen = scale_expansion_zeroelim(ytlen, detyt, bey, detyyt);
- for (i = 0; i < yytlen; i++) {
- detyyt[i] *= 2.0;
- }
- ytytlen = scale_expansion_zeroelim(ytlen, detyt, beytail, detytyt);
- y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1);
- y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2);
- zlen = scale_expansion_zeroelim(temp192len, temp192, bez, detz);
- zzlen = scale_expansion_zeroelim(zlen, detz, bez, detzz);
- ztlen = scale_expansion_zeroelim(temp192len, temp192, beztail, detzt);
- zztlen = scale_expansion_zeroelim(ztlen, detzt, bez, detzzt);
- for (i = 0; i < zztlen; i++) {
- detzzt[i] *= 2.0;
- }
- ztztlen = scale_expansion_zeroelim(ztlen, detzt, beztail, detztzt);
- z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1);
- z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2);
- xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy);
- blen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, bdet);
-
- temp32alen = scale_expansion_zeroelim(ablen, ab, -dez, temp32a);
- temp32blen = scale_expansion_zeroelim(ablen, ab, -deztail, temp32b);
- temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64a);
- temp32alen = scale_expansion_zeroelim(bdlen, bd, -aez, temp32a);
- temp32blen = scale_expansion_zeroelim(bdlen, bd, -aeztail, temp32b);
- temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64b);
- temp32alen = scale_expansion_zeroelim(dalen, da, -bez, temp32a);
- temp32blen = scale_expansion_zeroelim(dalen, da, -beztail, temp32b);
- temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64c);
- temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a,
- temp64blen, temp64b, temp128);
- temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c,
- temp128len, temp128, temp192);
- xlen = scale_expansion_zeroelim(temp192len, temp192, cex, detx);
- xxlen = scale_expansion_zeroelim(xlen, detx, cex, detxx);
- xtlen = scale_expansion_zeroelim(temp192len, temp192, cextail, detxt);
- xxtlen = scale_expansion_zeroelim(xtlen, detxt, cex, detxxt);
- for (i = 0; i < xxtlen; i++) {
- detxxt[i] *= 2.0;
- }
- xtxtlen = scale_expansion_zeroelim(xtlen, detxt, cextail, detxtxt);
- x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1);
- x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2);
- ylen = scale_expansion_zeroelim(temp192len, temp192, cey, dety);
- yylen = scale_expansion_zeroelim(ylen, dety, cey, detyy);
- ytlen = scale_expansion_zeroelim(temp192len, temp192, ceytail, detyt);
- yytlen = scale_expansion_zeroelim(ytlen, detyt, cey, detyyt);
- for (i = 0; i < yytlen; i++) {
- detyyt[i] *= 2.0;
- }
- ytytlen = scale_expansion_zeroelim(ytlen, detyt, ceytail, detytyt);
- y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1);
- y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2);
- zlen = scale_expansion_zeroelim(temp192len, temp192, cez, detz);
- zzlen = scale_expansion_zeroelim(zlen, detz, cez, detzz);
- ztlen = scale_expansion_zeroelim(temp192len, temp192, ceztail, detzt);
- zztlen = scale_expansion_zeroelim(ztlen, detzt, cez, detzzt);
- for (i = 0; i < zztlen; i++) {
- detzzt[i] *= 2.0;
- }
- ztztlen = scale_expansion_zeroelim(ztlen, detzt, ceztail, detztzt);
- z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1);
- z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2);
- xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy);
- clen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, cdet);
-
- temp32alen = scale_expansion_zeroelim(bclen, bc, aez, temp32a);
- temp32blen = scale_expansion_zeroelim(bclen, bc, aeztail, temp32b);
- temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64a);
- temp32alen = scale_expansion_zeroelim(aclen, ac, -bez, temp32a);
- temp32blen = scale_expansion_zeroelim(aclen, ac, -beztail, temp32b);
- temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64b);
- temp32alen = scale_expansion_zeroelim(ablen, ab, cez, temp32a);
- temp32blen = scale_expansion_zeroelim(ablen, ab, ceztail, temp32b);
- temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a,
- temp32blen, temp32b, temp64c);
- temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a,
- temp64blen, temp64b, temp128);
- temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c,
- temp128len, temp128, temp192);
- xlen = scale_expansion_zeroelim(temp192len, temp192, dex, detx);
- xxlen = scale_expansion_zeroelim(xlen, detx, dex, detxx);
- xtlen = scale_expansion_zeroelim(temp192len, temp192, dextail, detxt);
- xxtlen = scale_expansion_zeroelim(xtlen, detxt, dex, detxxt);
- for (i = 0; i < xxtlen; i++) {
- detxxt[i] *= 2.0;
- }
- xtxtlen = scale_expansion_zeroelim(xtlen, detxt, dextail, detxtxt);
- x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1);
- x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2);
- ylen = scale_expansion_zeroelim(temp192len, temp192, dey, dety);
- yylen = scale_expansion_zeroelim(ylen, dety, dey, detyy);
- ytlen = scale_expansion_zeroelim(temp192len, temp192, deytail, detyt);
- yytlen = scale_expansion_zeroelim(ytlen, detyt, dey, detyyt);
- for (i = 0; i < yytlen; i++) {
- detyyt[i] *= 2.0;
- }
- ytytlen = scale_expansion_zeroelim(ytlen, detyt, deytail, detytyt);
- y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1);
- y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2);
- zlen = scale_expansion_zeroelim(temp192len, temp192, dez, detz);
- zzlen = scale_expansion_zeroelim(zlen, detz, dez, detzz);
- ztlen = scale_expansion_zeroelim(temp192len, temp192, deztail, detzt);
- zztlen = scale_expansion_zeroelim(ztlen, detzt, dez, detzzt);
- for (i = 0; i < zztlen; i++) {
- detzzt[i] *= 2.0;
- }
- ztztlen = scale_expansion_zeroelim(ztlen, detzt, deztail, detztzt);
- z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1);
- z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2);
- xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy);
- dlen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, ddet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
- deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, deter);
-
- return deter[deterlen - 1];
-}
-
-REAL insphereadapt(pa, pb, pc, pd, pe, permanent)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
- REAL *pe;
- REAL permanent;
-{
- INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez;
- REAL det, errbound;
-
- INEXACT REAL aexbey1, bexaey1, bexcey1, cexbey1;
- INEXACT REAL cexdey1, dexcey1, dexaey1, aexdey1;
- INEXACT REAL aexcey1, cexaey1, bexdey1, dexbey1;
- REAL aexbey0, bexaey0, bexcey0, cexbey0;
- REAL cexdey0, dexcey0, dexaey0, aexdey0;
- REAL aexcey0, cexaey0, bexdey0, dexbey0;
- REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4];
- INEXACT REAL ab3, bc3, cd3, da3, ac3, bd3;
- REAL abeps, bceps, cdeps, daeps, aceps, bdeps;
- REAL temp8a[8], temp8b[8], temp8c[8], temp16[16], temp24[24], temp48[48];
- int temp8alen, temp8blen, temp8clen, temp16len, temp24len, temp48len;
- REAL xdet[96], ydet[96], zdet[96], xydet[192];
- int xlen, ylen, zlen, xylen;
- REAL adet[288], bdet[288], cdet[288], ddet[288];
- int alen, blen, clen, dlen;
- REAL abdet[576], cddet[576];
- int ablen, cdlen;
- REAL fin1[1152];
- int finlength;
-
- REAL aextail, bextail, cextail, dextail;
- REAL aeytail, beytail, ceytail, deytail;
- REAL aeztail, beztail, ceztail, deztail;
-
- INEXACT REAL bvirt;
- REAL avirt, bround, around;
- INEXACT REAL c;
- INEXACT REAL abig;
- REAL ahi, alo, bhi, blo;
- REAL err1, err2, err3;
- INEXACT REAL _i, _j;
- REAL _0;
-
- aex = (REAL) (pa[0] - pe[0]);
- bex = (REAL) (pb[0] - pe[0]);
- cex = (REAL) (pc[0] - pe[0]);
- dex = (REAL) (pd[0] - pe[0]);
- aey = (REAL) (pa[1] - pe[1]);
- bey = (REAL) (pb[1] - pe[1]);
- cey = (REAL) (pc[1] - pe[1]);
- dey = (REAL) (pd[1] - pe[1]);
- aez = (REAL) (pa[2] - pe[2]);
- bez = (REAL) (pb[2] - pe[2]);
- cez = (REAL) (pc[2] - pe[2]);
- dez = (REAL) (pd[2] - pe[2]);
-
- Two_Product(aex, bey, aexbey1, aexbey0);
- Two_Product(bex, aey, bexaey1, bexaey0);
- Two_Two_Diff(aexbey1, aexbey0, bexaey1, bexaey0, ab3, ab[2], ab[1], ab[0]);
- ab[3] = ab3;
-
- Two_Product(bex, cey, bexcey1, bexcey0);
- Two_Product(cex, bey, cexbey1, cexbey0);
- Two_Two_Diff(bexcey1, bexcey0, cexbey1, cexbey0, bc3, bc[2], bc[1], bc[0]);
- bc[3] = bc3;
-
- Two_Product(cex, dey, cexdey1, cexdey0);
- Two_Product(dex, cey, dexcey1, dexcey0);
- Two_Two_Diff(cexdey1, cexdey0, dexcey1, dexcey0, cd3, cd[2], cd[1], cd[0]);
- cd[3] = cd3;
-
- Two_Product(dex, aey, dexaey1, dexaey0);
- Two_Product(aex, dey, aexdey1, aexdey0);
- Two_Two_Diff(dexaey1, dexaey0, aexdey1, aexdey0, da3, da[2], da[1], da[0]);
- da[3] = da3;
-
- Two_Product(aex, cey, aexcey1, aexcey0);
- Two_Product(cex, aey, cexaey1, cexaey0);
- Two_Two_Diff(aexcey1, aexcey0, cexaey1, cexaey0, ac3, ac[2], ac[1], ac[0]);
- ac[3] = ac3;
-
- Two_Product(bex, dey, bexdey1, bexdey0);
- Two_Product(dex, bey, dexbey1, dexbey0);
- Two_Two_Diff(bexdey1, bexdey0, dexbey1, dexbey0, bd3, bd[2], bd[1], bd[0]);
- bd[3] = bd3;
-
- temp8alen = scale_expansion_zeroelim(4, cd, bez, temp8a);
- temp8blen = scale_expansion_zeroelim(4, bd, -cez, temp8b);
- temp8clen = scale_expansion_zeroelim(4, bc, dez, temp8c);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
- temp8blen, temp8b, temp16);
- temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
- temp16len, temp16, temp24);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, aex, temp48);
- xlen = scale_expansion_zeroelim(temp48len, temp48, -aex, xdet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, aey, temp48);
- ylen = scale_expansion_zeroelim(temp48len, temp48, -aey, ydet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, aez, temp48);
- zlen = scale_expansion_zeroelim(temp48len, temp48, -aez, zdet);
- xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
- alen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, adet);
-
- temp8alen = scale_expansion_zeroelim(4, da, cez, temp8a);
- temp8blen = scale_expansion_zeroelim(4, ac, dez, temp8b);
- temp8clen = scale_expansion_zeroelim(4, cd, aez, temp8c);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
- temp8blen, temp8b, temp16);
- temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
- temp16len, temp16, temp24);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, bex, temp48);
- xlen = scale_expansion_zeroelim(temp48len, temp48, bex, xdet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, bey, temp48);
- ylen = scale_expansion_zeroelim(temp48len, temp48, bey, ydet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, bez, temp48);
- zlen = scale_expansion_zeroelim(temp48len, temp48, bez, zdet);
- xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
- blen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, bdet);
-
- temp8alen = scale_expansion_zeroelim(4, ab, dez, temp8a);
- temp8blen = scale_expansion_zeroelim(4, bd, aez, temp8b);
- temp8clen = scale_expansion_zeroelim(4, da, bez, temp8c);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
- temp8blen, temp8b, temp16);
- temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
- temp16len, temp16, temp24);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, cex, temp48);
- xlen = scale_expansion_zeroelim(temp48len, temp48, -cex, xdet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, cey, temp48);
- ylen = scale_expansion_zeroelim(temp48len, temp48, -cey, ydet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, cez, temp48);
- zlen = scale_expansion_zeroelim(temp48len, temp48, -cez, zdet);
- xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
- clen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, cdet);
-
- temp8alen = scale_expansion_zeroelim(4, bc, aez, temp8a);
- temp8blen = scale_expansion_zeroelim(4, ac, -bez, temp8b);
- temp8clen = scale_expansion_zeroelim(4, ab, cez, temp8c);
- temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
- temp8blen, temp8b, temp16);
- temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
- temp16len, temp16, temp24);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, dex, temp48);
- xlen = scale_expansion_zeroelim(temp48len, temp48, dex, xdet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, dey, temp48);
- ylen = scale_expansion_zeroelim(temp48len, temp48, dey, ydet);
- temp48len = scale_expansion_zeroelim(temp24len, temp24, dez, temp48);
- zlen = scale_expansion_zeroelim(temp48len, temp48, dez, zdet);
- xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
- dlen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, ddet);
-
- ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
- cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
- finlength = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, fin1);
-
- det = estimate(finlength, fin1);
- errbound = isperrboundB * permanent;
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- Two_Diff_Tail(pa[0], pe[0], aex, aextail);
- Two_Diff_Tail(pa[1], pe[1], aey, aeytail);
- Two_Diff_Tail(pa[2], pe[2], aez, aeztail);
- Two_Diff_Tail(pb[0], pe[0], bex, bextail);
- Two_Diff_Tail(pb[1], pe[1], bey, beytail);
- Two_Diff_Tail(pb[2], pe[2], bez, beztail);
- Two_Diff_Tail(pc[0], pe[0], cex, cextail);
- Two_Diff_Tail(pc[1], pe[1], cey, ceytail);
- Two_Diff_Tail(pc[2], pe[2], cez, ceztail);
- Two_Diff_Tail(pd[0], pe[0], dex, dextail);
- Two_Diff_Tail(pd[1], pe[1], dey, deytail);
- Two_Diff_Tail(pd[2], pe[2], dez, deztail);
- if ((aextail == 0.0) && (aeytail == 0.0) && (aeztail == 0.0)
- && (bextail == 0.0) && (beytail == 0.0) && (beztail == 0.0)
- && (cextail == 0.0) && (ceytail == 0.0) && (ceztail == 0.0)
- && (dextail == 0.0) && (deytail == 0.0) && (deztail == 0.0)) {
- return det;
- }
-
- errbound = isperrboundC * permanent + resulterrbound * Absolute(det);
- abeps = (aex * beytail + bey * aextail)
- - (aey * bextail + bex * aeytail);
- bceps = (bex * ceytail + cey * bextail)
- - (bey * cextail + cex * beytail);
- cdeps = (cex * deytail + dey * cextail)
- - (cey * dextail + dex * ceytail);
- daeps = (dex * aeytail + aey * dextail)
- - (dey * aextail + aex * deytail);
- aceps = (aex * ceytail + cey * aextail)
- - (aey * cextail + cex * aeytail);
- bdeps = (bex * deytail + dey * bextail)
- - (bey * dextail + dex * beytail);
- det += (((bex * bex + bey * bey + bez * bez)
- * ((cez * daeps + dez * aceps + aez * cdeps)
- + (ceztail * da3 + deztail * ac3 + aeztail * cd3))
- + (dex * dex + dey * dey + dez * dez)
- * ((aez * bceps - bez * aceps + cez * abeps)
- + (aeztail * bc3 - beztail * ac3 + ceztail * ab3)))
- - ((aex * aex + aey * aey + aez * aez)
- * ((bez * cdeps - cez * bdeps + dez * bceps)
- + (beztail * cd3 - ceztail * bd3 + deztail * bc3))
- + (cex * cex + cey * cey + cez * cez)
- * ((dez * abeps + aez * bdeps + bez * daeps)
- + (deztail * ab3 + aeztail * bd3 + beztail * da3))))
- + 2.0 * (((bex * bextail + bey * beytail + bez * beztail)
- * (cez * da3 + dez * ac3 + aez * cd3)
- + (dex * dextail + dey * deytail + dez * deztail)
- * (aez * bc3 - bez * ac3 + cez * ab3))
- - ((aex * aextail + aey * aeytail + aez * aeztail)
- * (bez * cd3 - cez * bd3 + dez * bc3)
- + (cex * cextail + cey * ceytail + cez * ceztail)
- * (dez * ab3 + aez * bd3 + bez * da3)));
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- return insphereexact(pa, pb, pc, pd, pe);
-}
-
-REAL insphere(pa, pb, pc, pd, pe)
- REAL *pa;
- REAL *pb;
- REAL *pc;
- REAL *pd;
- REAL *pe;
-{
- REAL aex, bex, cex, dex;
- REAL aey, bey, cey, dey;
- REAL aez, bez, cez, dez;
- REAL aexbey, bexaey, bexcey, cexbey, cexdey, dexcey, dexaey, aexdey;
- REAL aexcey, cexaey, bexdey, dexbey;
- REAL alift, blift, clift, dlift;
- REAL ab, bc, cd, da, ac, bd;
- REAL abc, bcd, cda, dab;
- REAL aezplus, bezplus, cezplus, dezplus;
- REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus;
- REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus;
- REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus;
- REAL det;
- REAL permanent, errbound;
-
- aex = pa[0] - pe[0];
- bex = pb[0] - pe[0];
- cex = pc[0] - pe[0];
- dex = pd[0] - pe[0];
- aey = pa[1] - pe[1];
- bey = pb[1] - pe[1];
- cey = pc[1] - pe[1];
- dey = pd[1] - pe[1];
- aez = pa[2] - pe[2];
- bez = pb[2] - pe[2];
- cez = pc[2] - pe[2];
- dez = pd[2] - pe[2];
-
- aexbey = aex * bey;
- bexaey = bex * aey;
- ab = aexbey - bexaey;
- bexcey = bex * cey;
- cexbey = cex * bey;
- bc = bexcey - cexbey;
- cexdey = cex * dey;
- dexcey = dex * cey;
- cd = cexdey - dexcey;
- dexaey = dex * aey;
- aexdey = aex * dey;
- da = dexaey - aexdey;
-
- aexcey = aex * cey;
- cexaey = cex * aey;
- ac = aexcey - cexaey;
- bexdey = bex * dey;
- dexbey = dex * bey;
- bd = bexdey - dexbey;
-
- abc = aez * bc - bez * ac + cez * ab;
- bcd = bez * cd - cez * bd + dez * bc;
- cda = cez * da + dez * ac + aez * cd;
- dab = dez * ab + aez * bd + bez * da;
-
- alift = aex * aex + aey * aey + aez * aez;
- blift = bex * bex + bey * bey + bez * bez;
- clift = cex * cex + cey * cey + cez * cez;
- dlift = dex * dex + dey * dey + dez * dez;
-
- det = (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
-
- aezplus = Absolute(aez);
- bezplus = Absolute(bez);
- cezplus = Absolute(cez);
- dezplus = Absolute(dez);
- aexbeyplus = Absolute(aexbey);
- bexaeyplus = Absolute(bexaey);
- bexceyplus = Absolute(bexcey);
- cexbeyplus = Absolute(cexbey);
- cexdeyplus = Absolute(cexdey);
- dexceyplus = Absolute(dexcey);
- dexaeyplus = Absolute(dexaey);
- aexdeyplus = Absolute(aexdey);
- aexceyplus = Absolute(aexcey);
- cexaeyplus = Absolute(cexaey);
- bexdeyplus = Absolute(bexdey);
- dexbeyplus = Absolute(dexbey);
- permanent = ((cexdeyplus + dexceyplus) * bezplus
- + (dexbeyplus + bexdeyplus) * cezplus
- + (bexceyplus + cexbeyplus) * dezplus)
- * alift
- + ((dexaeyplus + aexdeyplus) * cezplus
- + (aexceyplus + cexaeyplus) * dezplus
- + (cexdeyplus + dexceyplus) * aezplus)
- * blift
- + ((aexbeyplus + bexaeyplus) * dezplus
- + (bexdeyplus + dexbeyplus) * aezplus
- + (dexaeyplus + aexdeyplus) * bezplus)
- * clift
- + ((bexceyplus + cexbeyplus) * aezplus
- + (cexaeyplus + aexceyplus) * bezplus
- + (aexbeyplus + bexaeyplus) * cezplus)
- * dlift;
- errbound = isperrboundA * permanent;
- if ((det > errbound) || (-det > errbound)) {
- return det;
- }
-
- return insphereadapt(pa, pb, pc, pd, pe, permanent);
-}
\ No newline at end of file
diff --git a/lib/ext/predicates.h b/lib/ext/predicates.h
deleted file mode 100644
index 95bedae..0000000
--- a/lib/ext/predicates.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * ##### # # # *
- * #### ##### ###### # # # # # # # *
- * # # # # # ## # # # # # *
- * # # # # ##### # # # # #### # ### *
- * # # ##### # # # # # # # # # # *
- * # # # # # ## # # # # # # *
- * #### # ###### # # ##### ##### # # *
- * *
- * This file is part of openGJK. *
- * *
- * openGJK 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 *
- * any later version. *
- * *
- * openGJK 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 Foobar. If not, see . *
- * *
- * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
- * Copyright (C) Mattia Montanari 2018 - 2019 *
- * http://iel.eng.ox.ac.uk/?page_id=504 *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-#include
-#include
-
-#ifndef CGJK_PREDICATES_H
-#define CGJK_PREDICATES_H
-
-#endif //CGJK_PREDICATES_H
-
-extern double orient3d(
- double *pa,
- double *pb,
- double *pc,
- double *pd
-);
-
-extern double orient2d(
- double *pa,
- double *pb,
- double *pc
-);
-
-extern void exactinit();
diff --git a/lib/include/openGJK/openGJK.h b/lib/include/openGJK/openGJK.h
deleted file mode 100644
index 6d96ef6..0000000
--- a/lib/include/openGJK/openGJK.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * ##### # # # *
- * #### ##### ###### # # # # # # # *
- * # # # # # ## # # # # # *
- * # # # # ##### # # # # #### # ### *
- * # # ##### # # # # # # # # # # *
- * # # # # # ## # # # # # # *
- * #### # ###### # # ##### ##### # # *
- * *
- * This file is part of openGJK. *
- * *
- * openGJK 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 *
- * any later version. *
- * *
- * openGJK 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 Foobar. If not, see . *
- * *
- * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
- * Copyright (C) Mattia Montanari 2018 - 2019 *
- * http://iel.eng.ox.ac.uk/?page_id=504 *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * *
- * This is the header file for the openGJK.c file. It defines the *
- * openGJK function and its structures. *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-#ifndef __OPENGJK_H__
-#define __OPENGJK_H__
-
-#include
-#include
-#include "math.h"
-
-
-/**
- * @brief Macro that implements the CompareSign function (see paper).
- */
- #define SAMESIGN( a, b ) ( (a>0) == (b>0) )
-
-
-/**
- * @brief Structure of a body.
- */
-struct bd {
- int numpoints; /**< Number of points defining the body. */
- double **coord; /**< Pointer to pointer to the points' coordinates. */
- double s [3]; /**< Support mapping computed last. */
-};
-
-
-
-
-/**
- * @brief Structure for a simplex.
- */
-struct simplex {
- int nvrtx ; /**< Number of simplex's vertices. */
- double vrtx [4][3]; /**< Coordinates of simplex's vertices. */
- int wids [4]; /**< Label of the simplex's vertices. */
- double lambdas [4]; /**< Barycentric coordiantes for each vertex. */
- double p [4][3]; /**< Points of P that form the simplex */
- double q [4][3]; /**< Points of Q that form the simplex */
-};
-
-
-
-
-/**
- * @brief The GJK algorithm which returns the minimum distance between
- * two bodies.
- */
-extern double gjk( struct bd, struct bd, struct simplex * ) ;
-
-#endif
\ No newline at end of file
diff --git a/lib/src/openGJK.c b/lib/src/openGJK.c
deleted file mode 100644
index 18d383e..0000000
--- a/lib/src/openGJK.c
+++ /dev/null
@@ -1,1009 +0,0 @@
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * ##### # # # *
- * #### ##### ###### # # # # # # # *
- * # # # # # ## # # # # # *
- * # # # # ##### # # # # #### # ### *
- * # # ##### # # # # # # # # # # *
- * # # # # # ## # # # # # # *
- * #### # ###### # # ##### ##### # # *
- * *
- * This file is part of openGJK. *
- * *
- * openGJK 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 *
- * any later version. *
- * *
- * openGJK 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 Foobar. If not, see . *
- * *
- * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
- * Copyright (C) Mattia Montanari 2018 - 2019 *
- * http://iel.eng.ox.ac.uk/?page_id=504 *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- * *
- * This file implements the GJK algorithm and the Signed Volumes method as*
- * presented in: *
- * M. Montanari, N. Petrinic, E. Barbieri, "Improving the GJK Algorithm *
- * for Faster and More Reliable Distance Queries Between Convex Objects"*
- * ACM Transactions on Graphics, vol. 36, no. 3, Jun. 2017. *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/**
- * @file openGJK.c
- * @author Mattia Montanari
- * @date April 2018
- * @brief File containing entire implementation of the GJK algorithm.
- *
- */
-
-#define _CRT_HAS_CXX17 0
-#include
-#include "openGJK/openGJK.h"
-
-/* If instricuted, uses adaptive floating point arithmetics. */
-#ifdef ADAPTIVEFP
-#include "predicates.h"
-#endif
-
-/* If instricuted, compile a mex function for Matlab. */
-#ifdef MATLABDOESMEXSTUFF
- #include "mex.h"
-#else
- #define mexPrintf printf
-#endif
-
-#ifdef unix
- #define _isnan(x) isnan(x)
-#endif
-
-#define dotProduct(a, b) (a[0]*b[0]+a[1]*b[1]+a[2]*b[2])
-
-/**
- * @brief Returns squared vector norm
- */
-double norm2(double *v) {
- double n2 = 0;
- for (int i = 0; i < 3; ++i)
- n2 += v[i] * v[i];
- return n2;
-}
-
-/**
- * @brief Finds point of minimum norm of 1-simplex. Robust, but slower, version of algorithm presented in paper.
- */
-inline static void S1D(struct simplex * s, double *vv) {
- int i = 0;
- int indexI = 1;
- int FacetsTest[2];
- double det_ap = 0;
- double det_pb = 0;
- double pt = 0;
- double leng = 0;
- double a[3];
- double b[3];
- double t[3];
- double nu_fabs[3];
-
- for (i = 0; i < 3; ++i) {
- b[i] = s->vrtx[0][i];
- a[i] = s->vrtx[1][i];
- t[i] = b[i] - a[i];
- leng += t[i];
- nu_fabs[i] = fabs(t[i]);
- }
-
- if (nu_fabs[0] > nu_fabs[1]) {
- if (nu_fabs[0] > nu_fabs[2])
- indexI = 0;
- else
- indexI = 2;
- }
- else if (nu_fabs[0] < nu_fabs[1]) {
- if (nu_fabs[1] > nu_fabs[2])
- indexI = 1;
- else
- indexI = 2;
- }
- else if (nu_fabs[0] < nu_fabs[2]) {
- indexI = 2;
- }
- else if (nu_fabs[1] < nu_fabs[2]) {
- indexI = 2;
- }
-
- /* Project origin onto the 1D simplex - line */
- pt = dotProduct(b, t) / (dotProduct(t, t)) * (a[indexI] - b[indexI]) + b[indexI];
-
- /* Compute signed determinants */
- det_ap = a[indexI] - pt;
- det_pb = pt - b[indexI];
-
- /* Compare signs of AB and auxiliary simplices */
- FacetsTest[0] = SAMESIGN(t[indexI], -1 * det_ap);
- FacetsTest[1] = SAMESIGN(t[indexI], -1 * det_pb);
-
- if (FacetsTest[0] + FacetsTest[1] == 2) {
- /* The origin is between A and B */
- s->lambdas[0] = det_ap * -1.0 / t[indexI];
- s->lambdas[1] = 1 - s->lambdas[0];
- s->wids[0] = 0;
- s->wids[1] = 1;
- s->nvrtx = 2;
- }
- else if (FacetsTest[0] == 0) {
- /* The origin is beyond A */
- s->lambdas[0] = 1;
- s->wids[0] = 0;
- s->nvrtx = 1;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[1][i];
- }
- }
- else {
- /* The origin is behind B */
- s->lambdas[0] = 1;
- s->wids[0] = 1;
- s->nvrtx = 1;
- }
-
- for (int j = 0; j < 3; ++j) {
- vv[j] = 0;
- for (i = 0; i < s->nvrtx; ++i) {
- vv[j] += (s->lambdas[i] * s->vrtx[i][j]);
- }
- }
-}
-
-/**
- * @brief Finds point of minimum norm of 2-simplex. Robust, but slower, version of algorithm presented in paper.
- */
-inline static void S2D(struct simplex * s, double *vv) {
- int i;
- int k;
- int l;
- int j;
- int indexI = 1;
- //int stemp[3];
- int FacetsTest[3];
- int indexJ[2] = { -1 };
- double nu_max = 0;
- double inv_detM = 0;
- double nnorm_sqrd = 0;
- double nnnorm = 0;
- double dotNA;
- double a[3];
- double b[3];
- double c[3];
- double s21[3];
- double s31[3];
- double nu_test[3];
- double nu_fabs[3];
- double B[3];
- double n[3];
- double v[3];
- double vtmp[3];
- double pp[3 - 1];
- double sa[3 - 1];
- double sb[3 - 1];
- double sc[3 - 1];
-
-
- for (i = 0; i < 3; ++i) {
- c[i] = s->vrtx[0][i];
- b[i] = s->vrtx[1][i];
- a[i] = s->vrtx[2][i];
- s21[i] = b[i] - a[i];
- s31[i] = c[i] - a[i];
- }
-
- /* Find best axis for projection */
- k = 1; l = 2;
- for (i = 0; i < 3; ++i) {
- nu_test[i] = pow(-1.0, i) * (b[k] * c[l] + a[k] * b[l] + c[k] * a[l] - b[k] * a[l] - c[k] * b[l] - a[k] * c[l]);
- k = l; l = i;
- }
-
- for (i = 0; i < 3; ++i) {
- nu_fabs[i] = fabs(nu_test[i]);
- }
-
- if (nu_fabs[0] > nu_fabs[1]) {
- if (nu_fabs[0] > nu_fabs[2]) {
- indexI = 0;
- indexJ[0] = 1;
- indexJ[1] = 2;
- }
- else {
- indexJ[0] = 0;
- indexJ[1] = 1;
- indexI = 2;
- }
- }
- else if (nu_fabs[0] < nu_fabs[1]) {
- if (nu_fabs[1] > nu_fabs[2]) {
- indexJ[0] = 0;
- indexI = 1;
- indexJ[1] = 2;
- }
- else {
- indexJ[0] = 0;
- indexJ[1] = 1;
- indexI = 2;
- }
- }
- else if (nu_fabs[0] < nu_fabs[2]) {
- indexJ[0] = 0;
- indexJ[1] = 1;
- indexI = 2;
- }
-
- nu_max = nu_test[indexI];
-
- k = 1; l = 2;
- for (i = 0; i < 3; ++i) {
- n[i] = s21[k] * s31[l] - s21[l] * s31[k];
- nnorm_sqrd += n[i] * n[i];
- k = l; l = i;
- }
- nnnorm = 1 / sqrt(nnorm_sqrd);
- for (i = 0; i < 3; ++i) {
- n[i] = n[i] * nnnorm;
- }
-
- dotNA = dotProduct(n, a);
-
- pp[0] = dotNA * n[indexJ[0]];
- pp[1] = dotNA * n[indexJ[1]];
-
- /* Compute signed determinants */
-#ifndef ADAPTIVEFP
- double ss[3][3 - 1];
-
- ss[0][0] = sa[0] = a[indexJ[0]];
- ss[0][1] = sa[1] = a[indexJ[1]];
- ss[1][0] = sb[0] = b[indexJ[0]];
- ss[1][1] = sb[1] = b[indexJ[1]];
- ss[2][0] = sc[0] = c[indexJ[0]];
- ss[2][1] = sc[1] = c[indexJ[1]];
-
- k = 1; l = 2;
- for (i = 0; i < 3; ++i) {
- B[i] = pp[0] * ss[k][1] + pp[1] * ss[l][0] + ss[k][0] * ss[l][1] - pp[0] * ss[l][1] - pp[1] * ss[k][0] -
- ss[l][0] * ss[k][1];
- k = l;
- l = i;
- }
-#else
-
- sa[0] = a[indexJ[0]];
- sa[1] = a[indexJ[1]];
- sb[0] = b[indexJ[0]];
- sb[1] = b[indexJ[1]];
- sc[0] = c[indexJ[0]];
- sc[1] = c[indexJ[1]];
-
- B[0] = orient2d(sa, pp, sc);
- B[1] = orient2d(sa, pp, sc);
- B[2] = orient2d(sa, sb, pp);
-#endif
-
- /* Test if sign of ABC is equal to the signes of the auxiliary simplices */
- for (i = 0; i < 3; ++i) {
- FacetsTest[i] = SAMESIGN(nu_max, B[i]);
- }
-
- // The nan check was not included originally and will be removed in v2.0
- if (FacetsTest[1] + FacetsTest[2] == 0 || isnan(n[0])) {
- struct simplex sTmp;
-
- sTmp.nvrtx = 2;
- s->nvrtx = 2;
- for (i = 0; i < 3; ++i) {
-
- sTmp.vrtx[0][i] = s->vrtx[1][i];
- sTmp.vrtx[1][i] = s->vrtx[2][i];
-
- s->vrtx[0][i] = s->vrtx[0][i];
- s->vrtx[1][i] = s->vrtx[2][i];
- }
-
- S1D(&sTmp, v);
- S1D(s, v);
-
- for (j = 0; j < 3; ++j) {
- vtmp[j] = 0;
- v[j] = 0;
- for (i = 0; i < sTmp.nvrtx; ++i) {
- vtmp[j] += (sTmp.lambdas[i] * sTmp.vrtx[i][j]);
- v[j] += (s->lambdas[i] * s->vrtx[i][j]);
- }
- }
-
- if (dotProduct(v, v) < dotProduct(vtmp, vtmp)) {
- /* Keep simplex. Need to update sID only*/
- for (i = 1; i < s->nvrtx; ++i) {
- s->wids[i] = s->wids[i] + 1;
- }
- }
- else {
- s->nvrtx = sTmp.nvrtx;
- for (j = 0; j < 3; ++j) {
- for (i = 0; i < s->nvrtx; ++i) {
- s->vrtx[i][j] = s->vrtx[i][j];
- s->lambdas[i] = sTmp.lambdas[i];
- /* No need to convert sID here since sTmp deal with the vertices A and B. ;*/
- s->wids[i] = sTmp.wids[i];
- }
- }
- }
- }
- else if ((FacetsTest[0] + FacetsTest[1] + FacetsTest[2]) == 3) {
- /* The origin projections lays onto the triangle */
- inv_detM = 1 / nu_max;
- s->lambdas[0] = B[2] * inv_detM;
- s->lambdas[1] = B[1] * inv_detM;
- s->lambdas[2] = 1 - s->lambdas[0] - s->lambdas[1];
- s->wids[0] = 0;
- s->wids[1] = 1;
- s->wids[2] = 2;
- s->nvrtx = 3;
- }
- else if (FacetsTest[2] == 0) {
- /* The origin projection P faces the segment AB */
- s->nvrtx = 2;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[1][i];
- s->vrtx[1][i] = s->vrtx[2][i];
- }
- S1D(s, v);
- }
- else if (FacetsTest[1] == 0) {
- /* The origin projection P faces the segment AC */
- s->nvrtx = 2;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[0][i];
- s->vrtx[1][i] = s->vrtx[2][i];
- }
- S1D(s, v);
- for (i = 1; i < s->nvrtx; ++i) {
- s->wids[i] = s->wids[i] + 1;
- }
- }
- else {
- /* The origin projection P faces the segment BC */
- s->nvrtx = 2;
- S1D(s, v);
-
- }
-
- for ( j = 0; j < 3; ++j) {
- vv[j] = 0;
- for (i = 0; i < s->nvrtx; ++i) {
- vv[j] += (s->lambdas[i] * s->vrtx[i][j]);
- }
- }
-}
-
-/**
- * @brief Finds point of minimum norm of 3-simplex. Robust, but slower, version of algorithm presented in paper.
- */
-inline static void S3D(struct simplex * s, double *vv) {
- int FacetsTest[4] = { 1,1,1,1 };
- int sID[4] = { 0, 0, 0, 0 };
- int TrianglesToTest[9] = { 3, 3, 3, 1, 2, 2, 0, 0, 1 };
- int i;
- int j;
- int k;
- int l;
- int vtxid;
- int ndoubts = 0;
- int nclosestS = 0;
- int firstaux = 0;
- int secondaux = 0;
- int Flag_sAuxused = 0;
- double a[3];
- double b[3];
- double c[3];
- double d[3];
- double vtmp[3];
- double v[3];
- double B[4];
- double tmplamda[4] = { 0, 0, 0, 0 };
- double tmpscoo1[4][3] = { 0 };
- double sqdist_tmp = 0;
- double detM;
- double inv_detM;
-#ifdef ADAPTIVEFP
- double o[3] = { 0 };
-#endif
- for (i = 0; i < 3; ++i) {
- d[i] = s->vrtx[0][i];
- c[i] = s->vrtx[1][i];
- b[i] = s->vrtx[2][i];
- a[i] = s->vrtx[3][i];
- }
-
-#ifndef ADAPTIVEFP
- B[0] = -1 * (b[0] * c[1] * d[2] + b[1] * c[2] * d[0] + b[2] * c[0] * d[1] - b[2] * c[1] * d[0] - b[1] * c[0] * d[2] - b[0] * c[2] * d[1]);
- B[1] = +1 * (a[0] * c[1] * d[2] + a[1] * c[2] * d[0] + a[2] * c[0] * d[1] - a[2] * c[1] * d[0] - a[1] * c[0] * d[2] - a[0] * c[2] * d[1]);
- B[2] = -1 * (a[0] * b[1] * d[2] + a[1] * b[2] * d[0] + a[2] * b[0] * d[1] - a[2] * b[1] * d[0] - a[1] * b[0] * d[2] - a[0] * b[2] * d[1]);
- B[3] = +1 * (a[0] * b[1] * c[2] + a[1] * b[2] * c[0] + a[2] * b[0] * c[1] - a[2] * b[1] * c[0] - a[1] * b[0] * c[2] - a[0] * b[2] * c[1]);
- detM = B[0] + B[1] + B[2] + B[3];
-#else
- B[0] = orient3d(o, b, c, d);
- B[1] = orient3d(a, o, c, d);
- B[2] = orient3d(a, b, o, d);
- B[3] = orient3d(a, b, c, o);
- detM = orient3d(a, b, c, d);
-#endif
-
- /* Test if sign of ABCD is equal to the signes of the auxiliary simplices */
- double eps = 1e-13;
- if (fabs(detM) < eps)
- {
- if (fabs(B[2]) < eps && fabs(B[3]) < eps)
- FacetsTest[1] = 0; /* A = B. Test only ACD */
- else if (fabs(B[1]) < eps && fabs(B[3]) < eps)
- FacetsTest[2] = 0; /* A = C. Test only ABD */
- else if (fabs(B[1]) < eps && fabs(B[2]) < eps)
- FacetsTest[3] = 0; /* A = D. Test only ABC */
- else if (fabs(B[0]) < eps && fabs(B[3]) < eps)
- FacetsTest[1] = 0; /* B = C. Test only ACD */
- else if (fabs(B[0]) < eps && fabs(B[2]) < eps)
- FacetsTest[1] = 0; /* B = D. Test only ABD */
- else if (fabs(B[0]) < eps && fabs(B[1]) < eps)
- FacetsTest[2] = 0; /* C = D. Test only ABC */
- else {
- for (i = 0; i < 4; i++)
- FacetsTest[i] = 0; /* Any other case. Test ABC, ABD, ACD */
- }
- }
- else
- {
- for (i = 0; i < 4; ++i)
- FacetsTest[i] = SAMESIGN(detM, B[i]);
- }
-
- /* Compare signed volumes and compute barycentric coordinates */
- if (FacetsTest[0] + FacetsTest[1] + FacetsTest[2] + FacetsTest[3] == 4) {
- /* All signs are equal, therefore the origin is inside the simplex */
- inv_detM = 1 / detM;
- s->lambdas[3] = B[0] * inv_detM;
- s->lambdas[2] = B[1] * inv_detM;
- s->lambdas[1] = B[2] * inv_detM;
- s->lambdas[0] = 1 - s->lambdas[1] - s->lambdas[2] - s->lambdas[3];
- s->wids[0] = 0;
- s->wids[1] = 1;
- s->wids[2] = 2;
- s->wids[3] = 3;
- s->nvrtx = 4;
- }
- else if (FacetsTest[1] + FacetsTest[2] + FacetsTest[3] == 0) {
- /* There are three facets facing the origin */
- ndoubts = 3;
-
- struct simplex sTmp;
-
- for (i = 0; i < ndoubts; ++i) {
- sTmp.nvrtx = 3;
- /* Assign coordinates to simplex */
- for (k = 0; k < sTmp.nvrtx; ++k) {
- vtxid = TrianglesToTest[i + (k * 3)];
- for (j = 0; j < 3; ++j) {
- sTmp.vrtx[2 - k][j] = s->vrtx[vtxid][j];
- }
- }
- /* ... and call S2D */
- S2D(&sTmp, v);
- /* ... compute aux squared distance */
- for (j = 0; j < 3; ++j) {
- vtmp[j] = 0;
- for (l = 0; l < sTmp.nvrtx; ++l) {
- vtmp[j] += sTmp.lambdas[l] * (sTmp.vrtx[l][j]);
- }
- }
-
- if (i == 0) {
- sqdist_tmp = dotProduct(vtmp, vtmp);
- nclosestS = sTmp.nvrtx;
- for (l = 0; l < nclosestS; ++l) {
- sID[l] = TrianglesToTest[i + (sTmp.wids[l] * 3)];
- tmplamda[l] = sTmp.lambdas[l];
- }
- }
- else if (dotProduct(vtmp, vtmp) < sqdist_tmp) {
- sqdist_tmp = dotProduct(vtmp, vtmp);
- nclosestS = sTmp.nvrtx;
- for (l = 0; l < nclosestS; ++l) {
- sID[l] = TrianglesToTest[i + (sTmp.wids[l] * 3)];
- tmplamda[l] = sTmp.lambdas[l];
- }
- }
- }
-
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 3; ++j) {
- tmpscoo1[i][j] = s->vrtx[i][j];
- }
- }
-
- /* Store closest simplex */
- s->nvrtx = nclosestS;
- for (i = 0; i < s->nvrtx; ++i) {
- for (j = 0; j < 3; ++j) {
- s->vrtx[nclosestS - 1 - i][j] = tmpscoo1[sID[i]][j];
- }
- s->lambdas[i] = tmplamda[i];
- s->wids[nclosestS - 1 - i] = sID[i];
- }
- }
- else if (FacetsTest[1] + FacetsTest[2] + FacetsTest[3] == 1) {
- /* There are two facets facing the origin, need to find the closest. */
- struct simplex sTmp;
- sTmp.nvrtx = 3;
-
- if (FacetsTest[1] == 0) {
- /* ... Test facet ACD */
- for (i = 0; i < 3; ++i) {
- sTmp.vrtx[0][i] = s->vrtx[0][i];
- sTmp.vrtx[1][i] = s->vrtx[1][i];
- sTmp.vrtx[2][i] = s->vrtx[3][i];
- }
- /* ... and call S2D */
- S2D(&sTmp, v);
- /* ... compute aux squared distance */
- for (j = 0; j < 3; ++j) {
- vtmp[j] = 0;
- for (i = 0; i < sTmp.nvrtx; ++i) {
- vtmp[j] += sTmp.lambdas[i] * (sTmp.vrtx[i][j]);
- }
- }
- sqdist_tmp = dotProduct(vtmp, vtmp);
- Flag_sAuxused = 1;
- firstaux = 0;
- }
- if (FacetsTest[2] == 0) {
- /* ... Test facet ABD */
- if (Flag_sAuxused == 0) {
-
- for (i = 0; i < 3; ++i) {
- sTmp.vrtx[0][i] = s->vrtx[0][i];
- sTmp.vrtx[1][i] = s->vrtx[2][i];
- sTmp.vrtx[2][i] = s->vrtx[3][i];
- }
- /* ... and call S2D */
- S2D(&sTmp, v);
- /* ... compute aux squared distance */
- for (j = 0; j < 3; ++j) {
- vtmp[j] = 0;
- for (i = 0; i < sTmp.nvrtx; ++i) {
- vtmp[j] += sTmp.lambdas[i] * (sTmp.vrtx[i][j]);
- }
- }
- sqdist_tmp = dotProduct(vtmp, vtmp);
- firstaux = 1;
- }
- else {
- s->nvrtx = 3;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[0][i];
- s->vrtx[1][i] = s->vrtx[2][i];
- s->vrtx[2][i] = s->vrtx[3][i];
- }
- /* ... and call S2D itself */
- S2D(s, v);
- secondaux = 1;
- }
- }
-
- if (FacetsTest[3] == 0) {
- /* ... Test facet ABC */
- s->nvrtx = 3;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[1][i];
- s->vrtx[1][i] = s->vrtx[2][i];
- s->vrtx[2][i] = s->vrtx[3][i];
- }
- /* ... and call S2D */
- S2D(s, v);
- secondaux = 2;
- }
- /* Compare outcomes */
- for (j = 0; j < 3; ++j) {
- v[j] = 0;
- for (i = 0; i < s->nvrtx; ++i) {
- v[j] += s->lambdas[i] * (s->vrtx[i][j]);
- }
- }
- if (dotProduct(v, v) < sqdist_tmp) {
- /* Keep simplex. Need to update sID only*/
- for (i = 0; i < s->nvrtx; ++i) {
- /* Assume that vertex a is always included in sID. */
- s->wids[s->nvrtx - 1 - i] = TrianglesToTest[secondaux + (s->wids[i] * 3)];
- }
- }
- else {
- s->nvrtx = sTmp.nvrtx;
- for (i = 0; i < s->nvrtx; ++i) {
- for (j = 0; j < 3; ++j) {
- s->vrtx[i][j] = sTmp.vrtx[i][j];
- }
- s->lambdas[i] = sTmp.lambdas[i];
- s->wids[sTmp.nvrtx - 1 - i] = TrianglesToTest[firstaux + (sTmp.wids[i] * 3)];
- }
- }
- }
- else if (FacetsTest[1] + FacetsTest[2] + FacetsTest[3] == 2) {
- /* Only one facet is facing the origin */
- if (FacetsTest[1] == 0) {
- /* The origin projection P faces the facet ACD */
- s->nvrtx = 3;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[0][i];
- s->vrtx[1][i] = s->vrtx[1][i];
- s->vrtx[2][i] = s->vrtx[3][i];
- }
- S2D(s, v);
-
- /* Keep simplex. Need to update sID only*/
- for (i = 0; i < s->nvrtx; ++i) {
- s->wids[i] = s->wids[i];
- }
- }
- else if (FacetsTest[2] == 0) {
- /* The origin projection P faces the facet ABD */
- s->nvrtx = 3;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[0][i];
- s->vrtx[1][i] = s->vrtx[2][i];
- s->vrtx[2][i] = s->vrtx[3][i];
- }
- S2D(s, v);
- /* Keep simplex. Need to update sID only*/
- for (i = 2; i < s->nvrtx; ++i) {
- /* Assume that vertex a is always included in sID. */
- s->wids[i] = s->wids[i] + 1;
- }
- }
- else if (FacetsTest[3] == 0) {
- /* The origin projection P faces the facet ABC */
- s->nvrtx = 3;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[1][i];
- s->vrtx[1][i] = s->vrtx[2][i];
- s->vrtx[2][i] = s->vrtx[3][i];
- }
- S2D(s, v);
- }
- }
- else {
- /* The origin projection P faces the facet BCD */
- s->nvrtx = 3;
- for (i = 0; i < 3; ++i) {
- s->vrtx[0][i] = s->vrtx[0][i];
- s->vrtx[1][i] = s->vrtx[1][i];
- s->vrtx[2][i] = s->vrtx[2][i];
- }
- /* ... and call S2D */
- S2D(s, v);
- /* Keep simplex. Need to update sID only*/
- for (i = 0; i < s->nvrtx; ++i) {
- /* Assume that vertex a is always included in sID. */
- s->wids[i] = s->wids[i] + 1;
- }
- }
-
-
- for ( j = 0; j < 3; ++j) {
- vv[j] = 0;
- for (i = 0; i < s->nvrtx; ++i) {
- vv[j] += (s->lambdas[i] * s->vrtx[i][j]);
- }
- }
-}
-
-
-inline static void support( struct bd *body, double *v ) {
- int better = -1;
- int i;
- double s;
- double maxs;
- double *vrt;
-
- maxs = dotProduct(body->s, v);
-
- for (i = 0; i < body->numpoints; ++i) {
- vrt = body->coord[i];
- s = dotProduct (vrt, v);
- if ( s > maxs ){
- maxs = s;
- better = i;
- }
- }
-
- if (better != -1 ){
- body->s[0] = body->coord[better][0];
- body->s[1] = body->coord[better][1];
- body->s[2] = body->coord[better][2];
- }
-}
-
-inline static void subalgorithm( struct simplex *s, double *v ) {
-
- switch ( s->nvrtx ){
- case 4:
- S3D( s, v );
- break;
- case 3:
- S2D( s, v );
- break;
- case 2:
- S1D( s, v );
- break;
- }
-}
-
-double gjk( struct bd bd1, struct bd bd2, struct simplex *s) {
-
- int i;
- int k = 0; /**< Iteration counter */
- int mk = 50; /**< Maximum number of iterations of the GJK algorithm */
- int exeedtol_rel = 0; /**< Flag for 1st exit condition */
- double v[3]; /**< Search direction */
- double vminus[3]; /**< Search direction * -1 */
- double w[3]; /**< Vertex on CSO boundary given by the difference of support functions on both bodies */
- double eps_rel = 1e-5; /**< Tolerance on relative distance */
- double eps_tot = 1e-15; /**< Tolerance on absolute distance */
- double norm2Wmax = 0;
- double tesnorm = 0;
-
-#ifdef ADAPTIVEFP
- exactinit();
-#endif
-
- double eps_rel2 = eps_rel * eps_rel ;
-
- /* Initialise */
- s->nvrtx = 1;
- for ( i = 0; i < 3; i++)
- {
- v[i] = bd1.coord[0][i] - bd2.coord[0][i];
- bd1.s[i] = bd1.coord[0][i];
- bd2.s[i] = bd2.coord[0][i];
- s->vrtx[0][i] = v[i];
- s->p[0][i] = bd1.s[i];
- s->q[0][i] = bd2.s[i];
- }
-
- /* Begin GJK iteration */
- do {
-
- k++;
-
- /* Update negative search direction */
- vminus[0] = -v[0];
- vminus[1] = -v[1];
- vminus[2] = -v[2];
-
- /* Support function */
- support( &bd1 , vminus );
- support( &bd2 , v );
- w[0] = bd1.s[0] - bd2.s[0];
- w[1] = bd1.s[1] - bd2.s[1];
- w[2] = bd1.s[2] - bd2.s[2];
-
- /* 1st exit condition */
- exeedtol_rel = (norm2(v) - dotProduct (v,w) ) <= eps_rel2 * norm2(v);
- if ( exeedtol_rel ){
- break;
- }
-
- /* 2nd exit condition */
- if (norm2(v) < eps_rel2)
- break;
-
- /* Add new vertex to simplex */
- i = s->nvrtx;
- s->vrtx[i][0] = w[0];
- s->vrtx[i][1] = w[1];
- s->vrtx[i][2] = w[2];
- s->nvrtx++;
-
- /* Invoke distance sub-algorithm */
- subalgorithm ( s, v );
-
- for (i = 0; i < 3; i++)
- {
- s->p[s->nvrtx - 1][i] = bd1.s[i];
- s->q[s->nvrtx - 1][i] = bd2.s[i];
- }
-
- /* 3rd exit condition */
- for (i = 0; i < s->nvrtx; i++)
- {
- tesnorm = norm2(s->vrtx[i]);
- if (tesnorm > norm2Wmax) {
- norm2Wmax = tesnorm;
- }
- }
- if (norm2(v) <= (eps_tot * eps_tot * norm2Wmax))
- break;
-
- /* 4th and 5th exit conditions */
- } while((s->nvrtx != 4) && (k != mk));
-
- /* Compute and return distance */
- return sqrt(norm2(v));
-}
-
-#ifdef MATLABDOESMEXSTUFF
-/**
- * @brief Mex function for Matlab.
- */
-void mexFunction( int nlhs, mxArray *plhs[],
- int nrhs, const mxArray *prhs[])
-{
-
- double *inCoordsA;
- double *inCoordsB;
- size_t nCoordsA;
- size_t nCoordsB;
- int i;
- double *distance;
- int c = 3;
- int count = 0;
- double**arr1;
- double**arr2;
-
- /**************** PARSE INPUTS AND OUTPUTS **********************/
- /*----------------------------------------------------------------*/
- /* Examine input (right-hand-side) arguments. */
- if(nrhs!=2) {
- mexErrMsgIdAndTxt("MyToolbox:gjk:nrhs","Two inputs required.");
- }
- /* Examine output (left-hand-side) arguments. */
- if(nlhs!=1) {
- mexErrMsgIdAndTxt("MyToolbox:gjk:nlhs","One output required.");
- }
-
- /* make sure the two input arguments are any numerical type */
- /* .. first input */
- if( !mxIsNumeric(prhs[0])) {
- mexErrMsgIdAndTxt("MyToolbox:gjk:notNumeric","Input matrix must be type numeric.");
- }
- /* .. second input */
- if( !mxIsNumeric(prhs[1])) {
- mexErrMsgIdAndTxt("MyToolbox:gjk:notNumeric","Input matrix must be type numeric.");
- }
-
- /* make sure the two input arguments have 3 columns */
- /* .. first input */
- if(mxGetM(prhs[0])!=3) {
- mexErrMsgIdAndTxt("MyToolbox:gjk:notColumnVector","First input must have 3 columns.");
- }
- /* .. second input */
- if(mxGetM(prhs[1])!=3) {
- mexErrMsgIdAndTxt("MyToolbox:gjk:notColumnVector","Second input must have 3 columns.");
- }
-
- /*----------------------------------------------------------------*/
- /* CREATE DATA COMPATIBLE WITH MATALB */
-
- /* create a pointer to the real data in the input matrix */
- inCoordsA = mxGetPr(prhs[0]);
- inCoordsB = mxGetPr(prhs[1]);
-
- /* get the length of each input vector */
- nCoordsA = mxGetN(prhs[0]);
- nCoordsB = mxGetN(prhs[1]);
-
- /* Create output */
- plhs[0]=mxCreateDoubleMatrix(1,1,mxREAL);
-
- /* get a pointer to the real data in the output matrix */
- distance = mxGetPr(plhs[0]);
-
- /* Copy data from Matlab's vectors into two new arrays */
- arr1 = (double **)mxMalloc( sizeof(double *) * (int)nCoordsA );
- arr2 = (double **)mxMalloc( sizeof(double *) * (int)nCoordsB );
-
- for (i = 0; i < nCoordsA; i++)
- arr1[i] = &inCoordsA[i * 3];
-
- for (i = 0; i < nCoordsB; i++)
- arr2[i] = &inCoordsB[i * 3];
-
- /*----------------------------------------------------------------*/
- /* POPULATE BODIES' STRUCTURES */
-
- struct bd bd1; /* Structure of body A */
- struct bd bd2; /* Structure of body B */
-
- /* Assign number of vertices to each body */
- bd1.numpoints = (int) nCoordsA;
- bd2.numpoints = (int) nCoordsB;
-
- bd1.coord = arr1;
- bd2.coord = arr2;
-
- /*----------------------------------------------------------------*/
- /*CALL COMPUTATIONAL ROUTINE */
-
- struct simplex s;
- s.nvrtx = 0;
-
- /* Compute squared distance using GJK algorithm */
- distance[0] = gjk (bd1, bd2, &s);
-
- mxFree(arr1);
- mxFree(arr2);
-
-}
-#endif
-
-/**
- * @brief Invoke this function from C# applications
- */
-double csFunction( int nCoordsA, double *inCoordsA, int nCoordsB, double *inCoordsB )
-{
- double distance = 0;
- int i, j;
-
- /*----------------------------------------------------------------*/
- /* POPULATE BODIES' STRUCTURES */
-
- struct bd bd1; /* Structure of body A */
- struct bd bd2; /* Structure of body B */
-
- /* Assign number of vertices to each body */
- bd1.numpoints = (int) nCoordsA;
- bd2.numpoints = (int) nCoordsB;
-
- double **pinCoordsA = (double **)malloc(bd1.numpoints * sizeof(double *));
- for (i=0; i< bd1.numpoints ; i++)
- pinCoordsA[i] = (double *)malloc(3 * sizeof(double));
-
- for (i = 0; i < 3; i++)
- for (j = 0; j < bd1.numpoints; j++)
- pinCoordsA[j][i] = inCoordsA[ i*bd1.numpoints + j] ;
-
- double **pinCoordsB = (double **)malloc(bd2.numpoints * sizeof(double *));
- for (i=0; i< bd2.numpoints ; i++)
- pinCoordsB[i] = (double *)malloc(3 * sizeof(double));
-
- for (i = 0; i < 3; i++)
- for (j = 0; j < bd2.numpoints; j++)
- pinCoordsB[j][i] = inCoordsB[ i*bd2.numpoints + j] ;
-
- bd1.coord = pinCoordsA;
- bd2.coord = pinCoordsB;
-
-
- /*----------------------------------------------------------------*/
- /*CALL COMPUTATIONAL ROUTINE */
- struct simplex s;
-
- /* Initialise simplex as empty */
- s.nvrtx = 0;
-
- /* Compute squared distance using GJK algorithm */
- distance = gjk (bd1, bd2, &s);
-
- for (i=0; i< bd1.numpoints ; i++)
- free(pinCoordsA[i]);
- free( pinCoordsA );
-
- for (i=0; i< bd2.numpoints ; i++)
- free(pinCoordsB[i]);
- free( pinCoordsB );
-
- return distance;
-}
diff --git a/src/openGJK.c b/src/openGJK.c
new file mode 100644
index 0000000..7066525
--- /dev/null
+++ b/src/openGJK.c
@@ -0,0 +1,946 @@
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
+ * ##### # # # *
+ * #### ##### ###### # # # # # # # *
+ * # # # # # ## # # # # # *
+ * # # # # ##### # # # # #### # ### *
+ * # # ##### # # # # # # # # # # *
+ * # # # # # ## # # # # # # *
+ * #### # ###### # # ##### ##### # # *
+ * *
+ * This file is part of openGJK. *
+ * *
+ * openGJK 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 *
+ * any later version. *
+ * *
+ * openGJK 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 Foobar. If not, see . *
+ * *
+ * openGJK: open-source Gilbert-Johnson-Keerthi algorithm *
+ * Copyright (C) Mattia Montanari 2018 - 2019 *
+ * http://iel.eng.ox.ac.uk/?page_id=504 *
+ * *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#include "openGJK/openGJK.h"
+
+/* If instricuted, compile a mex function for Matlab. */
+#ifdef MATLABDOESMEXSTUFF
+#include "mex.h"
+#else
+#define mexPrintf printf
+#endif
+
+#define eps_rel22 1e-10
+#define eps_tot22 1e-12
+
+/* Select distance sub-algorithm */
+
+#define norm2(a) (a[0]*a[0]+a[1]*a[1]+a[2]*a[2])
+
+#define dotProduct(a, b) (a[0]*b[0]+a[1]*b[1]+a[2]*b[2])
+
+#define S3Dregion1234() v[0] = 0;\
+ v[1] = 0;\
+ v[2] = 0;\
+ s->nvrtx = 4;
+
+#define select_1ik() s->nvrtx = 3;\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[2][t] = s->vrtx[3][t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[1][t] = si[t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[0][t] = sk[t];
+
+#define select_1ij() s->nvrtx = 3;\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[2][t] = s->vrtx[3][t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[1][t] = si[t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[0][t] = sj[t];
+
+#define select_1jk() s->nvrtx = 3;\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[2][t] = s->vrtx[3][t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[1][t] = sj[t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[0][t] = sk[t];
+
+#define select_1i() s->nvrtx = 2;\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[1][t] = s->vrtx[3][t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[0][t] = si[t];
+
+#define select_1j() s->nvrtx = 2;\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[1][t] = s->vrtx[3][t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[0][t] = sj[t];
+
+#define select_1k() s->nvrtx = 2;\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[1][t] = s->vrtx[3][t];\
+ for (t = 0; t < 3; t++)\
+ s->vrtx[0][t] = sk[t];
+
+#define getvrtx(point, location) point[0] = s->vrtx[location][0];\
+ point[1] = s->vrtx[location][1];\
+ point[2] = s->vrtx[location][2];
+
+#define calculateEdgeVector(p1p2, p2) p1p2[0] = p2[0] - s->vrtx[3][0];\
+ p1p2[1] = p2[1] - s->vrtx[3][1];\
+ p1p2[2] = p2[2] - s->vrtx[3][2];
+
+#define S1Dregion1() v[0] = s->vrtx[1][0];\
+ v[1] = s->vrtx[1][1];\
+ v[2] = s->vrtx[1][2];\
+ s->nvrtx = 1;\
+ s->vrtx[0][0] = s->vrtx[1][0];\
+ s->vrtx[0][1] = s->vrtx[1][1];\
+ s->vrtx[0][2] = s->vrtx[1][2];
+
+#define S2Dregion1() v[0] = s->vrtx[2][0];\
+ v[1] = s->vrtx[2][1];\
+ v[2] = s->vrtx[2][2];\
+ s->nvrtx = 1;\
+ s->vrtx[0][0] = s->vrtx[2][0];\
+ s->vrtx[0][1] = s->vrtx[2][1];\
+ s->vrtx[0][2] = s->vrtx[2][2];
+
+#define S2Dregion12() s->nvrtx = 2;\
+ s->vrtx[0][0] = s->vrtx[2][0];\
+ s->vrtx[0][1] = s->vrtx[2][1];\
+ s->vrtx[0][2] = s->vrtx[2][2];
+
+#define S2Dregion13() s->nvrtx = 2;\
+ s->vrtx[1][0] = s->vrtx[2][0];\
+ s->vrtx[1][1] = s->vrtx[2][1];\
+ s->vrtx[1][2] = s->vrtx[2][2];
+
+#define S3Dregion1() v[0] = s1[0];\
+ v[1] = s1[1];\
+ v[2] = s1[2];\
+ s->nvrtx = 1;\
+ s->vrtx[0][0] = s1[0];\
+ s->vrtx[0][1] = s1[1];\
+ s->vrtx[0][2] = s1[2];
+
+inline static double determinant(const double *p, const double *q, const double *r) {
+ return p[0] * ((q[1] * r[2]) - (r[1] * q[2])) - p[1] * (q[0] * r[2] - r[0] * q[2]) + p[2] * (q[0] * r[1] - r[0] * q[1]);
+}
+
+inline static void crossProduct(const double *a, const double *b, double *c)
+{
+ c[0] = a[1] * b[2] - a[2] * b[1];
+ c[1] = a[2] * b[0] - a[0] * b[2];
+ c[2] = a[0] * b[1] - a[1] * b[0];
+}
+
+inline static void projectOnLine(const double *p, const double *q, double *v)
+{
+ double pq[3];
+ double tmp;
+ pq[0] = p[0] - q[0];
+ pq[1] = p[1] - q[1];
+ pq[2] = p[2] - q[2];
+
+ tmp = dotProduct(p, pq) / dotProduct(pq, pq);
+
+ for (int i = 0; i < 3; i++)
+ v[i] = p[i] - pq[i] * tmp;
+}
+
+inline static void projectOnPlane(const double *p, const double *q, const double *r, double *v)
+{
+ double n[3], pq[3], pr[3];
+ double tmp;
+
+ for (int i = 0; i < 3; i++)
+ pq[i] = p[i] - q[i];
+
+ for (int i = 0; i < 3; i++)
+ pr[i] = p[i] - r[i];
+
+ crossProduct(pq, pr, n);
+ tmp = dotProduct(n, p) / dotProduct(n, n);
+
+ for (int i = 0; i < 3; i++)
+ v[i] = n[i] * tmp;
+}
+
+inline static int hff1(const double *p, const double *q)
+{
+ double tmp = 0;
+
+#pragma omp simd reduction(+:tmp)
+ for (int i = 0; i < 3; i++)
+ tmp += (p[i] * p[i] - p[i] * q[i]);
+
+ if (tmp > 0)
+ return 1; // keep q
+
+ return 0;
+}
+
+inline static int hff2(const double *p, const double *q, const double *r)
+{
+ double ntmp[3];
+ double n[3], pq[3], pr[3];
+ double tmp = 0;
+
+ for (int i = 0; i < 3; i++)
+ pq[i] = q[i] - p[i];
+
+ for (int i = 0; i < 3; i++)
+ pr[i] = r[i] - p[i];
+
+ crossProduct(pq, pr, ntmp);
+ crossProduct(pq, ntmp, n);
+
+#pragma omp simd reduction(+:tmp)
+ for (int i = 0; i < 3; i++)
+ tmp = tmp + (p[i] * n[i]);
+
+ if (tmp < 0)
+ return 1; // Discard r
+
+ return 0;
+}
+
+inline static int hff3(const double *p, const double *q, const double *r)
+{
+ double n[3], pq[3], pr[3];
+ double tmp = 0;
+
+ for (int i = 0; i < 3; i++)
+ pq[i] = q[i] - p[i];
+
+ for (int i = 0; i < 3; i++)
+ pr[i] = r[i] - p[i];
+
+ crossProduct(pq, pr, n);
+
+#pragma omp simd reduction(+:tmp)
+ for (int i = 0; i < 3; i++)
+ tmp = tmp + (p[i] * n[i]);
+
+ if (tmp > 0)
+ return 0; // discard s
+
+ return 1;
+}
+
+inline static void S1D(struct simplex * s, double *v)
+{
+ double *s1p = s->vrtx[1];
+ double *s2p = s->vrtx[0];
+
+ if (hff1(s1p, s2p)) {
+ projectOnLine(s1p, s2p, v); // Update v, no need to update s
+ return; // Return V{1,2}
+ }
+ else {
+ S1Dregion1(); // Update v and s
+ return; // Return V{1}
+ }
+}
+
+
+inline static void S2D(struct simplex * s, double *v)
+{
+ double *s1p = s->vrtx[2];
+ double *s2p = s->vrtx[1];
+ double *s3p = s->vrtx[0];
+ int hff1f_s12 = hff1(s1p, s2p);
+ int hff1f_s13 = hff1(s1p, s3p);
+ int hff2f_23 = !hff2(s1p, s2p, s3p);
+ int hff2f_32 = !hff2(s1p, s3p, s2p);
+
+ if (hff1f_s12) {
+ if (hff2f_23) {
+ if (hff1f_s13) {
+ if (hff2f_32) {
+ projectOnPlane(s1p, s2p, s3p, v); // Update s, no need to update c
+ return; // Return V{1,2,3}
+ }
+ else
+ {
+ projectOnLine(s1p, s3p, v); // Update v
+ S2Dregion13(); // Update s
+ return; // Return V{1,3}
+ }
+ }
+ else
+ {
+ projectOnPlane(s1p, s2p, s3p, v); // Update s, no need to update c
+ return; // Return V{1,2,3}
+ }
+ }
+ else
+ {
+ projectOnLine(s1p, s2p, v); // Update v
+ S2Dregion12(); // Update s
+ return; // Return V{1,2}
+ }
+ }
+ else if (hff1f_s13) {
+ if (hff2f_32) {
+ projectOnPlane(s1p, s2p, s3p, v); // Update s, no need to update v
+ return; // Return V{1,2,3}
+ }
+ else
+ {
+ projectOnLine(s1p, s3p, v); // Update v
+ S2Dregion13(); // Update s
+ return; // Return V{1,3}
+ }
+ }
+ else {
+ S2Dregion1(); // Update s and v
+ return; // Return V{1}
+ }
+
+}
+
+inline static void S3D(struct simplex * s, double *v) {
+
+ double s1[3], s2[3], s3[3], s4[3], s1s2[3], s1s3[3], s1s4[3];
+ double si[3], sj[3], sk[3];
+ int testLineThree, testLineFour, testPlaneTwo, testPlaneThree, testPlaneFour, dotTotal;
+ int i, j, k, t;
+
+ getvrtx(s1, 3);
+ getvrtx(s2, 2);
+ getvrtx(s3, 1);
+ getvrtx(s4, 0);
+ calculateEdgeVector(s1s2, s2);
+ calculateEdgeVector(s1s3, s3);
+ calculateEdgeVector(s1s4, s4);
+
+ int hff1_tests[3];
+ hff1_tests[2] = hff1(s1, s2);
+ hff1_tests[1] = hff1(s1, s3);
+ hff1_tests[0] = hff1(s1, s4);
+ testLineThree = hff1(s1, s3);
+ testLineFour = hff1(s1, s4);
+
+ dotTotal = hff1(s1, s2) + testLineThree + testLineFour;
+ if (dotTotal == 0) { /* case 0.0 -------------------------------------- */
+ S3Dregion1();
+ return;
+ }
+
+ double det134 = determinant(s1s3, s1s4, s1s2);
+ int sss;
+ if (det134 > 0) {
+ sss = 0;
+ }
+ else {
+ sss = 1;
+ }
+
+ testPlaneTwo = hff3(s1, s3, s4) - sss;
+ testPlaneTwo = testPlaneTwo * testPlaneTwo;
+ testPlaneThree = hff3(s1, s4, s2) - sss;
+ testPlaneThree = testPlaneThree * testPlaneThree;
+ testPlaneFour = hff3(s1, s2, s3) - sss;
+ testPlaneFour = testPlaneFour * testPlaneFour;
+
+ switch (testPlaneTwo + testPlaneThree + testPlaneFour) {
+ case 3:
+ S3Dregion1234();
+ break;
+
+ case 2:
+ // Only one facing the oring
+ // 1,i,j, are the indices of the points on the triangle and remove k from simplex
+ s->nvrtx = 3;
+ if (!testPlaneTwo) { // k = 2; removes s2
+ for (i = 0; i < 3; i++)
+ s->vrtx[2][i] = s->vrtx[3][i];
+ }
+ else if (!testPlaneThree) {// k = 1; // removes s3
+ for (i = 0; i < 3; i++)
+ s->vrtx[1][i] = s2[i];
+ for (i = 0; i < 3; i++)
+ s->vrtx[2][i] = s->vrtx[3][i];
+ }
+ else if (!testPlaneFour) { // k = 0; // removes s4 and no need to reorder
+ for (i = 0; i < 3; i++)
+ s->vrtx[0][i] = s3[i];
+ for (i = 0; i < 3; i++)
+ s->vrtx[1][i] = s2[i];
+ for (i = 0; i < 3; i++)
+ s->vrtx[2][i] = s->vrtx[3][i];
+ }
+ // Call S2D
+ S2D(s, v);
+ break;
+ case 1:
+ // Two triangles face the origins:
+ // The only positive hff3 is for triangle 1,i,j, therefore k must be in the solution as it supports the the point of minimum norm.
+
+ // 1,i,j, are the indices of the points on the triangle and remove k from simplex
+ s->nvrtx = 3;
+ if (testPlaneTwo) {
+ k = 2; // s2
+ i = 1;
+ j = 0;
+ }
+ else if (testPlaneThree) {
+ k = 1; // s3
+ i = 0;
+ j = 2;
+ }
+ else {
+ k = 0; // s4
+ i = 2;
+ j = 1;
+ }
+
+ getvrtx(si, i);
+ getvrtx(sj, j);
+ getvrtx(sk, k);
+
+ if (dotTotal == 1) {
+ if (hff1_tests[k]) {
+ if (!hff2(s1, sk, si)) {
+ select_1ik();
+ projectOnPlane(s1, si, sk, v);
+ }
+ else if (!hff2(s1, sk, sj)) {
+ select_1jk();
+ projectOnPlane(s1, sj, sk, v);
+ }
+ else {
+ select_1k(); // select region 1i
+ projectOnLine(s1, sk, v);
+ }
+ }
+ else if (hff1_tests[i]) {
+ if (!hff2(s1, si, sk)) {
+ select_1ik();
+ projectOnPlane(s1, si, sk, v);
+ }
+ else {
+ select_1i(); // select region 1i
+ projectOnLine(s1, si, v);
+ }
+ }
+ else {
+ if (!hff2(s1, sj, sk)) {
+ select_1jk();
+ projectOnPlane(s1, sj, sk, v);
+ }
+ else {
+ select_1j(); // select region 1i
+ projectOnLine(s1, sj, v);
+ }
+ }
+ }
+ else if (dotTotal == 2) {
+ // Two edges have positive hff1, meaning that for two edges the origin's project fall on the segement.
+ // Certainly the edge 1,k supports the the point of minimum norm, and so hff1_1k is positive
+
+ if (hff1_tests[i]) {
+ if (!hff2(s1, sk, si))
+ if (!hff2(s1, si, sk)) {
+ select_1ik(); // select region 1ik
+ projectOnPlane(s1, si, sk, v);
+ }
+ else {
+ select_1k(); // select region 1k
+ projectOnLine(s1, sk, v);
+ }
+ else {
+ if (!hff2(s1, sk, sj)) {
+ select_1jk(); // select region 1jk
+ projectOnPlane(s1, sj, sk, v);
+ }
+ else {
+ select_1k(); // select region 1k
+ projectOnLine(s1, sk, v);
+ }
+ }
+ }
+ else if (hff1_tests[j]) {// there is no other choice
+ if (!hff2(s1, sk, sj))
+ if (!hff2(s1, sj, sk)) {
+ select_1jk(); // select region 1jk
+ projectOnPlane(s1, sj, sk, v);
+ }
+ else {
+ select_1j(); // select region 1j
+ projectOnLine(s1, sj, v);
+ }
+ else {
+ if (!hff2(s1, sk, si)) {
+ select_1ik(); // select region 1ik
+ projectOnPlane(s1, si, sk, v);
+ }
+ else {
+ select_1k(); // select region 1k
+ projectOnLine(s1, sk, v);
+ }
+ }
+ }
+ else {
+ // ERROR;
+ }
+
+ }
+ else if (dotTotal == 3) {
+ // MM : ALL THIS HYPHOTESIS IS FALSE
+ // sk is s.t. hff3 for sk < 0. So, sk must support the origin because there are 2 triangles facing the origin.
+
+ int hff2_ik = hff2(s1,si,sk);
+ int hff2_jk = hff2(s1,sj,sk);
+ int hff2_ki = hff2(s1,sk,si);
+ int hff2_kj = hff2(s1,sk,sj);
+
+ if (hff2_ki == 0 && hff2_kj == 0){
+ mexPrintf("\n\n UNEXPECTED VALUES!!! \n\n");
+ }
+ if (hff2_ki == 1 && hff2_kj == 1){
+ select_1k();
+ projectOnLine(s1, sk, v);
+ }
+ else if (hff2_ki) {
+ // discard i
+ if (hff2_jk){
+ // discard k
+ select_1j();
+ projectOnLine(s1, sj, v);
+ }
+ else{
+ select_1jk();
+ projectOnPlane(s1, sk, sj, v);
+ }
+ }
+ else {
+ // discard j
+ if (hff2_ik){
+ // discard k
+ select_1i();
+ projectOnLine(s1, si, v);
+ }
+ else{
+ select_1ik();
+ projectOnPlane(s1, sk, si, v);
+ }
+ }
+ }
+ break;
+
+ case 0:
+ // The origin is outside all 3 triangles
+ if (dotTotal == 1) {
+ // Here si is set such that hff(s1,si) > 0
+ if (testLineThree) {
+ k = 2;
+ i = 1; // s3
+ j = 0;
+ }
+ else if (testLineFour) {
+ k = 1; // s3
+ i = 0;
+ j = 2;
+ }
+ else {
+ k = 0;
+ i = 2; // s2
+ j = 1;
+ }
+ getvrtx(si, i);
+ getvrtx(sj, j);
+ getvrtx(sk, k);
+
+ if (!hff2(s1, si, sj)) {
+ select_1ij();
+ projectOnPlane(s1, si, sj, v);
+ }
+ else if (!hff2(s1, si, sk)) {
+ select_1ik();
+ projectOnPlane(s1, si, sk, v);
+ }
+ else {
+ select_1i();
+ projectOnLine(s1, si, v);
+ }
+ }
+ else if (dotTotal == 2) {
+ // Here si is set such that hff(s1,si) < 0
+ s->nvrtx = 3;
+ if (!testLineThree) {
+ k = 2;
+ i = 1; // s3
+ j = 0;
+ }
+ else if (!testLineFour) {
+ k = 1;
+ i = 0; // s4
+ j = 2;
+ }
+ else {
+ k = 0;
+ i = 2; // s2
+ j = 1;
+ }
+ getvrtx(si, i);
+ getvrtx(sj, j);
+ getvrtx(sk, k);
+
+ if (!hff2(s1, sj, sk)) {
+ if (!hff2(s1, sk, sj)) {
+ select_1jk(); // select region 1jk
+ projectOnPlane(s1, sj, sk, v);
+ }
+ else if (!hff2(s1, sk, si)) {
+ select_1ik();
+ projectOnPlane(s1, sk, si, v);
+ }
+ else {
+ select_1k();
+ projectOnLine(s1, sk, v);
+ }
+ }
+ else if (!hff2(s1, sj, si)) {
+ select_1ij();
+ projectOnPlane(s1, si, sj, v);
+ }
+ else {
+ select_1j();
+ projectOnLine(s1, sj, v);
+ }
+ }
+ break;
+ default:
+ mexPrintf("\nERROR:\tunhandled");
+ }
+
+}
+
+inline static void support(struct bd *body, const double *v) {
+
+ double s, maxs;
+ double *vrt;
+ int better = -1;
+
+ maxs = dotProduct(body->s, v);
+
+ for (int i = 0; i < body->numpoints; ++i) {
+ vrt = body->coord[i];
+ s = dotProduct(vrt, v);
+ if (s > maxs) {
+ maxs = s;
+ better = i;
+ }
+ }
+
+ if (better != -1) {
+ body->s[0] = body->coord[better][0];
+ body->s[1] = body->coord[better][1];
+ body->s[2] = body->coord[better][2];
+ }
+}
+
+inline static void subalgorithm(struct simplex *s, double *v) {
+
+ switch (s->nvrtx) {
+ case 4:
+ S3D(s, v);
+ break;
+ case 3:
+ S2D(s, v);
+ break;
+ case 2:
+ S1D(s, v);
+ break;
+ default:
+ mexPrintf("\nERROR:\t invalid simplex\n");
+ }
+}
+
+double gjk(struct bd bd1, struct bd bd2, struct simplex *s) {
+
+ int k = 0; /**< Iteration counter */
+ int i; /**< General purpose counter */
+ int mk = 25; /**< Maximum number of iterations of the GJK algorithm */
+ int absTestin;
+ double norm2Wmax = 0;
+ double tesnorm;
+ double v[3]; /**< Search direction */
+ double vminus[3]; /**< Search direction * -1 */
+ double w[3]; /**< Vertex on CSO boundary given by the difference of support functions on both bodies */
+ double eps_rel = eps_rel22; /**< Tolerance on relative */
+ double eps_rel2 = eps_rel * eps_rel;
+ double eps_tot = eps_tot22;
+ double exeedtol_rel; /**< Test for 1st exit condition */
+ int nullV = 0;
+
+#ifdef DEBUG
+ mexPrintf("Num points A = %i \n", bd1.numpoints);
+ mexPrintf("Num points B = %i \n", bd2.numpoints);
+ for (i = 0; i < bd1.numpoints; ++i) {
+ for (int j = 0; j < 3; j++) {
+ mexPrintf("%.4f ", bd1.coord[i][j]);
+ }
+ mexPrintf("\n");
+ }
+
+ for (i = 0; i < bd2.numpoints; ++i) {
+ for (int j = 0; j < 3; j++) {
+ mexPrintf("%.4f ", bd2.coord[i][j]);
+ }
+ mexPrintf("\n");
+ }
+#endif
+
+ /* Initialise search direction */
+ v[0] = bd1.coord[0][0] - bd2.coord[0][0];
+ v[1] = bd1.coord[0][1] - bd2.coord[0][1];
+ v[2] = bd1.coord[0][2] - bd2.coord[0][2];
+
+ /* Inialise simplex */
+ s->nvrtx = 1;
+ for (int t = 0; t < 3; ++t)
+ s->vrtx[0][t] = v[t];
+
+ for (int t = 0; t < 3; ++t)
+ bd1.s[t] = bd1.coord[0][t];
+
+ for (int t = 0; t < 3; ++t)
+ bd2.s[t] = bd2.coord[0][t];
+
+ /* Begin GJK iteration */
+ do {
+
+ k++;
+
+ /* Update negative search direction */
+ for (int t = 0; t < 3; ++t)
+ vminus[t] = -v[t];
+
+ /* Support function */
+ support(&bd1, vminus);
+ support(&bd2, v);
+ for (int t = 0; t < 3; ++t)
+ w[t] = bd1.s[t] - bd2.s[t];
+
+ /* Test first exit condition (new point already in simplex/can't move further) */
+ exeedtol_rel = (norm2(v) - dotProduct(v, w));
+ if ( exeedtol_rel <= (eps_rel * norm2(v)) || exeedtol_rel < eps_tot22) {
+ break;
+ }
+
+ nullV = norm2(v) < eps_rel2;
+ if (nullV) {
+ break;
+ }
+
+ /* Add new vertex to simplex */
+ i = s->nvrtx;
+ for (int t = 0; t < 3; ++t)
+ s->vrtx[i][t] = w[t];
+ s->nvrtx++;
+
+ /* Invoke distance sub-algorithm */
+ subalgorithm(s, v);
+
+ /* Test */
+ for (int jj = 0; jj < s->nvrtx; jj++) {
+ tesnorm = norm2(s->vrtx[jj]);
+ if (tesnorm > norm2Wmax) {
+ norm2Wmax = tesnorm;
+ }
+ }
+
+ absTestin = (norm2(v) <= (eps_tot * eps_tot * norm2Wmax));
+ if (absTestin) {
+ break;
+ }
+
+ } while ((s->nvrtx != 4) && (k != mk));
+
+ if (k == mk) {
+ mexPrintf("\n * * * * * * * * * * * * MAXIMUM ITERATION NUMBER REACHED!!! * * * * * * * * * * * * * * \n");
+ }
+
+ return sqrt(norm2(v));
+}
+
+
+
+#ifdef MATLABDOESMEXSTUFF
+/**
+ * @brief Mex function for Matlab.
+ */
+void mexFunction(int nlhs, mxArray *plhs[],
+ int nrhs, const mxArray *prhs[])
+{
+
+ double *inCoordsA;
+ double *inCoordsB;
+ size_t nCoordsA;
+ size_t nCoordsB;
+ int i;
+ double *distance;
+ int c = 3;
+ int count = 0;
+ double**arr1;
+ double**arr2;
+
+ /**************** PARSE INPUTS AND OUTPUTS **********************/
+ /*----------------------------------------------------------------*/
+ /* Examine input (right-hand-side) arguments. */
+ if (nrhs != 2) {
+ mexErrMsgIdAndTxt("MyToolbox:gjk:nrhs", "Two inputs required.");
+ }
+ /* Examine output (left-hand-side) arguments. */
+ if (nlhs != 1) {
+ mexErrMsgIdAndTxt("MyToolbox:gjk:nlhs", "One output required.");
+ }
+
+ /* make sure the two input arguments are any numerical type */
+ /* .. first input */
+ if (!mxIsNumeric(prhs[0])) {
+ mexErrMsgIdAndTxt("MyToolbox:gjk:notNumeric", "Input matrix must be type numeric.");
+ }
+ /* .. second input */
+ if (!mxIsNumeric(prhs[1])) {
+ mexErrMsgIdAndTxt("MyToolbox:gjk:notNumeric", "Input matrix must be type numeric.");
+ }
+
+ /* make sure the two input arguments have 3 columns */
+ /* .. first input */
+ if (mxGetM(prhs[0]) != 3) {
+ mexErrMsgIdAndTxt("MyToolbox:gjk:notColumnVector", "First input must have 3 columns.");
+ }
+ /* .. second input */
+ if (mxGetM(prhs[1]) != 3) {
+ mexErrMsgIdAndTxt("MyToolbox:gjk:notColumnVector", "Second input must have 3 columns.");
+ }
+
+ /*----------------------------------------------------------------*/
+ /* CREATE DATA COMPATIBLE WITH MATALB */
+
+ /* create a pointer to the real data in the input matrix */
+ inCoordsA = mxGetPr(prhs[0]);
+ inCoordsB = mxGetPr(prhs[1]);
+
+ /* get the length of each input vector */
+ nCoordsA = mxGetN(prhs[0]);
+ nCoordsB = mxGetN(prhs[1]);
+
+ /* Create output */
+ plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
+
+ /* get a pointer to the real data in the output matrix */
+ distance = mxGetPr(plhs[0]);
+
+ /* Copy data from Matlab's vectors into two new arrays */
+ arr1 = (double **)mxMalloc(sizeof(double *) * (int)nCoordsA);
+ arr2 = (double **)mxMalloc(sizeof(double *) * (int)nCoordsB);
+
+ for (i = 0; i < nCoordsA; i++)
+ arr1[i] = &inCoordsA[i * 3];
+
+ for (i = 0; i < nCoordsB; i++)
+ arr2[i] = &inCoordsB[i * 3];
+
+ /*----------------------------------------------------------------*/
+ /* POPULATE BODIES' STRUCTURES */
+
+ struct bd bd1; /* Structure of body A */
+ struct bd bd2; /* Structure of body B */
+
+ /* Assign number of vertices to each body */
+ bd1.numpoints = (int)nCoordsA;
+ bd2.numpoints = (int)nCoordsB;
+
+ bd1.coord = arr1;
+ bd2.coord = arr2;
+
+ /*----------------------------------------------------------------*/
+ /*CALL COMPUTATIONAL ROUTINE */
+
+ struct simplex s;
+ s.nvrtx = 0;
+
+ /* Compute squared distance using GJK algorithm */
+ distance[0] = gjk(bd1, bd2, &s);
+
+ mxFree(arr1);
+ mxFree(arr2);
+
+}
+#endif
+
+/**
+ * @brief Invoke this function from C# applications
+ */
+double csFunction(int nCoordsA, double *inCoordsA, int nCoordsB, double *inCoordsB)
+{
+ double distance = 0;
+ int i, j;
+
+ /*----------------------------------------------------------------*/
+ /* POPULATE BODIES' STRUCTURES */
+
+ struct bd bd1; /* Structure of body A */
+ struct bd bd2; /* Structure of body B */
+
+ /* Assign number of vertices to each body */
+ bd1.numpoints = (int)nCoordsA;
+ bd2.numpoints = (int)nCoordsB;
+
+ double **pinCoordsA = (double **)malloc(bd1.numpoints * sizeof(double *));
+ for (i = 0; i < bd1.numpoints; i++)
+ pinCoordsA[i] = (double *)malloc(3 * sizeof(double));
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < bd1.numpoints; j++)
+ pinCoordsA[j][i] = inCoordsA[i*bd1.numpoints + j];
+
+ double **pinCoordsB = (double **)malloc(bd2.numpoints * sizeof(double *));
+ for (i = 0; i < bd2.numpoints; i++)
+ pinCoordsB[i] = (double *)malloc(3 * sizeof(double));
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < bd2.numpoints; j++)
+ pinCoordsB[j][i] = inCoordsB[i*bd2.numpoints + j];
+
+ bd1.coord = pinCoordsA;
+ bd2.coord = pinCoordsB;
+
+
+ /*----------------------------------------------------------------*/
+ /*CALL COMPUTATIONAL ROUTINE */
+ struct simplex s;
+
+ /* Initialise simplex as empty */
+ s.nvrtx = 0;
+
+ /* Compute squared distance using GJK algorithm */
+ distance = gjk(bd1, bd2, &s);
+
+ for (i = 0; i < bd1.numpoints; i++)
+ free(pinCoordsA[i]);
+ free(pinCoordsA);
+
+ for (i = 0; i < bd2.numpoints; i++)
+ free(pinCoordsB[i]);
+ free(pinCoordsB);
+
+ return distance;
+}