diff --git a/trunk/fcl/CMakeLists.txt b/trunk/fcl/CMakeLists.txt
index d948e8b182b3182ed6e46e01680afae6f2b35804..fbe11232fc30236acebdc12ae8445128cbfd1267 100644
--- a/trunk/fcl/CMakeLists.txt
+++ b/trunk/fcl/CMakeLists.txt
@@ -32,7 +32,7 @@ set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
 add_definitions(-DUSE_PQP=0)
 add_definitions(-DUSE_SVMLIGHT=0)
 
-rosbuild_add_library(${PROJECT_NAME} src/AABB.cpp src/OBB.cpp src/RSS.cpp src/vec_3f.cpp src/traversal_node_base.cpp src/traversal_node_bvhs.cpp src/intersect.cpp src/motion.cpp src/BV_fitter.cpp src/BV_splitter.cpp src/BVH_model.cpp src/BVH_utility.cpp src/transform.cpp src/simple_setup.cpp src/geometric_shapes.cpp src/geometric_shapes_utility.cpp src/geometric_shapes_intersect.cpp src/collision_node.cpp src/traversal_recurse.cpp src/broad_phase_collision.cpp src/collision.cpp src/collision_func_matrix.cpp src/interval_tree.cpp src/conservative_advancement.cpp src/matrix_3f.cpp)
+rosbuild_add_library(${PROJECT_NAME} src/AABB.cpp src/OBB.cpp src/RSS.cpp src/vec_3f.cpp src/traversal_node_base.cpp src/traversal_node_bvhs.cpp src/intersect.cpp src/motion.cpp src/BV_fitter.cpp src/BV_splitter.cpp src/BVH_model.cpp src/BVH_utility.cpp src/transform.cpp src/simple_setup.cpp src/geometric_shapes.cpp src/geometric_shapes_utility.cpp src/geometric_shapes_intersect.cpp src/collision_node.cpp src/traversal_recurse.cpp src/broad_phase_collision.cpp src/collision.cpp src/collision_func_matrix.cpp src/interval_tree.cpp src/conservative_advancement.cpp src/matrix_3f.cpp src/interval.cpp src/interval_vector.cpp src/interval_matrix.cpp src/taylor_model.cpp)
 
 rosbuild_add_gtest(test_core_collision test/test_core_collision.cpp)
 target_link_libraries(test_core_collision fcl)
diff --git a/trunk/fcl/include/fcl/broad_phase_collision.h b/trunk/fcl/include/fcl/broad_phase_collision.h
index 087e90a38c4790416d124532f978899b1c7ec984..b99359cbc78ca0cd99dc0c5f9c18881456bba6b8 100644
--- a/trunk/fcl/include/fcl/broad_phase_collision.h
+++ b/trunk/fcl/include/fcl/broad_phase_collision.h
@@ -465,7 +465,7 @@ protected:
   };
 
   /** \brief Extention interval tree's interval to SAP interval, adding more information */
-  struct SAPInterval : public Interval
+  struct SAPInterval : public SimpleInterval
   {
     CollisionObject* obj;
     SAPInterval(double low_, double high_, CollisionObject* obj_)
diff --git a/trunk/fcl/include/fcl/interval.h b/trunk/fcl/include/fcl/interval.h
new file mode 100644
index 0000000000000000000000000000000000000000..06eeb0d17cf02bc2e8a03b362a702e80ef6d62d8
--- /dev/null
+++ b/trunk/fcl/include/fcl/interval.h
@@ -0,0 +1,222 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+
+#ifndef FCL_INTERVAL_H
+#define FCL_INTERVAL_H
+
+#include "fcl/BVH_internal.h"
+#include <cstdlib>
+
+namespace fcl
+{
+
+struct Interval
+{
+  BVH_REAL i_[2];
+
+  Interval() {}
+  Interval(BVH_REAL v)
+  {
+    i_[0] = i_[1] = v;
+  }
+
+  Interval(BVH_REAL left, BVH_REAL right)
+  {
+    i_[0] = left; i_[1] = right;
+  }
+
+  inline void setValue(BVH_REAL a, BVH_REAL b)
+  {
+    i_[0] = a; i_[1] = b;
+  }
+
+  inline void setValue(BVH_REAL x)
+  {
+    i_[0] = i_[1] = x;
+  }
+
+  inline BVH_REAL operator [] (size_t i) const
+  {
+    return i_[i];
+  }
+
+  inline BVH_REAL& operator [] (size_t i)
+  {
+    return i_[i];
+  }
+
+  inline bool operator == (const Interval& other) const
+  {
+    if(i_[0] != other.i_[0]) return false;
+    if(i_[1] != other.i_[1]) return false;
+    return true;
+  }
+
+  inline Interval operator + (const Interval& other) const
+  {
+    return Interval(i_[0] + other.i_[0], i_[1] + other.i_[1]);
+  }
+
+  inline Interval operator - (const Interval& other) const
+  {
+    return Interval(i_[0] - other.i_[1], i_[1] - other.i_[0]);
+  }
+
+  inline Interval& operator += (const Interval& other)
+  {
+    i_[0] += other.i_[0];
+    i_[1] += other.i_[1];
+    return *this;
+  }
+
+  inline Interval& operator -= (const Interval& other)
+  {
+    i_[0] -= other.i_[1];
+    i_[1] -= other.i_[0];
+    return *this;
+  }
+
+  Interval operator * (const Interval& other) const;
+
+  inline Interval operator * (BVH_REAL d) const
+  {
+    if(d >= 0) return Interval(i_[0] * d, i_[1] * d);
+    return Interval(i_[1] * d, i_[0] * d);
+  }
+
+  inline Interval& operator *= (BVH_REAL d)
+  {
+    if(d >= 0)
+    {
+      i_[0] *= d;
+      i_[1] *= d;
+    }
+    else
+    {
+      BVH_REAL tmp = i_[0];
+      i_[0] = i_[1] * d;
+      i_[1] = tmp * d;
+    }
+
+    return *this;
+  }
+
+  /** \brief other must not contain 0 */
+  Interval operator / (const Interval& other) const;
+
+  /** \brief determine whether the intersection between intervals is empty */
+  inline bool overlap(const Interval& other) const
+  {
+    if(i_[1] < other.i_[0]) return false;
+    if(i_[0] > other.i_[1]) return false;
+    return true;
+  }
+
+  inline void intersect(const Interval& other)
+  {
+    if(i_[1] < other.i_[0]) return;
+    if(i_[0] > other.i_[1]) return;
+    if(i_[1] > other.i_[1]) i_[1] = other.i_[1];
+    if(i_[0] < other.i_[0]) i_[0] = other.i_[0];
+    return;
+  }
+
+  inline Interval operator - () const
+  {
+    return Interval(-i_[1], -i_[0]);
+  }
+
+  /** \brief Return the nearest distance for points within the interval to zero */
+  inline BVH_REAL getAbsLower() const
+  {
+    if(i_[0] >= 0) return i_[0];
+    if(i_[1] >= 0) return 0;
+    return -i_[1];
+  }
+
+  /** \brief Return the farthest distance for points within the interval to zero */
+  inline BVH_REAL getAbsUpper() const
+  {
+    if(i_[0] + i_[1] >= 0) return i_[1];
+    return i_[0];
+  }
+
+
+  inline bool contains(BVH_REAL v) const
+  {
+    if(v < i_[0]) return false;
+    if(v > i_[1]) return false;
+    return true;
+  }
+
+  /** \brief Compute the minimum interval contains v and original interval */
+  inline void bound(BVH_REAL v)
+  {
+    if(v < i_[0]) i_[0] = v;
+    if(v > i_[1]) i_[1] = v;
+  }
+
+  inline Interval bounded(BVH_REAL v) const
+  {
+    Interval res = *this;
+    if(v < res.i_[0]) res.i_[0] = v;
+    if(v > res.i_[1]) res.i_[1] = v;
+    return res;
+  }
+
+  /** \brief Compute the minimum interval contains other and original interval */
+  inline void bound(const Interval& other)
+  {
+    if(other.i_[0] < i_[0]) i_[0] = other.i_[0];
+    if(other.i_[1] > i_[1]) i_[1] = other.i_[1];
+  }
+
+  inline Interval bounded(const Interval& other) const
+  {
+    Interval res = *this;
+    if(other.i_[0] < res.i_[0]) res.i_[0] = other.i_[0];
+    if(other.i_[1] > res.i_[1]) res.i_[1] = other.i_[1];
+    return res;
+  }
+
+  void print() const;
+  inline BVH_REAL center() const { return 0.5 * (i_[0] + i_[1]); }
+  inline BVH_REAL diameter() const { return i_[1] -i_[0]; }
+};
+
+}
+#endif
diff --git a/trunk/fcl/include/fcl/interval_matrix.h b/trunk/fcl/include/fcl/interval_matrix.h
new file mode 100644
index 0000000000000000000000000000000000000000..c21f61a2d03c57e85d5762c73125b8430cbcccbb
--- /dev/null
+++ b/trunk/fcl/include/fcl/interval_matrix.h
@@ -0,0 +1,83 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+
+#ifndef FCL_INTERVAL_MATRIX_H
+#define FCL_INTERVAL_MATRIX_H
+
+#include "fcl/interval.h"
+#include "fcl/matrix_3f.h"
+#include "fcl/interval_vector.h"
+
+namespace fcl
+{
+
+struct IMatrix3
+{
+  Interval i_[3][3];
+
+  IMatrix3();
+  IMatrix3(BVH_REAL v);
+  IMatrix3(const Matrix3f& m);
+  IMatrix3(BVH_REAL m[3][3][2]);
+  IMatrix3(BVH_REAL m[3][3]);
+
+  void setIdentity();
+
+  IVector3 getColumn(size_t i) const;
+  IVector3 getRow(size_t i) const;
+
+  Vec3f getRealColumn(size_t i) const;
+  Vec3f getRealRow(size_t i) const;
+
+  IVector3 operator * (const Vec3f& v) const;
+  IVector3 operator * (const IVector3& v) const;
+  IMatrix3 operator * (const IMatrix3& m) const;
+  IMatrix3 operator * (const Matrix3f& m) const;
+  IMatrix3 operator + (const IMatrix3& m) const;
+  IMatrix3& operator += (const IMatrix3& m);
+
+  void print() const;
+
+  IMatrix3 nonIntervalAddMatrix(const IMatrix3& m) const;
+  IVector3 nonIntervalTimesVector(const IVector3& v) const;
+  IVector3 nonIntervalTimesVector(const Vec3f& v) const;
+
+};
+
+}
+
+#endif
diff --git a/trunk/fcl/include/fcl/interval_tree.h b/trunk/fcl/include/fcl/interval_tree.h
index 90763b07727268d5571212c48a5bd6afc8eb411d..94f290a571a3fbb786f0c21a1a947cf7789cd1dd 100644
--- a/trunk/fcl/include/fcl/interval_tree.h
+++ b/trunk/fcl/include/fcl/interval_tree.h
@@ -50,11 +50,11 @@ namespace fcl
  * Can be replaced in part by boost::icl::interval_set, which is only supported after boost 1.46 and does not support delete node routine.
  */
 
-struct Interval
+struct SimpleInterval
 {
 public:
-  Interval() {}
-  virtual ~Interval() {}
+  SimpleInterval() {}
+  virtual ~SimpleInterval() {}
   virtual void print() {}
 
   double low, high;
@@ -69,13 +69,13 @@ public:
 
   IntervalTreeNode();
 
-  IntervalTreeNode(Interval* new_interval);
+  IntervalTreeNode(SimpleInterval* new_interval);
 
   ~IntervalTreeNode();
 
 protected:
 
-  Interval* stored_interval;
+  SimpleInterval* stored_interval;
 
   double key;
 
@@ -120,10 +120,10 @@ public:
   void print() const;
 
   /** \brief Delete one node of the interval tree */
-  Interval* deleteNode(IntervalTreeNode* node);
+  SimpleInterval* deleteNode(IntervalTreeNode* node);
 
   /** \brief Insert one node of the interval tree */
-  IntervalTreeNode* insert(Interval* new_interval);
+  IntervalTreeNode* insert(SimpleInterval* new_interval);
 
   /** \brief get the predecessor of a given node */
   IntervalTreeNode* getPredecessor(IntervalTreeNode* node) const;
@@ -132,7 +132,7 @@ public:
   IntervalTreeNode* getSuccessor(IntervalTreeNode* node) const;
 
   /** \brief Return result for a given query */
-  std::deque<Interval*> query(double low, double high);
+  std::deque<SimpleInterval*> query(double low, double high);
 
 protected:
 
diff --git a/trunk/fcl/include/fcl/interval_vector.h b/trunk/fcl/include/fcl/interval_vector.h
new file mode 100644
index 0000000000000000000000000000000000000000..dba1f789d920c632b1e14f6c327e27e9a747087c
--- /dev/null
+++ b/trunk/fcl/include/fcl/interval_vector.h
@@ -0,0 +1,96 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+
+#ifndef FCL_INTERVAL_VECTOR_H
+#define FCL_INTERVAL_VECTOR_H
+
+#include "fcl/interval.h"
+#include "fcl/vec_3f.h"
+
+namespace fcl
+{
+
+struct IVector3
+{
+  Interval i_[3];
+
+  IVector3();
+  IVector3(BVH_REAL v);
+  IVector3(BVH_REAL x, BVH_REAL y, BVH_REAL z);
+  IVector3(BVH_REAL xl, BVH_REAL xu, BVH_REAL yl, BVH_REAL yu, BVH_REAL zl, BVH_REAL zu);
+  IVector3(Interval v[3]);
+  IVector3(BVH_REAL v[3][2]);
+  IVector3(const Interval& v1, const Interval& v2, const Interval& v3);
+  IVector3(const Vec3f& v);
+
+  IVector3 operator + (const IVector3& other) const;
+  IVector3& operator += (const IVector3& other);
+  IVector3 operator - (const IVector3& other) const;
+  IVector3& operator -= (const IVector3& other);
+  IVector3& operator = (const Vec3f& other);
+  Interval dot(const IVector3& other) const;
+  IVector3 cross(const IVector3& other) const;
+
+  inline const Interval& operator [] (size_t i) const
+  {
+    return i_[i];
+  }
+
+  inline Interval& operator [] (size_t i)
+  {
+    return i_[i];
+  }
+
+  void print() const;
+  Vec3f center() const;
+  BVH_REAL volumn() const;
+  void setZero();
+
+  void bound(const Vec3f& v);
+  void bound(const IVector3& v);
+
+  IVector3 bounded(const Vec3f& v) const;
+  IVector3 bounded(const IVector3& v) const;
+
+  bool overlap(const IVector3& v) const;
+  bool contain(const IVector3& v) const;
+  void normalize();
+};
+
+}
+
+#endif
diff --git a/trunk/fcl/include/fcl/taylor_matrix.h b/trunk/fcl/include/fcl/taylor_matrix.h
new file mode 100644
index 0000000000000000000000000000000000000000..92d9f7766e02c7d2bc579648898226f8899eb868
--- /dev/null
+++ b/trunk/fcl/include/fcl/taylor_matrix.h
@@ -0,0 +1,63 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+#ifndef FCL_TAYLOR_MATRIX_H
+#define FCL_TAYLOR_MATRIX_H
+
+#include "fcl/taylor_model.h"
+#include "fcl/matrix_3f.h"
+#include "fcl/taylor_vector.h"
+
+namespace fcl
+{
+
+struct TMatrix3
+{
+  TaylorModel i_[3][3];
+
+  TMatrix3();
+  TMatrix3(TaylorModel m[3][3]);
+  TMatrix3(const Matrix3f& m);
+
+  TVector3 getColumn(size_t i) const;
+  TVector3 getRow(size_t i) const;
+
+
+};
+
+}
+
+#endif
diff --git a/trunk/fcl/include/fcl/taylor_model.h b/trunk/fcl/include/fcl/taylor_model.h
new file mode 100644
index 0000000000000000000000000000000000000000..c7c414289062af77ee5ef763d4ad53851e91dcef
--- /dev/null
+++ b/trunk/fcl/include/fcl/taylor_model.h
@@ -0,0 +1,101 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+#ifndef FCL_TAYLOR_MODEL_H
+#define FCL_TAYLOR_MODEL_H
+
+#include "fcl/interval.h"
+
+namespace fcl
+{
+
+/** \brief TaylorModel implements a third order Taylor model, i.e., a cubic approximation of a function
+ * over a time interval, with an interval remainder.
+ * All the operations on two Taylor models assume their time intervals are the same.
+ */
+struct TaylorModel
+{
+  /** \brief Coefficients of the cubic polynomial approximation */
+  BVH_REAL coeffs_[4];
+
+  /** \brief interval remainder */
+  Interval r_;
+
+  void setTimeInterval(BVH_REAL l, BVH_REAL r);
+
+  TaylorModel();
+  TaylorModel(BVH_REAL coeff);
+  TaylorModel(BVH_REAL coeffs[3], const Interval& r);
+  TaylorModel(BVH_REAL c0, BVH_REAL c1, BVH_REAL c2, BVH_REAL c3, const Interval& r);
+
+  TaylorModel operator + (const TaylorModel& other) const;
+  TaylorModel operator - (const TaylorModel& other) const;
+  TaylorModel& operator += (const TaylorModel& other);
+  TaylorModel& operator -= (const TaylorModel& other);
+  TaylorModel operator * (const TaylorModel& other) const;
+  TaylorModel operator * (BVH_REAL d) const;
+  TaylorModel operator - () const;
+
+  void print() const;
+
+  Interval getBound() const;
+  Interval getBound(BVH_REAL l, BVH_REAL r) const;
+
+  Interval getTightBound() const;
+  Interval getTightBound(BVH_REAL l, BVH_REAL r) const;
+
+  Interval getBound(BVH_REAL t) const;
+
+  void setZero();
+
+  /** \brief time interval and different powers */
+  Interval t_; // [t1, t2]
+  Interval t2_; // [t1, t2]^2
+  Interval t3_; // [t1, t2]^3
+  Interval t4_; // [t1, t2]^4
+  Interval t5_; // [t1, t2]^5
+  Interval t6_; // [t1, t2]^6
+
+  static const BVH_REAL PI_;
+};
+
+void generateTaylorModelForCosFunc(TaylorModel& tm, BVH_REAL w, BVH_REAL q0);
+void generateTaylorModelForSinFunc(TaylorModel& tm, BVH_REAL w, BVH_REAL q0);
+void generateTaylorModelForLinearFunc(TaylorModel& tm, BVH_REAL p, BVH_REAL v);
+
+}
+
+#endif
diff --git a/trunk/fcl/include/fcl/taylor_vector.h b/trunk/fcl/include/fcl/taylor_vector.h
new file mode 100644
index 0000000000000000000000000000000000000000..46b69db1355c8054a369e029b8e9cc447a152766
--- /dev/null
+++ b/trunk/fcl/include/fcl/taylor_vector.h
@@ -0,0 +1,79 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+#ifndef FCL_TAYLOR_VECTOR_H
+#define FCL_TAYLOR_VECTOR_H
+
+#include "fcl/taylor_model.h"
+
+namespace fcl
+{
+
+struct TVector3
+{
+  TaylorModel i_[3];
+
+  TVector3();
+  TVector3(TaylorModel v[3]);
+  TVector3(const TaylorModel& v0, const TaylorModel& v1, const TaylorModel& v2);
+  TVector3(const Vec3f& v);
+
+  TVector3 operator + (const TVector3& other) const;
+  TVector3 operator + (BVH_REAL d) const;
+  TVector3& operator += (const TVector3& other);
+  TVector3 operator - (const TVector3& other) const;
+  TVector3& operator -= (const TVector3& other);
+  TVector3& operator = (const Vec3f& u);
+
+  TaylorModel dot(const TVector3& other) const;
+  TVector3 cross(const TVector3& other) const;
+
+  IVector3 getBound() const;
+  IVector3 getBound(BVH_REAL t) const;
+
+  void print() const;
+  BVH_REAL volumn() const;
+  void setZero();
+
+  TaylorModel squareLength() const;
+};
+
+void generateTVector3lForLinearFunc(TVector3& v, const Vec3f& position, const Vec3f& velocity);
+
+
+}
+
+#endif
diff --git a/trunk/fcl/include/fcl/vec_3f.h b/trunk/fcl/include/fcl/vec_3f.h
index 6534e9635493322852dc8521ce2c3090ed8f089d..1b927a2d480a47a904ee7d2bb7a5e38330e44440 100644
--- a/trunk/fcl/include/fcl/vec_3f.h
+++ b/trunk/fcl/include/fcl/vec_3f.h
@@ -212,6 +212,20 @@ namespace fcl
       return false;
     }
 
+    inline Vec3f normalized() const
+    {
+      BVH_REAL sqr_length = v_[0] * v_[0] + v_[1] * v_[1] + v_[2] * v_[2];
+      if(sqr_length > EPSILON * EPSILON)
+      {
+        BVH_REAL inv_length = (BVH_REAL)1.0 / (BVH_REAL)sqrt(sqr_length);
+        return *this * inv_length;
+      }
+      else
+      {
+        return *this;
+      }
+    }
+
     /** \brief Return vector length */
     inline float length() const
     {
@@ -412,6 +426,21 @@ namespace fcl
       return false;
     }
 
+    inline Vec3f normalized() const
+    {
+      BVH_REAL sqr_length = v_[0] * v_[0] + v_[1] * v_[1] + v_[2] * v_[2];
+      if(sqr_length > EPSILON * EPSILON)
+      {
+        BVH_REAL inv_length = (BVH_REAL)1.0 / (BVH_REAL)sqrt(sqr_length);
+        return *this * inv_length;
+      }
+      else
+      {
+        return *this;
+      }
+    }
+
+
     /** \brief Return vector length */
     inline BVH_REAL length() const
     {
diff --git a/trunk/fcl/src/broad_phase_collision.cpp b/trunk/fcl/src/broad_phase_collision.cpp
index 2bedad2ef41f848625df7dcb780201d6fa331ce4..d259f0a2cfd8db99fd4832efa3586714ae8da961 100644
--- a/trunk/fcl/src/broad_phase_collision.cpp
+++ b/trunk/fcl/src/broad_phase_collision.cpp
@@ -917,7 +917,7 @@ void IntervalTreeCollisionManager::collide(CollisionObject* obj, void* cdata, Co
 {
   static const unsigned int CUTOFF = 100;
 
-  std::deque<Interval*> results0, results1, results2;
+  std::deque<SimpleInterval*> results0, results1, results2;
 
   results0 = interval_trees[0]->query(obj->getAABB().min_[0], obj->getAABB().max_[0]);
   if(results0.size() > CUTOFF)
diff --git a/trunk/fcl/src/interval.cpp b/trunk/fcl/src/interval.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7cb9a3e0971442191cfc28164e52272ff119d803
--- /dev/null
+++ b/trunk/fcl/src/interval.cpp
@@ -0,0 +1,87 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+#include "fcl/interval.h"
+#include <iostream>
+
+namespace fcl
+{
+
+Interval Interval::operator * (const Interval& other) const
+{
+  if(other.i_[0] >= 0)
+  {
+    if(i_[0] >= 0) return Interval(i_[0] * other.i_[0], i_[1] * other.i_[1]);
+    if(i_[1] <= 0) return Interval(i_[0] * other.i_[1], i_[1] * other.i_[0]);
+    return Interval(i_[0] * other.i_[1], i_[1] * other.i_[1]);
+  }
+  if(other.i_[1] <= 0)
+  {
+    if(i_[0] >= 0) return Interval(i_[1] * other.i_[0], i_[0] * other.i_[1]);
+    if(i_[1] <= 0) return Interval(i_[1] * other.i_[1], i_[0] * other.i_[0]);
+    return Interval(i_[1] * other.i_[0], i_[0] * other.i_[0]);
+  }
+
+  if(i_[0] >= 0) return Interval(i_[1] * other.i_[0], i_[1] * other.i_[1]);
+  if(i_[1] <= 0) return Interval(i_[0] * other.i_[1], i_[0] * other.i_[0]);
+
+  BVH_REAL v00 = i_[0] * other.i_[0];
+  BVH_REAL v11 = i_[1] * other.i_[1];
+  if(v00 <= v11)
+  {
+    BVH_REAL v01 = i_[0] * other.i_[1];
+    BVH_REAL v10 = i_[1] * other.i_[0];
+    if(v01 < v10) return Interval(v01, v11);
+    return Interval(v10, v11);
+  }
+
+  BVH_REAL v01 = i_[0] * other.i_[1];
+  BVH_REAL v10 = i_[1] * other.i_[0];
+  if(v01 < v10) return Interval(v01, v00);
+  return Interval(v10, v00);
+}
+
+Interval Interval::operator / (const Interval& other) const
+{
+  return *this * Interval(1.0 / other.i_[1], 1.0 / other.i_[0]);
+}
+
+void Interval::print() const
+{
+  std::cout << "[" << i_[0] << ", " << i_[1] << "]" << std::endl;
+}
+
+}
diff --git a/trunk/fcl/src/interval_matrix.cpp b/trunk/fcl/src/interval_matrix.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1dab6143e80093f4f024f241e48c4c7cef724702
--- /dev/null
+++ b/trunk/fcl/src/interval_matrix.cpp
@@ -0,0 +1,746 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+#include "fcl/interval_matrix.h"
+#include <iostream>
+
+namespace fcl
+{
+
+IMatrix3::IMatrix3()
+{
+  i_[0][0] = i_[0][1] = i_[0][2] = i_[1][0] = i_[1][1] = i_[1][2] = i_[2][0] = i_[2][1] = i_[2][2] = 0;
+}
+
+IMatrix3::IMatrix3(BVH_REAL v)
+{
+  i_[0][0] = i_[0][1] = i_[0][2] = i_[1][0] = i_[1][1] = i_[1][2] = i_[2][0] = i_[2][1] = i_[2][2] = v;
+}
+
+IMatrix3::IMatrix3(const Matrix3f& m)
+{
+  i_[0][0] = m[0][0];
+  i_[0][1] = m[0][1];
+  i_[0][2] = m[0][2];
+
+  i_[1][0] = m[1][0];
+  i_[1][1] = m[1][1];
+  i_[1][2] = m[1][2];
+
+  i_[2][0] = m[2][0];
+  i_[2][1] = m[2][1];
+  i_[2][2] = m[2][2];
+}
+
+IMatrix3::IMatrix3(BVH_REAL m[3][3][2])
+{
+  i_[0][0].setValue(m[0][0][0], m[0][0][1]);
+  i_[0][1].setValue(m[0][1][0], m[0][1][1]);
+  i_[0][2].setValue(m[0][2][0], m[0][2][1]);
+
+  i_[1][0].setValue(m[1][0][0], m[1][0][1]);
+  i_[1][1].setValue(m[1][1][0], m[1][1][1]);
+  i_[1][2].setValue(m[1][2][0], m[1][2][1]);
+
+  i_[2][0].setValue(m[2][0][0], m[2][0][1]);
+  i_[2][1].setValue(m[2][1][0], m[2][1][1]);
+  i_[2][2].setValue(m[2][2][0], m[2][2][1]);
+}
+
+IMatrix3::IMatrix3(BVH_REAL m[3][3])
+{
+  i_[0][0].setValue(m[0][0]);
+  i_[0][1].setValue(m[0][1]);
+  i_[0][2].setValue(m[0][2]);
+
+  i_[1][0].setValue(m[1][0]);
+  i_[1][1].setValue(m[1][1]);
+  i_[1][2].setValue(m[1][2]);
+
+  i_[2][0].setValue(m[2][0]);
+  i_[2][1].setValue(m[2][1]);
+  i_[2][2].setValue(m[2][2]);
+}
+
+void IMatrix3::setIdentity()
+{
+  i_[0][0] = 1;
+  i_[0][1] = 0;
+  i_[0][2] = 0;
+
+  i_[1][0] = 0;
+  i_[1][1] = 1;
+  i_[1][2] = 0;
+
+  i_[2][0] = 0;
+  i_[2][1] = 0;
+  i_[2][2] = 1;
+}
+
+IVector3 IMatrix3::getColumn(size_t i) const
+{
+  return IVector3(i_[0][i], i_[1][i], i_[2][i]);
+}
+
+IVector3 IMatrix3::getRow(size_t i) const
+{
+  return IVector3(i_[i][0], i_[i][1], i_[i][2]);
+}
+
+Vec3f IMatrix3::getRealColumn(size_t i) const
+{
+  return Vec3f(i_[0][i][0], i_[1][i][0], i_[2][i][0]);
+}
+
+Vec3f IMatrix3::getRealRow(size_t i) const
+{
+  return Vec3f(i_[i][0][0], i_[i][1][0], i_[i][2][0]);
+}
+
+IMatrix3 IMatrix3::operator * (const Matrix3f& m) const
+{
+  BVH_REAL res[3][3][2];
+
+  if(m[0][0] < 0)
+  {
+    res[0][0][0] = m[0][0] * i_[0][0][1];
+    res[0][0][1] = m[0][0] * i_[0][0][0];
+    res[1][0][0] = m[0][0] * i_[1][0][1];
+    res[1][0][1] = m[0][0] * i_[1][0][0];
+    res[2][0][0] = m[0][0] * i_[2][0][1];
+    res[2][0][1] = m[0][0] * i_[2][0][0];
+  }
+  else
+  {
+    res[0][0][0] = m[0][0] * i_[0][0][0];
+    res[0][0][1] = m[0][0] * i_[0][0][1];
+    res[1][0][0] = m[0][0] * i_[1][0][0];
+    res[1][0][1] = m[0][0] * i_[1][0][1];
+    res[2][0][0] = m[0][0] * i_[2][0][0];
+    res[2][0][1] = m[0][0] * i_[2][0][1];
+  }
+
+  if(m[0][1] < 0)
+  {
+    res[0][1][0] = m[0][1] * i_[0][0][1];
+    res[0][1][1] = m[0][1] * i_[0][0][0];
+    res[1][1][0] = m[0][1] * i_[1][0][1];
+    res[1][1][1] = m[0][1] * i_[1][0][0];
+    res[2][1][0] = m[0][1] * i_[2][0][1];
+    res[2][1][1] = m[0][1] * i_[2][0][0];
+  }
+  else
+  {
+    res[0][1][0] = m[0][1] * i_[0][0][0];
+    res[0][1][1] = m[0][1] * i_[0][0][1];
+    res[1][1][0] = m[0][1] * i_[1][0][0];
+    res[1][1][1] = m[0][1] * i_[1][0][1];
+    res[2][1][0] = m[0][1] * i_[2][0][0];
+    res[2][1][1] = m[0][1] * i_[2][0][1];
+  }
+
+  if(m[0][2] < 0)
+  {
+    res[0][2][0] = m[0][2] * i_[0][0][1];
+    res[0][2][1] = m[0][2] * i_[0][0][0];
+    res[1][2][0] = m[0][2] * i_[1][0][1];
+    res[1][2][1] = m[0][2] * i_[1][0][0];
+    res[2][2][0] = m[0][2] * i_[2][0][1];
+    res[2][2][1] = m[0][2] * i_[2][0][0];
+  }
+  else
+  {
+    res[0][2][0] = m[0][2] * i_[0][0][0];
+    res[0][2][1] = m[0][2] * i_[0][0][1];
+    res[1][2][0] = m[0][2] * i_[1][0][0];
+    res[1][2][1] = m[0][2] * i_[1][0][1];
+    res[2][2][0] = m[0][2] * i_[2][0][0];
+    res[2][2][1] = m[0][2] * i_[2][0][1];
+  }
+
+  if(m[1][0] < 0)
+  {
+    res[0][0][0] += m[1][0] * i_[0][1][1];
+    res[0][0][1] += m[1][0] * i_[0][1][0];
+    res[1][0][0] += m[1][0] * i_[1][1][1];
+    res[1][0][1] += m[1][0] * i_[1][1][0];
+    res[2][0][0] += m[1][0] * i_[2][1][1];
+    res[2][0][1] += m[1][0] * i_[2][1][0];
+  }
+  else
+  {
+    res[0][0][0] += m[1][0] * i_[0][1][0];
+    res[0][0][1] += m[1][0] * i_[0][1][1];
+    res[1][0][0] += m[1][0] * i_[1][1][0];
+    res[1][0][1] += m[1][0] * i_[1][1][1];
+    res[2][0][0] += m[1][0] * i_[2][1][0];
+    res[2][0][1] += m[1][0] * i_[2][1][1];
+  }
+
+  if(m[1][1] < 0)
+  {
+    res[0][1][0] += m[1][1] * i_[0][1][1];
+    res[0][1][1] += m[1][1] * i_[0][1][0];
+    res[1][1][0] += m[1][1] * i_[1][1][1];
+    res[1][1][1] += m[1][1] * i_[1][1][0];
+    res[2][1][0] += m[1][1] * i_[2][1][1];
+    res[2][1][1] += m[1][1] * i_[2][1][0];
+  }
+  else
+  {
+    res[0][1][0] += m[1][1] * i_[0][1][0];
+    res[0][1][1] += m[1][1] * i_[0][1][1];
+    res[1][1][0] += m[1][1] * i_[1][1][0];
+    res[1][1][1] += m[1][1] * i_[1][1][1];
+    res[2][1][0] += m[1][1] * i_[2][1][0];
+    res[2][1][1] += m[1][1] * i_[2][1][1];
+  }
+
+  if(m[1][2] < 0)
+  {
+    res[0][2][0] += m[1][2] * i_[0][1][1];
+    res[0][2][1] += m[1][2] * i_[0][1][0];
+    res[1][2][0] += m[1][2] * i_[1][1][1];
+    res[1][2][1] += m[1][2] * i_[1][1][0];
+    res[2][2][0] += m[1][2] * i_[2][1][1];
+    res[2][2][1] += m[1][2] * i_[2][1][0];
+  }
+  else
+  {
+    res[0][2][0] += m[1][2] * i_[0][1][0];
+    res[0][2][1] += m[1][2] * i_[0][1][1];
+    res[1][2][0] += m[1][2] * i_[1][1][0];
+    res[1][2][1] += m[1][2] * i_[1][1][1];
+    res[2][2][0] += m[1][2] * i_[2][1][0];
+    res[2][2][1] += m[1][2] * i_[2][1][1];
+  }
+
+  if(m[2][0] < 0)
+  {
+    res[0][0][0] += m[2][0] * i_[0][2][1];
+    res[0][0][1] += m[2][0] * i_[0][2][0];
+    res[1][0][0] += m[2][0] * i_[1][2][1];
+    res[1][0][1] += m[2][0] * i_[1][2][0];
+    res[2][0][0] += m[2][0] * i_[2][2][1];
+    res[2][0][1] += m[2][0] * i_[2][2][0];
+  }
+  else
+  {
+    res[0][0][0] += m[2][0] * i_[0][2][0];
+    res[0][0][1] += m[2][0] * i_[0][2][1];
+    res[1][0][0] += m[2][0] * i_[1][2][0];
+    res[1][0][1] += m[2][0] * i_[1][2][1];
+    res[2][0][0] += m[2][0] * i_[2][2][0];
+    res[2][0][1] += m[2][0] * i_[2][2][1];
+  }
+
+  if(m[2][1] < 0)
+  {
+    res[0][1][0] += m[2][1] * i_[0][2][1];
+    res[0][1][1] += m[2][1] * i_[0][2][0];
+    res[1][1][0] += m[2][1] * i_[1][2][1];
+    res[1][1][1] += m[2][1] * i_[1][2][0];
+    res[2][1][0] += m[2][1] * i_[2][2][1];
+    res[2][1][1] += m[2][1] * i_[2][2][0];
+  }
+  else
+  {
+    res[0][1][0] += m[2][1] * i_[0][2][0];
+    res[0][1][1] += m[2][1] * i_[0][2][1];
+    res[1][1][0] += m[2][1] * i_[1][2][0];
+    res[1][1][1] += m[2][1] * i_[1][2][1];
+    res[2][1][0] += m[2][1] * i_[2][2][0];
+    res[2][1][1] += m[2][1] * i_[2][2][1];
+  }
+
+  if(m[2][2] < 0)
+  {
+    res[0][2][0] += m[2][2] * i_[0][2][1];
+    res[0][2][1] += m[2][2] * i_[0][2][0];
+    res[1][2][0] += m[2][2] * i_[1][2][1];
+    res[1][2][1] += m[2][2] * i_[1][2][0];
+    res[2][2][0] += m[2][2] * i_[2][2][1];
+    res[2][2][1] += m[2][2] * i_[2][2][0];
+  }
+  else
+  {
+    res[0][2][0] += m[2][2] * i_[0][2][0];
+    res[0][2][1] += m[2][2] * i_[0][2][1];
+    res[1][2][0] += m[2][2] * i_[1][2][0];
+    res[1][2][1] += m[2][2] * i_[1][2][1];
+    res[2][2][0] += m[2][2] * i_[2][2][0];
+    res[2][2][1] += m[2][2] * i_[2][2][1];
+  }
+
+  return IMatrix3(res);
+}
+
+IVector3 IMatrix3::operator * (const Vec3f& v) const
+{
+  BVH_REAL res[3][2];
+
+  if(v[0] < 0)
+  {
+    res[0][0] = v[0] * i_[0][0][1];
+    res[0][1] = v[0] * i_[0][0][0];
+    res[1][0] = v[0] * i_[1][0][1];
+    res[1][1] = v[0] * i_[1][0][0];
+    res[2][0] = v[0] * i_[2][0][1];
+    res[2][1] = v[0] * i_[2][0][0];
+  }
+  else
+  {
+    res[0][0] = v[0] * i_[0][0][0];
+    res[0][1] = v[0] * i_[0][0][1];
+    res[1][0] = v[0] * i_[1][0][0];
+    res[1][1] = v[0] * i_[1][0][1];
+    res[2][0] = v[0] * i_[2][0][0];
+    res[2][1] = v[0] * i_[2][0][1];
+  }
+
+  if(v[1] < 0)
+  {
+    res[0][0] += v[1] * i_[0][1][1];
+    res[0][1] += v[1] * i_[0][1][0];
+    res[1][0] += v[1] * i_[1][1][1];
+    res[1][1] += v[1] * i_[1][1][0];
+    res[2][0] += v[1] * i_[2][1][1];
+    res[2][1] += v[1] * i_[2][1][0];
+  }
+  else
+  {
+    res[0][0] += v[1] * i_[0][1][0];
+    res[0][1] += v[1] * i_[0][1][1];
+    res[1][0] += v[1] * i_[1][1][0];
+    res[1][1] += v[1] * i_[1][1][1];
+    res[2][0] += v[1] * i_[2][1][0];
+    res[2][1] += v[1] * i_[2][1][1];
+  }
+
+  if(v[2] < 0)
+  {
+    res[0][0] += v[2] * i_[0][2][1];
+    res[0][1] += v[2] * i_[0][2][0];
+    res[1][0] += v[2] * i_[1][2][1];
+    res[1][1] += v[2] * i_[1][2][0];
+    res[2][0] += v[2] * i_[2][2][1];
+    res[2][1] += v[2] * i_[2][2][0];
+  }
+  else
+  {
+    res[0][0] += v[2] * i_[0][2][0];
+    res[0][1] += v[2] * i_[0][2][1];
+    res[1][0] += v[2] * i_[1][2][0];
+    res[1][1] += v[2] * i_[1][2][1];
+    res[2][0] += v[2] * i_[2][2][0];
+    res[2][1] += v[2] * i_[2][2][1];
+  }
+
+  return IVector3(res);
+}
+
+
+IMatrix3 IMatrix3::nonIntervalAddMatrix(const IMatrix3& m) const
+{
+  BVH_REAL res[3][3];
+
+  res[0][0] = i_[0][0][0] + m.i_[0][0][0];
+  res[0][1] = i_[0][1][0] + m.i_[0][1][0];
+  res[0][2] = i_[0][2][0] + m.i_[0][2][0];
+
+  res[1][0] = i_[1][0][0] + m.i_[1][0][0];
+  res[1][1] = i_[1][1][0] + m.i_[1][1][0];
+  res[1][2] = i_[1][2][0] + m.i_[1][2][0];
+
+  res[2][0] = i_[2][0][0] + m.i_[2][0][0];
+  res[2][1] = i_[2][1][0] + m.i_[2][1][0];
+  res[2][2] = i_[2][2][0] + m.i_[2][2][0];
+
+  return IMatrix3(res);
+}
+
+IVector3 IMatrix3::operator * (const IVector3& v) const
+{
+  BVH_REAL xl, xu, yl, yu, zl, zu;
+  register BVH_REAL temp, vmin, vmax;
+
+  // r.v.i_[0]
+  vmin = vmax = i_[0][0][0] * v.i_[0][0];
+  temp = i_[0][0][1] * v.i_[0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  xl = vmin; xu = vmax;
+
+  vmin = vmax = i_[0][1][0] * v.i_[1][0];
+  temp = i_[0][1][0] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * v.i_[1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  xl += vmin; xu += vmax;
+
+  vmin = vmax = i_[0][2][0] * v.i_[2][0];
+  temp = i_[0][2][0] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * v.i_[2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  xl += vmin; xu += vmax;
+
+  // r.v.i_[1]
+
+  vmin = vmax = i_[1][0][0] * v.i_[0][0];
+  temp = i_[1][0][0] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * v.i_[0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  yl = vmin; yu = vmax;
+
+  vmin = vmax = i_[1][1][0] * v.i_[1][0];
+  temp = i_[1][1][0] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * v.i_[1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  yl += vmin; yu += vmax;
+
+  vmin = vmax = i_[1][2][0] * v.i_[2][0];
+  temp = i_[1][2][0] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * v.i_[2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  yl += vmin; yu += vmax;
+
+  // r.v.i_[2]
+
+  vmin = vmax = i_[2][0][0] * v.i_[0][0];
+  temp = i_[2][0][0] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * v.i_[0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  zl = vmin; zu = vmax;
+
+  vmin = vmax = i_[2][1][0] * v.i_[1][0];
+  temp = i_[2][1][0] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * v.i_[1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  zl += vmin; zu += vmax;
+
+  vmin = vmax = i_[2][2][0] * v.i_[2][0];
+  temp = i_[2][2][0] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * v.i_[2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  zl += vmin; zu += vmax;      vmin = vmax = i_[0][0][0] * v.i_[0][0];
+  temp = i_[0][0][0] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * v.i_[0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  xl = vmin; xu = vmax;
+
+  vmin = vmax = i_[0][1][0] * v.i_[1][0];
+  temp = i_[0][1][0] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * v.i_[1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  xl += vmin; xu += vmax;
+
+  vmin = vmax = i_[0][2][0] * v.i_[2][0];
+  temp = i_[0][2][0] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * v.i_[2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  xl += vmin; xu += vmax;
+
+  // r.v.i_[1]
+
+  vmin = vmax = i_[1][0][0] * v.i_[0][0];
+  temp = i_[1][0][0] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * v.i_[0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  yl = vmin; yu = vmax;
+
+  vmin = vmax = i_[1][1][0] * v.i_[1][0];
+  temp = i_[1][1][0] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * v.i_[1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  yl += vmin; yu += vmax;
+
+  vmin = vmax = i_[1][2][0] * v.i_[2][0];
+  temp = i_[1][2][0] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * v.i_[2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  yl += vmin; yu += vmax;
+
+  // r.v.i_[2]
+
+  vmin = vmax = i_[2][0][0] * v.i_[0][0];
+  temp = i_[2][0][0] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * v.i_[0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * v.i_[0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  zl = vmin; zu = vmax;
+
+  vmin = vmax = i_[2][1][0] * v.i_[1][0];
+  temp = i_[2][1][0] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * v.i_[1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * v.i_[1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  zl += vmin; zu += vmax;
+
+  vmin = vmax = i_[2][2][0] * v.i_[2][0];
+  temp = i_[2][2][0] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * v.i_[2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * v.i_[2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  zl += vmin; zu += vmax;
+
+  return IVector3(xl, xu, yl, yu, zl, zu);
+}
+
+IMatrix3 IMatrix3::operator * (const IMatrix3& m) const
+{
+
+  register BVH_REAL temp, vmin, vmax;
+  BVH_REAL res[3][3][2];
+
+  // res[0][0]
+
+  vmin = vmax = i_[0][0][0] * m.i_[0][0][0];
+  temp = i_[0][0][0] * m.i_[0][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * m.i_[0][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * m.i_[0][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][0][0] = vmin; res[0][0][1] = vmax;
+
+  vmin = vmax = i_[0][1][0] * m.i_[1][0][0];
+  temp = i_[0][1][0] * m.i_[1][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * m.i_[1][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * m.i_[1][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][0][0] += vmin; res[0][0][1] += vmax;
+
+  vmin = vmax = i_[0][2][0] * m.i_[2][0][0];
+  temp = i_[0][2][0] * m.i_[2][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * m.i_[2][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * m.i_[2][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][0][0] += vmin; res[0][0][1] += vmax;
+
+  // res[1][0]
+
+  vmin = vmax = i_[1][0][0] * m.i_[0][0][0];
+  temp = i_[1][0][0] * m.i_[0][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * m.i_[0][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * m.i_[0][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][0][0] = vmin; res[1][0][1] = vmax;
+
+  vmin = vmax = i_[1][1][0] * m.i_[1][0][0];
+  temp = i_[1][1][0] * m.i_[1][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * m.i_[1][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * m.i_[1][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][0][0] += vmin; res[1][0][1] += vmax;
+
+  vmin = vmax = i_[1][2][0] * m.i_[2][0][0];
+  temp = i_[1][2][0] * m.i_[2][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * m.i_[2][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * m.i_[2][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][0][0] += vmin; res[1][0][1] += vmax;
+
+  // res[2][0]
+
+  vmin = vmax = i_[2][0][0] * m.i_[0][0][0];
+  temp = i_[2][0][0] * m.i_[0][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * m.i_[0][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * m.i_[0][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][0][0] = vmin; res[2][0][1] = vmax;
+
+  vmin = vmax = i_[2][1][0] * m.i_[1][0][0];
+  temp = i_[2][1][0] * m.i_[1][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * m.i_[1][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * m.i_[1][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][0][0] += vmin; res[2][0][1] += vmax;
+
+  vmin = vmax = i_[2][2][0] * m.i_[2][0][0];
+  temp = i_[2][2][0] * m.i_[2][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * m.i_[2][0][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * m.i_[2][0][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][0][0] += vmin; res[2][0][1] += vmax;
+
+  // res[0][1]
+
+  vmin = vmax = i_[0][0][0] * m.i_[0][1][0];
+  temp = i_[0][0][0] * m.i_[0][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * m.i_[0][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * m.i_[0][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][1][0] = vmin; res[0][1][1] = vmax;
+
+  vmin = vmax = i_[0][1][0] * m.i_[1][1][0];
+  temp = i_[0][1][0] * m.i_[1][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * m.i_[1][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * m.i_[1][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][1][0] += vmin; res[0][1][1] += vmax;
+
+  vmin = vmax = i_[0][2][0] * m.i_[2][1][0];
+  temp = i_[0][2][0] * m.i_[2][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * m.i_[2][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * m.i_[2][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][1][0] += vmin; res[0][1][1] += vmax;
+
+  // res[1][1]
+
+  vmin = vmax = i_[1][0][0] * m.i_[0][1][0];
+  temp = i_[1][0][0] * m.i_[0][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * m.i_[0][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * m.i_[0][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][1][0] = vmin; res[1][1][1] = vmax;
+
+  vmin = vmax = i_[1][1][0] * m.i_[1][1][0];
+  temp = i_[1][1][0] * m.i_[1][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * m.i_[1][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * m.i_[1][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][1][0] += vmin; res[1][1][1] += vmax;
+
+  vmin = vmax = i_[1][2][0] * m.i_[2][1][0];
+  temp = i_[1][2][0] * m.i_[2][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * m.i_[2][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * m.i_[2][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][1][0] += vmin; res[1][1][1] += vmax;
+
+  // res[2][1]
+
+  vmin = vmax = i_[2][0][0] * m.i_[0][1][0];
+  temp = i_[2][0][0] * m.i_[0][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * m.i_[0][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * m.i_[0][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][1][0] = vmin; res[2][1][1] = vmax;
+
+  vmin = vmax = i_[2][1][0] * m.i_[1][1][0];
+  temp = i_[2][1][0] * m.i_[1][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * m.i_[1][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * m.i_[1][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][1][0] += vmin; res[2][1][1] += vmax;
+
+  vmin = vmax = i_[2][2][0] * m.i_[2][1][0];
+  temp = i_[2][2][0] * m.i_[2][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * m.i_[2][1][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * m.i_[2][1][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][1][0] += vmin; res[2][1][1] += vmax;
+
+  // res[0][2]
+
+  vmin = vmax = i_[0][0][0] * m.i_[0][2][0];
+  temp = i_[0][0][0] * m.i_[0][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * m.i_[0][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][0][1] * m.i_[0][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][2][0] = vmin; res[0][2][1] = vmax;
+
+  vmin = vmax = i_[0][1][0] * m.i_[1][2][0];
+  temp = i_[0][1][0] * m.i_[1][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * m.i_[1][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][1][1] * m.i_[1][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][2][0] += vmin; res[0][2][1] += vmax;
+
+  vmin = vmax = i_[0][2][0] * m.i_[2][2][0];
+  temp = i_[0][2][0] * m.i_[2][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * m.i_[2][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[0][2][1] * m.i_[2][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[0][2][0] += vmin; res[0][2][1] += vmax;
+
+  // res[1][2]
+
+  vmin = vmax = i_[1][0][0] * m.i_[0][2][0];
+  temp = i_[1][0][0] * m.i_[0][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * m.i_[0][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][0][1] * m.i_[0][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][2][0] = vmin; res[1][2][1] = vmax;
+
+  vmin = vmax = i_[1][1][0] * m.i_[1][2][0];
+  temp = i_[1][1][0] * m.i_[1][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * m.i_[1][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][1][1] * m.i_[1][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][2][0] += vmin; res[1][2][1] += vmax;
+
+  vmin = vmax = i_[1][2][0] * m.i_[2][2][0];
+  temp = i_[1][2][0] * m.i_[2][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * m.i_[2][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[1][2][1] * m.i_[2][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[1][2][0] += vmin; res[1][2][1] += vmax;
+
+  // res[2][2]
+
+  vmin = vmax = i_[2][0][0] * m.i_[0][2][0];
+  temp = i_[2][0][0] * m.i_[0][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * m.i_[0][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][0][1] * m.i_[0][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][2][0] = vmin; res[2][2][1] = vmax;
+
+  vmin = vmax = i_[2][1][0] * m.i_[1][2][0];
+  temp = i_[2][1][0] * m.i_[1][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * m.i_[1][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][1][1] * m.i_[1][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][2][0] += vmin; res[2][2][1] += vmax;
+
+  vmin = vmax = i_[2][2][0] * m.i_[2][2][0];
+  temp = i_[2][2][0] * m.i_[2][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * m.i_[2][2][0]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  temp = i_[2][2][1] * m.i_[2][2][1]; if(temp < vmin) vmin = temp; else if(temp > vmax) vmax = temp;
+  res[2][2][0] += vmin; res[2][2][1] += vmax;
+
+  return IMatrix3(res);
+}
+
+IMatrix3 IMatrix3::operator + (const IMatrix3& m) const
+{
+  BVH_REAL res[3][3][2];
+  res[0][0][0] = i_[0][0][0] + m.i_[0][0][0]; res[0][0][1] = i_[0][0][1] + m.i_[0][0][1]; res[0][1][0] = i_[0][1][0] + m.i_[0][1][0]; res[0][1][1] = i_[0][1][1] + m.i_[0][1][1]; res[0][2][0] = i_[0][2][0] + m.i_[0][2][0]; res[0][2][1] = i_[0][2][1] + m.i_[0][2][1];
+  res[1][0][0] = i_[1][0][0] + m.i_[1][0][0]; res[1][0][1] = i_[1][0][1] + m.i_[1][0][1]; res[1][1][0] = i_[1][1][0] + m.i_[1][1][0]; res[1][1][1] = i_[1][1][1] + m.i_[1][1][1]; res[1][2][0] = i_[1][2][0] + m.i_[1][2][0]; res[1][2][1] = i_[1][2][1] + m.i_[1][2][1];
+  res[2][0][0] = i_[2][0][0] + m.i_[2][0][0]; res[2][0][1] = i_[2][0][1] + m.i_[2][0][1]; res[2][1][0] = i_[2][1][0] + m.i_[2][1][0]; res[2][1][1] = i_[2][1][1] + m.i_[2][1][1]; res[2][2][0] = i_[2][2][0] + m.i_[2][2][0]; res[2][2][1] = i_[2][2][1] + m.i_[2][2][1];
+
+  return IMatrix3(res);
+}
+
+IMatrix3& IMatrix3::operator += (const IMatrix3& m)
+{
+  i_[0][0][0] += m.i_[0][0][0]; i_[0][0][1] += m.i_[0][0][1]; i_[0][1][0] += m.i_[0][1][0]; i_[0][1][1] += m.i_[0][1][1]; i_[0][2][0] += m.i_[0][2][0]; i_[0][2][1] += m.i_[0][2][1];
+  i_[1][0][0] += m.i_[1][0][0]; i_[1][0][1] += m.i_[1][0][1]; i_[1][1][0] += m.i_[1][1][0]; i_[1][1][1] += m.i_[1][1][1]; i_[1][2][0] += m.i_[1][2][0]; i_[1][2][1] += m.i_[1][2][1];
+  i_[2][0][0] += m.i_[2][0][0]; i_[2][0][1] += m.i_[2][0][1]; i_[2][1][0] += m.i_[2][1][0]; i_[2][1][1] += m.i_[2][1][1]; i_[2][2][0] += m.i_[2][2][0]; i_[2][2][1] += m.i_[2][2][1];
+
+  return *this;
+}
+
+IVector3 IMatrix3::nonIntervalTimesVector(const Vec3f& v) const
+{
+  return IVector3(i_[0][0][0] * v[0] + i_[0][1][0] * v[1] + i_[0][2][0] * v[2],
+                  i_[1][0][0] * v[0] + i_[1][1][0] * v[1] + i_[1][2][0] * v[2],
+                  i_[2][0][0] * v[0] + i_[2][1][0] * v[1] + i_[2][2][0] * v[2]);
+}
+
+IVector3 IMatrix3::nonIntervalTimesVector(const IVector3& v) const
+{
+  return IVector3(i_[0][0][0] * v[0][0] + i_[0][1][0] * v[1][0] + i_[0][2][0] * v[2][0],
+                  i_[1][0][0] * v[0][0] + i_[1][1][0] * v[1][0] + i_[1][2][0] * v[2][0],
+                  i_[2][0][0] * v[0][0] + i_[2][1][0] * v[1][0] + i_[2][2][0] * v[2][0]);
+}
+
+void IMatrix3::print() const
+{
+  std::cout << "[" << i_[0][0][0] << "," << i_[0][0][1] << "]" << " [" << i_[0][1][0] << "," << i_[0][1][1] << "]" << " [" << i_[0][2][0] << "," << i_[0][2][1] << "]" << std::endl;
+  std::cout << "[" << i_[1][0][0] << "," << i_[1][0][1] << "]" << " [" << i_[1][1][0] << "," << i_[1][1][1] << "]" << " [" << i_[1][2][0] << "," << i_[1][2][1] << "]" << std::endl;
+  std::cout << "[" << i_[2][0][0] << "," << i_[2][0][1] << "]" << " [" << i_[2][1][0] << "," << i_[2][1][1] << "]" << " [" << i_[2][2][0] << "," << i_[2][2][1] << "]" << std::endl;
+}
+
+}
diff --git a/trunk/fcl/src/interval_tree.cpp b/trunk/fcl/src/interval_tree.cpp
index 5a106b50f646c301912056f2a59313859c2888d6..397cd16beeba6dc3884bdd851273bb269698203a 100644
--- a/trunk/fcl/src/interval_tree.cpp
+++ b/trunk/fcl/src/interval_tree.cpp
@@ -44,7 +44,7 @@ namespace fcl
 
 IntervalTreeNode::IntervalTreeNode(){}
 
-IntervalTreeNode::IntervalTreeNode(Interval* new_interval) :
+IntervalTreeNode::IntervalTreeNode(SimpleInterval* new_interval) :
     stored_interval (new_interval),
     key(new_interval->low),
     high(new_interval->high),
@@ -157,7 +157,7 @@ void IntervalTree::fixupMaxHigh(IntervalTreeNode* x)
   }
 }
 
-IntervalTreeNode* IntervalTree::insert(Interval* new_interval)
+IntervalTreeNode* IntervalTree::insert(SimpleInterval* new_interval)
 {
   IntervalTreeNode* y;
   IntervalTreeNode* x;
@@ -406,11 +406,11 @@ void IntervalTree::deleteFixup(IntervalTreeNode* x)
   x->red = false;
 }
 
-Interval* IntervalTree::deleteNode(IntervalTreeNode* z)
+SimpleInterval* IntervalTree::deleteNode(IntervalTreeNode* z)
 {
   IntervalTreeNode* y;
   IntervalTreeNode* x;
-  Interval* node_to_delete = z->stored_interval;
+  SimpleInterval* node_to_delete = z->stored_interval;
 
   y= ((z->left == nil) || (z->right == nil)) ? z : getSuccessor(z);
   x= (y->left == nil) ? y->right : y->left;
@@ -477,9 +477,9 @@ bool overlap(double a1, double a2, double b1, double b2)
   }
 }
 
-std::deque<Interval*> IntervalTree::query(double low, double high)
+std::deque<SimpleInterval*> IntervalTree::query(double low, double high)
 {
-  std::deque<Interval*> result_stack;
+  std::deque<SimpleInterval*> result_stack;
   IntervalTreeNode* x = root->left;
   bool run = (x != nil);
 
diff --git a/trunk/fcl/src/interval_vector.cpp b/trunk/fcl/src/interval_vector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5074850d33e4aa422decf5f5bca1239a749faffb
--- /dev/null
+++ b/trunk/fcl/src/interval_vector.cpp
@@ -0,0 +1,239 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+#include "fcl/interval_vector.h"
+#include <iostream>
+
+namespace fcl
+{
+
+
+IVector3::IVector3() {}
+
+IVector3::IVector3(BVH_REAL v) { i_[0] = i_[1] = i_[2] = v; }
+
+IVector3::IVector3(BVH_REAL x, BVH_REAL y, BVH_REAL z)
+{
+  i_[0].setValue(x);
+  i_[1].setValue(y);
+  i_[2].setValue(z);
+}
+
+IVector3::IVector3(BVH_REAL xl, BVH_REAL xu, BVH_REAL yl, BVH_REAL yu, BVH_REAL zl, BVH_REAL zu)
+{
+  i_[0].setValue(xl, xu);
+  i_[1].setValue(yl, yu);
+  i_[2].setValue(zl, zu);
+}
+
+IVector3::IVector3(BVH_REAL v[3][2])
+{
+  i_[0].setValue(v[0][0], v[0][1]);
+  i_[1].setValue(v[1][0], v[1][1]);
+  i_[2].setValue(v[2][0], v[2][1]);
+}
+
+IVector3::IVector3(Interval v[3])
+{
+  i_[0] = v[0];
+  i_[1] = v[1];
+  i_[2] = v[2];
+}
+
+IVector3::IVector3(const Interval& v1, const Interval& v2, const Interval& v3)
+{
+  i_[0] = v1;
+  i_[1] = v2;
+  i_[2] = v3;
+}
+
+IVector3::IVector3(const Vec3f& v)
+{
+  i_[0].setValue(v[0]);
+  i_[1].setValue(v[1]);
+  i_[2].setValue(v[2]);
+}
+
+void IVector3::setZero()
+{
+  i_[0].setValue(0);
+  i_[1].setValue(0);
+  i_[2].setValue(0);
+}
+
+IVector3 IVector3::operator + (const IVector3& other) const
+{
+  Interval res[3];
+  res[0] = i_[0] + other[0];
+  res[1] = i_[1] + other[1];
+  res[2] = i_[2] + other[2];
+  return IVector3(res);
+}
+
+IVector3& IVector3::operator += (const IVector3& other)
+{
+  i_[0] += other[0];
+  i_[1] += other[1];
+  i_[2] += other[2];
+  return *this;
+}
+
+IVector3 IVector3::operator - (const IVector3& other) const
+{
+  Interval res[3];
+  res[0] = i_[0] - other[0];
+  res[1] = i_[1] - other[1];
+  res[2] = i_[2] - other[2];
+  return IVector3(res);
+}
+
+IVector3& IVector3::operator -= (const IVector3& other)
+{
+  i_[0] -= other[0];
+  i_[1] -= other[1];
+  i_[2] -= other[2];
+  return *this;
+}
+
+Interval IVector3::dot(const IVector3& other) const
+{
+  return i_[0] * other[0] + i_[1] * other[1] + i_[2] * other[2];
+}
+
+IVector3 IVector3::cross(const IVector3& other) const
+{
+  Interval res[3];
+  res[0] = i_[1] * other[2] - i_[2] * other[1];
+  res[1] = i_[2] * other[0] - i_[0] * other[2];
+  res[2] = i_[0] * other[1] - i_[1] * other[0];
+  return IVector3(res);
+}
+
+BVH_REAL IVector3::volumn() const
+{
+  return i_[0].diameter() * i_[1].diameter() * i_[2].diameter();
+}
+
+void IVector3::print() const
+{
+  std::cout << "[" << i_[0][0] << "," << i_[0][1] << "]" << std::endl;
+  std::cout << "[" << i_[1][0] << "," << i_[1][1] << "]" << std::endl;
+  std::cout << "[" << i_[2][0] << "," << i_[2][1] << "]" << std::endl;
+}
+
+Vec3f IVector3::center() const
+{
+  return Vec3f(i_[0].center(), i_[1].center(), i_[2].center());
+}
+
+void IVector3::bound(const IVector3& v)
+{
+  if(v[0][0] < i_[0][0]) i_[0][0] = v[0][0];
+  if(v[1][0] < i_[1][0]) i_[1][0] = v[1][0];
+  if(v[2][0] < i_[2][0]) i_[2][0] = v[2][0];
+
+  if(v[0][1] > i_[0][1]) i_[0][1] = v[0][1];
+  if(v[1][1] > i_[1][1]) i_[1][1] = v[1][1];
+  if(v[2][1] > i_[2][1]) i_[2][1] = v[2][1];
+}
+
+void IVector3::bound(const Vec3f& v)
+{
+  if(v[0] < i_[0][0]) i_[0][0] = v[0];
+  if(v[1] < i_[1][0]) i_[1][0] = v[1];
+  if(v[2] < i_[2][0]) i_[2][0] = v[2];
+
+  if(v[0] > i_[0][1]) i_[0][1] = v[0];
+  if(v[1] > i_[1][1]) i_[1][1] = v[1];
+  if(v[2] > i_[2][1]) i_[2][1] = v[2];
+}
+
+
+IVector3 IVector3::bounded(const IVector3& v) const
+{
+  IVector3 res = *this;
+  if(v[0][0] < res.i_[0][0]) res.i_[0][0] = v[0][0];
+  if(v[1][0] < res.i_[1][0]) res.i_[1][0] = v[1][0];
+  if(v[2][0] < res.i_[2][0]) res.i_[2][0] = v[2][0];
+
+  if(v[0][1] > res.i_[0][1]) res.i_[0][1] = v[0][1];
+  if(v[1][1] > res.i_[1][1]) res.i_[1][1] = v[1][1];
+  if(v[2][1] > res.i_[2][1]) res.i_[2][1] = v[2][1];
+
+  return res;
+}
+
+IVector3 IVector3::bounded(const Vec3f& v) const
+{
+  IVector3 res = *this;
+  if(v[0] < res.i_[0][0]) res.i_[0][0] = v[0];
+  if(v[1] < res.i_[1][0]) res.i_[1][0] = v[1];
+  if(v[2] < res.i_[2][0]) res.i_[2][0] = v[2];
+
+  if(v[0] > res.i_[0][1]) res.i_[0][1] = v[0];
+  if(v[1] > res.i_[1][1]) res.i_[1][1] = v[1];
+  if(v[2] > res.i_[2][1]) res.i_[2][1] = v[2];
+
+  return res;
+}
+
+bool IVector3::overlap(const IVector3& v) const
+{
+  if(v[0][1] < i_[0][0]) return false;
+  if(v[1][1] < i_[1][0]) return false;
+  if(v[2][1] < i_[2][0]) return false;
+
+  if(v[0][0] > i_[0][1]) return false;
+  if(v[1][0] > i_[1][1]) return false;
+  if(v[2][0] > i_[2][1]) return false;
+
+  return true;
+}
+
+bool IVector3::contain(const IVector3& v) const
+{
+  if(v[0][0] < i_[0][0]) return false;
+  if(v[1][0] < i_[1][0]) return false;
+  if(v[2][0] < i_[2][0]) return false;
+
+  if(v[0][1] > i_[0][1]) return false;
+  if(v[1][1] > i_[1][1]) return false;
+  if(v[2][1] > i_[2][1]) return false;
+
+  return true;
+}
+
+}
diff --git a/trunk/fcl/src/taylor_model.cpp b/trunk/fcl/src/taylor_model.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d512f5189fd8cfc438ca57073220f095fa71ebbf
--- /dev/null
+++ b/trunk/fcl/src/taylor_model.cpp
@@ -0,0 +1,439 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011, Willow Garage, Inc.
+ *  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 Willow Garage, Inc. 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.
+ */
+
+/** \author Jia Pan */
+
+#include "fcl/taylor_model.h"
+#include <cassert>
+#include <iostream>
+#include <cmath>
+
+namespace fcl
+{
+
+const BVH_REAL TaylorModel::PI_ = 3.1415626535;
+
+TaylorModel::TaylorModel() {}
+
+TaylorModel::TaylorModel(BVH_REAL coeff)
+{
+  coeffs_[0] = coeff;
+  coeffs_[1] = coeffs_[2] = coeffs_[3] = r_[0] = r_[1] = 0;
+}
+
+TaylorModel::TaylorModel(BVH_REAL coeffs[3], const Interval& r)
+{
+  coeffs_[0] = coeffs[0];
+  coeffs_[1] = coeffs[1];
+  coeffs_[2] = coeffs[2];
+  coeffs_[3] = coeffs[3];
+
+  r_ = r;
+}
+
+TaylorModel::TaylorModel(BVH_REAL c0, BVH_REAL c1, BVH_REAL c2, BVH_REAL c3, const Interval& r)
+{
+  coeffs_[0] = c0;
+  coeffs_[1] = c1;
+  coeffs_[2] = c2;
+  coeffs_[3] = c3;
+
+  r_ = r;
+}
+
+void TaylorModel::setTimeInterval(BVH_REAL l, BVH_REAL r)
+{
+  t_.setValue(l, r);
+  t2_.setValue(l * t_[0], r * t_[1]);
+  t3_.setValue(l * t2_[0], r * t2_[1]);
+  t4_.setValue(l * t3_[0], r * t3_[1]);
+  t5_.setValue(l * t4_[0], r * t4_[1]);
+  t6_.setValue(l * t5_[0], r * t5_[1]);
+}
+
+TaylorModel TaylorModel::operator + (const TaylorModel& other) const
+{
+  assert(other.t_ == t_);
+  return TaylorModel(coeffs_[0] + other.coeffs_[0], coeffs_[1] + other.coeffs_[1], coeffs_[2] + other.coeffs_[2], coeffs_[3] + other.coeffs_[3], r_ + other.r_);
+}
+
+TaylorModel TaylorModel::operator - (const TaylorModel& other) const
+{
+  assert(other.t_ == t_);
+  return TaylorModel(coeffs_[0] - other.coeffs_[0], coeffs_[1] - other.coeffs_[1], coeffs_[2] - other.coeffs_[2], coeffs_[3] - other.coeffs_[3], r_ - other.r_);
+}
+TaylorModel& TaylorModel::operator += (const TaylorModel& other)
+{
+  assert(other.t_ == t_);
+  coeffs_[0] += other.coeffs_[0];
+  coeffs_[1] += other.coeffs_[1];
+  coeffs_[2] += other.coeffs_[2];
+  coeffs_[3] += other.coeffs_[3];
+  r_ += other.r_;
+  return *this;
+}
+
+TaylorModel& TaylorModel::operator -= (const TaylorModel& other)
+{
+  assert(other.t_ == t_);
+  coeffs_[0] -= other.coeffs_[0];
+  coeffs_[1] -= other.coeffs_[1];
+  coeffs_[2] -= other.coeffs_[2];
+  coeffs_[3] -= other.coeffs_[3];
+  r_ -= other.r_;
+  return *this;
+}
+
+/** \brief Taylor model multiplication:
+ * f(t) = c0+c1*t+c2*t^2+c3*t^3+[a,b]
+ * g(t) = c0'+c1'*t+c2'*t^2+c3'*t^2+[c,d]
+ * f(t)g(t)= c0c0'+
+ *           (c0c1'+c1c0')t+
+ *           (c0c2'+c1c1'+c2c0')t^2+
+ *           (c0c3'+c1c2'+c2c1'+c3c0')t^3+
+ *           [a,b][c,d]+
+ *           (c1c3'+c2c2'+c3c1')t^4+
+ *           (c2c3'+c3c2')t^5+
+ *           (c3c3')t^6+
+ *           (c0+c1*t+c2*t^2+c3*t^3)[c,d]+
+ *           (c0'+c1'*t+c2'*t^2+c3'*c^3)[a,b]
+ */
+
+TaylorModel TaylorModel::operator * (const TaylorModel& other) const
+{
+  assert(other.t_ == t_);
+  register BVH_REAL c0, c1, c2, c3;
+  register BVH_REAL c0b = other.coeffs_[0], c1b = other.coeffs_[1], c2b = other.coeffs_[2], c3b = other.coeffs_[3];
+
+  const Interval& rb = other.r_;
+
+  c0 = coeffs_[0] * c0b;
+  c1 = coeffs_[0] * c1b + coeffs_[1] * c0b;
+  c2 = coeffs_[0] * c2b + coeffs_[1] * c1b + coeffs_[2] * c0b;
+  c3 = coeffs_[0] * c3b + coeffs_[1] * c2b + coeffs_[2] * c1b + coeffs_[3] * c0b;
+
+  Interval remainder(r_ * rb);
+  register BVH_REAL tempVal = coeffs_[1] * c3b + coeffs_[2] * c2b + coeffs_[3] * c1b;
+  remainder += t4_ * tempVal;
+
+  tempVal = coeffs_[2] * c3b + coeffs_[3] * c2b;
+  remainder += t5_ * tempVal;
+
+  tempVal = coeffs_[3] * c3b;
+  remainder += t6_ * tempVal;
+
+  remainder += ((Interval(coeffs_[0]) + t_ * coeffs_[1] + t2_ * coeffs_[2] + t3_ * coeffs_[3]) * rb +
+      (Interval(c0b) + t_ * c1b + t2_ * c2b + t3_ * c3b) * r_);
+
+  return TaylorModel(c0, c1, c2, c3, remainder);
+}
+
+TaylorModel TaylorModel::operator * (BVH_REAL d) const
+{
+  return TaylorModel(coeffs_[0] * d, coeffs_[1] * d, coeffs_[2] * d, coeffs_[3] * d,  r_ * d);
+}
+
+
+TaylorModel TaylorModel::operator - () const
+{
+  return TaylorModel(-coeffs_[0], -coeffs_[1], -coeffs_[2], -coeffs_[3], -r_);
+}
+
+void TaylorModel::print() const
+{
+  std::cout << coeffs_[0] << "+" << coeffs_[1] << "*t+" << coeffs_[2] << "*t^2+" << coeffs_[3] << "*t^3+[" << r_[0] << "," << r_[1] << "]" << std::endl;
+}
+
+Interval TaylorModel::getBound(BVH_REAL t) const
+{
+  return Interval(coeffs_[0] + t * (coeffs_[1] + t * (coeffs_[2] + t * coeffs_[3]))) + r_;
+}
+
+Interval TaylorModel::getBound(BVH_REAL t0, BVH_REAL t1) const
+{
+  Interval t(t0, t1);
+  Interval t2(t0 * t0, t1 * t1);
+  Interval t3(t0 * t2[0], t1 * t2[1]);
+
+  return Interval(coeffs_[0]) + t * coeffs_[1] + t2 * coeffs_[2] + t3 * coeffs_[3] + r_;
+}
+
+Interval TaylorModel::getBound() const
+{
+  return Interval(coeffs_[0] + r_[0], coeffs_[1] + r_[1]) + t_ * coeffs_[1] + t2_ * coeffs_[2] + t3_ * coeffs_[3];
+}
+
+Interval TaylorModel::getTightBound(BVH_REAL t0, BVH_REAL t1) const
+{
+
+  if(t0 < t_[0]) t0 = t_[0];
+  if(t1 > t_[1]) t1 = t_[1];
+
+  if(coeffs_[3] == 0)
+  {
+    register BVH_REAL a = -coeffs_[1] / (2 * coeffs_[2]);
+    Interval polybounds;
+    if(a <= t1 && a >= t0)
+    {
+      BVH_REAL AQ = coeffs_[0] + a * (coeffs_[1] + a * coeffs_[2]);
+      register BVH_REAL t = t0;
+      BVH_REAL LQ = coeffs_[0] + t * (coeffs_[1] + t * coeffs_[2]);
+      t = t1;
+      BVH_REAL RQ = coeffs_[0] + t * (coeffs_[1] + t * coeffs_[2]);
+
+      BVH_REAL minQ = LQ, maxQ = RQ;
+      if(LQ > RQ)
+      {
+        minQ = RQ;
+        maxQ = LQ;
+      }
+
+      if(minQ > AQ) minQ = AQ;
+      if(maxQ < AQ) maxQ = AQ;
+
+      polybounds.setValue(minQ, maxQ);
+    }
+    else
+    {
+      register BVH_REAL t = t0;
+      BVH_REAL LQ = coeffs_[0] + t * (coeffs_[1] + t * coeffs_[2]);
+      t = t1;
+      BVH_REAL RQ = coeffs_[0] + t * (coeffs_[1] + t * coeffs_[2]);
+
+      if(LQ > RQ) polybounds.setValue(RQ, LQ);
+      else polybounds.setValue(LQ, RQ);
+    }
+
+    return polybounds + r_;
+  }
+  else
+  {
+    register BVH_REAL t = t0;
+    BVH_REAL LQ = coeffs_[0] + t * (coeffs_[1] + t * (coeffs_[2] + t * coeffs_[3]));
+    t = t1;
+    BVH_REAL RQ = coeffs_[0] + t * (coeffs_[1] + t * (coeffs_[2] + t * coeffs_[3]));
+
+    if(LQ > RQ)
+    {
+      BVH_REAL tmp = LQ;
+      LQ = RQ;
+      RQ = tmp;
+    }
+
+    // derivative: c1+2*c2*t+3*c3*t^2
+
+    BVH_REAL delta = coeffs_[2] * coeffs_[2] - 3 * coeffs_[1] * coeffs_[3];
+    if(delta < 0)
+      return Interval(LQ, RQ) + r_;
+
+    BVH_REAL r1=(-coeffs_[2]-sqrt(delta))/(3*coeffs_[3]);
+    BVH_REAL r2=(-coeffs_[2]+sqrt(delta))/(3*coeffs_[3]);
+
+    if(r1 <= t1 && r1 >= t0)
+    {
+      BVH_REAL Q = coeffs_[0] + r1 * (coeffs_[1] + r1 * (coeffs_[2] + r1 * coeffs_[3]));
+      if(Q < LQ) LQ = Q;
+      else if(Q > RQ) RQ = Q;
+    }
+
+    if(r2 <= t1 && r2 >= t0)
+    {
+      BVH_REAL Q = coeffs_[0] + r2 * (coeffs_[1] + r2 * (coeffs_[2] + r2 * coeffs_[3]));
+      if(Q < LQ) LQ = Q;
+      else if(Q > RQ) RQ = Q;
+    }
+
+    return Interval(LQ, RQ) + r_;
+  }
+}
+
+Interval TaylorModel::getTightBound() const
+{
+  return getTightBound(t_[0], t_[1]);
+}
+
+void TaylorModel::setZero()
+{
+  coeffs_[0] = coeffs_[1] = coeffs_[2] = coeffs_[3] = 0;
+  r_.setValue(0);
+}
+
+
+void generateTaylorModelForCosFunc(TaylorModel& tm, BVH_REAL w, BVH_REAL q0)
+{
+  BVH_REAL a = tm.t_.center();
+  BVH_REAL t = w * a + q0;
+  BVH_REAL w2 = w * w;
+  BVH_REAL fa = cos(t);
+  BVH_REAL fda = -w*sin(t);
+  BVH_REAL fdda = -w2*fa;
+  BVH_REAL fddda = -w2*fda;
+
+  tm.coeffs_[0] = fa-a*(fda-0.5*a*(fdda-1.0/3.0*a*fddda));
+  tm.coeffs_[1] = fda-a*fdda+0.5*a*a*fddda;
+  tm.coeffs_[2] = 0.5*(fdda-a*fddda);
+  tm.coeffs_[3] = 1.0/6.0*fddda;
+
+  // compute bounds for w^3 cos(wt+q0)/16, t \in [t0, t1]
+  Interval fddddBounds;
+  if(w == 0) fddddBounds.setValue(0);
+  else
+  {
+    BVH_REAL cosQL = cos(tm.t_[0] * w + q0);
+    BVH_REAL cosQR = cos(tm.t_[1] * w + q0);
+
+    if(cosQL < cosQR) fddddBounds.setValue(cosQL, cosQR);
+    else fddddBounds.setValue(cosQR, cosQL);
+
+    // enlarge to handle round-off errors
+    fddddBounds[0] -= 1e-15;
+    fddddBounds[1] += 1e-15;
+
+    // cos reaches maximum if there exists an integer k in [(w*t0+q0)/2pi, (w*t1+q0)/2pi];
+    // cos reaches minimum if there exists an integer k in [(w*t0+q0-pi)/2pi, (w*t1+q0-pi)/2pi]
+
+    BVH_REAL k1 = (tm.t_[0] * w + q0) / (2 * TaylorModel::PI_);
+    BVH_REAL k2 = (tm.t_[1] * w + q0) / (2 * TaylorModel::PI_);
+
+
+    if(w > 0)
+    {
+      if(ceil(k2) - floor(k1) > 1) fddddBounds[1] = 1;
+      k1 -= 0.5;
+      k2 -= 0.5;
+      if(ceil(k2) - floor(k1) > 1) fddddBounds[0] = -1;
+    }
+    else
+    {
+      if(ceil(k1) - floor(k2) > 1) fddddBounds[1] = 1;
+      k1 -= 0.5;
+      k2 -= 0.5;
+      if(ceil(k1) - floor(k2) > 1) fddddBounds[0] = -1;
+    }
+  }
+
+  BVH_REAL w4 = w2 * w2;
+  fddddBounds *= w4;
+
+  BVH_REAL midSize = 0.5 * (tm.t_[1] - tm.t_[0]);
+  BVH_REAL midSize2 = midSize * midSize;
+  BVH_REAL midSize4 = midSize2 * midSize2;
+
+  // [0, midSize4] * fdddBounds
+  if(fddddBounds[0] > 0)
+    tm.r_.setValue(0, fddddBounds[1] * midSize4 * (1.0 / 24));
+  else if(fddddBounds[0] < 0)
+    tm.r_.setValue(fddddBounds[0] * midSize4 * (1.0 / 24), 0);
+  else
+    tm.r_.setValue(fddddBounds[0] * midSize4 * (1.0 / 24), fddddBounds[1] * midSize4 * (1.0 / 24));
+}
+
+void generateTaylorModelForSinFunc(TaylorModel& tm, BVH_REAL w, BVH_REAL q0)
+{
+  BVH_REAL a = tm.t_.center();
+  BVH_REAL t = w * a + q0;
+  BVH_REAL w2 = w * w;
+  BVH_REAL fa = sin(t);
+  BVH_REAL fda = w*cos(t);
+  BVH_REAL fdda = -w2*fa;
+  BVH_REAL fddda = -w2*fda;
+
+  tm.coeffs_[0] = fa-a*(fda-0.5*a*(fdda-1.0/3.0*a*fddda));
+  tm.coeffs_[1] = fda-a*fdda+0.5*a*a*fddda;
+  tm.coeffs_[2] = 0.5*(fdda-a*fddda);
+  tm.coeffs_[3] = 1.0/6.0*fddda;
+
+  // compute bounds for w^3 sin(wt+q0)/16, t \in [t0, t1]
+
+  Interval fddddBounds;
+
+  if(w == 0) fddddBounds.setValue(0);
+  else
+  {
+    BVH_REAL sinQL = sin(w * tm.t_[0] + q0);
+    BVH_REAL sinQR = sin(w * tm.t_[1] + q0);
+
+    if(sinQL < sinQR) fddddBounds.setValue(sinQL, sinQR);
+    else fddddBounds.setValue(sinQR, sinQL);
+
+    // enlarge to handle round-off errors
+    fddddBounds[0] -= 1e-15;
+    fddddBounds[1] += 1e-15;
+
+    // sin reaches maximum if there exists an integer k in [(w*t0+q0-pi/2)/2pi, (w*t1+q0-pi/2)/2pi];
+    // sin reaches minimum if there exists an integer k in [(w*t0+q0-pi-pi/2)/2pi, (w*t1+q0-pi-pi/2)/2pi]
+
+    BVH_REAL k1 = (tm.t_[0] * w + q0) / (2 * TaylorModel::PI_) - 0.25;
+    BVH_REAL k2 = (tm.t_[1] * w + q0) / (2 * TaylorModel::PI_) - 0.25;
+
+    if(w > 0)
+    {
+      if(ceil(k2) - floor(k1) > 1) fddddBounds[1] = 1;
+      k1 -= 0.5;
+      k2 -= 0.5;
+      if(ceil(k2) - floor(k1) > 1) fddddBounds[0] = -1;
+    }
+    else
+    {
+      if(ceil(k1) - floor(k2) > 1) fddddBounds[1] = 1;
+      k1 -= 0.5;
+      k2 -= 0.5;
+      if(ceil(k1) - floor(k2) > 1) fddddBounds[0] = -1;
+    }
+
+    BVH_REAL w4 = w2 * w2;
+    fddddBounds *= w4;
+
+    BVH_REAL midSize = 0.5 * (tm.t_[1] - tm.t_[0]);
+    BVH_REAL midSize2 = midSize * midSize;
+    BVH_REAL midSize4 = midSize2 * midSize2;
+
+    // [0, midSize4] * fdddBounds
+    if(fddddBounds[0] > 0)
+      tm.r_.setValue(0, fddddBounds[1] * midSize4 * (1.0 / 24));
+    else if(fddddBounds[0] < 0)
+      tm.r_.setValue(fddddBounds[0] * midSize4 * (1.0 / 24), 0);
+    else
+      tm.r_.setValue(fddddBounds[0] * midSize4 * (1.0 / 24), fddddBounds[1] * midSize4 * (1.0 / 24));
+  }
+}
+
+void generateTaylorModelForLinearFunc(TaylorModel& tm, BVH_REAL p, BVH_REAL v)
+{
+  tm.coeffs_[0] = p;
+  tm.coeffs_[1] = v;
+  tm.coeffs_[2] = tm.coeffs_[3] = tm.r_[0] = tm.r_[1] = 0;
+}
+
+}