Revision: 77311
          http://sourceforge.net/p/brlcad/code/77311
Author:   starseeker
Date:     2020-10-01 20:42:02 +0000 (Thu, 01 Oct 2020)
Log Message:
-----------
Upstream has moved quite a bit from this version of SPSR, we've added the 
library call to it which still isn't in upstream, and experiments with the 
latest PoissonRecon project code indicated it now takes a huge amount of RAM to 
compile out of the box.  Strip this down somewhat and move it into a subdir of 
libbg, since a system version is currently guaranteed not to be suitable...  No 
particular point in paying the third party build maintenance overhead right now.

Modified Paths:
--------------
    brlcad/trunk/INSTALL
    brlcad/trunk/configure
    brlcad/trunk/doc/legal/embedded/SPSR.txt
    brlcad/trunk/misc/CMake/BRLCAD_Targets.cmake
    brlcad/trunk/src/external/Creo/CMakeLists.txt
    brlcad/trunk/src/libbg/CMakeLists.txt
    brlcad/trunk/src/libbg/spsr.c
    brlcad/trunk/src/other/CMakeLists.txt

Added Paths:
-----------
    brlcad/trunk/src/libbg/spsr/
    brlcad/trunk/src/libbg/spsr/Allocator.h
    brlcad/trunk/src/libbg/spsr/Array.h
    brlcad/trunk/src/libbg/spsr/Array.inl
    brlcad/trunk/src/libbg/spsr/BSplineData.h
    brlcad/trunk/src/libbg/spsr/BSplineData.inl
    brlcad/trunk/src/libbg/spsr/BinaryNode.h
    brlcad/trunk/src/libbg/spsr/Factor.cpp
    brlcad/trunk/src/libbg/spsr/Factor.h
    brlcad/trunk/src/libbg/spsr/FunctionData.h
    brlcad/trunk/src/libbg/spsr/FunctionData.inl
    brlcad/trunk/src/libbg/spsr/Geometry.cpp
    brlcad/trunk/src/libbg/spsr/Geometry.h
    brlcad/trunk/src/libbg/spsr/Geometry.inl
    brlcad/trunk/src/libbg/spsr/Hash.h
    brlcad/trunk/src/libbg/spsr/LICENSE
    brlcad/trunk/src/libbg/spsr/MAT.h
    brlcad/trunk/src/libbg/spsr/MAT.inl
    brlcad/trunk/src/libbg/spsr/MarchingCubes.cpp
    brlcad/trunk/src/libbg/spsr/MarchingCubes.h
    brlcad/trunk/src/libbg/spsr/MemoryUsage.h
    brlcad/trunk/src/libbg/spsr/MultiGridOctreeData.IsoSurface.inl
    brlcad/trunk/src/libbg/spsr/MultiGridOctreeData.SortedTreeNodes.inl
    brlcad/trunk/src/libbg/spsr/MultiGridOctreeData.h
    brlcad/trunk/src/libbg/spsr/MultiGridOctreeData.inl
    brlcad/trunk/src/libbg/spsr/Octree.h
    brlcad/trunk/src/libbg/spsr/Octree.inl
    brlcad/trunk/src/libbg/spsr/PPolynomial.h
    brlcad/trunk/src/libbg/spsr/PPolynomial.inl
    brlcad/trunk/src/libbg/spsr/PlyVertexMini.h
    brlcad/trunk/src/libbg/spsr/PointStream.h
    brlcad/trunk/src/libbg/spsr/PointStream.inl
    brlcad/trunk/src/libbg/spsr/Polynomial.h
    brlcad/trunk/src/libbg/spsr/Polynomial.inl
    brlcad/trunk/src/libbg/spsr/SPSR.cpp
    brlcad/trunk/src/libbg/spsr/SPSR.h
    brlcad/trunk/src/libbg/spsr/SparseMatrix.h
    brlcad/trunk/src/libbg/spsr/SparseMatrix.inl
    brlcad/trunk/src/libbg/spsr/Vector.h
    brlcad/trunk/src/libbg/spsr/Vector.inl
    brlcad/trunk/src/libbg/spsr/cvertex.h

Removed Paths:
-------------
    brlcad/trunk/src/other/libspsr/
    brlcad/trunk/src/other/libspsr.dist

Modified: brlcad/trunk/INSTALL
===================================================================
--- brlcad/trunk/INSTALL        2020-10-01 19:56:41 UTC (rev 77310)
+++ brlcad/trunk/INSTALL        2020-10-01 20:42:02 UTC (rev 77311)
@@ -661,16 +661,6 @@
 Aliases:  ENABLE_OPENNURBS
 
 
---- BRLCAD_SPSR ---
-
-Option for enabling and disabling compilation of the Screened Poisson
-Surface Reconstruction library provided with BRL-CAD's source code.
-Default is AUTO, responsive to the toplevel BRLCAD_BUNDLED_LIBS option
-and testing first for a system version if BRLCAD_BUNDLED_LIBS is also AUTO.
-
-Aliases:  ENABLE_SPSR
-
-
 --- BRLCAD_SC ---
 
 Option for enabling and disabling compilation of the NIST Step Class

Modified: brlcad/trunk/configure
===================================================================
--- brlcad/trunk/configure      2020-10-01 19:56:41 UTC (rev 77310)
+++ brlcad/trunk/configure      2020-10-01 20:42:02 UTC (rev 77311)
@@ -162,10 +162,6 @@
                                   shift;;
      --disable-opennurbs)                options="$options 
-DBRLCAD_OPENNURBS=SYSTEM";
                                   shift;;
-     --enable-spsr)                options="$options -DBRLCAD_SPSR=BUNDLED";
-                                  shift;;
-     --disable-spsr)                options="$options -DBRLCAD_SPSR=SYSTEM";
-                                  shift;;
      --enable-scl)                options="$options -DBRLCAD_SC=BUNDLED";
                                   shift;;
      --disable-scl)                options="$options -DBRLCAD_SC=SYSTEM";

Modified: brlcad/trunk/doc/legal/embedded/SPSR.txt
===================================================================
--- brlcad/trunk/doc/legal/embedded/SPSR.txt    2020-10-01 19:56:41 UTC (rev 
77310)
+++ brlcad/trunk/doc/legal/embedded/SPSR.txt    2020-10-01 20:42:02 UTC (rev 
77311)
@@ -85,49 +85,43 @@
 reason for such modification.
 
 file:/include/bg/spsr.h
-file:/src/other/libspsr/Src/Allocator.h
-file:/src/other/libspsr/Src/Array.h
-file:/src/other/libspsr/Src/Array.inl
-file:/src/other/libspsr/Src/BSplineData.h
-file:/src/other/libspsr/Src/BSplineData.inl
-file:/src/other/libspsr/Src/BinaryNode.h
-file:/src/other/libspsr/Src/CmdLineParser.cpp
-file:/src/other/libspsr/Src/CmdLineParser.h
-file:/src/other/libspsr/Src/CmdLineParser.inl
-file:/src/other/libspsr/Src/Factor.cpp
-file:/src/other/libspsr/Src/Factor.h
-file:/src/other/libspsr/Src/FunctionData.h
-file:/src/other/libspsr/Src/FunctionData.inl
-file:/src/other/libspsr/Src/Geometry.cpp
-file:/src/other/libspsr/Src/Geometry.h
-file:/src/other/libspsr/Src/Geometry.inl
-file:/src/other/libspsr/Src/Hash.h
-file:/src/other/libspsr/Src/MAT.h
-file:/src/other/libspsr/Src/MAT.inl
-file:/src/other/libspsr/Src/MarchingCubes.cpp
-file:/src/other/libspsr/Src/MarchingCubes.h
-file:/src/other/libspsr/Src/MemoryUsage.h
-file:/src/other/libspsr/Src/MultiGridOctreeData.IsoSurface.inl
-file:/src/other/libspsr/Src/MultiGridOctreeData.SortedTreeNodes.inl
-file:/src/other/libspsr/Src/MultiGridOctreeData.h
-file:/src/other/libspsr/Src/MultiGridOctreeData.inl
-file:/src/other/libspsr/Src/MyTime.h
-file:/src/other/libspsr/Src/Octree.h
-file:/src/other/libspsr/Src/Octree.inl
-file:/src/other/libspsr/Src/PPolynomial.h
-file:/src/other/libspsr/Src/PPolynomial.inl
-file:/src/other/libspsr/Src/PlyVertexMini.h
-file:/src/other/libspsr/Src/PointStream.h
-file:/src/other/libspsr/Src/PointStream.inl
-file:/src/other/libspsr/Src/PoissonRecon.cpp
-file:/src/other/libspsr/Src/Polynomial.h
-file:/src/other/libspsr/Src/Polynomial.inl
-file:/src/other/libspsr/Src/SPSR.cpp
-file:/src/other/libspsr/Src/SPSR.h
-file:/src/other/libspsr/Src/SparseMatrix.h
-file:/src/other/libspsr/Src/SparseMatrix.inl
-file:/src/other/libspsr/Src/SurfaceTrimmer.cpp
-file:/src/other/libspsr/Src/Vector.h
-file:/src/other/libspsr/Src/Vector.inl
-file:/src/other/libspsr/Src/cvertex.h
+file:/src/libbg/spsr/Allocator.h
+file:/src/libbg/spsr/Array.h
+file:/src/libbg/spsr/Array.inl
+file:/src/libbg/spsr/BSplineData.h
+file:/src/libbg/spsr/BSplineData.inl
+file:/src/libbg/spsr/BinaryNode.h
+file:/src/libbg/spsr/Factor.cpp
+file:/src/libbg/spsr/Factor.h
+file:/src/libbg/spsr/FunctionData.h
+file:/src/libbg/spsr/FunctionData.inl
+file:/src/libbg/spsr/Geometry.cpp
+file:/src/libbg/spsr/Geometry.h
+file:/src/libbg/spsr/Geometry.inl
+file:/src/libbg/spsr/Hash.h
+file:/src/libbg/spsr/MAT.h
+file:/src/libbg/spsr/MAT.inl
+file:/src/libbg/spsr/MarchingCubes.cpp
+file:/src/libbg/spsr/MarchingCubes.h
+file:/src/libbg/spsr/MemoryUsage.h
+file:/src/libbg/spsr/MultiGridOctreeData.IsoSurface.inl
+file:/src/libbg/spsr/MultiGridOctreeData.SortedTreeNodes.inl
+file:/src/libbg/spsr/MultiGridOctreeData.h
+file:/src/libbg/spsr/MultiGridOctreeData.inl
+file:/src/libbg/spsr/Octree.h
+file:/src/libbg/spsr/Octree.inl
+file:/src/libbg/spsr/PPolynomial.h
+file:/src/libbg/spsr/PPolynomial.inl
+file:/src/libbg/spsr/PlyVertexMini.h
+file:/src/libbg/spsr/PointStream.h
+file:/src/libbg/spsr/PointStream.inl
+file:/src/libbg/spsr/Polynomial.h
+file:/src/libbg/spsr/Polynomial.inl
+file:/src/libbg/spsr/SPSR.cpp
+file:/src/libbg/spsr/SPSR.h
+file:/src/libbg/spsr/SparseMatrix.h
+file:/src/libbg/spsr/SparseMatrix.inl
+file:/src/libbg/spsr/Vector.h
+file:/src/libbg/spsr/Vector.inl
+file:/src/libbg/spsr/cvertex.h
 

Modified: brlcad/trunk/misc/CMake/BRLCAD_Targets.cmake
===================================================================
--- brlcad/trunk/misc/CMake/BRLCAD_Targets.cmake        2020-10-01 19:56:41 UTC 
(rev 77310)
+++ brlcad/trunk/misc/CMake/BRLCAD_Targets.cmake        2020-10-01 20:42:02 UTC 
(rev 77311)
@@ -121,9 +121,9 @@
     endwhile(NOT "${f_ext}" STREQUAL "")
 
     # C++
-    if(${srcfile_ext} STREQUAL ".cxx" OR ${srcfile_ext} STREQUAL ".cpp" OR 
${srcfile_ext} STREQUAL ".cc")
+    if(${srcfile_ext} STREQUAL ".cxx" OR ${srcfile_ext} STREQUAL ".cpp" OR 
${srcfile_ext} STREQUAL ".cc" OR ${srcfile_ext} STREQUAL ".inl")
       set(file_language CXX)
-    endif(${srcfile_ext} STREQUAL ".cxx" OR ${srcfile_ext} STREQUAL ".cpp" OR 
${srcfile_ext} STREQUAL ".cc")
+    endif(${srcfile_ext} STREQUAL ".cxx" OR ${srcfile_ext} STREQUAL ".cpp" OR 
${srcfile_ext} STREQUAL ".cc" OR ${srcfile_ext} STREQUAL ".inl")
     if(${srcfile_ext} STREQUAL ".hxx" OR ${srcfile_ext} STREQUAL ".hpp" OR 
${srcfile_ext} STREQUAL ".hh")
       set(file_language CXX)
     endif(${srcfile_ext} STREQUAL ".hxx" OR ${srcfile_ext} STREQUAL ".hpp" OR 
${srcfile_ext} STREQUAL ".hh")

Modified: brlcad/trunk/src/external/Creo/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/external/Creo/CMakeLists.txt       2020-10-01 19:56:41 UTC 
(rev 77310)
+++ brlcad/trunk/src/external/Creo/CMakeLists.txt       2020-10-01 20:42:02 UTC 
(rev 77311)
@@ -207,7 +207,6 @@
     libnmg
     librt
     libwdb
-    SPSR
     gdiam
     openNURBS
     poly2tri
@@ -295,7 +294,6 @@
       configure_file(creo-brl.dat.in 
${CMAKE_CURRENT_BINARY_DIR}/${CFG_TYPE}/creo-brl-debug.dat @ONLY)
     endforeach(CFG_TYPE ${CMAKE_CONFIGURATION_TYPES})
        set_property(TARGET creo-brl-exe APPEND PROPERTY COMPILE_DEFINITIONS 
"TINYCTHREAD_DLL_IMPORTS")
-       set_property(TARGET creo-brl-exe APPEND PROPERTY COMPILE_DEFINITIONS 
"SPSR_DLL_IMPORTS")
   endif(DEFINED CREO_EXEC_PLUGIN)
 
   # Install the resource files

Modified: brlcad/trunk/src/libbg/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libbg/CMakeLists.txt       2020-10-01 19:56:41 UTC (rev 
77310)
+++ brlcad/trunk/src/libbg/CMakeLists.txt       2020-10-01 20:42:02 UTC (rev 
77311)
@@ -8,6 +8,47 @@
   )
 BRLCAD_LIB_INCLUDE_DIRS(bg BG_INCLUDE_DIRS "")
 
+set(SPSR_srcs
+  spsr/Allocator.h
+  spsr/Array.h
+  spsr/Array.inl
+  spsr/BinaryNode.h
+  spsr/BSplineData.h
+  spsr/BSplineData.inl
+  spsr/cvertex.h
+  spsr/Factor.cpp
+  spsr/Factor.h
+  spsr/FunctionData.h
+  spsr/FunctionData.inl
+  spsr/Geometry.cpp
+  spsr/Geometry.h
+  spsr/Geometry.inl
+  spsr/Hash.h
+  spsr/MarchingCubes.cpp
+  spsr/MarchingCubes.h
+  spsr/MAT.h
+  spsr/MAT.inl
+  spsr/MultiGridOctreeData.h
+  spsr/MultiGridOctreeData.inl
+  spsr/MultiGridOctreeData.IsoSurface.inl
+  spsr/MultiGridOctreeData.SortedTreeNodes.inl
+  spsr/Octree.h
+  spsr/Octree.inl
+  spsr/PlyVertexMini.h
+  spsr/PointStream.h
+  spsr/PointStream.inl
+  spsr/Polynomial.h
+  spsr/Polynomial.inl
+  spsr/PPolynomial.h
+  spsr/PPolynomial.inl
+  spsr/SparseMatrix.h
+  spsr/SparseMatrix.inl
+  spsr/SPSR.cpp
+  spsr/SPSR.h
+  spsr/Vector.h
+  spsr/Vector.inl
+  )
+
 set(LIBBG_SOURCES
   aabb_ray.c
   chull.c
@@ -23,6 +64,7 @@
   polygon_triangulate.cpp
   polygon_point_in.c
   spsr.c
+  ${SPSR_srcs}
   tri_pt.c
   tri_ray.c
   tri_tri.c
@@ -31,15 +73,13 @@
   util.c
   )
 
-BRLCAD_ADDLIB(libbg "${LIBBG_SOURCES}" "libbn;libbu;SPSR;${P2T_LIBRARY}")
+BRLCAD_ADDLIB(libbg "${LIBBG_SOURCES}" "libbn;libbu;${P2T_LIBRARY}")
 set_target_properties(libbg PROPERTIES VERSION 20.0.1 SOVERSION 20)
 if (HIDE_INTERNAL_SYMBOLS)
-  set_property(TARGET libbg APPEND PROPERTY COMPILE_DEFINITIONS 
"SPSR_DLL_IMPORTS")
   if (TARGET poly2tri OR HIDE_INTERNAL_SYMBOLS_EXT)
     set_property(TARGET libbg APPEND PROPERTY COMPILE_DEFINITIONS 
"P2T_DLL_IMPORTS")
   endif (TARGET poly2tri OR HIDE_INTERNAL_SYMBOLS_EXT)
   if (TARGET libbg-obj)
-    set_property(TARGET libbg-obj APPEND PROPERTY COMPILE_DEFINITIONS 
"SPSR_DLL_IMPORTS")
     if (TARGET poly2tri OR HIDE_INTERNAL_SYMBOLS_EXT)
       set_property(TARGET libbg-obj APPEND PROPERTY COMPILE_DEFINITIONS 
"P2T_DLL_IMPORTS")
     endif (TARGET poly2tri OR HIDE_INTERNAL_SYMBOLS_EXT)
@@ -55,6 +95,7 @@
   delaunator.hpp
   earcut.hpp
   pointgen.c
+  spsr/LICENSE
   )
 
 CMAKEFILES(${bg_ignore})
@@ -66,3 +107,4 @@
 # indent-tabs-mode: t
 # End:
 # ex: shiftwidth=2 tabstop=8
+

Added: brlcad/trunk/src/libbg/spsr/Allocator.h
===================================================================
--- brlcad/trunk/src/libbg/spsr/Allocator.h                             (rev 0)
+++ brlcad/trunk/src/libbg/spsr/Allocator.h     2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,163 @@
+/*
+Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+#ifndef ALLOCATOR_INCLUDED
+#define ALLOCATOR_INCLUDED
+#include <vector>
+
+class AllocatorState{
+public:
+       int index,remains;
+};
+/** This templated class assists in memory allocation and is well suited for 
instances
+  * when it is known that the sequence of memory allocations is performed in a 
stack-based
+  * manner, so that memory allocated last is released first. It also 
preallocates memory
+  * in chunks so that multiple requests for small chunks of memory do not 
require separate
+  * system calls to the memory manager.
+  * The allocator is templated off of the class of objects that we would like 
it to allocate,
+  * ensuring that appropriate constructors and destructors are called as 
necessary.
+  */
+template<class T>
+class Allocator
+{
+       int blockSize;
+       int index , remains;
+       std::vector< T* > memory;
+public:
+       Allocator( void ){ blockSize = index = remains = 0; }
+       ~Allocator( void ){ reset(); }
+
+       /** This method is the allocators destructor. It frees up any of the 
memory that
+         * it has allocated. */
+       void reset( void )
+       {
+               for(size_t i=0;i<memory.size();i++){delete[] memory[i];}
+               memory.clear();
+               blockSize=index=remains=0;
+       }
+       /** This method returns the memory state of the allocator. */
+       AllocatorState getState( void ) const
+       {
+               AllocatorState s;
+               s.index=index;
+               s.remains=remains;
+               return s;
+       }
+
+
+       /** This method rolls back the allocator so that it makes all of the 
memory previously
+         * allocated available for re-allocation. Note that it does it not 
call the constructor
+         * again, so after this method has been called, assumptions about the 
state of the values
+         * in memory are no longer valid. */
+       void rollBack(void)
+       {
+               if( memory.size() )
+               {
+                       for( size_t i=0 ; i<memory.size() ; i++ )
+                       {
+                               for( int j=0 ; j<blockSize ; j++ )
+                               {
+                                       memory[i][j].~T();
+                                       new(&memory[i][j]) T();
+                               }
+                       }
+                       index=0;
+                       remains=blockSize;
+               }
+       }
+       /** This method rolls back the allocator to the previous memory state 
and makes all of the memory previously
+         * allocated available for re-allocation. Note that it does it not 
call the constructor
+         * again, so after this method has been called, assumptions about the 
state of the values
+         * in memory are no longer valid. */
+       void rollBack(const AllocatorState& state){
+               if(state.index<index || (state.index==index && 
state.remains<remains)){
+                       if(state.index<index){
+                               for(int j=state.remains;j<blockSize;j++){
+                                       memory[state.index][j].~T();
+                                       new(&memory[state.index][j]) T();
+                               }
+                               for(int i=state.index+1;i<index-1;i++){
+                                       for(int j=0;j<blockSize;j++){
+                                               memory[i][j].~T();
+                                               new(&memory[i][j]) T();
+                                       }
+                               }
+                               for(int j=0;j<remains;j++){
+                                       memory[index][j].~T();
+                                       new(&memory[index][j]) T();
+                               }
+                               index=state.index;
+                               remains=state.remains;
+                       }
+                       else{
+                               for(int j=0;j<state.remains;j<remains){
+                                       memory[index][j].~T();
+                                       new(&memory[index][j]) T();
+                               }
+                               remains=state.remains;
+                       }
+               }
+       }
+
+       /** This method initializes the constructor and the blockSize variable 
specifies the
+         * the number of objects that should be pre-allocated at a time. */
+       void set( int blockSize)
+       {
+               reset();
+               this->blockSize = blockSize;
+               index=-1;
+               remains=0;
+       }
+
+       /** This method returns a pointer to an array of elements objects. If 
there is left over pre-allocated
+         * memory, this method simply returns a pointer to the next free piece 
of memory, otherwise it pre-allocates
+         * more memory. Note that if the number of objects requested is larger 
than the value blockSize with which
+         * the allocator was initialized, the request for memory will fail.
+         */
+       T* newElements( int elements=1 )
+       {
+               T* mem;
+               if( !elements ) return NULL;
+               if( elements>blockSize ) fprintf( stderr , "[ERROR] Allocator: 
elements bigger than block-size: %d>%d\n" , elements , blockSize ) , exit( 0 );
+               if( remains<elements )
+               {
+                       if( index==memory.size()-1 )
+                       {
+                               mem = new T[blockSize];
+                               if( !mem ) fprintf( stderr , "[ERROR] Failed to 
allocate memory\n" ) , exit(0);
+                               memory.push_back( mem );
+                       }
+                       index++;
+                       remains=blockSize;
+               }
+               mem = &(memory[index][blockSize-remains]);
+               remains -= elements;
+               return mem;
+       }
+};
+#endif // ALLOCATOR_INCLUDE


Property changes on: brlcad/trunk/src/libbg/spsr/Allocator.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/Array.h
===================================================================
--- brlcad/trunk/src/libbg/spsr/Array.h                         (rev 0)
+++ brlcad/trunk/src/libbg/spsr/Array.h 2020-10-01 20:42:02 UTC (rev 77311)
@@ -0,0 +1,97 @@
+/*
+Copyright (c) 2011, Michael Kazhdan and Ming Chuang
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+#ifndef ARRAY_INCLUDED
+#define ARRAY_INCLUDED
+
+#include <vector>
+
+#define ARRAY_DEBUG 0
+
+// Code from http://stackoverflow.com
+void* aligned_malloc( size_t size , size_t align )
+{
+       // Align enough for the data, the alignment padding, and room to store 
a pointer to the actual start of the memory
+       void*  mem = malloc( size + align + sizeof( void* ) );
+       // The position at which we could potentially start addressing
+       char* amem = ( (char*)mem ) + sizeof( void* );
+       // Add align-1 to the start of the address and then zero out at most of 
the first align-1 bits.
+       amem = ( char* )( ( (size_t)( ( (char*)amem ) + (align-1) ) ) & ~( 
align-1 ) );
+       // Pre-write the actual address
+       ( ( void** ) amem )[-1] = mem;
+       return amem;
+}
+void aligned_free( void* mem ) { free( ( ( void** )mem )[-1] ); }
+
+#if ARRAY_DEBUG
+#pragma message ( "[WARNING] Array debugging is enabled" )
+#include "Array.inl"
+#define      Pointer( ... )      Array< __VA_ARGS__ >
+#define ConstPointer( ... ) ConstArray< __VA_ARGS__ >
+template< class C > void        FreePointer( Array< C >& a ){ a.Free( ); }
+template< class C > void AlignedFreePointer( Array< C >& a ){ a.Free( ); }
+template< class C > void       VFreePointer( Array< C >& a ){ a.Free( ); }
+template< class C > void      DeletePointer( Array< C >& a ){ a.Delete( ); }
+
+template< class C > Array< C >          NewPointer(                  size_t 
size ,                 const char* name=NULL ){ return Array< C >::New         
(     size ,                     name ); }
+template< class C > Array< C >        AllocPointer(                  size_t 
size ,                 const char* name=NULL ){ return Array< C >::Alloc       
(     size ,             false , name ); }
+template< class C > Array< C > AlignedAllocPointer(                  size_t 
size , size_t alignment , const char* name=NULL ){ return Array< C 
>::AlignedAlloc(     size , alignment , false , name ); }
+template< class C > Array< C >      ReAllocPointer( Array< C >&  a , size_t 
size ,                 const char* name=NULL ){ return Array< C >::ReAlloc     
( a , size ,             false , name ); }
+
+template< class C > Array< C > NullPointer( void ){ return Array< C >( ); }
+
+template< class C >       C* PointerAddress(      Array< C >& a ) { return 
a.pointer(); }
+template< class C > const C* PointerAddress( ConstArray< C >& a ) { return 
a.pointer(); }
+template< class C >      Array< C > GetPointer(       C& c ) { return      
Array< C >::FromPointer( &c , 1 ); }
+template< class C > ConstArray< C > GetPointer( const C& c ) { return 
ConstArray< C >::FromPointer( &c , 1 ); }
+template< class C >      Array< C > GetPointer(       std::vector< C >& v ){ 
return      Array< C >::FromPointer( &v[0] , v.size() ); }
+template< class C > ConstArray< C > GetPointer( const std::vector< C >& v ){ 
return ConstArray< C >::FromPointer( &v[0] , v.size() ); }
+
+#else // !ARRAY_DEBUG
+#define      Pointer( ... )       __VA_ARGS__*
+#define ConstPointer( ... ) const __VA_ARGS__*
+
+#define        FreePointer( ... ) { if( __VA_ARGS__ )         free( 
__VA_ARGS__ ) ,                   __VA_ARGS__ = NULL; }
+#define AlignedFreePointer( ... ) { if( __VA_ARGS__ ) aligned_free( 
__VA_ARGS__ ) ,                   __VA_ARGS__ = NULL; }
+#define      DeletePointer( ... ) { if( __VA_ARGS__ )      delete[] 
__VA_ARGS__ ,                     __VA_ARGS__ = NULL; }
+
+template< class C > C*          NewPointer(        size_t size ,               
     const char* name=NULL ){ return new C[size]; }
+template< class C > C*        AllocPointer(        size_t size ,               
     const char* name=NULL ){ return (C*)        malloc(        sizeof(C) * 
size             ); }
+template< class C > C* AlignedAllocPointer(        size_t size , size_t 
alignment , const char* name=NULL ){ return (C*)aligned_malloc(        
sizeof(C) * size , alignment ); }
+template< class C > C*      ReAllocPointer( C* c , size_t size ,               
     const char* name=NULL ){ return (C*)       realloc( c    , sizeof(C) * 
size             ); }
+
+template< class C > C* NullPointer( void ){ return NULL; }
+
+template< class C >       C* PointerAddress(       C* c ){ return c; }
+template< class C > const C* PointerAddress( const C* c ){ return c; }
+template< class C >       C* GetPointer(       C& c ){ return &c; }
+template< class C > const C* GetPointer( const C& c ){ return &c; }
+template< class C >       C* GetPointer(       std::vector< C >& v ){ return 
&v[0]; }
+template< class C > const C* GetPointer( const std::vector< C >& v ){ return 
&v[0]; }
+#endif // ARRAY_DEBUG
+#endif // ARRAY_INCLUDED


Property changes on: brlcad/trunk/src/libbg/spsr/Array.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/Array.inl
===================================================================
--- brlcad/trunk/src/libbg/spsr/Array.inl                               (rev 0)
+++ brlcad/trunk/src/libbg/spsr/Array.inl       2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,655 @@
+/*
+Copyright (c) 2011, Michael Kazhdan and Ming Chuang
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+#define FULL_ARRAY_DEBUG    0  // Note that this is not thread-safe
+
+#include <stdio.h>
+#include <emmintrin.h>
+#include <vector>
+#include <stddef.h>
+
+inline bool isfinitef( float fp ){ float f=fp; return ((*(unsigned 
*)&f)&0x7f800000)!=0x7f800000; }
+
+
+template< class C >        bool IsValid( const C& c );
+#if _DEBUG
+template< >         inline bool IsValid< float >( const float& f ) { return 
isfinitef( f ) &&  ( f==0.f || abs(f)>1e-31f ); }
+#else // !_DEBUG
+template< >         inline bool IsValid< float >( const float& f ) { return 
isfinitef( f ); }
+#endif // _DEBUG
+template< >         inline bool IsValid< __m128 >( const __m128& m )
+{
+       const __m128* addr = &m;
+       if( size_t(addr) & 15 ) return false;
+       else                    return true;
+}
+template< class C > inline bool IsValid( const C& c ){ return true; }
+
+
+#if FULL_ARRAY_DEBUG
+class DebugMemoryInfo
+{
+public:
+       const void* address;
+       char name[512];
+};
+static std::vector< DebugMemoryInfo > memoryInfo;
+#endif // FULL_ARRAY_DEBUG
+
+template< class C >
+class Array
+{
+       void _assertBounds( long long idx ) const
+       {
+               if( idx<min || idx>=max )
+               {
+                       fprintf( stderr , "Array index out-of-bounds: %lld <= 
%lld < %lld\n" , min , idx , max );
+                       ASSERT( 0 );
+                       exit( 0 );
+               }
+       }
+protected:
+       C *data , *_data;
+       long long min , max;
+#if FULL_ARRAY_DEBUG
+       static void _AddMemoryInfo( const void* ptr , const char* name )
+       {
+               size_t sz = memoryInfo.size();
+               memoryInfo.resize( sz + 1 );
+               memoryInfo[sz].address = ptr;
+               if( name ) strcpy( memoryInfo[sz].name , name );
+               else memoryInfo[sz].name[0] = 0;
+       }
+       static void _RemoveMemoryInfo( const void* ptr )
+       {
+               {
+                       size_t idx;
+                       for( idx=0 ; idx<memoryInfo.size( ) ; idx++ ) if( 
memoryInfo[idx].address==ptr ) break;
+                       if( idx==memoryInfo.size() )
+                       {
+                               fprintf( stderr , "Could not find memory in 
address table\n" );
+                               ASSERT( 0 );
+                       }
+                       else
+                       {
+                               memoryInfo[idx] = 
memoryInfo[memoryInfo.size()-1];
+                               memoryInfo.pop_back( );
+                       }
+               }
+       }
+#endif // FULL_ARRAY_DEBUG
+
+public:
+       long long minimum( void ) const { return min; }
+       long long maximum( void ) const { return max; }
+
+       static inline Array New( size_t size , const char* name=NULL )
+       {
+               Array a;
+               a._data = a.data = new C[size];
+               a.min = 0;
+#pragma message( "[WARNING] Casting unsigned to signed" )
+               a.max = ( long long ) size;
+#if FULL_ARRAY_DEBUG
+               _AddMemoryInfo( a._data , name );
+#endif // FULL_ARRAY_DEBUG
+               return a;
+       }
+       static inline Array Alloc( size_t size , bool clear , const char* 
name=NULL )
+       {
+               Array a;
+               a._data = a.data = ( C* ) malloc( size * sizeof( C ) );
+               if( clear ) memset( a.data ,  0 , size * sizeof( C ) );
+//             else        memset( a.data , -1 , size * sizeof( C ) );
+               a.min = 0;
+#pragma message( "[WARNING] Casting unsigned to signed" )
+               a.max = ( long long ) size;
+#if FULL_ARRAY_DEBUG
+               _AddMemoryInfo( a._data , name );
+#endif // FULL_ARRAY_DEBUG
+               return a;
+       }
+       static inline Array AlignedAlloc( size_t size , size_t alignment , bool 
clear , const char* name=NULL )
+       {
+               Array a;
+               a.data = ( C* ) aligned_malloc( sizeof(C) * size , alignment );
+               a._data = ( C* )( ( ( void** )a.data )[-1] );
+               if( clear ) memset( a.data ,  0 , size * sizeof( C ) );
+//             else        memset( a.data , -1 , size * sizeof( C ) );
+               a.min = 0;
+#pragma message( "[WARNING] Casting unsigned to signed" )
+               a.max = ( long long ) size;
+#if FULL_ARRAY_DEBUG
+               _AddMemoryInfo( a._data , name );
+#endif // FULL_ARRAY_DEBUG
+               return a;
+       }
+       static inline Array ReAlloc( Array& a , size_t size , bool clear , 
const char* name=NULL )
+       {
+               Array _a;
+               _a._data = _a.data = ( C* ) realloc( a.data , size * sizeof( C 
) );
+               if( clear ) memset( _a.data ,  0 , size * sizeof( C ) );
+#if FULL_ARRAY_DEBUG
+               _RemoveMemoryInfo( a._data );
+#endif // FULL_ARRAY_DEBUG
+               a._data = NULL;
+               _a.min = 0;
+#pragma message( "[WARNING] Casting unsigned to signed" )
+               _a.max = ( long long ) size;
+#if FULL_ARRAY_DEBUG
+               _AddMemoryInfo( _a._data , name );
+#endif // FULL_ARRAY_DEBUG
+               return _a;
+       }
+
+       Array( void )
+       {
+               data = _data = NULL;
+               min = max = 0;
+       }
+       template< class D >
+       Array( Array< D >& a )
+       {
+               _data = NULL;
+               if( !a )
+               {
+                       data =  NULL;
+                       min = max = 0;
+               }
+               else
+               {
+                       // [WARNING] Changing szC and szD to size_t causes some 
really strange behavior.
+                       long long szC = sizeof( C );
+                       long long szD = sizeof( D );
+                       data = (C*)&a[0];
+                       min = ( a.minimum() * szD ) / szC;
+                       max = ( a.maximum() * szD ) / szC;
+                       if( min*szC!=a.minimum()*szD || 
max*szC!=a.maximum()*szD )
+                       {
+                               fprintf( stderr , "Could not convert array [ 
%lld , %lld ] * %lld => [ %lld , %lld ] * %lld\n" , a.minimum() , a.maximum() , 
szD , min , max , szC );
+                               ASSERT( 0 );
+                               exit( 0 );
+                       }
+               }
+       }
+       static Array FromPointer( C* data , long long max )
+       {
+               Array a;
+               a._data = NULL;
+               a.data = data;
+               a.min = 0;
+               a.max = max;
+               return a;
+       }
+       static Array FromPointer( C* data , long long min , long long max )
+       {
+               Array a;
+               a._data = NULL;
+               a.data = data;
+               a.min = min;
+               a.max = max;
+               return a;
+       }
+       inline bool operator == ( const Array< C >& a ) const { return 
data==a.data; }
+       inline bool operator != ( const Array< C >& a ) const { return 
data!=a.data; }
+       inline bool operator == ( const C* c ) const { return data==c; }
+       inline bool operator != ( const C* c ) const { return data!=c; }
+       inline C* operator -> ( void )
+       {
+               _assertBounds( 0 );
+               return data;
+       }
+       inline const C* operator -> ( ) const
+       {
+               _assertBounds( 0 );
+               return data;
+       }
+       inline C& operator[]( long long idx )
+       {
+               _assertBounds( idx );
+               return data[idx];
+       }
+       inline const C& operator[]( long long idx ) const
+       {
+               _assertBounds( idx );
+               return data[idx];
+       }
+       inline Array operator + ( int idx ) const
+       {
+               Array a;
+               a._data = _data;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline Array operator + ( long long idx ) const
+       {
+               Array a;
+               a._data = _data;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline Array operator + ( unsigned int idx ) const
+       {
+               Array a;
+               a._data = _data;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline Array operator + ( unsigned long long idx ) const
+       {
+               Array a;
+               a._data = _data;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline Array& operator += ( int idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline Array& operator += ( long long idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline Array& operator += ( unsigned int idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline Array& operator += ( unsigned long long idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline Array& operator ++ ( void  ) { return (*this) += 1; }
+       Array  operator -  ( int idx ) const { return (*this) +  (-idx); }
+       Array  operator -  ( long long idx ) const { return (*this) +  (-idx); }
+       Array  operator -  ( unsigned int idx ) const { return (*this) +  
(-idx); }
+       Array  operator -  ( unsigned long long idx ) const { return (*this) +  
(-idx); }
+       Array& operator -= ( int idx )    { return (*this) += (-idx); }
+       Array& operator -= ( long long idx )    { return (*this) += (-idx); }
+       Array& operator -= ( unsigned int idx )    { return (*this) += (-idx); }
+       Array& operator -= ( unsigned long long idx )    { return (*this) += 
(-idx); }
+       Array& operator -- ( void ) { return (*this) -= 1; }
+       long long operator - ( const Array& a ) const { return ( long long )( 
data - a.data ); }
+
+       void Free( void )
+       {
+               if( _data )
+               {
+                       free( _data );
+#if FULL_ARRAY_DEBUG
+                       _RemoveMemoryInfo( _data );
+#endif // FULL_ARRAY_DEBUG
+               }
+               (*this) = Array( );
+       }
+       void Delete( void )
+       {
+               if( _data )
+               {
+                       delete[] _data;
+#if FULL_ARRAY_DEBUG
+                       _RemoveMemoryInfo( _data );
+#endif // FULL_ARRAY_DEBUG
+               }
+               (*this) = Array( );
+       }
+       C* pointer( void ){ return data; }
+       const C* pointer( void ) const { return data; }
+       bool operator !( void ) const { return data==NULL; }
+       operator bool( ) const { return data!=NULL; }
+};
+
+template< class C >
+class ConstArray
+{
+       void _assertBounds( long long idx ) const
+       {
+               if( idx<min || idx>=max )
+               {
+                       fprintf( stderr , "ConstArray index out-of-bounds: %lld 
<= %lld < %lld\n" , min , idx , max );
+                       ASSERT( 0 );
+                       exit( 0 );
+               }
+       }
+protected:
+       const C *data;
+       long long min , max;
+public:
+       long long minimum( void ) const { return min; }
+       long long maximum( void ) const { return max; }
+
+       inline ConstArray( void )
+       {
+               data = NULL;
+               min = max = 0;
+       }
+       inline ConstArray( const Array< C >& a )
+       {
+               // [WARNING] Changing szC and szD to size_t causes some really 
strange behavior.
+               data = ( const C* )a.pointer( );
+               min = a.minimum();
+               max = a.maximum();
+       }
+       template< class D >
+       inline ConstArray( const Array< D >& a )
+       {
+               // [WARNING] Changing szC and szD to size_t causes some really 
strange behavior.
+               long long szC = ( long long ) sizeof( C );
+               long long szD = ( long long ) sizeof( D );
+               data = ( const C* )a.pointer( );
+               min = ( a.minimum() * szD ) / szC;
+               max = ( a.maximum() * szD ) / szC;
+               if( min*szC!=a.minimum()*szD || max*szC!=a.maximum()*szD )
+               {
+//                     fprintf( stderr , "Could not convert const array [ %lld 
, %lld ] * %lld => [ %lld , %lld ] * %lld\n" , a.minimum() , a.maximum() , szD 
, min , max , szC );
+                       fprintf( stderr , "Could not convert const array [ %lld 
, %lld ] * %lld => [ %lld , %lld ] * %lld\n %lld %lld %lld\n" , a.minimum() , 
a.maximum() , szD , min , max , szC , a.minimum() , a.minimum()*szD , 
(a.minimum()*szD)/szC );
+                       ASSERT( 0 );
+                       exit( 0 );
+               }
+       }
+       template< class D >
+       inline ConstArray( const ConstArray< D >& a )
+       {
+               // [WARNING] Changing szC and szD to size_t causes some really 
strange behavior.
+               long long szC = sizeof( C );
+               long long szD = sizeof( D );
+               data = ( const C*)a.pointer( );
+               min = ( a.minimum() * szD ) / szC;
+               max = ( a.maximum() * szD ) / szC;
+               if( min*szC!=a.minimum()*szD || max*szC!=a.maximum()*szD )
+               {
+                       fprintf( stderr , "Could not convert array [ %lld , 
%lld ] * %lld => [ %lld , %lld ] * %lld\n" , a.minimum() , a.maximum() , szD , 
min , max , szC );
+                       ASSERT( 0 );
+                       exit( 0 );
+               }
+       }
+       static ConstArray FromPointer( const C* data , long long max )
+       {
+               ConstArray a;
+               a.data = data;
+               a.min = 0;
+               a.max = max;
+               return a;
+       }
+       static ConstArray FromPointer( const C* data , long long min , long 
long max )
+       {
+               ConstArray a;
+               a.data = data;
+               a.min = min;
+               a.max = max;
+               return a;
+       }
+
+       inline bool operator == ( const ConstArray< C >& a ) const { return 
data==a.data; }
+       inline bool operator != ( const ConstArray< C >& a ) const { return 
data!=a.data; }
+       inline bool operator == ( const C* c ) const { return data==c; }
+       inline bool operator != ( const C* c ) const { return data!=c; }
+       inline const C* operator -> ( void )
+       {
+               _assertBounds( 0 );
+               return data;
+       }
+       inline const C& operator[]( long long idx ) const
+       {
+               _assertBounds( idx );
+               return data[idx];
+       }
+       inline ConstArray operator + ( int idx ) const
+       {
+               ConstArray a;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline ConstArray operator + ( long long idx ) const
+       {
+               ConstArray a;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline ConstArray operator + ( unsigned int idx ) const
+       {
+               ConstArray a;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline ConstArray operator + ( unsigned long long idx ) const
+       {
+               ConstArray a;
+               a.data = data+idx;
+               a.min = min-idx;
+               a.max = max-idx;
+               return a;
+       }
+       inline ConstArray& operator += ( int idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline ConstArray& operator += ( long long idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline ConstArray& operator += ( unsigned int idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline ConstArray& operator += ( unsigned long long idx  )
+       {
+               min -= idx;
+               max -= idx;
+               data += idx;
+               return (*this);
+       }
+       inline ConstArray& operator ++ ( void ) { return (*this) += 1; }
+       ConstArray  operator -  ( int idx ) const { return (*this) +  (-idx); }
+       ConstArray  operator -  ( long long idx ) const { return (*this) +  
(-idx); }
+       ConstArray  operator -  ( unsigned int idx ) const { return (*this) +  
(-idx); }
+       ConstArray  operator -  ( unsigned long long idx ) const { return 
(*this) +  (-idx); }
+       ConstArray& operator -= ( int idx )    { return (*this) += (-idx); }
+       ConstArray& operator -= ( long long idx )    { return (*this) += 
(-idx); }
+       ConstArray& operator -= ( unsigned int idx )    { return (*this) += 
(-idx); }
+       ConstArray& operator -= ( unsigned long long idx )    { return (*this) 
+= (-idx); }
+       ConstArray& operator -- ( void ) { return (*this) -= 1; }
+       long long operator - ( const ConstArray& a ) const { return ( long long 
)( data - a.data ); }
+       long long operator - ( const Array< C >& a ) const { return ( long long 
)( data - a.pointer() ); }
+
+       const C* pointer( void ) const { return data; }
+       bool operator !( void ) { return data==NULL; }
+       operator bool( ) { return data!=NULL; }
+};
+
+#if FULL_ARRAY_DEBUG
+inline void PrintMemoryInfo( void ){ for( size_t i=0 ; i<memoryInfo.size() ; 
i++ ) printf( "%d] %s\n" , i , memoryInfo[i].name ); }
+#endif // FULL_ARRAY_DEBUG
+template< class C >
+Array< C > memcpy( Array< C > destination , const void* source , size_t size )
+{
+       if( size>destination.maximum()*sizeof(C) )
+       {
+               fprintf( stderr , "Size of copy exceeds destination maximum: 
%lld > %lld\n" , ( long long )( size ) , ( long long )( 
destination.maximum()*sizeof( C ) ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size ) memcpy( &destination[0] , source , size );
+       return destination;
+}
+template< class C , class D >
+Array< C > memcpy( Array< C > destination , Array< D > source , size_t size )
+{
+       if( size>destination.maximum()*sizeof( C ) )
+       {
+               fprintf( stderr , "Size of copy exceeds destination maximum: 
%lld > %lld\n" , ( long long )( size ) , ( long long )( 
destination.maximum()*sizeof( C ) ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size>source.maximum()*sizeof( D ) )
+       {
+               fprintf( stderr , "Size of copy exceeds source maximum: %lld > 
%lld\n" , ( long long )( size ) , ( long long )( source.maximum()*sizeof( D ) ) 
);
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size ) memcpy( &destination[0] , &source[0] , size );
+       return destination;
+}
+template< class C , class D >
+Array< C > memcpy( Array< C > destination , ConstArray< D > source , size_t 
size )
+{
+       if( size>destination.maximum()*sizeof( C ) )
+       {
+               fprintf( stderr , "Size of copy exceeds destination maximum: 
%lld > %lld\n" , ( long long )( size ) , ( long  long )( 
destination.maximum()*sizeof( C ) ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size>source.maximum()*sizeof( D ) )
+       {
+               fprintf( stderr , "Size of copy exceeds source maximum: %lld > 
%lld\n" , ( long long )( size ) , ( long long )( source.maximum()*sizeof( D ) ) 
);
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size ) memcpy( &destination[0] , &source[0] , size );
+       return destination;
+}
+template< class D >
+void* memcpy( void* destination , Array< D > source , size_t size )
+{
+       if( size>source.maximum()*sizeof( D ) )
+       {
+               fprintf( stderr , "Size of copy exceeds source maximum: %lld > 
%lld\n" , ( long long )( size ) , ( long long )( source.maximum()*sizeof( D ) ) 
);
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size ) memcpy( destination , &source[0] , size );
+       return destination;
+}
+template< class D >
+void* memcpy( void* destination , ConstArray< D > source , size_t size )
+{
+       if( size>source.maximum()*sizeof( D ) )
+       {
+               fprintf( stderr , "Size of copy exceeds source maximum: %lld > 
%lld\n" , ( long long )( size ) , ( long long )( source.maximum()*sizeof( D ) ) 
);
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size ) memcpy( destination , &source[0] , size );
+       return destination;
+}
+template< class C >
+Array< C > memset( Array< C > destination , int value , size_t size )
+{
+       if( size>destination.maximum()*sizeof( C ) )
+       {
+               fprintf( stderr , "Size of set exceeds destination maximum: 
%lld > %lld\n" , ( long long )( size ) , ( long long )( 
destination.maximum()*sizeof( C ) ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( size ) memset( &destination[0] , value , size );
+       return destination;
+}
+
+template< class C >
+size_t fread( Array< C > destination , size_t eSize , size_t count , FILE* fp )
+{
+       if( count*eSize>destination.maximum()*sizeof( C ) )
+       {
+               fprintf( stderr , "Size of read exceeds source maximum: %lld > 
%lld\n" , ( long long )( count*eSize ) , ( long long )( 
destination.maximum()*sizeof( C ) ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       return fread( &destination[0] , eSize , count , fp );
+}
+template< class C >
+size_t fwrite( Array< C > source , size_t eSize , size_t count , FILE* fp )
+{
+       if( count*eSize>source.maximum()*sizeof( C ) )
+       {
+               fprintf( stderr , "Size of write exceeds source maximum: %lld > 
%lld\n" , ( long long )( count*eSize ) , ( long long )( 
source.maximum()*sizeof( C ) ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       return fwrite( &source[0] , eSize , count , fp );
+}
+template< class C >
+size_t fwrite( ConstArray< C > source , size_t eSize , size_t count , FILE* fp 
)
+{
+       if( count*eSize>source.maximum()*sizeof( C ) )
+       {
+               fprintf( stderr , "Size of write exceeds source maximum: %lld > 
%lld\n" , ( long long )( count*eSize ) , ( long long )( 
source.maximum()*sizeof( C ) ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       return fwrite( &source[0] , eSize , count , fp );
+}
+template< class C >
+void qsort( Array< C > base , size_t numElements , size_t elementSize , int 
(*compareFunction)( const void* , const void* ) )
+{
+       if( sizeof(C)!=elementSize )
+       {
+               fprintf( stderr , "Element sizes differ: %lld != %lld\n" , ( 
long long )( sizeof(C) ) , ( long long )( elementSize ) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       if( base.minimum()>0 || base.maximum()<numElements )
+       {
+               fprintf( stderr , "Array access out of bounds: %lld <= 0 <= 
%lld <= %lld\n" , base.minimum() , base.maximum() , ( long long )( numElements 
) );
+               ASSERT( 0 );
+               exit( 0 );
+       }
+       qsort( base.pointer() , numElements , elementSize , compareFunction );
+}


Property changes on: brlcad/trunk/src/libbg/spsr/Array.inl
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/BSplineData.h
===================================================================
--- brlcad/trunk/src/libbg/spsr/BSplineData.h                           (rev 0)
+++ brlcad/trunk/src/libbg/spsr/BSplineData.h   2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,191 @@
+/*
+Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+#ifndef BSPLINE_DATA_INCLUDED
+#define BSPLINE_DATA_INCLUDED
+
+#include "PPolynomial.h"
+#include "Array.h"
+
+template< int Degree >
+struct BSplineElementCoefficients
+{
+       int coeffs[Degree+1];
+       BSplineElementCoefficients( void ){ memset( coeffs , 0 , sizeof( int ) 
* ( Degree+1 ) ); }
+       int& operator[]( int idx ){ return coeffs[idx]; }
+       const int& operator[]( int idx ) const { return coeffs[idx]; }
+};
+template< int Degree >
+struct BSplineElements : public std::vector< BSplineElementCoefficients< 
Degree > >
+{
+       static const int _off = (Degree+1)/2;
+       void _addLeft ( int offset , int boundary );
+       void _addRight( int offset , int boundary );
+public:
+       enum
+       {
+               NONE      =  0,
+               DIRICHLET = -1,
+               NEUMANN   =  1
+       };
+       // Coefficients are ordered as "/" "-" "\"
+       int denominator;
+
+       BSplineElements( void ) { denominator = 1; }
+       BSplineElements( int res , int offset , int boundary=NONE , int inset=0 
);
+
+       void upSample( BSplineElements& high ) const;
+       void differentiate( BSplineElements< Degree-1 >& d ) const;
+
+       void print( FILE* fp=stdout ) const
+       {
+               for( int i=0 ; i<std::vector< BSplineElementCoefficients< 
Degree > >::size() ; i++ )
+               {
+                       printf( "%d]" , i );
+                       for( int j=0 ; j<=Degree ; j++ ) printf( " %d" , 
(*this)[i][j] );
+                       printf( " (%d)\n" , denominator );
+               }
+       }
+};
+
+template< int Degree >
+class BSplineData
+{
+       int _boundaryType;
+       double _vvIntegrals[Degree+1][Degree+1];
+       double _vdIntegrals[Degree+1][Degree  ];
+       double _dvIntegrals[Degree  ][Degree+1];
+       double _ddIntegrals[Degree  ][Degree  ];
+
+public:
+       struct Integrator
+       {
+               struct IntegralTables
+               {
+                       double vv_ccIntegrals[2*Degree+1][2*Degree+1] , 
vv_cpIntegrals[(2*Degree+1)*2][2*Degree+1];
+                       double dv_ccIntegrals[2*Degree+1][2*Degree+1] , 
dv_cpIntegrals[(2*Degree+1)*2][2*Degree+1];
+                       double vd_ccIntegrals[2*Degree+1][2*Degree+1] , 
vd_cpIntegrals[(2*Degree+1)*2][2*Degree+1];
+                       double dd_ccIntegrals[2*Degree+1][2*Degree+1] , 
dd_cpIntegrals[(2*Degree+1)*2][2*Degree+1];
+               };
+               std::vector< IntegralTables > iTables;
+               double dot( int depth , int off1 , int off2 , bool d1 , bool d2 
, bool childParent=false ) const;
+       };
+       double dot( int depth1 , int off1 , int depth2 , int off2 , bool d1 , 
bool d2 , bool inset=false ) const;
+       void setIntegrator( Integrator& integrator , bool inset , bool 
useDotRatios=false ) const;
+       template< int Radius >
+       struct CenterEvaluator
+       {
+               struct ValueTables
+               {
+                       double vValues[2*Degree+1][ 3*(2*Radius+1) ];
+                       double dValues[2*Degree+1][ 3*(2*Radius+1) ];
+               };
+               std::vector< ValueTables > vTables;
+               double value( int depth , int off1 , int off2 , bool d , bool 
childParent=false ) const;
+       };
+       template< int Radius >
+       void setCenterEvaluator( CenterEvaluator< Radius >& evaluator , double 
smoothingRadius , double dSmoothingRadius, bool inset ) const;
+       double value( int depth , int off , double smoothingRadius , double s , 
bool d , bool inset=false ) const;
+       template< int Radius >
+       struct CornerEvaluator
+       {
+               struct ValueTables
+               {
+                       double vValues[2*Degree+1][4*Radius+3];
+                       double dValues[2*Degree+1][4*Radius+3];
+               };
+               std::vector< ValueTables > vTables;
+               double value( int depth , int off1 , int c1 , int off2 , bool d 
, bool childParent=false ) const;
+       };
+       template< int Radius >
+       void setCornerEvaluator( CornerEvaluator< Radius >& evaluator , double 
smoothingRadius , double dSmoothingRadius, bool inset ) const;
+
+       struct BSplineComponents
+       {
+               Polynomial< Degree > polys[Degree+1];
+               Polynomial< Degree >& operator[] ( int idx ) { return 
polys[idx]; }
+               const Polynomial< Degree >& operator[] ( int idx ) const { 
return polys[idx]; }
+               void printnl( void ) const  { for( int d=0 ; d<=Degree ; d++ ) 
polys[d].printnl(); }
+               BSplineComponents scale( double s ) const { BSplineComponents b 
; for( int d=0 ; d<=Degree ; d++ ) b[d] = polys[d].scale(s) ; return b; }
+               BSplineComponents shift( double s ) const { BSplineComponents b 
; for( int d=0 ; d<=Degree ; d++ ) b[d] = polys[d].shift(s) ; return b; }
+       };
+
+       int depth;
+       size_t functionCount , sampleCount;
+       PPolynomial< Degree   >  baseFunction ,  leftBaseFunction ,  
rightBaseFunction ,  leftRightBaseFunction;
+       PPolynomial< Degree-1 > dBaseFunction , dLeftBaseFunction , 
dRightBaseFunction , dLeftRightBaseFunction;
+       BSplineComponents baseBSpline , leftBSpline , rightBSpline , 
leftRightBSpline;
+       Pointer( PPolynomial< Degree > ) baseFunctions;
+       Pointer( BSplineComponents ) baseBSplines;
+
+       BSplineData( void );
+
+       const static int  VV_DOT_FLAG = 1;
+       const static int  DV_DOT_FLAG = 2;
+       const static int  DD_DOT_FLAG = 4;
+       const static int   VALUE_FLAG = 1;
+       const static int D_VALUE_FLAG = 2;
+       template< class Real >
+       struct DotTables
+       {
+               size_t functionCount;
+               Pointer( Real ) vvDotTable;
+               Pointer( Real ) dvDotTable;
+               Pointer( Real ) ddDotTable;
+
+               DotTables( void );
+               ~DotTables( void );
+
+               inline size_t Index( int i1 , int i2 ) const;
+               static inline size_t SymmetricIndex( int i1 , int i2 );
+               static inline int SymmetricIndex( int i1 , int i2 , size_t& 
index );
+       };
+       template< class Real >
+       struct ValueTables
+       {
+               size_t functionCount , sampleCount;
+               Pointer( Real ) valueTable;
+               Pointer( Real ) dValueTable;
+
+               ValueTables( void );
+               ~ValueTables( void );
+
+               inline size_t Index( int i1 , int i2 ) const;
+               void setSampleSpan( int idx , int& start , int& end , double 
smooth=0 ) const;
+       };
+       void set( int maxDepth , int boundaryType=BSplineElements< Degree 
>::NONE );
+       template< class Real >
+       typename BSplineData< Degree >::template DotTables< Real > 
getDotTables( int flags , bool useDotRatios=true , bool inset=false ) const;
+       template< class Real >
+       typename BSplineData< Degree >::template ValueTables< Real > 
getValueTables( int flags , double valueSmooth=0 , double normalSmooth=0 ) 
const;
+};
+
+template< int Degree1 , int Degree2 > void SetBSplineElementIntegrals( double 
integrals[Degree1+1][Degree2+1] );
+
+#include "BSplineData.inl"
+#endif // BSPLINE_DATA_INCLUDED


Property changes on: brlcad/trunk/src/libbg/spsr/BSplineData.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/BSplineData.inl
===================================================================
--- brlcad/trunk/src/libbg/spsr/BSplineData.inl                         (rev 0)
+++ brlcad/trunk/src/libbg/spsr/BSplineData.inl 2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,733 @@
+/*
+Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+/////////////////
+// BSplineData //
+/////////////////
+// Support[i]:
+//             Odd:  i +/- 0.5 * ( 1 + Degree )
+//                     i - 0.5 * ( 1 + Degree ) < 0
+// <=>         i < 0.5 * ( 1 + Degree )
+//                     i + 0.5 * ( 1 + Degree ) > 0
+// <=>         i > - 0.5 * ( 1 + Degree )
+//                     i + 0.5 * ( 1 + Degree ) > r
+// <=>      i > r - 0.5 * ( 1 + Degree )
+//                     i - 0.5 * ( 1 + Degree ) < r
+// <=>      i < r + 0.5 * ( 1 + Degree )
+//             Even: i + 0.5 +/- 0.5 * ( 1 + Degree )
+//                     i - 0.5 * Degree < 0
+// <=>         i < 0.5 * Degree
+//                     i + 1 + 0.5 * Degree > 0
+// <=>         i > -1 - 0.5 * Degree
+//                     i + 1 + 0.5 * Degree > r
+// <=>         i > r - 1 - 0.5 * Degree
+//                     i - 0.5 * Degree < r
+// <=>         i < r + 0.5 * Degree
+template< int Degree > inline bool LeftOverlap( unsigned int depth , int 
offset )
+{
+       offset <<= 1;
+       if( Degree & 1 ) return (offset < 1+Degree) && (offset > -1-Degree );
+       else             return (offset <   Degree) && (offset > -2-Degree );
+}
+template< int Degree > inline bool RightOverlap( unsigned int depth , int 
offset )
+{
+       offset <<= 1;
+       int r = 1<<(depth+1);
+       if( Degree & 1 ) return (offset > 2-1-Degree) && (offset < 2+1+Degree );
+       else             return (offset > 2-2-Degree) && (offset < 2+  Degree );
+}
+template< int Degree > inline int ReflectLeft( unsigned int depth , int offset 
)
+{
+       if( Degree&1 ) return   -offset;
+       else           return -1-offset;
+}
+template< int Degree > inline int ReflectRight( unsigned int depth , int 
offset )
+{
+       int r = 1<<(depth+1);
+       if( Degree&1 ) return r  -offset;
+       else           return r-1-offset;
+}
+
+template< int Degree >
+BSplineData< Degree >::BSplineData( void )
+{
+       functionCount = sampleCount = 0;
+       SetBSplineElementIntegrals< Degree   , Degree   >( _vvIntegrals );
+       SetBSplineElementIntegrals< Degree   , Degree-1 >( _vdIntegrals );
+       SetBSplineElementIntegrals< Degree-1 , Degree   >( _dvIntegrals );
+       SetBSplineElementIntegrals< Degree-1 , Degree-1 >( _ddIntegrals );
+}
+
+template< int Degree >
+double BSplineData< Degree >::Integrator::dot( int depth , int off1 , int off2 
, bool d1 , bool d2 , bool childParent ) const
+{
+       if( depth<0 || depth>=int( iTables.size() ) ) return 0.;
+       const typename Integrator::IntegralTables& iTable = iTables[depth];
+       if( childParent )
+       {
+               int c = off1&1;
+               off1 >>= 1 , depth--;
+               int ii , d = off2-off1 , res = (1<<depth);
+               if( depth<0 || off1<0 || off2<0 || off1>=res || off2>=res || 
d<-Degree || d>Degree ) return 0;
+               if     ( off1<     Degree ) ii = off1;
+               else if( off1>=res-Degree ) ii = 2*Degree + off1 - (res-1);
+               else                        ii = Degree;
+               if     ( d1 && d2 ) return 
iTable.dd_cpIntegrals[2*ii+c][d+Degree];
+               else if( d1       ) return 
iTable.dv_cpIntegrals[2*ii+c][d+Degree];
+               else if(       d2 ) return 
iTable.vd_cpIntegrals[2*ii+c][d+Degree];
+               else                return 
iTable.vv_cpIntegrals[2*ii+c][d+Degree];
+       }
+       else
+       {
+               int ii , d = off2-off1 , res = (1<<depth);
+               if( off1<0 || off2<0 || off1>=res || off2>=res || d<-Degree || 
d>Degree ) return 0;
+               if     ( off1<     Degree ) ii = off1;
+               else if( off1>=res-Degree ) ii = 2*Degree + off1 - (res-1);
+               else                        ii = Degree;
+               if     ( d1 && d2 ) return iTable.dd_ccIntegrals[ii][d+Degree];
+               else if( d1       ) return iTable.dv_ccIntegrals[ii][d+Degree];
+               else if(       d2 ) return iTable.vd_ccIntegrals[ii][d+Degree];
+               else                return iTable.vv_ccIntegrals[ii][d+Degree];
+       }
+}
+template< int Degree >
+template< int Radius >
+double BSplineData< Degree >::CenterEvaluator< Radius >::value( int depth , 
int off1 , int off2 , bool d , bool childParent ) const
+{
+       if( depth<0 || depth>=int( vTables.size() ) ) return 0.;
+       if( childParent )
+       {
+               int c = off1&1;
+               off1 >>= 1 , depth--;
+               const typename CenterEvaluator::ValueTables& vTable = 
vTables[depth];
+               int ii , dd = off1-off2 , res = (1<<depth);
+               if( depth<0 || off1<0 || off2<0 || off1>=res || off2>=res || 
dd<-Radius || dd>Radius ) return 0;
+               if     ( off2<     Degree ) ii = off2;
+               else if( off2>=res-Degree ) ii = 2*Degree + off2 - (res-1);
+               else                        ii = Degree;
+               if( d ) return vTable.dValues[ii][(dd+Radius)*3+2*c];
+               else    return vTable.vValues[ii][(dd+Radius)*3+2*c];
+       }
+       else
+       {
+               const typename CenterEvaluator::ValueTables& vTable = 
vTables[depth];
+               int ii , dd = off1-off2 , res = (1<<depth);
+               if( off1<0 || off2<0 || off1>=res || off2>=res || dd<-Radius || 
dd>Radius ) return 0;
+               if     ( off2<     Degree ) ii = off2;
+               else if( off2>=res-Degree ) ii = 2*Degree + off2 - (res-1);
+               else                        ii = Degree;
+               if( d ) return vTable.dValues[ii][(dd+Radius)*3+1];
+               else    return vTable.vValues[ii][(dd+Radius)*3+1];
+       }
+}
+template< int Degree >
+template< int Radius >
+double BSplineData< Degree >::CornerEvaluator< Radius >::value( int depth , 
int off1 , int c1 , int off2 , bool d , bool childParent ) const
+{
+       if( c1<0 || c1>=2 )
+       {
+               fprintf( stderr , "[WARNING] Clamping corner to {0,1}\n" );
+               c1 = std::max< int >( 0 , std::min< int >( c1 , 1 ) );
+       }
+       if( depth<0 || depth>=int( vTables.size() ) ) return 0.;
+       if( childParent )
+       {
+               int c = off1&1;
+               off1 >>= 1 , depth--;
+               const typename CornerEvaluator::ValueTables& vTable = 
vTables[depth];
+               int ii , dd = off1-off2 , res = (1<<depth);
+               if( depth<0 || off1<0 || off2<0 || off1>=res || off2>=res || 
dd<-Radius || dd>Radius ) return 0;
+               if     ( off2<     Degree ) ii = off2;
+               else if( off2>=res-Degree ) ii = 2*Degree + off2 - (res-1);
+               else                        ii = Degree;
+               if( d ) return vTable.dValues[ii][(dd+Radius)*2+c+c1];
+               else    return vTable.vValues[ii][(dd+Radius)*2+c+c1];
+       }
+       else
+       {
+               const typename CornerEvaluator::ValueTables& vTable = 
vTables[depth];
+               int ii , dd = off1-off2 , res = (1<<depth);
+               if( off1<0 || off2<0 || off1>=res || off2>=res || dd<-Radius || 
dd>Radius ) return 0;
+               if     ( off2<     Degree ) ii = off2;
+               else if( off2>=res-Degree ) ii = 2*Degree + off2 - (res-1);
+               else                        ii = Degree;
+               if( d ) return vTable.dValues[ii][(dd+Radius)*2+2*c1];
+               else    return vTable.vValues[ii][(dd+Radius)*2+2*c1];
+       }
+}
+template< int Degree >
+void BSplineData< Degree >::set( int maxDepth , int boundaryType )
+{
+       _boundaryType = boundaryType;
+
+       depth = maxDepth;
+       // [Warning] This assumes that the functions spacing is dual
+       functionCount = BinaryNode::CumulativeCenterCount( depth );
+       sampleCount   = BinaryNode::CenterCount( depth ) + 
BinaryNode::CornerCount( depth );
+       baseFunctions = NewPointer< PPolynomial< Degree > >( functionCount );
+       baseBSplines = NewPointer< BSplineComponents >( functionCount );
+
+       baseFunction = PPolynomial< Degree >::BSpline();
+       for( int i=0 ; i<=Degree ; i++ ) baseBSpline[i] = Polynomial< Degree 
>::BSplineComponent( i ).shift( double(-(Degree+1)/2) + i - 0.5 );
+       dBaseFunction = baseFunction.derivative();
+       StartingPolynomial< Degree > sPolys[Degree+4];
+
+       for( int i=0 ; i<Degree+3 ; i++ )
+       {
+               sPolys[i].start = double(-(Degree+1)/2) + i - 1.5;
+               sPolys[i].p *= 0;
+               if(         i<=Degree   )  sPolys[i].p += baseBSpline[i  
].shift( -1 ) * _boundaryType;
+               if( i>=1 && i<=Degree+1 )  sPolys[i].p += baseBSpline[i-1];
+               for( int j=0 ; j<i ; j++ ) sPolys[i].p -= sPolys[j].p;
+       }
+       leftBaseFunction.set( sPolys , Degree+3 );
+       for( int i=0 ; i<Degree+3 ; i++ )
+       {
+               sPolys[i].start = double(-(Degree+1)/2) + i - 0.5;
+               sPolys[i].p *= 0;
+               if(         i<=Degree   )  sPolys[i].p += baseBSpline[i  ];
+               if( i>=1 && i<=Degree+1 )  sPolys[i].p += 
baseBSpline[i-1].shift( 1 ) * _boundaryType;
+               for( int j=0 ; j<i ; j++ ) sPolys[i].p -= sPolys[j].p;
+       }
+       rightBaseFunction.set( sPolys , Degree+3 );
+       for( int i=0 ; i<Degree+4 ; i++ )
+       {
+               sPolys[i].start = double(-(Degree+1)/2) + i - 1.5;
+               sPolys[i].p *= 0;
+               if(         i<=Degree   )  sPolys[i].p += baseBSpline[i  
].shift( -1 ) * _boundaryType; // The left-shifted B-spline
+               if( i>=1 && i<=Degree+1 )  sPolys[i].p += baseBSpline[i-1];     
        // The centered B-Spline
+               if( i>=2 && i<=Degree+2 )  sPolys[i].p += 
baseBSpline[i-2].shift(  1 ) * _boundaryType; // The right-shifted B-spline
+               for( int j=0 ; j<i ; j++ ) sPolys[i].p -= sPolys[j].p;
+       }
+       leftRightBaseFunction.set( sPolys , Degree+4 );
+
+       dLeftBaseFunction  =  leftBaseFunction.derivative();
+       dRightBaseFunction = rightBaseFunction.derivative();
+       dLeftRightBaseFunction = leftRightBaseFunction.derivative();
+       leftRightBSpline = leftBSpline = rightBSpline = baseBSpline;
+       leftBSpline [1] +=  leftBSpline[2].shift( -1 ) ,  leftBSpline[0] *= 0;
+       rightBSpline[1] += rightBSpline[0].shift(  1 ) , rightBSpline[2] *= 0;
+       leftRightBSpline[1] += leftRightBSpline[2].shift( -1 ) + 
leftRightBSpline[0].shift( 1 ) , leftRightBSpline[0] *= 0 , leftRightBSpline[2] 
*= 0 ;
+
+       double c , w;
+       for( size_t i=0 ; i<functionCount ; i++ )
+       {
+               BinaryNode::CenterAndWidth( int(i) , c , w );
+               baseFunctions[i] = baseFunction.scale(w).shift(c);
+               baseBSplines[i] = baseBSpline.scale(w).shift(c);
+               if( _boundaryType )
+               {
+                       int d , off , r;
+                       BinaryNode::DepthAndOffset( int(i) , d , off );
+                       r = 1<<d;
+                       if     ( off==0 && off==r-1 ) baseFunctions[i] = 
leftRightBaseFunction.scale(w).shift(c);
+                       else if( off==0             ) baseFunctions[i] =      
leftBaseFunction.scale(w).shift(c);
+                       else if(           off==r-1 ) baseFunctions[i] =     
rightBaseFunction.scale(w).shift(c);
+                       if     ( off==0 && off==r-1 ) baseBSplines [i] = 
leftRightBSpline.scale(w).shift(c);
+                       else if( off==0             ) baseBSplines [i] =      
leftBSpline.scale(w).shift(c);
+                       else if(           off==r-1 ) baseBSplines [i] =     
rightBSpline.scale(w).shift(c);
+               }
+       }
+}
+template< int Degree >
+double BSplineData< Degree >::dot( int depth1 ,  int off1 , int depth2 , int 
off2 , bool d1 , bool d2 , bool inset ) const
+{
+       const int _Degree1 = (d1 ? (Degree-1) : Degree) , _Degree2 = (d2 ? 
(Degree-1) : Degree);
+       int sums[ Degree+1 ][ Degree+1 ];
+
+       int depth = std::max< int >( depth1 , depth2 );
+
+       BSplineElements< Degree > b1( 1<<depth1 , off1 , _boundaryType , inset 
? ( 1<<(depth1-2) ) : 0 ) , b2( 1<<depth2 , off2 , _boundaryType , inset ? ( 
1<<(depth2-2) ) : 0 );
+
+       BSplineElements< Degree > b;
+       while( depth1<depth ) b=b1 , b.upSample( b1 ) , depth1++;
+       while( depth2<depth ) b=b2 , b.upSample( b2 ) , depth2++;
+
+       BSplineElements< Degree-1 > db1 , db2;
+       b1.differentiate( db1 ) , b2.differentiate( db2 );
+
+       int start1=-1 , end1=-1 , start2=-1 , end2=-1;
+       for( int i=0 ; i<int( b1.size() ) ; i++ ) for( int j=0 ; j<=Degree ; 
j++ )
+       {
+               if( b1[i][j] && start1==-1 ) start1 = i;
+               if( b1[i][j] ) end1 = i+1;
+               if( b2[i][j] && start2==-1 ) start2 = i;
+               if( b2[i][j] ) end2 = i+1;
+       }
+       if( start1==end1 || start2==end2 || start1>=end2 || start2>=end1 ) 
return 0.;
+       int start = std::max< int >( start1 , start2 ) , end = std::min< int >( 
end1 , end2 );
+       memset( sums , 0 , sizeof( sums ) );
+       for( int i=start ; i<end ; i++ ) for( int j=0 ; j<=_Degree1 ; j++ ) 
for( int k=0 ; k<=_Degree2 ; k++ ) sums[j][k] += ( d1 ?  db1[i][j] : b1[i][j] ) 
* ( d2 ? db2[i][k] : b2[i][k] );
+       double _dot = 0;
+       if     ( d1 && d2 ) for( int j=0 ; j<=_Degree1 ; j++ ) for( int k=0 ; 
k<=_Degree2 ; k++ ) _dot += _ddIntegrals[j][k] * sums[j][k];
+       else if( d1       ) for( int j=0 ; j<=_Degree1 ; j++ ) for( int k=0 ; 
k<=_Degree2 ; k++ ) _dot += _dvIntegrals[j][k] * sums[j][k];
+       else if(       d2 ) for( int j=0 ; j<=_Degree1 ; j++ ) for( int k=0 ; 
k<=_Degree2 ; k++ ) _dot += _vdIntegrals[j][k] * sums[j][k];
+       else                for( int j=0 ; j<=_Degree1 ; j++ ) for( int k=0 ; 
k<=_Degree2 ; k++ ) _dot += _vvIntegrals[j][k] * sums[j][k];
+       _dot /= b1.denominator;
+       _dot /= b2.denominator;
+       if     ( d1 && d2 ) return _dot * (1<<depth);
+       else if( d1 || d2 ) return _dot;
+       else                return _dot / (1<<depth);
+}
+template< int Degree >
+double BSplineData< Degree >::value( int depth ,  int off , double 
smoothingRadius ,  double s , bool d , bool inset ) const
+{
+       PPolynomial< Degree+1 >  function;
+       PPolynomial< Degree   > dFunction;
+
+       if( off<0 || off>=(1<<depth) ) return 0;
+       int idx = BinaryNode::CenterIndex( depth , off );
+
+       if( smoothingRadius>0 ) function = baseFunctions[idx].MovingAverage( 
smoothingRadius );
+       else                    function = baseFunctions[idx];
+       dFunction = function.derivative();
+
+       if( d ) return dFunction(s);
+       else    return  function(s);
+}
+template< int Degree >
+void BSplineData< Degree >::setIntegrator( Integrator& integrator , bool inset 
, bool useDotRatios ) const
+{
+       integrator.iTables.resize( depth+1 );
+       for( int d=0 ; d<=depth ; d++ ) for( int i=0 ; i<=2*Degree ; i++ ) for( 
int j=-Degree ; j<=Degree ; j++ )
+       {
+               int res = 1<<d , ii = (i<=Degree ? i : i+res-1 - 2*Degree );
+               integrator.iTables[d].vv_ccIntegrals[i][j+Degree] = dot( d , ii 
, d , ii+j , false , false , inset );
+               integrator.iTables[d].dv_ccIntegrals[i][j+Degree] = dot( d , ii 
, d , ii+j , true  , false , inset );
+               integrator.iTables[d].vd_ccIntegrals[i][j+Degree] = dot( d , ii 
, d , ii+j , false , true  , inset );
+               integrator.iTables[d].dd_ccIntegrals[i][j+Degree] = dot( d , ii 
, d , ii+j , true  , true  , inset );
+               if( useDotRatios )
+               {
+                       integrator.iTables[d].dv_ccIntegrals[i][j+Degree] /= 
integrator.iTables[d].vv_ccIntegrals[i][j+Degree];
+                       integrator.iTables[d].vd_ccIntegrals[i][j+Degree] /= 
integrator.iTables[d].vv_ccIntegrals[i][j+Degree];
+                       integrator.iTables[d].dd_ccIntegrals[i][j+Degree] /= 
integrator.iTables[d].vv_ccIntegrals[i][j+Degree];
+               }
+       }
+       for( int d=1 ; d<=depth ; d++ ) for( int i=0 ; i<=2*Degree ; i++ ) for( 
int j=-Degree ; j<=Degree ; j++ )
+       {
+               int res = 1<<d , ii = (i<=Degree ? i : i+(res/2)-1 - 2*Degree );
+               for( int c=0 ; c<2 ; c++ )
+               {
+                       integrator.iTables[d].vv_cpIntegrals[2*i+c][j+Degree] = 
dot( d , 2*ii+c , d-1 , ii+j , false , false , inset );
+                       integrator.iTables[d].dv_cpIntegrals[2*i+c][j+Degree] = 
dot( d , 2*ii+c , d-1 , ii+j , true  , false , inset );
+                       integrator.iTables[d].vd_cpIntegrals[2*i+c][j+Degree] = 
dot( d , 2*ii+c , d-1 , ii+j , false , true  , inset );
+                       integrator.iTables[d].dd_cpIntegrals[2*i+c][j+Degree] = 
dot( d , 2*ii+c , d-1 , ii+j , true  , true  , inset );
+                       if( useDotRatios )
+                       {
+                               
integrator.iTables[d].dv_cpIntegrals[2*i+c][j+Degree] /= 
integrator.iTables[d].vv_cpIntegrals[2*i+c][j+Degree];
+                               
integrator.iTables[d].vd_cpIntegrals[2*i+c][j+Degree] /= 
integrator.iTables[d].vv_cpIntegrals[2*i+c][j+Degree];
+                               
integrator.iTables[d].dd_cpIntegrals[2*i+c][j+Degree] /= 
integrator.iTables[d].vv_cpIntegrals[2*i+c][j+Degree];
+                       }
+               }
+       }
+}
+template< int Degree >
+template< int Radius >
+void BSplineData< Degree >::setCenterEvaluator( CenterEvaluator< Radius >& 
evaluator , double smoothingRadius , double dSmoothingRadius , bool inset ) 
const
+{
+       evaluator.vTables.resize( depth+1 );
+       for( int d=0 ; d<=depth ; d++ ) for( int i=0 ; i<=2*Degree ; i++ ) for( 
int j=-Radius ; j<=Radius ; j++ ) for( int k=-1 ; k<=1 ; k++ )
+       {
+               int res = 1<<d , ii = (i<=Degree ? i : i+res-1 - 2*Degree );
+               double s = 0.5+ii+j+0.25*k;
+               evaluator.vTables[d].vValues[i][(j+Radius)*3+(k+1)] = value( d 
, ii ,  smoothingRadius , s/res , false , inset );
+               evaluator.vTables[d].dValues[i][(j+Radius)*3+(k+1)] = value( d 
, ii , dSmoothingRadius , s/res , true  , inset );
+       }
+}
+template< int Degree >
+template< int Radius >
+void BSplineData< Degree >::setCornerEvaluator( CornerEvaluator< Radius >& 
evaluator , double smoothingRadius , double dSmoothingRadius , bool inset ) 
const
+{
+       evaluator.vTables.resize( depth+1 );
+       for( int d=0 ; d<=depth ; d++ ) for( int i=0 ; i<=2*Degree ; i++ ) for( 
int j=-Radius ; j<=Radius ; j++ ) for( int k=0 ; k<=2 ; k++ )
+       {
+               int res = 1<<d , ii = (i<=Degree ? i : i+res-1 - 2*Degree );
+               double s = ii+j+0.5*k;
+               evaluator.vTables[d].vValues[i][(j+Radius)*2+k] = value( d , ii 
,  smoothingRadius , s/res , false , inset );
+               evaluator.vTables[d].dValues[i][(j+Radius)*2+k] = value( d , ii 
, dSmoothingRadius , s/res , true  , inset );
+       }
+}
+
+
+template< int Degree >
+template< class Real >
+BSplineData< Degree >::DotTables< Real >::DotTables( void )
+{
+       vvDotTable = NullPointer< Real >();
+       dvDotTable = NullPointer< Real >();
+       ddDotTable = NullPointer< Real >();
+}
+template< int Degree >
+template< class Real >
+BSplineData< Degree >::DotTables< Real >::~DotTables( void )
+{
+       DeletePointer( vvDotTable );
+       DeletePointer( dvDotTable );
+       DeletePointer( ddDotTable );
+}
+template< int Degree >
+template< class Real >
+inline size_t BSplineData< Degree >::DotTables< Real >::Index( int i1 , int i2 
) const { return size_t(i1)*functionCount + size_t(i2); }
+template< int Degree >
+template< class Real >
+inline size_t BSplineData< Degree >::DotTables< Real >::SymmetricIndex( int i1 
, int i2 )
+{
+       size_t _i1 = i1 , _i2 = i2;
+       if( i1>i2 ) return ((_i1*_i1+i1)>>1)+_i2;
+       else        return ((_i2*_i2+i2)>>1)+_i1;
+}
+template< int Degree >
+template< class Real >
+inline int BSplineData< Degree >::DotTables< Real >::SymmetricIndex( int i1 , 
int i2 , size_t& index )
+{
+       size_t _i1 = i1 , _i2 = i2;
+       if( i1<i2 )
+       {
+               index = ((_i2*_i2+_i2)>>1)+_i1;
+               return 1;
+       }
+       else
+       {
+               index = ((_i1*_i1+_i1)>>1)+_i2;
+               return 0;
+       }
+}
+template< int Degree >
+template< class Real >
+typename BSplineData< Degree >::template DotTables< Real > BSplineData< Degree 
>::getDotTables( int flags , bool useDotRatios , bool inset ) const
+{
+       typename BSplineData< Degree >::template DotTables< Real > dTables;
+       dTables.functionCount = functionCount;
+
+       size_t size = ( functionCount*functionCount + functionCount )>>1;
+       size_t fullSize = functionCount*functionCount;
+       if( flags & VV_DOT_FLAG )
+       {
+               dTables.vvDotTable = NewPointer< Real >( size );
+               memset( dTables.vvDotTable , 0 , sizeof(Real)*size );
+       }
+       if( flags & DV_DOT_FLAG )
+       {
+               dTables.dvDotTable = NewPointer< Real >( fullSize );
+               memset( dTables.dvDotTable , 0 , sizeof(Real)*fullSize );
+       }
+       if( flags & DD_DOT_FLAG )
+       {
+               dTables.ddDotTable = NewPointer< Real >( size );
+               memset( dTables.ddDotTable , 0 , sizeof(Real)*size );
+       }
+       int vvSums[Degree+1][Degree+1];
+       int vdSums[Degree+1][Degree  ];
+       int dvSums[Degree  ][Degree+1];
+       int ddSums[Degree  ][Degree  ];
+       double vvIntegrals[Degree+1][Degree+1];
+       double vdIntegrals[Degree+1][Degree  ];
+       double dvIntegrals[Degree  ][Degree+1];
+       double ddIntegrals[Degree  ][Degree  ];
+       SetBSplineElementIntegrals< Degree   , Degree   >( vvIntegrals );
+       SetBSplineElementIntegrals< Degree   , Degree-1 >( vdIntegrals );
+       SetBSplineElementIntegrals< Degree-1 , Degree   >( dvIntegrals );
+       SetBSplineElementIntegrals< Degree-1 , Degree-1 >( ddIntegrals );
+
+       for( int d1=0 ; d1<=depth ; d1++ ) for( int off1=0 ; off1<(1<<d1) ; 
off1++ )
+       {
+               int ii = BinaryNode::CenterIndex( d1 , off1 );
+               BSplineElements< Degree > b1( 1<<d1 , off1 , _boundaryType , 
inset ? ( 1<<(d1-2) ) : 0 );
+               BSplineElements< Degree-1 > db1;
+               b1.differentiate( db1 );
+               int start1 , end1;
+
+               start1 = -1 , end1 = -1;
+               for( int i=0 ; i<int(b1.size()) ; i++ ) for( int j=0 ; 
j<=Degree ; j++ )
+               {
+                       if( b1[i][j] && start1==-1 ) start1 = i;
+                       if( b1[i][j] ) end1 = i+1;
+               }
+               if( start1==end1 ) continue;
+               for( int d2=d1 ; d2<=depth ; d2++ )
+               {
+                       for( int off2=0 ; off2<(1<<d2) ; off2++ )
+                       {
+                               int start2 = off2-Degree;
+                               int end2   = off2+Degree+1;
+                               if( start2>=end1 || start1>=end2 ) continue;
+                               start2 = std::max< int >( start1 , start2 );
+                               end2   = std::min< int >(   end1 ,   end2 );
+                               if( d1==d2 && off2<off1 ) continue;
+                               int jj = BinaryNode::CenterIndex( d2 , off2 );
+                               BSplineElements< Degree > b2( 1<<d2 , off2 , 
_boundaryType , inset ? ( 1<<(d2-2) ) : 0 );
+                               BSplineElements< Degree-1 > db2;
+                               b2.differentiate( db2 );
+
+                               size_t idx = DotTables< Real >::SymmetricIndex( 
ii , jj );
+                               size_t idx1 = DotTables< Real >::Index( ii , jj 
) , idx2 = DotTables< Real >::Index( jj , ii );
+
+                               memset( vvSums , 0 , sizeof( int ) * ( Degree+1 
) * ( Degree+1 ) );
+                               memset( vdSums , 0 , sizeof( int ) * ( Degree+1 
) * ( Degree   ) );
+                               memset( dvSums , 0 , sizeof( int ) * ( Degree   
) * ( Degree+1 ) );
+                               memset( ddSums , 0 , sizeof( int ) * ( Degree   
) * ( Degree   ) );
+                               for( int i=start2 ; i<end2 ; i++ )
+                               {
+                                       for( int j=0 ; j<=Degree ; j++ ) for( 
int k=0 ; k<=Degree ; k++ ) vvSums[j][k] +=  b1[i][j] *  b2[i][k];
+                                       for( int j=0 ; j<=Degree ; j++ ) for( 
int k=0 ; k< Degree ; k++ ) vdSums[j][k] +=  b1[i][j] * db2[i][k];
+                                       for( int j=0 ; j< Degree ; j++ ) for( 
int k=0 ; k<=Degree ; k++ ) dvSums[j][k] += db1[i][j] *  b2[i][k];
+                                       for( int j=0 ; j< Degree ; j++ ) for( 
int k=0 ; k< Degree ; k++ ) ddSums[j][k] += db1[i][j] * db2[i][k];
+                               }
+                               double vvDot = 0 , dvDot = 0 , vdDot = 0 , 
ddDot = 0;
+                               for( int j=0 ; j<=Degree ; j++ ) for( int k=0 ; 
k<=Degree ; k++ ) vvDot += vvIntegrals[j][k] * vvSums[j][k];
+                               for( int j=0 ; j<=Degree ; j++ ) for( int k=0 ; 
k< Degree ; k++ ) vdDot += vdIntegrals[j][k] * vdSums[j][k];
+                               for( int j=0 ; j< Degree ; j++ ) for( int k=0 ; 
k<=Degree ; k++ ) dvDot += dvIntegrals[j][k] * dvSums[j][k];
+                               for( int j=0 ; j< Degree ; j++ ) for( int k=0 ; 
k< Degree ; k++ ) ddDot += ddIntegrals[j][k] * ddSums[j][k];
+                               vvDot /= (1<<d2);
+                               ddDot *= (1<<d2);
+                               vvDot /= ( b1.denominator * b2.denominator );
+                               dvDot /= ( b1.denominator * b2.denominator );
+                               vdDot /= ( b1.denominator * b2.denominator );
+                               ddDot /= ( b1.denominator * b2.denominator );
+                               if( fabs(vvDot)<1e-15 ) continue;
+                               if( flags & VV_DOT_FLAG ) 
dTables.vvDotTable[idx] = Real( vvDot );
+                               if( flags & DV_DOT_FLAG ) 
dTables.dvDotTable[idx1] = Real( dvDot );
+                               if( flags & DV_DOT_FLAG ) 
dTables.dvDotTable[idx2] = Real( dvDot );
+                               if( flags & DD_DOT_FLAG ) 
dTables.ddDotTable[idx ] = Real( ddDot );
+                       }
+                       BSplineElements< Degree > b;
+                       b = b1;
+                       b.upSample( b1 );
+                       b1.differentiate( db1 );
+                       start1 = -1;
+                       for( int i=0 ; i<int(b1.size()) ; i++ ) for( int j=0 ; 
j<=Degree ; j++ )
+                       {
+                               if( b1[i][j] && start1==-1 ) start1 = i;
+                               if( b1[i][j] ) end1 = i+1;
+                       }
+               }
+       }
+       return dTables;
+}
+template< int Degree >
+template< class Real >
+BSplineData< Degree >::ValueTables< Real >::ValueTables( void )
+{
+       valueTable = NullPointer< Real >();
+       dValueTable = NullPointer< Real >();
+}
+template< int Degree >
+template< class Real >
+BSplineData< Degree >::ValueTables< Real >::~ValueTables( void )
+{
+       DeletePointer( valueTable );
+       DeletePointer( dValueTable );
+}
+template< int Degree >
+template< class Real >
+inline size_t BSplineData< Degree >::ValueTables< Real >::Index( int i1 , int 
i2 ) const { return size_t(i1)*functionCount + size_t(i2); }
+template< int Degree >
+template< class Real >
+typename BSplineData< Degree >::template ValueTables< Real > BSplineData< 
Degree >::getValueTables( int flags , double valueSmooth , double 
derivativeSmooth ) const
+{
+       typename BSplineData< Degree >::template ValueTables< Real > vTables;
+       vTables.functionCount = functionCount;
+       vTables.sampleCount = sampleCount;
+
+       if( flags &   VALUE_FLAG ) vTables.valueTable = NewPointer< Real >( 
functionCount*sampleCount );
+       if( flags & D_VALUE_FLAG ) vTables.dValueTable = NewPointer< Real >( 
functionCount*sampleCount );
+       PPolynomial< Degree+1 >  function;
+       PPolynomial< Degree   > dFunction;
+       for( size_t i=0 ; i<functionCount ; i++ )
+       {
+               if( valueSmooth>0 )      
function=baseFunctions[i].MovingAverage( valueSmooth );
+               else                     function=baseFunctions[i];
+               if( derivativeSmooth>0 ) 
dFunction=baseFunctions[i].derivative().MovingAverage( derivativeSmooth );
+               else                     
dFunction=baseFunctions[i].derivative();
+
+               for( size_t j=0 ; j<sampleCount ; j++ )
+               {
+                       double x=double(j)/(sampleCount-1);
+                       if( flags &   VALUE_FLAG ) 
vTables.valueTable[j*functionCount+i] = Real( function(x));
+                       if( flags & D_VALUE_FLAG ) 
vTables.dValueTable[j*functionCount+i] = Real(dFunction(x));
+               }
+       }
+       return vTables;
+}
+template< int Degree >
+template< class Real >
+void BSplineData< Degree >::ValueTables< Real >::setSampleSpan( int idx , int& 
start , int& end , double smooth ) const
+{
+       int d , off , res;
+       BinaryNode::DepthAndOffset( idx , d , off );
+       res = 1<<d;
+       double _start = ( off + 0.5 - 0.5*(Degree+1) ) / res - smooth;
+       double _end   = ( off + 0.5 + 0.5*(Degree+1) ) / res + smooth;
+       //   (start)/(sampleCount-1) >_start && 
(start-1)/(sampleCount-1)<=_start
+       // => start > _start * (sampleCount-1 ) && start <= 
_start*(sampleCount-1) + 1
+       // => _start * (sampleCount-1) + 1 >= start > _start * (sampleCount-1)
+       start = int( floor( _start * (sampleCount-1) + 1 ) );
+       if( start<0 ) start = 0;
+       //   (end)/(sampleCount-1)<_end && (end+1)/(sampleCount-1)>=_end
+       // => end < _end * (sampleCount-1 ) && end >= _end*(sampleCount-1) - 1
+       // => _end * (sampleCount-1) > end >= _end * (sampleCount-1) - 1
+       end = int( ceil( _end * (sampleCount-1) - 1 ) );
+       if( end>=int(sampleCount) ) end = int(sampleCount)-1;
+}
+
+
+/////////////////////
+// BSplineElements //
+/////////////////////
+template< int Degree >
+BSplineElements< Degree >::BSplineElements( int res , int offset , int 
boundary , int inset )
+{
+       denominator = 1;
+       std::vector< BSplineElementCoefficients< Degree > >::resize( res , 
BSplineElementCoefficients< Degree >() );
+
+       for( int i=0 ; i<=Degree ; i++ )
+       {
+               int idx = -_off + offset + i;
+               if( idx>=0 && idx<res ) (*this)[idx][i] = 1;
+       }
+       if( boundary!=0 )
+       {
+               _addLeft( offset-2*res , boundary ) , _addRight( offset+2*res , 
boundary );
+               if( Degree&1 ) _addLeft( offset-res , boundary ) , _addRight(  
offset+res     , boundary );
+               else           _addLeft( -offset-1  , boundary ) , _addRight( 
-offset-1+2*res , boundary );
+       }
+       if( inset ) for( int i=0 ; i<inset && i<res ; i++ ) for( int j=0 ; 
j<=Degree ; j++ ) (*this)[i][j] = (*this)[res-1-i][j] = 0;
+}
+template< int Degree >
+void BSplineElements< Degree >::_addLeft( int offset , int boundary )
+{
+       int res = int( std::vector< BSplineElementCoefficients< Degree > 
>::size() );
+       bool set = false;
+       for( int i=0 ; i<=Degree ; i++ )
+       {
+               int idx = -_off + offset + i;
+               if( idx>=0 && idx<res ) (*this)[idx][i] += boundary , set = 
true;
+       }
+       if( set ) _addLeft( offset-2*res , boundary );
+}
+template< int Degree >
+void BSplineElements< Degree >::_addRight( int offset , int boundary )
+{
+       int res = int( std::vector< BSplineElementCoefficients< Degree > 
>::size() );
+       bool set = false;
+       for( int i=0 ; i<=Degree ; i++ )
+       {
+               int idx = -_off + offset + i;
+               if( idx>=0 && idx<res ) (*this)[idx][i] += boundary , set = 
true;
+       }
+       if( set ) _addRight( offset+2*res , boundary );
+}
+template< int Degree >
+void BSplineElements< Degree >::upSample( BSplineElements< Degree >& high ) 
const
+{
+       fprintf( stderr , "[ERROR] B-spline up-sampling not supported for 
degree %d\n" , Degree );
+       exit( 0 );
+}
+template<>
+void BSplineElements< 1 >::upSample( BSplineElements< 1 >& high ) const
+{
+       high.resize( size()*2 );
+       high.assign( high.size() , BSplineElementCoefficients<1>() );
+       for( int i=0 ; i<int(size()) ; i++ )
+       {
+               high[2*i+0][0] += 1 * (*this)[i][0];
+               high[2*i+0][1] += 0 * (*this)[i][0];
+               high[2*i+1][0] += 2 * (*this)[i][0];
+               high[2*i+1][1] += 1 * (*this)[i][0];
+
+               high[2*i+0][0] += 1 * (*this)[i][1];
+               high[2*i+0][1] += 2 * (*this)[i][1];
+               high[2*i+1][0] += 0 * (*this)[i][1];
+               high[2*i+1][1] += 1 * (*this)[i][1];
+       }
+       high.denominator = denominator * 2;
+}
+template<>
+void BSplineElements< 2 >::upSample( BSplineElements< 2 >& high ) const
+{
+       /*    /----\                                                            
      */
+       /*   /      \                                                           
      */
+       /*  /        \  = 1  /--\       +3    /--\     +3      /--\   +1        
/--\  */
+       /* /          \     /    \           /    \           /    \           
/    \ */
+       /* |----------|     |----------|   |----------|   |----------|   
|----------| */
+
+       high.resize( size()*2 );
+       high.assign( high.size() , BSplineElementCoefficients<2>() );
+       for( int i=0 ; i<int(size()) ; i++ )
+       {
+               high[2*i+0][0] += 1 * (*this)[i][0];
+               high[2*i+0][1] += 0 * (*this)[i][0];
+               high[2*i+0][2] += 0 * (*this)[i][0];
+               high[2*i+1][0] += 3 * (*this)[i][0];
+               high[2*i+1][1] += 1 * (*this)[i][0];
+               high[2*i+1][2] += 0 * (*this)[i][0];
+
+               high[2*i+0][0] += 3 * (*this)[i][1];
+               high[2*i+0][1] += 3 * (*this)[i][1];
+               high[2*i+0][2] += 1 * (*this)[i][1];
+               high[2*i+1][0] += 1 * (*this)[i][1];
+               high[2*i+1][1] += 3 * (*this)[i][1];
+               high[2*i+1][2] += 3 * (*this)[i][1];
+
+               high[2*i+0][0] += 0 * (*this)[i][2];
+               high[2*i+0][1] += 1 * (*this)[i][2];
+               high[2*i+0][2] += 3 * (*this)[i][2];
+               high[2*i+1][0] += 0 * (*this)[i][2];
+               high[2*i+1][1] += 0 * (*this)[i][2];
+               high[2*i+1][2] += 1 * (*this)[i][2];
+       }
+       high.denominator = denominator * 4;
+}
+
+template< int Degree >
+void BSplineElements< Degree >::differentiate( BSplineElements< Degree-1 >& d 
) const
+{
+       d.resize( std::vector< BSplineElementCoefficients< Degree > >::size() );
+       d.assign( d.size()  , BSplineElementCoefficients< Degree-1 >() );
+       for( int i=0 ; i<int(std::vector< BSplineElementCoefficients< Degree > 
>::size()) ; i++ ) for( int j=0 ; j<=Degree ; j++ )
+       {
+               if( j-1>=0 )   d[i][j-1] -= (*this)[i][j];
+               if( j<Degree ) d[i][j  ] += (*this)[i][j];
+       }
+       d.denominator = denominator;
+}
+// If we were really good, we would implement this integral table to store
+// rational values to improve precision...
+template< int Degree1 , int Degree2 >
+void SetBSplineElementIntegrals( double integrals[Degree1+1][Degree2+1] )
+{
+       for( int i=0 ; i<=Degree1 ; i++ )
+       {
+               Polynomial< Degree1 > p1 = Polynomial< Degree1 
>::BSplineComponent( i );
+               for( int j=0 ; j<=Degree2 ; j++ )
+               {
+                       Polynomial< Degree2 > p2 = Polynomial< Degree2 
>::BSplineComponent( j );
+                       integrals[i][j] = ( p1 * p2 ).integral( 0 , 1 );
+               }
+       }
+}


Property changes on: brlcad/trunk/src/libbg/spsr/BSplineData.inl
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/BinaryNode.h
===================================================================
--- brlcad/trunk/src/libbg/spsr/BinaryNode.h                            (rev 0)
+++ brlcad/trunk/src/libbg/spsr/BinaryNode.h    2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,78 @@
+/*
+Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+#ifndef BINARY_NODE_INCLUDED
+#define BINARY_NODE_INCLUDED
+
+#define MSVC_2010_FIX 1
+
+
+class BinaryNode
+{
+public:
+       static inline int CenterCount( int depth ) { return  1<<depth; }
+       static inline int CornerCount( int depth ) { return (1<<depth)+1; }
+       static inline int CumulativeCenterCount( int maxDepth ) { return 
(1<<(maxDepth+1))-1; }
+       static inline int CumulativeCornerCount( int maxDepth ) { return 
(1<<(maxDepth+1))+maxDepth; }
+       static inline int CenterIndex( int depth , int offSet ) { return 
(1<<depth)+offSet-1; }
+       static inline int CornerIndex( int depth , int offSet ) { return 
(1<<depth)+offSet+depth; }
+
+       static inline int CornerIndex( int maxDepth , int depth , int offSet , 
int forwardCorner ){ return (offSet+forwardCorner)<<(maxDepth-depth); }
+       template< class Real > static inline Real CornerIndexPosition(int 
index,int maxDepth){ return Real(index)/(1<<maxDepth); }
+       template< class Real > static inline Real Width(int depth){ return 
Real(1.0/(1<<depth)); }
+       template< class Real > static inline void CenterAndWidth( int depth , 
int offset , Real& center , Real& width )
+         {
+           width=Real (1.0/(1<<depth) );
+           center=Real((0.5+offset)*width);
+         }
+       template< class Real > static inline void CenterAndWidth( int idx , 
Real& center , Real& width )
+         {
+           int depth , offset;
+           DepthAndOffset( idx , depth , offset );
+           CenterAndWidth( depth , offset , center , width );
+         }
+       static inline void DepthAndOffset( int idx , int& depth , int& offset )
+         {
+           int i=idx+1;
+#if MSVC_2010_FIX
+               depth = 0;
+#else // !MSVC_2010_FIX
+           depth = -1;
+#endif // MSVC_2010_FIX
+           while( i )
+               {
+             i >>= 1;
+             depth++;
+           }
+#if MSVC_2010_FIX
+               depth--;
+#endif // MSVC_2010_FIX
+           offset = ( idx+1 ) - (1<<depth);
+         }
+};
+#endif // BINARY_NODE_INCLUDED


Property changes on: brlcad/trunk/src/libbg/spsr/BinaryNode.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/Factor.cpp
===================================================================
--- brlcad/trunk/src/libbg/spsr/Factor.cpp                              (rev 0)
+++ brlcad/trunk/src/libbg/spsr/Factor.cpp      2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,285 @@
+/*
+Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+#if defined(__GNUC__) && !defined(__clang__)
+#  pragma GCC diagnostic push
+#endif
+#if defined(__clang__)
+#  pragma clang diagnostic push
+#endif
+#if defined(__GNUC__) && !defined(__clang__)
+#  pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+#if defined(__clang__)
+#  pragma clang diagnostic ignored "-Wfloat-equal"
+#endif
+
+//////////////////////
+// Polynomial Roots //
+//////////////////////
+#include <math.h>
+#include "Factor.h"
+int Factor(double a1,double a0,double roots[1][2],double EPS){
+       if(fabs(a1)<=EPS){return 0;}
+       roots[0][0]=-a0/a1;
+       roots[0][1]=0;
+       return 1;
+}
+int Factor(double a2,double a1,double a0,double roots[2][2],double EPS){
+       double d;
+       if(fabs(a2)<=EPS){return Factor(a1,a0,roots,EPS);}
+
+       d=a1*a1-4*a0*a2;
+       a1/=(2*a2);
+       if(d<0){
+               d=sqrt(-d)/(2*a2);
+               roots[0][0]=roots[1][0]=-a1;
+               roots[0][1]=-d;
+               roots[1][1]= d;
+       }
+       else{
+               d=sqrt(d)/(2*a2);
+               roots[0][1]=roots[1][1]=0;
+               roots[0][0]=-a1-d;
+               roots[1][0]=-a1+d;
+       }
+       return 2;
+}
+// Solution taken from: http://mathworld.wolfram.com/CubicFormula.html
+// and http://www.csit.fsu.edu/~burkardt/f_src/subpak/subpak.f90
+int Factor(double a3,double a2,double a1,double a0,double roots[3][2],double 
EPS){
+       double q,r,r2,q3;
+
+       if(fabs(a3)<=EPS){return Factor(a2,a1,a0,roots,EPS);}
+       a2/=a3;
+       a1/=a3;
+       a0/=a3;
+
+       q=-(3*a1-a2*a2)/9;
+       r=-(9*a2*a1-27*a0-2*a2*a2*a2)/54;
+       r2=r*r;
+       q3=q*q*q;
+
+       if(r2<q3){
+               double sqrQ=sqrt(q);
+               double theta = acos ( r / (sqrQ*q) );
+               double cTheta=cos(theta/3)*sqrQ;
+               double sTheta=sin(theta/3)*sqrQ*SQRT_3/2;
+               roots[0][1]=roots[1][1]=roots[2][1]=0;
+               roots[0][0]=-2*cTheta;
+               roots[1][0]=-2*(-cTheta*0.5-sTheta);
+               roots[2][0]=-2*(-cTheta*0.5+sTheta);
+       }
+       else{
+               double s1,s2,sqr=sqrt(r2-q3);
+               double t;
+               t=-r+sqr;
+               if(t<0){s1=-pow(-t,1.0/3);}
+               else{s1=pow(t,1.0/3);}
+               t=-r-sqr;
+               if(t<0){s2=-pow(-t,1.0/3);}
+               else{s2=pow(t,1.0/3);}
+               roots[0][1]=0;
+               roots[0][0]=s1+s2;
+               s1/=2;
+               s2/=2;
+               roots[1][0]= roots[2][0]=-s1-s2;
+               roots[1][1]= SQRT_3*(s1-s2);
+               roots[2][1]=-roots[1][1];
+       }
+       roots[0][0]-=a2/3;
+       roots[1][0]-=a2/3;
+       roots[2][0]-=a2/3;
+       return 3;
+}
+double ArcTan2(double y,double x){
+       /* This first case should never happen */
+       if(y==0 && x==0){return 0;}
+       if(x==0){
+               if(y>0){return PI/2.0;}
+               else{return -PI/2.0;}
+       }
+       if(x>=0){return atan(y/x);}
+       else{
+               if(y>=0){return atan(y/x)+PI;}
+               else{return atan(y/x)-PI;}
+       }
+}
+double Angle(const double in[2]){
+       if((in[0]*in[0]+in[1]*in[1])==0.0){return 0;}
+       else{return ArcTan2(in[1],in[0]);}
+}
+void Sqrt(const double in[2],double out[2]){
+       double r=sqrt(sqrt(in[0]*in[0]+in[1]*in[1]));
+       double a=Angle(in)*0.5;
+       out[0]=r*cos(a);
+       out[1]=r*sin(a);
+}
+void Add(const double in1[2],const double in2[2],double out[2]){
+       out[0]=in1[0]+in2[0];
+       out[1]=in1[1]+in2[1];
+}
+void Subtract(const double in1[2],const double in2[2],double out[2]){
+       out[0]=in1[0]-in2[0];
+       out[1]=in1[1]-in2[1];
+}
+void Multiply(const double in1[2],const double in2[2],double out[2]){
+       out[0]=in1[0]*in2[0]-in1[1]*in2[1];
+       out[1]=in1[0]*in2[1]+in1[1]*in2[0];
+}
+void Divide(const double in1[2],const double in2[2],double out[2]){
+       double temp[2];
+       double l=in2[0]*in2[0]+in2[1]*in2[1];
+       temp[0]= in2[0]/l;
+       temp[1]=-in2[1]/l;
+       Multiply(in1,temp,out);
+}
+// Solution taken from: http://mathworld.wolfram.com/QuarticEquation.html
+// and http://www.csit.fsu.edu/~burkardt/f_src/subpak/subpak.f90
+int Factor(double a4,double a3,double a2,double a1,double a0,double 
roots[4][2],double EPS){
+       double R[2],D[2],E[2],R2[2];
+
+       if(fabs(a4)<EPS){return Factor(a3,a2,a1,a0,roots,EPS);}
+       a3/=a4;
+       a2/=a4;
+       a1/=a4;
+       a0/=a4;
+
+       Factor(1.0,-a2,a3*a1-4.0*a0,-a3*a3*a0+4.0*a2*a0-a1*a1,roots,EPS);
+
+       R2[0]=a3*a3/4.0-a2+roots[0][0];
+       R2[1]=0;
+       Sqrt(R2,R);
+       if(fabs(R[0])>10e-8){
+               double temp1[2],temp2[2];
+               double p1[2],p2[2];
+
+               p1[0]=a3*a3*0.75-2.0*a2-R2[0];
+               p1[1]=0;
+
+               temp2[0]=((4.0*a3*a2-8.0*a1-a3*a3*a3)/4.0);
+               temp2[1]=0;
+               Divide(temp2,R,p2);
+
+               Add     (p1,p2,temp1);
+               Subtract(p1,p2,temp2);
+
+               Sqrt(temp1,D);
+               Sqrt(temp2,E);
+       }
+       else{
+               R[0]=R[1]=0;
+               double temp1[2],temp2[2];
+               temp1[0]=roots[0][0]*roots[0][0]-4.0*a0;
+               temp1[1]=0;
+               Sqrt(temp1,temp2);
+               temp1[0]=a3*a3*0.75-2.0*a2+2.0*temp2[0];
+               temp1[1]=                  2.0*temp2[1];
+               Sqrt(temp1,D);
+               temp1[0]=a3*a3*0.75-2.0*a2-2.0*temp2[0];
+               temp1[1]=                 -2.0*temp2[1];
+               Sqrt(temp1,E);
+       }
+
+       roots[0][0]=-a3/4.0+R[0]/2.0+D[0]/2.0;
+       roots[0][1]=        R[1]/2.0+D[1]/2.0;
+
+       roots[1][0]=-a3/4.0+R[0]/2.0-D[0]/2.0;
+       roots[1][1]=        R[1]/2.0-D[1]/2.0;
+
+       roots[2][0]=-a3/4.0-R[0]/2.0+E[0]/2.0;
+       roots[2][1]=       -R[1]/2.0+E[1]/2.0;
+
+       roots[3][0]=-a3/4.0-R[0]/2.0-E[0]/2.0;
+       roots[3][1]=       -R[1]/2.0-E[1]/2.0;
+       return 4;
+}
+
+int Solve(const double* eqns,const double* values,double* solutions,int dim){
+       int i,j,eIndex;
+       double v,m;
+       int *index=new int[dim];
+       int *set=new int[dim];
+       double* myEqns=new double[dim*dim];
+       double* myValues=new double[dim];
+
+       for(i=0;i<dim*dim;i++){myEqns[i]=eqns[i];}
+       for(i=0;i<dim;i++){
+               myValues[i]=values[i];
+               set[i]=0;
+       }
+       for(i=0;i<dim;i++){
+               // Find the largest equation that has a non-zero entry in the 
i-th index
+               m=-1;
+               eIndex=-1;
+               for(j=0;j<dim;j++){
+                       if(set[j]){continue;}
+                       if(myEqns[j*dim+i]!=0 && fabs(myEqns[j*dim+i])>m){
+                               m=fabs(myEqns[j*dim+i]);
+                               eIndex=j;
+                       }
+               }
+               if(eIndex==-1){
+                       delete[] index;
+                       delete[] myValues;
+                       delete[] myEqns;
+                       delete[] set;
+                       return 0;
+               }
+               // The position in which the solution for the i-th variable can 
be found
+               index[i]=eIndex;
+               set[eIndex]=1;
+
+               // Normalize the equation
+               v=myEqns[eIndex*dim+i];
+               for(j=0;j<dim;j++){myEqns[eIndex*dim+j]/=v;}
+               myValues[eIndex]/=v;
+
+               // Subtract it off from everything else
+               for(j=0;j<dim;j++){
+                       if(j==eIndex){continue;}
+                       double vv=myEqns[j*dim+i];
+                       for(int 
k=0;k<dim;k++){myEqns[j*dim+k]-=myEqns[eIndex*dim+k]*vv;}
+                       myValues[j]-=myValues[eIndex]*vv;
+               }
+       }
+       for(i=0;i<dim;i++){solutions[i]=myValues[index[i]];}
+       delete[] index;
+       delete[] myValues;
+       delete[] myEqns;
+       delete[] set;
+       return 1;
+}
+
+#if defined(__GNUC__) && !defined(__clang__)
+#  pragma GCC diagnostic pop
+#endif
+#if defined(__clang__)
+#  pragma clang diagnostic pop
+#endif
+


Property changes on: brlcad/trunk/src/libbg/spsr/Factor.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/Factor.h
===================================================================
--- brlcad/trunk/src/libbg/spsr/Factor.h                                (rev 0)
+++ brlcad/trunk/src/libbg/spsr/Factor.h        2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+#ifndef FACTOR_INCLUDED
+#define FACTOR_INCLUDED
+
+#define PI 3.1415926535897932384
+#define SQRT_3 1.7320508075688772935
+
+double ArcTan2(double y,double x);
+double Angle(const double in[2]);
+void Sqrt(const double in[2],double out[2]);
+void Add(const double in1[2],const double in2[2],double out[2]);
+void Subtract(const double in1[2],const double in2[2],double out[2]);
+void Multiply(const double in1[2],const double in2[2],double out[2]);
+void Divide(const double in1[2],const double in2[2],double out[2]);
+
+int Factor(double a1,double a0,double roots[1][2],double EPS);
+int Factor(double a2,double a1,double a0,double roots[2][2],double EPS);
+int Factor(double a3,double a2,double a1,double a0,double roots[3][2],double 
EPS);
+int Factor(double a4,double a3,double a2,double a1,double a0,double 
roots[4][2],double EPS);
+
+int Solve(const double* eqns,const double* values,double* solutions, int dim);
+
+#endif // FACTOR_INCLUDED


Property changes on: brlcad/trunk/src/libbg/spsr/Factor.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbg/spsr/FunctionData.h
===================================================================
--- brlcad/trunk/src/libbg/spsr/FunctionData.h                          (rev 0)
+++ brlcad/trunk/src/libbg/spsr/FunctionData.h  2020-10-01 20:42:02 UTC (rev 
77311)
@@ -0,0 +1,109 @@
+/*
+Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
list of
+conditions and the following disclaimer. Redistributions in binary form must 
reproduce
+the above copyright notice, this list of conditions and the following 
disclaimer
+in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Johns Hopkins University nor the names of its 
contributors
+may be used to endorse or promote products derived from this software without 
specific
+prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+#ifndef FUNCTION_DATA_INCLUDED
+#define FUNCTION_DATA_INCLUDED
+
+#define BOUNDARY_CONDITIONS 1
+
+
+#include "PPolynomial.h"
+
+template<int Degree,class Real>
+class FunctionData{
+       bool useDotRatios;
+       int normalize;
+#if BOUNDARY_CONDITIONS
+       bool reflectBoundary;
+#endif // BOUNDARY_CONDITIONS
+public:
+       const static int     DOT_FLAG = 1;
+       const static int   D_DOT_FLAG = 2;
+       const static int  D2_DOT_FLAG = 4;
+       const static int   VALUE_FLAG = 1;
+       const static int D_VALUE_FLAG = 2;
+
+       int depth , res , res2;
+       Real *dotTable , *dDotTable , *d2DotTable;
+       Real *valueTables , *dValueTables;
+#if BOUNDARY_CONDITIONS
+       PPolynomial<Degree> baseFunction , leftBaseFunction , rightBaseFunction;
+       PPolynomial<Degree-1> dBaseFunction , dLeftBaseFunction , 
dRightBaseFunction;
+#else // !BOUNDARY_CONDITIONS
+       PPolynomial<Degree> baseFunction;
+       PPolynomial<Degree-1> dBaseFunction;
+#endif // BOUNDARY_CONDITIONS
+       PPolynomial<Degree+1>* baseFunctions;
+
+       FunctionData(void);
+       ~FunctionData(void);
+
+       virtual void   setDotTables(const int& flags);
+       virtual void clearDotTables(const int& flags);
+
+       virtual void   setValueTables(const int& flags,const double& smooth=0);
+       virtual void   setValueTables(const int& flags,const double& 
valueSmooth,const double& normalSmooth);
+       virtual void clearValueTables(void);
+
+       /********************************************************

@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to